diff --git a/allegro/allegro.h b/allegro/allegro.h new file mode 100644 index 0000000000..8df1804e30 --- /dev/null +++ b/allegro/allegro.h @@ -0,0 +1,82 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Main header file for the entire Allegro library. + * (separate modules can be included from the allegro/ directory) + * + * By Shawn Hargreaves. + * + * Vincent Penquerc'h split the original allegro.h into separate headers. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_H +#define ALLEGRO_H + +#include "allegro/base.h" + +#include "allegro/system.h" +#include "allegro/debug.h" + +#include "allegro/unicode.h" + +#include "allegro/mouse.h" +#include "allegro/timer.h" +#include "allegro/keyboard.h" +#include "allegro/joystick.h" + +#include "allegro/palette.h" +#include "allegro/gfx.h" +#include "allegro/color.h" +#include "allegro/draw.h" +#include "allegro/rle.h" +#include "allegro/compiled.h" +#include "allegro/text.h" +#include "allegro/font.h" + +#include "allegro/fli.h" +#include "allegro/config.h" +#include "allegro/gui.h" + +#include "allegro/sound.h" + +#include "allegro/file.h" +#include "allegro/lzss.h" +#include "allegro/datafile.h" + +#include "allegro/fixed.h" +#include "allegro/fmaths.h" +#include "allegro/matrix.h" +#include "allegro/quat.h" + +#include "allegro/3d.h" +#include "allegro/3dmaths.h" + + +#ifndef ALLEGRO_NO_COMPATIBILITY + #include "allegro/alcompat.h" +#endif + +#ifndef ALLEGRO_NO_FIX_CLASS + #ifdef __cplusplus + #include "allegro/fix.h" + #endif +#endif + + +#ifdef ALLEGRO_EXTRA_HEADER + #include ALLEGRO_EXTRA_HEADER +#endif + +#endif /* ifndef ALLEGRO_H */ + + diff --git a/allegro/allegro/3d.h b/allegro/allegro/3d.h new file mode 100644 index 0000000000..8daed76315 --- /dev/null +++ b/allegro/allegro/3d.h @@ -0,0 +1,104 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 3D polygon drawing routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_3D_H +#define ALLEGRO_3D_H + +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +typedef struct V3D /* a 3d point (fixed point version) */ +{ + fixed x, y, z; /* position */ + fixed u, v; /* texture map coordinates */ + int c; /* color */ +} V3D; + + +typedef struct V3D_f /* a 3d point (floating point version) */ +{ + float x, y, z; /* position */ + float u, v; /* texture map coordinates */ + int c; /* color */ +} V3D_f; + + +#define POLYTYPE_FLAT 0 +#define POLYTYPE_GCOL 1 +#define POLYTYPE_GRGB 2 +#define POLYTYPE_ATEX 3 +#define POLYTYPE_PTEX 4 +#define POLYTYPE_ATEX_MASK 5 +#define POLYTYPE_PTEX_MASK 6 +#define POLYTYPE_ATEX_LIT 7 +#define POLYTYPE_PTEX_LIT 8 +#define POLYTYPE_ATEX_MASK_LIT 9 +#define POLYTYPE_PTEX_MASK_LIT 10 +#define POLYTYPE_ATEX_TRANS 11 +#define POLYTYPE_PTEX_TRANS 12 +#define POLYTYPE_ATEX_MASK_TRANS 13 +#define POLYTYPE_PTEX_MASK_TRANS 14 +#define POLYTYPE_MAX 15 +#define POLYTYPE_ZBUF 16 + +AL_VAR(float, scene_gap); + +AL_FUNC(void, _soft_polygon3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])); +AL_FUNC(void, _soft_polygon3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])); +AL_FUNC(void, _soft_triangle3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)); +AL_FUNC(void, _soft_triangle3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)); +AL_FUNC(void, _soft_quad3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)); +AL_FUNC(void, _soft_quad3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)); +AL_FUNC(int, clip3d, (int type, fixed min_z, fixed max_z, int vc, AL_CONST V3D *vtx[], V3D *vout[], V3D *vtmp[], int out[])); +AL_FUNC(int, clip3d_f, (int type, float min_z, float max_z, int vc, AL_CONST V3D_f *vtx[], V3D_f *vout[], V3D_f *vtmp[], int out[])); + +AL_FUNC(fixed, polygon_z_normal, (AL_CONST V3D *v1, AL_CONST V3D *v2, AL_CONST V3D *v3)); +AL_FUNC(float, polygon_z_normal_f, (AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, AL_CONST V3D_f *v3)); + +/* Note: You are not supposed to mix ZBUFFER with BITMAP even though it is + * currently possible. This is just the internal representation, and it may + * change in the future. + */ +typedef struct BITMAP ZBUFFER; + +AL_FUNC(ZBUFFER *, create_zbuffer, (struct BITMAP *bmp)); +AL_FUNC(ZBUFFER *, create_sub_zbuffer, (ZBUFFER *parent, int x, int y, int width, int height)); +AL_FUNC(void, set_zbuffer, (ZBUFFER *zbuf)); +AL_FUNC(void, clear_zbuffer, (ZBUFFER *zbuf, float z)); +AL_FUNC(void, destroy_zbuffer, (ZBUFFER *zbuf)); + +AL_FUNC(int, create_scene, (int nedge, int npoly)); +AL_FUNC(void, clear_scene, (struct BITMAP* bmp)); +AL_FUNC(void, destroy_scene, (void)); +AL_FUNC(int, scene_polygon3d, (int type, struct BITMAP *texture, int vx, V3D *vtx[])); +AL_FUNC(int, scene_polygon3d_f, (int type, struct BITMAP *texture, int vx, V3D_f *vtx[])); +AL_FUNC(void, render_scene, (void)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_3D_H */ + + diff --git a/allegro/allegro/3dmaths.h b/allegro/allegro/3dmaths.h new file mode 100644 index 0000000000..3977892f49 --- /dev/null +++ b/allegro/allegro/3dmaths.h @@ -0,0 +1,64 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 3D oriented math routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_3DMATHS_H +#define ALLEGRO_3DMATHS_H + +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct QUAT; +struct MATRIX_f; + +AL_FUNC(fixed, vector_length, (fixed x, fixed y, fixed z)); +AL_FUNC(float, vector_length_f, (float x, float y, float z)); + +AL_FUNC(void, normalize_vector, (fixed *x, fixed *y, fixed *z)); +AL_FUNC(void, normalize_vector_f, (float *x, float *y, float *z)); + +AL_FUNC(void, cross_product, (fixed x1, fixed y_1, fixed z1, fixed x2, fixed y2, fixed z2, fixed *xout, fixed *yout, fixed *zout)); +AL_FUNC(void, cross_product_f, (float x1, float y_1, float z1, float x2, float y2, float z2, float *xout, float *yout, float *zout)); + +AL_VAR(fixed, _persp_xscale); +AL_VAR(fixed, _persp_yscale); +AL_VAR(fixed, _persp_xoffset); +AL_VAR(fixed, _persp_yoffset); + +AL_VAR(float, _persp_xscale_f); +AL_VAR(float, _persp_yscale_f); +AL_VAR(float, _persp_xoffset_f); +AL_VAR(float, _persp_yoffset_f); + +AL_FUNC(void, set_projection_viewport, (int x, int y, int w, int h)); + +AL_FUNC(void, quat_to_matrix, (AL_CONST struct QUAT *q, struct MATRIX_f *m)); +AL_FUNC(void, matrix_to_quat, (AL_CONST struct MATRIX_f *m, struct QUAT *q)); + +#ifdef __cplusplus + } +#endif + +#include "inline/3dmaths.inl" + +#endif /* ifndef ALLEGRO_3DMATHS_H */ + + diff --git a/allegro/allegro/alcompat.h b/allegro/allegro/alcompat.h new file mode 100644 index 0000000000..e302bfdcf4 --- /dev/null +++ b/allegro/allegro/alcompat.h @@ -0,0 +1,237 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Backward compatibility stuff. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COMPAT_H +#define ALLEGRO_COMPAT_H + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifndef ALLEGRO_LIB_BUILD + + #ifndef ALLEGRO_NO_CLEAR_BITMAP_ALIAS + #if (defined ALLEGRO_GCC) + static __attribute__((unused)) __inline__ void clear(BITMAP *bmp) + { + clear_bitmap(bmp); + } + #else + static INLINE void clear(BITMAP *bmp) + { + clear_bitmap(bmp); + } + #endif + #endif + + #ifndef ALLEGRO_NO_FIX_ALIASES + AL_ALIAS(fixed fadd(fixed x, fixed y), fixadd(x, y)) + AL_ALIAS(fixed fsub(fixed x, fixed y), fixsub(x, y)) + AL_ALIAS(fixed fmul(fixed x, fixed y), fixmul(x, y)) + AL_ALIAS(fixed fdiv(fixed x, fixed y), fixdiv(x, y)) + AL_ALIAS(int fceil(fixed x), fixceil(x)) + AL_ALIAS(int ffloor(fixed x), fixfloor(x)) + AL_ALIAS(fixed fcos(fixed x), fixcos(x)) + AL_ALIAS(fixed fsin(fixed x), fixsin(x)) + AL_ALIAS(fixed ftan(fixed x), fixtan(x)) + AL_ALIAS(fixed facos(fixed x), fixacos(x)) + AL_ALIAS(fixed fasin(fixed x), fixasin(x)) + AL_ALIAS(fixed fatan(fixed x), fixatan(x)) + AL_ALIAS(fixed fatan2(fixed y, fixed x), fixatan2(y, x)) + AL_ALIAS(fixed fsqrt(fixed x), fixsqrt(x)) + AL_ALIAS(fixed fhypot(fixed x, fixed y), fixhypot(x, y)) + #endif + +#endif /* !defined ALLEGRO_LIB_BUILD */ + + +#define KB_NORMAL 1 +#define KB_EXTENDED 2 + +#define SEND_MESSAGE object_message + +#define cpu_fpu (cpu_capabilities & CPU_FPU) +#define cpu_mmx (cpu_capabilities & CPU_MMX) +#define cpu_3dnow (cpu_capabilities & CPU_3DNOW) +#define cpu_cpuid (cpu_capabilities & CPU_ID) + +#define joy_x (joy[0].stick[0].axis[0].pos) +#define joy_y (joy[0].stick[0].axis[1].pos) +#define joy_left (joy[0].stick[0].axis[0].d1) +#define joy_right (joy[0].stick[0].axis[0].d2) +#define joy_up (joy[0].stick[0].axis[1].d1) +#define joy_down (joy[0].stick[0].axis[1].d2) +#define joy_b1 (joy[0].button[0].b) +#define joy_b2 (joy[0].button[1].b) +#define joy_b3 (joy[0].button[2].b) +#define joy_b4 (joy[0].button[3].b) +#define joy_b5 (joy[0].button[4].b) +#define joy_b6 (joy[0].button[5].b) +#define joy_b7 (joy[0].button[6].b) +#define joy_b8 (joy[0].button[7].b) + +#define joy2_x (joy[1].stick[0].axis[0].pos) +#define joy2_y (joy[1].stick[0].axis[1].pos) +#define joy2_left (joy[1].stick[0].axis[0].d1) +#define joy2_right (joy[1].stick[0].axis[0].d2) +#define joy2_up (joy[1].stick[0].axis[1].d1) +#define joy2_down (joy[1].stick[0].axis[1].d2) +#define joy2_b1 (joy[1].button[0].b) +#define joy2_b2 (joy[1].button[1].b) + +#define joy_throttle (joy[0].stick[2].axis[0].pos) + +#define joy_hat ((joy[0].stick[1].axis[0].d1) ? 1 : \ + ((joy[0].stick[1].axis[0].d2) ? 3 : \ + ((joy[0].stick[1].axis[1].d1) ? 4 : \ + ((joy[0].stick[1].axis[1].d2) ? 2 : \ + 0)))) + +#define JOY_HAT_CENTRE 0 +#define JOY_HAT_CENTER 0 +#define JOY_HAT_LEFT 1 +#define JOY_HAT_DOWN 2 +#define JOY_HAT_RIGHT 3 +#define JOY_HAT_UP 4 + +AL_FUNC_DEPRECATED(int, initialise_joystick, (void)); + + +/* in case you want to spell 'palette' as 'pallete' */ +#define PALLETE PALETTE +#define black_pallete black_palette +#define desktop_pallete desktop_palette +#define set_pallete set_palette +#define get_pallete get_palette +#define set_pallete_range set_palette_range +#define get_pallete_range get_palette_range +#define fli_pallete fli_palette +#define pallete_color palette_color +#define DAT_PALLETE DAT_PALETTE +#define select_pallete select_palette +#define unselect_pallete unselect_palette +#define generate_332_pallete generate_332_palette +#define generate_optimised_pallete generate_optimised_palette + + +/* a pretty vague name */ +#define fix_filename_path canonicalize_filename + + +/* the good old file selector */ +#define OLD_FILESEL_WIDTH -1 +#define OLD_FILESEL_HEIGHT -1 + +AL_INLINE_DEPRECATED(int, file_select, (AL_CONST char *message, char *path, AL_CONST char *ext), +{ + return file_select_ex(message, path, ext, 1024, OLD_FILESEL_WIDTH, OLD_FILESEL_HEIGHT); +}) + + +/* the old (and broken!) file enumeration function */ +AL_FUNC_DEPRECATED(int, for_each_file, (AL_CONST char *name, int attrib, AL_METHOD(void, callback, (AL_CONST char *filename, int attrib, int param)), int param)); +/* long is 32-bit only on some systems, and we want to list DVDs! */ +AL_FUNC_DEPRECATED(long, file_size, (AL_CONST char *filename)); + + +/* the old state-based textout functions */ +AL_VAR(int, _textmode); +AL_FUNC_DEPRECATED(int, text_mode, (int mode)); + +AL_INLINE_DEPRECATED(void, textout, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), +{ + textout_ex(bmp, f, str, x, y, color, _textmode); +}) + +AL_INLINE_DEPRECATED(void, textout_centre, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), +{ + textout_centre_ex(bmp, f, str, x, y, color, _textmode); +}) + +AL_INLINE_DEPRECATED(void, textout_right, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x, int y, int color), +{ + textout_right_ex(bmp, f, str, x, y, color, _textmode); +}) + +AL_INLINE_DEPRECATED(void, textout_justify, (struct BITMAP *bmp, AL_CONST FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color), +{ + textout_justify_ex(bmp, f, str, x1, x2, y, diff, color, _textmode); +}) + +AL_PRINTFUNC_DEPRECATED(void, textprintf, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); +AL_PRINTFUNC_DEPRECATED(void, textprintf_centre, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); +AL_PRINTFUNC_DEPRECATED(void, textprintf_right, (struct BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color, AL_CONST char *format, ...), 6, 7); +AL_PRINTFUNC_DEPRECATED(void, textprintf_justify, (struct BITMAP *bmp, AL_CONST FONT *f, int x1, int x2, int y, int diff, int color, AL_CONST char *format, ...), 8, 9); + +AL_INLINE_DEPRECATED(void, draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), +{ + draw_character_ex(bmp, sprite, x, y, color, _textmode); +}) + +AL_INLINE_DEPRECATED(int, gui_textout, (struct BITMAP *bmp, AL_CONST char *s, int x, int y, int color, int centre), +{ + return gui_textout_ex(bmp, s, x, y, color, _textmode, centre); +}) + + +/* the old close button functions */ +AL_INLINE_DEPRECATED(int, set_window_close_button, (int enable), +{ + (void)enable; + return 0; +}) + +AL_INLINE_DEPRECATED(void, set_window_close_hook, (void (*proc)(void)), +{ + set_close_button_callback(proc); +}) + + +/* the weird old clipping API */ +AL_FUNC_DEPRECATED(void, set_clip, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); + + +/* unnecessary, can use rest(0) */ +AL_INLINE_DEPRECATED(void, yield_timeslice, (void), +{ + ASSERT(system_driver); + + if (system_driver->yield_timeslice) + system_driver->yield_timeslice(); +}) + + +/* DOS-ish monitor retrace ideas that don't work elsewhere */ +AL_FUNCPTR(void, retrace_proc, (void)); + +#ifdef ALLEGRO_LIB_BUILD + AL_FUNC(int, timer_can_simulate_retrace, (void)); + AL_FUNC(void, timer_simulate_retrace, (int enable)); +#else + AL_FUNC_DEPRECATED(int, timer_can_simulate_retrace, (void)); + AL_FUNC_DEPRECATED(void, timer_simulate_retrace, (int enable)); +#endif +AL_FUNC_DEPRECATED(int, timer_is_using_retrace, (void)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_COMPAT_H */ + diff --git a/allegro/allegro/alinline.h b/allegro/allegro/alinline.h new file mode 100644 index 0000000000..0efa507d6f --- /dev/null +++ b/allegro/allegro/alinline.h @@ -0,0 +1,34 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#include "inline/system.inl" + +#include "inline/gfx.inl" + +#include "inline/color.inl" + +#include "inline/draw.inl" + +#include "inline/fmaths.inl" + +#include "inline/3dmaths.inl" + +#include "inline/matrix.inl" + +/* alcompat.h includes some inline functions */ +#include "alcompat.h" diff --git a/allegro/allegro/base.h b/allegro/allegro/base.h new file mode 100644 index 0000000000..a66e8d8e35 --- /dev/null +++ b/allegro/allegro/base.h @@ -0,0 +1,96 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Base header, defines basic stuff needed by pretty much + * everything else. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_BASE_H +#define ALLEGRO_BASE_H + +#ifndef ALLEGRO_NO_STD_HEADERS + #include + #include + #include + #include + #include + #include + #include +#endif + +#if (defined DEBUGMODE) && (defined FORTIFY) + #include +#endif + +#if (defined DEBUGMODE) && (defined DMALLOC) + #include +#endif + +#include "internal/alconfig.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define ALLEGRO_VERSION 4 +#define ALLEGRO_SUB_VERSION 2 +#define ALLEGRO_WIP_VERSION 2 +#define ALLEGRO_VERSION_STR "4.2.2" +#define ALLEGRO_DATE_STR "2007" +#define ALLEGRO_DATE 20070722 /* yyyymmdd */ + +/*******************************************/ +/************ Some global stuff ************/ +/*******************************************/ + +#ifndef TRUE + #define TRUE -1 + #define FALSE 0 +#endif + +#undef MIN +#undef MAX +#undef MID + +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define MID(x,y,z) MAX((x), MIN((y), (z))) + +#undef ABS +#define ABS(x) (((x) >= 0) ? (x) : (-(x))) + +#undef SGN +#define SGN(x) (((x) >= 0) ? 1 : -1) + +#define AL_PI 3.14159265358979323846 + +#define AL_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) + +AL_VAR(int *, allegro_errno); + +typedef struct _DRIVER_INFO /* info about a hardware driver */ +{ + int id; /* integer ID */ + void *driver; /* the driver structure */ + int autodetect; /* set to allow autodetection */ +} _DRIVER_INFO; + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_BASE_H */ + + diff --git a/allegro/allegro/color.h b/allegro/allegro/color.h new file mode 100644 index 0000000000..46dbd61d16 --- /dev/null +++ b/allegro/allegro/color.h @@ -0,0 +1,155 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Color manipulation routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COLOR_H +#define ALLEGRO_COLOR_H + +#include "base.h" +#include "palette.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +AL_VAR(PALETTE, black_palette); +AL_VAR(PALETTE, desktop_palette); +AL_VAR(PALETTE, default_palette); + +typedef struct { + unsigned char data[32][32][32]; +} RGB_MAP; + +typedef struct { + unsigned char data[PAL_SIZE][PAL_SIZE]; +} COLOR_MAP; + +AL_VAR(RGB_MAP *, rgb_map); +AL_VAR(COLOR_MAP *, color_map); + +AL_VAR(PALETTE, _current_palette); + +AL_VAR(int, _rgb_r_shift_15); +AL_VAR(int, _rgb_g_shift_15); +AL_VAR(int, _rgb_b_shift_15); +AL_VAR(int, _rgb_r_shift_16); +AL_VAR(int, _rgb_g_shift_16); +AL_VAR(int, _rgb_b_shift_16); +AL_VAR(int, _rgb_r_shift_24); +AL_VAR(int, _rgb_g_shift_24); +AL_VAR(int, _rgb_b_shift_24); +AL_VAR(int, _rgb_r_shift_32); +AL_VAR(int, _rgb_g_shift_32); +AL_VAR(int, _rgb_b_shift_32); +AL_VAR(int, _rgb_a_shift_32); + +AL_ARRAY(int, _rgb_scale_5); +AL_ARRAY(int, _rgb_scale_6); + +#define MASK_COLOR_8 0 +#define MASK_COLOR_15 0x7C1F +#define MASK_COLOR_16 0xF81F +#define MASK_COLOR_24 0xFF00FF +#define MASK_COLOR_32 0xFF00FF + +AL_VAR(int *, palette_color); + +AL_FUNC(void, set_color, (int idx, AL_CONST RGB *p)); +AL_FUNC(void, set_palette, (AL_CONST PALETTE p)); +AL_FUNC(void, set_palette_range, (AL_CONST PALETTE p, int from, int to, int retracesync)); + +AL_FUNC(void, get_color, (int idx, RGB *p)); +AL_FUNC(void, get_palette, (PALETTE p)); +AL_FUNC(void, get_palette_range, (PALETTE p, int from, int to)); + +AL_FUNC(void, fade_interpolate, (AL_CONST PALETTE source, AL_CONST PALETTE dest, PALETTE output, int pos, int from, int to)); +AL_FUNC(void, fade_from_range, (AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed, int from, int to)); +AL_FUNC(void, fade_in_range, (AL_CONST PALETTE p, int speed, int from, int to)); +AL_FUNC(void, fade_out_range, (int speed, int from, int to)); +AL_FUNC(void, fade_from, (AL_CONST PALETTE source, AL_CONST PALETTE dest, int speed)); +AL_FUNC(void, fade_in, (AL_CONST PALETTE p, int speed)); +AL_FUNC(void, fade_out, (int speed)); + +AL_FUNC(void, select_palette, (AL_CONST PALETTE p)); +AL_FUNC(void, unselect_palette, (void)); + +AL_FUNC(void, generate_332_palette, (PALETTE pal)); +AL_FUNC(int, generate_optimized_palette, (struct BITMAP *image, PALETTE pal, AL_CONST signed char rsvdcols[256])); + +AL_FUNC(void, create_rgb_table, (RGB_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_light_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_trans_table, (COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b, AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_color_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, blend, (AL_CONST PALETTE pal, int x, int y, RGB *rgb)), AL_METHOD(void, callback, (int pos)))); +AL_FUNC(void, create_blender_table, (COLOR_MAP *table, AL_CONST PALETTE pal, AL_METHOD(void, callback, (int pos)))); + +typedef AL_METHOD(unsigned long, BLENDER_FUNC, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(void, set_blender_mode, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, int r, int g, int b, int a)); +AL_FUNC(void, set_blender_mode_ex, (BLENDER_FUNC b15, BLENDER_FUNC b16, BLENDER_FUNC b24, BLENDER_FUNC b32, BLENDER_FUNC b15x, BLENDER_FUNC b16x, BLENDER_FUNC b24x, int r, int g, int b, int a)); + +AL_FUNC(void, set_alpha_blender, (void)); +AL_FUNC(void, set_write_alpha_blender, (void)); +AL_FUNC(void, set_trans_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_add_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_burn_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_color_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_difference_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_dissolve_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_dodge_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_hue_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_invert_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_luminance_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_multiply_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_saturation_blender, (int r, int g, int b, int a)); +AL_FUNC(void, set_screen_blender, (int r, int g, int b, int a)); + +AL_FUNC(void, hsv_to_rgb, (float h, float s, float v, int *r, int *g, int *b)); +AL_FUNC(void, rgb_to_hsv, (int r, int g, int b, float *h, float *s, float *v)); + +AL_FUNC(int, bestfit_color, (AL_CONST PALETTE pal, int r, int g, int b)); + +AL_FUNC(int, makecol, (int r, int g, int b)); +AL_FUNC(int, makecol8, (int r, int g, int b)); +AL_FUNC(int, makecol_depth, (int color_depth, int r, int g, int b)); + +AL_FUNC(int, makeacol, (int r, int g, int b, int a)); +AL_FUNC(int, makeacol_depth, (int color_depth, int r, int g, int b, int a)); + +AL_FUNC(int, makecol15_dither, (int r, int g, int b, int x, int y)); +AL_FUNC(int, makecol16_dither, (int r, int g, int b, int x, int y)); + +AL_FUNC(int, getr, (int c)); +AL_FUNC(int, getg, (int c)); +AL_FUNC(int, getb, (int c)); +AL_FUNC(int, geta, (int c)); + +AL_FUNC(int, getr_depth, (int color_depth, int c)); +AL_FUNC(int, getg_depth, (int color_depth, int c)); +AL_FUNC(int, getb_depth, (int color_depth, int c)); +AL_FUNC(int, geta_depth, (int color_depth, int c)); + +#ifdef __cplusplus + } +#endif + +#include "inline/color.inl" + +#endif /* ifndef ALLEGRO_COLOR_H */ + + diff --git a/allegro/allegro/compiled.h b/allegro/allegro/compiled.h new file mode 100644 index 0000000000..46d621b287 --- /dev/null +++ b/allegro/allegro/compiled.h @@ -0,0 +1,62 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Compiled sprites. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COMPILED_H +#define ALLEGRO_COMPILED_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +#if (defined ALLEGRO_I386) && (!defined ALLEGRO_NO_ASM) + +/* compiled sprite structure */ +typedef struct COMPILED_SPRITE +{ + short planar; /* set if it's a planar (mode-X) sprite */ + short color_depth; /* color depth of the image */ + short w, h; /* size of the sprite */ + struct { + void *draw; /* routines to draw the image */ + int len; /* length of the drawing functions */ + } proc[4]; +} COMPILED_SPRITE; + +#else + +/* emulate compiled sprites using RLE on other platforms */ +struct RLE_SPRITE; +typedef struct RLE_SPRITE COMPILED_SPRITE; + +#endif + +AL_FUNC(COMPILED_SPRITE *, get_compiled_sprite, (struct BITMAP *bitmap, int planar)); +AL_FUNC(void, destroy_compiled_sprite, (COMPILED_SPRITE *sprite)); +AL_FUNC(void, draw_compiled_sprite, (struct BITMAP *bmp, AL_CONST COMPILED_SPRITE *sprite, int x, int y)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_COMPILED_H */ + + diff --git a/allegro/allegro/config.h b/allegro/allegro/config.h new file mode 100644 index 0000000000..64539a73a8 --- /dev/null +++ b/allegro/allegro/config.h @@ -0,0 +1,65 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration file access routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_CONFIG_H +#define ALLEGRO_CONFIG_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(void, set_config_file, (AL_CONST char *filename)); +AL_FUNC(void, set_config_data, (AL_CONST char *data, int length)); +AL_FUNC(void, override_config_file, (AL_CONST char *filename)); +AL_FUNC(void, override_config_data, (AL_CONST char *data, int length)); +AL_FUNC(void, flush_config_file, (void)); +AL_FUNC(void, reload_config_texts, (AL_CONST char *new_language)); + +AL_FUNC(void, push_config_state, (void)); +AL_FUNC(void, pop_config_state, (void)); + +AL_FUNC(void, hook_config_section, (AL_CONST char *section, AL_METHOD(int, intgetter, (AL_CONST char *, int)), AL_METHOD(AL_CONST char *, stringgetter, (AL_CONST char *, AL_CONST char *)), AL_METHOD(void, stringsetter, (AL_CONST char *, AL_CONST char *)))); +AL_FUNC(int, config_is_hooked, (AL_CONST char *section)); + +AL_FUNC(AL_CONST char *, get_config_string, (AL_CONST char *section, AL_CONST char *name, AL_CONST char *def)); +AL_FUNC(int, get_config_int, (AL_CONST char *section, AL_CONST char *name, int def)); +AL_FUNC(int, get_config_hex, (AL_CONST char *section, AL_CONST char *name, int def)); +AL_FUNC(float, get_config_float, (AL_CONST char *section, AL_CONST char *name, float def)); +AL_FUNC(int, get_config_id, (AL_CONST char *section, AL_CONST char *name, int def)); +AL_FUNC(char **, get_config_argv, (AL_CONST char *section, AL_CONST char *name, int *argc)); +AL_FUNC(AL_CONST char *, get_config_text, (AL_CONST char *msg)); + +AL_FUNC(void, set_config_string, (AL_CONST char *section, AL_CONST char *name, AL_CONST char *val)); +AL_FUNC(void, set_config_int, (AL_CONST char *section, AL_CONST char *name, int val)); +AL_FUNC(void, set_config_hex, (AL_CONST char *section, AL_CONST char *name, int val)); +AL_FUNC(void, set_config_float, (AL_CONST char *section, AL_CONST char *name, float val)); +AL_FUNC(void, set_config_id, (AL_CONST char *section, AL_CONST char *name, int val)); + +AL_FUNC(int, list_config_entries, (AL_CONST char *section, AL_CONST char ***names)); +AL_FUNC(int, list_config_sections, (AL_CONST char ***names)); +AL_FUNC(void, free_config_entries, (AL_CONST char ***names)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_CONFIG_H */ + + diff --git a/allegro/allegro/datafile.h b/allegro/allegro/datafile.h new file mode 100644 index 0000000000..d44e9a31cf --- /dev/null +++ b/allegro/allegro/datafile.h @@ -0,0 +1,114 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Datafile access routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DATAFILE_H +#define ALLEGRO_DATAFILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; +struct PACKFILE; +struct RGB; + +#define DAT_ID(a,b,c,d) AL_ID(a,b,c,d) + +#define DAT_MAGIC DAT_ID('A','L','L','.') +#define DAT_FILE DAT_ID('F','I','L','E') +#define DAT_DATA DAT_ID('D','A','T','A') +#define DAT_FONT DAT_ID('F','O','N','T') +#define DAT_SAMPLE DAT_ID('S','A','M','P') +#define DAT_MIDI DAT_ID('M','I','D','I') +#define DAT_PATCH DAT_ID('P','A','T',' ') +#define DAT_FLI DAT_ID('F','L','I','C') +#define DAT_BITMAP DAT_ID('B','M','P',' ') +#define DAT_RLE_SPRITE DAT_ID('R','L','E',' ') +#define DAT_C_SPRITE DAT_ID('C','M','P',' ') +#define DAT_XC_SPRITE DAT_ID('X','C','M','P') +#define DAT_PALETTE DAT_ID('P','A','L',' ') +#define DAT_PROPERTY DAT_ID('p','r','o','p') +#define DAT_NAME DAT_ID('N','A','M','E') +#define DAT_END -1 + + +typedef struct DATAFILE_PROPERTY +{ + char *dat; /* pointer to the data */ + int type; /* property type */ +} DATAFILE_PROPERTY; + + +typedef struct DATAFILE +{ + void *dat; /* pointer to the data */ + int type; /* object type */ + long size; /* size of the object */ + DATAFILE_PROPERTY *prop; /* object properties */ +} DATAFILE; + + +typedef struct DATAFILE_INDEX +{ + char *filename; /* datafile name (path) */ + long *offset; /* list of offsets */ +} DATAFILE_INDEX; + + +AL_FUNC(DATAFILE *, load_datafile, (AL_CONST char *filename)); +AL_FUNC(DATAFILE *, load_datafile_callback, (AL_CONST char *filename, AL_METHOD(void, callback, (DATAFILE *)))); +AL_FUNC(DATAFILE_INDEX *, create_datafile_index, (AL_CONST char *filename)); +AL_FUNC(void, unload_datafile, (DATAFILE *dat)); +AL_FUNC(void, destroy_datafile_index, (DATAFILE_INDEX *index)); + +AL_FUNC(DATAFILE *, load_datafile_object, (AL_CONST char *filename, AL_CONST char *objectname)); +AL_FUNC(DATAFILE *, load_datafile_object_indexed, (AL_CONST DATAFILE_INDEX *index, int item)); +AL_FUNC(void, unload_datafile_object, (DATAFILE *dat)); + +AL_FUNC(DATAFILE *, find_datafile_object, (AL_CONST DATAFILE *dat, AL_CONST char *objectname)); +AL_FUNC(AL_CONST char *, get_datafile_property, (AL_CONST DATAFILE *dat, int type)); +AL_FUNC(void, register_datafile_object, (int id_, AL_METHOD(void *, load, (struct PACKFILE *f, long size)), AL_METHOD(void, destroy, (void *data)))); + +AL_FUNC(void, fixup_datafile, (DATAFILE *data)); + +AL_FUNC(struct BITMAP *, load_bitmap, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_bmp, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_bmp_pf, (PACKFILE *f, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_lbm, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_pcx, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_pcx_pf, (PACKFILE *f, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_tga, (AL_CONST char *filename, struct RGB *pal)); +AL_FUNC(struct BITMAP *, load_tga_pf, (PACKFILE *f, struct RGB *pal)); + +AL_FUNC(int, save_bitmap, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_bmp, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_bmp_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_pcx, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_pcx_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_tga, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)); +AL_FUNC(int, save_tga_pf, (PACKFILE *f, struct BITMAP *bmp, AL_CONST struct RGB *pal)); + +AL_FUNC(void, register_bitmap_file_type, (AL_CONST char *ext, AL_METHOD(struct BITMAP *, load, (AL_CONST char *filename, struct RGB *pal)), AL_METHOD(int, save, (AL_CONST char *filename, struct BITMAP *bmp, AL_CONST struct RGB *pal)))); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DATAFILE_H */ diff --git a/allegro/allegro/debug.h b/allegro/allegro/debug.h new file mode 100644 index 0000000000..87c52d4b38 --- /dev/null +++ b/allegro/allegro/debug.h @@ -0,0 +1,49 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Debug facilities. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DEBUG_H +#define ALLEGRO_DEBUG_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(void, al_assert, (AL_CONST char *file, int linenr)); +AL_PRINTFUNC(void, al_trace, (AL_CONST char *msg, ...), 1, 2); + +AL_FUNC(void, register_assert_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); +AL_FUNC(void, register_trace_handler, (AL_METHOD(int, handler, (AL_CONST char *msg)))); + + +#ifdef DEBUGMODE + #define ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } + #define TRACE al_trace +#else + #define ASSERT(condition) + #define TRACE 1 ? (void) 0 : al_trace +#endif + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DEBUG_H */ + + diff --git a/allegro/allegro/digi.h b/allegro/allegro/digi.h new file mode 100644 index 0000000000..5f4868b952 --- /dev/null +++ b/allegro/allegro/digi.h @@ -0,0 +1,219 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Digital sound routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DIGI_H +#define ALLEGRO_DIGI_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct PACKFILE; + + +#define DIGI_VOICES 64 /* Theoretical maximums: */ + /* actual drivers may not be */ + /* able to handle this many */ + +typedef struct SAMPLE /* a sample */ +{ + int bits; /* 8 or 16 */ + int stereo; /* sample type flag */ + int freq; /* sample frequency */ + int priority; /* 0-255 */ + unsigned long len; /* length (in samples) */ + unsigned long loop_start; /* loop start position */ + unsigned long loop_end; /* loop finish position */ + unsigned long param; /* for internal use by the driver */ + void *data; /* sample data */ +} SAMPLE; + + +#define DIGI_AUTODETECT -1 /* for passing to install_sound() */ +#define DIGI_NONE 0 + +typedef struct DIGI_DRIVER /* driver for playing digital sfx */ +{ + int id; /* driver ID code */ + AL_CONST char *name; /* driver name */ + AL_CONST char *desc; /* description string */ + AL_CONST char *ascii_name; /* ASCII format name string */ + int voices; /* available voices */ + int basevoice; /* voice number offset */ + int max_voices; /* maximum voices we can support */ + int def_voices; /* default number of voices to use */ + + /* setup routines */ + AL_METHOD(int, detect, (int input)); + AL_METHOD(int, init, (int input, int voices)); + AL_METHOD(void, exit, (int input)); + AL_METHOD(int, set_mixer_volume, (int volume)); + AL_METHOD(int, get_mixer_volume, (void)); + + /* for use by the audiostream functions */ + AL_METHOD(void *, lock_voice, (int voice, int start, int end)); + AL_METHOD(void, unlock_voice, (int voice)); + AL_METHOD(int, buffer_size, (void)); + + /* voice control functions */ + AL_METHOD(void, init_voice, (int voice, AL_CONST SAMPLE *sample)); + AL_METHOD(void, release_voice, (int voice)); + AL_METHOD(void, start_voice, (int voice)); + AL_METHOD(void, stop_voice, (int voice)); + AL_METHOD(void, loop_voice, (int voice, int playmode)); + + /* position control functions */ + AL_METHOD(int, get_position, (int voice)); + AL_METHOD(void, set_position, (int voice, int position)); + + /* volume control functions */ + AL_METHOD(int, get_volume, (int voice)); + AL_METHOD(void, set_volume, (int voice, int volume)); + AL_METHOD(void, ramp_volume, (int voice, int tyme, int endvol)); + AL_METHOD(void, stop_volume_ramp, (int voice)); + + /* pitch control functions */ + AL_METHOD(int, get_frequency, (int voice)); + AL_METHOD(void, set_frequency, (int voice, int frequency)); + AL_METHOD(void, sweep_frequency, (int voice, int tyme, int endfreq)); + AL_METHOD(void, stop_frequency_sweep, (int voice)); + + /* pan control functions */ + AL_METHOD(int, get_pan, (int voice)); + AL_METHOD(void, set_pan, (int voice, int pan)); + AL_METHOD(void, sweep_pan, (int voice, int tyme, int endpan)); + AL_METHOD(void, stop_pan_sweep, (int voice)); + + /* effect control functions */ + AL_METHOD(void, set_echo, (int voice, int strength, int delay)); + AL_METHOD(void, set_tremolo, (int voice, int rate, int depth)); + AL_METHOD(void, set_vibrato, (int voice, int rate, int depth)); + + /* input functions */ + int rec_cap_bits; + int rec_cap_stereo; + AL_METHOD(int, rec_cap_rate, (int bits, int stereo)); + AL_METHOD(int, rec_cap_parm, (int rate, int bits, int stereo)); + AL_METHOD(int, rec_source, (int source)); + AL_METHOD(int, rec_start, (int rate, int bits, int stereo)); + AL_METHOD(void, rec_stop, (void)); + AL_METHOD(int, rec_read, (void *buf)); +} DIGI_DRIVER; + +AL_ARRAY(_DRIVER_INFO, _digi_driver_list); + +/* macros for constructing the driver lists */ +#define BEGIN_DIGI_DRIVER_LIST \ + _DRIVER_INFO _digi_driver_list[] = \ + { + +#define END_DIGI_DRIVER_LIST \ + { 0, NULL, 0 } \ + }; + +AL_VAR(DIGI_DRIVER *, digi_driver); + +AL_VAR(DIGI_DRIVER *, digi_input_driver); + +AL_VAR(int, digi_card); + +AL_VAR(int, digi_input_card); + +AL_FUNC(int, detect_digi_driver, (int driver_id)); + + +AL_FUNC(SAMPLE *, load_sample, (AL_CONST char *filename)); +AL_FUNC(SAMPLE *, load_wav, (AL_CONST char *filename)); +AL_FUNC(SAMPLE *, load_wav_pf, (struct PACKFILE *f)); +AL_FUNC(SAMPLE *, load_voc, (AL_CONST char *filename)); +AL_FUNC(SAMPLE *, load_voc_pf, (struct PACKFILE *f)); +AL_FUNC(int, save_sample, (AL_CONST char *filename, SAMPLE *spl)); +AL_FUNC(SAMPLE *, create_sample, (int bits, int stereo, int freq, int len)); +AL_FUNC(void, destroy_sample, (SAMPLE *spl)); + +AL_FUNC(int, play_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop)); +AL_FUNC(void, stop_sample, (AL_CONST SAMPLE *spl)); +AL_FUNC(void, adjust_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop)); + +AL_FUNC(int, allocate_voice, (AL_CONST SAMPLE *spl)); +AL_FUNC(void, deallocate_voice, (int voice)); +AL_FUNC(void, reallocate_voice, (int voice, AL_CONST SAMPLE *spl)); +AL_FUNC(void, release_voice, (int voice)); +AL_FUNC(void, voice_start, (int voice)); +AL_FUNC(void, voice_stop, (int voice)); +AL_FUNC(void, voice_set_priority, (int voice, int priority)); +AL_FUNC(SAMPLE *, voice_check, (int voice)); + +#define PLAYMODE_PLAY 0 +#define PLAYMODE_LOOP 1 +#define PLAYMODE_FORWARD 0 +#define PLAYMODE_BACKWARD 2 +#define PLAYMODE_BIDIR 4 + +AL_FUNC(void, voice_set_playmode, (int voice, int playmode)); + +AL_FUNC(int, voice_get_position, (int voice)); +AL_FUNC(void, voice_set_position, (int voice, int position)); + +AL_FUNC(int, voice_get_volume, (int voice)); +AL_FUNC(void, voice_set_volume, (int voice, int volume)); +AL_FUNC(void, voice_ramp_volume, (int voice, int tyme, int endvol)); +AL_FUNC(void, voice_stop_volumeramp, (int voice)); + +AL_FUNC(int, voice_get_frequency, (int voice)); +AL_FUNC(void, voice_set_frequency, (int voice, int frequency)); +AL_FUNC(void, voice_sweep_frequency, (int voice, int tyme, int endfreq)); +AL_FUNC(void, voice_stop_frequency_sweep, (int voice)); + +AL_FUNC(int, voice_get_pan, (int voice)); +AL_FUNC(void, voice_set_pan, (int voice, int pan)); +AL_FUNC(void, voice_sweep_pan, (int voice, int tyme, int endpan)); +AL_FUNC(void, voice_stop_pan_sweep, (int voice)); + +AL_FUNC(void, voice_set_echo, (int voice, int strength, int delay)); +AL_FUNC(void, voice_set_tremolo, (int voice, int rate, int depth)); +AL_FUNC(void, voice_set_vibrato, (int voice, int rate, int depth)); + +#define SOUND_INPUT_MIC 1 +#define SOUND_INPUT_LINE 2 +#define SOUND_INPUT_CD 3 + +AL_FUNC(int, get_sound_input_cap_bits, (void)); +AL_FUNC(int, get_sound_input_cap_stereo, (void)); +AL_FUNC(int, get_sound_input_cap_rate, (int bits, int stereo)); +AL_FUNC(int, get_sound_input_cap_parm, (int rate, int bits, int stereo)); +AL_FUNC(int, set_sound_input_source, (int source)); +AL_FUNC(int, start_sound_input, (int rate, int bits, int stereo)); +AL_FUNC(void, stop_sound_input, (void)); +AL_FUNC(int, read_sound_input, (void *buffer)); + +AL_FUNCPTR(void, digi_recorder, (void)); + +AL_FUNC(void, lock_sample, (struct SAMPLE *spl)); + +AL_FUNC(void, register_sample_file_type, (AL_CONST char *ext, AL_METHOD(struct SAMPLE *, load, (AL_CONST char *filename)), AL_METHOD(int, save, (AL_CONST char *filename, struct SAMPLE *spl)))); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DIGI_H */ + + diff --git a/allegro/allegro/draw.h b/allegro/allegro/draw.h new file mode 100644 index 0000000000..b983c0ff00 --- /dev/null +++ b/allegro/allegro/draw.h @@ -0,0 +1,70 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Drawing and sprite routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DRAW_H +#define ALLEGRO_DRAW_H + +#include "base.h" +#include "fixed.h" +#include "gfx.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define DRAW_MODE_SOLID 0 /* flags for drawing_mode() */ +#define DRAW_MODE_XOR 1 +#define DRAW_MODE_COPY_PATTERN 2 +#define DRAW_MODE_SOLID_PATTERN 3 +#define DRAW_MODE_MASKED_PATTERN 4 +#define DRAW_MODE_TRANS 5 + +AL_FUNC(void, drawing_mode, (int mode, struct BITMAP *pattern, int x_anchor, int y_anchor)); +AL_FUNC(void, xor_mode, (int on)); +AL_FUNC(void, solid_mode, (void)); +AL_FUNC(void, do_line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); +AL_FUNC(void, _soft_polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); +AL_FUNC(void, _soft_rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, do_circle, (struct BITMAP *bmp, int x, int y, int radius, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); +AL_FUNC(void, _soft_circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); +AL_FUNC(void, do_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); +AL_FUNC(void, _soft_ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); +AL_FUNC(void, do_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int d, AL_METHOD(void, proc, (struct BITMAP *, int, int, int)))); +AL_FUNC(void, _soft_arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); +AL_FUNC(void, calc_spline, (AL_CONST int points[8], int npts, int *x, int *y)); +AL_FUNC(void, _soft_spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); +AL_FUNC(void, _soft_floodfill, (struct BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); +AL_FUNC(void, masked_stretch_blit, (struct BITMAP *s, struct BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h)); +AL_FUNC(void, stretch_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int w, int h)); +AL_FUNC(void, _soft_draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); + +#ifdef __cplusplus + } +#endif + +#include "inline/draw.inl" + +#endif /* ifndef ALLEGRO_DRAW_H */ + + diff --git a/allegro/allegro/file.h b/allegro/allegro/file.h new file mode 100644 index 0000000000..c8b2e97c5e --- /dev/null +++ b/allegro/allegro/file.h @@ -0,0 +1,182 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FILE_H +#define ALLEGRO_FILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(char *, fix_filename_case, (char *path)); +AL_FUNC(char *, fix_filename_slashes, (char *path)); +AL_FUNC(char *, canonicalize_filename, (char *dest, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_absolute_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_relative_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(int, is_relative_filename, (AL_CONST char *filename)); +AL_FUNC(char *, replace_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, replace_extension, (char *dest, AL_CONST char *filename, AL_CONST char *ext, int size)); +AL_FUNC(char *, append_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, get_filename, (AL_CONST char *path)); +AL_FUNC(char *, get_extension, (AL_CONST char *filename)); +AL_FUNC(void, put_backslash, (char *filename)); +AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret)); +AL_FUNC(int, exists, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex_password, (AL_CONST char *filename, AL_CONST char *password)); +AL_FUNC(time_t, file_time, (AL_CONST char *filename)); +AL_FUNC(int, delete_file, (AL_CONST char *filename)); +AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param)); +AL_FUNC(int, set_allegro_resource_path, (int priority, AL_CONST char *path)); +AL_FUNC(int, find_allegro_resource, (char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size)); + +struct al_ffblk /* file info block for the al_find*() routines */ +{ + int attrib; /* actual attributes of the file found */ + time_t time; /* modification time of file */ + long size; /* size of file */ + char name[512]; /* name of file */ + void *ff_data; /* private hook */ +}; + +AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info)); + +AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib)); +AL_FUNC(int, al_findnext, (struct al_ffblk *info)); +AL_FUNC(void, al_findclose, (struct al_ffblk *info)); + +#ifndef EOF + #define EOF (-1) +#endif + +#define F_READ "r" +#define F_WRITE "w" +#define F_READ_PACKED "rp" +#define F_WRITE_PACKED "wp" +#define F_WRITE_NOPACK "w!" + +#define F_BUF_SIZE 4096 /* 4K buffer for caching data */ +#define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ +#define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ +#define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ + +#define PACKFILE_FLAG_WRITE 1 /* the file is being written */ +#define PACKFILE_FLAG_PACK 2 /* data is compressed */ +#define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ +#define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ +#define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ +#define PACKFILE_FLAG_OLD_CRYPT 32 /* backward compatibility mode */ +#define PACKFILE_FLAG_EXEDAT 64 /* reading from our executable */ + + +typedef struct PACKFILE_VTABLE PACKFILE_VTABLE; +typedef struct PACKFILE PACKFILE; + +struct LZSS_PACK_DATA; +struct LZSS_UNPACK_DATA; + + +struct _al_normal_packfile_details +{ + int hndl; /* DOS file handle */ + int flags; /* PACKFILE_FLAG_* constants */ + unsigned char *buf_pos; /* position in buffer */ + int buf_size; /* number of bytes in the buffer */ + long todo; /* number of bytes still on the disk */ + struct PACKFILE *parent; /* nested, parent file */ + struct LZSS_PACK_DATA *pack_data; /* for LZSS compression */ + struct LZSS_UNPACK_DATA *unpack_data; /* for LZSS decompression */ + char *filename; /* name of the file */ + char *passdata; /* encryption key data */ + char *passpos; /* current key position */ + unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ +}; + + +struct PACKFILE /* our very own FILE structure... */ +{ + AL_CONST PACKFILE_VTABLE *vtable; + void *userdata; + int is_normal_packfile; + + /* The following is only to be used for the "normal" PACKFILE vtable, + * i.e. what is implemented by Allegro itself. If is_normal_packfile is + * false then the following is not even allocated. This must be the last + * member in the structure. + */ + struct _al_normal_packfile_details normal; +}; + + +struct PACKFILE_VTABLE +{ + AL_METHOD(int, pf_fclose, (void *userdata)); + AL_METHOD(int, pf_getc, (void *userdata)); + AL_METHOD(int, pf_ungetc, (int c, void *userdata)); + AL_METHOD(long, pf_fread, (void *p, long n, void *userdata)); + AL_METHOD(int, pf_putc, (int c, void *userdata)); + AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata)); + AL_METHOD(int, pf_fseek, (void *userdata, int offset)); + AL_METHOD(int, pf_feof, (void *userdata)); + AL_METHOD(int, pf_ferror, (void *userdata)); +}; + + +#define uconvert_tofilename(s, buf) uconvert(s, U_CURRENT, buf, get_file_encoding(), sizeof(buf)) + +AL_FUNC(void, set_file_encoding, (int encoding)); +AL_FUNC(int, get_file_encoding, (void)); + +AL_FUNC(void, packfile_password, (AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode)); +AL_FUNC(PACKFILE *, pack_fopen_password, (AL_CONST char *filename, AL_CONST char *mode, AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata)); +AL_FUNC(int, pack_fclose, (PACKFILE *f)); +AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset)); +AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack)); +AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f)); +AL_FUNC(int, pack_getc, (PACKFILE *f)); +AL_FUNC(int, pack_putc, (int c, PACKFILE *f)); +AL_FUNC(int, pack_feof, (PACKFILE *f)); +AL_FUNC(int, pack_ferror, (PACKFILE *f)); +AL_FUNC(int, pack_igetw, (PACKFILE *f)); +AL_FUNC(long, pack_igetl, (PACKFILE *f)); +AL_FUNC(int, pack_iputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_iputl, (long l, PACKFILE *f)); +AL_FUNC(int, pack_mgetw, (PACKFILE *f)); +AL_FUNC(long, pack_mgetl, (PACKFILE *f)); +AL_FUNC(int, pack_mputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_mputl, (long l, PACKFILE *f)); +AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f)); +AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f)); +AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f)); +AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f)); +AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f)); +AL_FUNC(void *, pack_get_userdata, (PACKFILE *f)); + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FILE_H */ + + diff --git a/allegro/allegro/file.h.old b/allegro/allegro/file.h.old new file mode 100644 index 0000000000..3512ff9109 --- /dev/null +++ b/allegro/allegro/file.h.old @@ -0,0 +1,180 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FILE_H +#define ALLEGRO_FILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(char *, fix_filename_case, (char *path)); +AL_FUNC(char *, fix_filename_slashes, (char *path)); +AL_FUNC(char *, canonicalize_filename, (char *dest, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_absolute_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_relative_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(int, is_relative_filename, (AL_CONST char *filename)); +AL_FUNC(char *, replace_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, replace_extension, (char *dest, AL_CONST char *filename, AL_CONST char *ext, int size)); +AL_FUNC(char *, append_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, get_filename, (AL_CONST char *path)); +AL_FUNC(char *, get_extension, (AL_CONST char *filename)); +AL_FUNC(void, put_backslash, (char *filename)); +AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret)); +AL_FUNC(int, exists, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, file_time, (AL_CONST char *filename)); +AL_FUNC(int, delete_file, (AL_CONST char *filename)); +AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param)); +AL_FUNC(int, set_allegro_resource_path, (int priority, AL_CONST char *path)); +AL_FUNC(int, find_allegro_resource, (char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size)); + +struct al_ffblk /* file info block for the al_find*() routines */ +{ + int attrib; /* actual attributes of the file found */ + time_t time; /* modification time of file */ + long size; /* size of file */ + char name[512]; /* name of file */ + void *ff_data; /* private hook */ +}; + +AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info)); + +AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib)); +AL_FUNC(int, al_findnext, (struct al_ffblk *info)); +AL_FUNC(void, al_findclose, (struct al_ffblk *info)); + +#ifndef EOF + #define EOF (-1) +#endif + +#define F_READ "r" +#define F_WRITE "w" +#define F_READ_PACKED "rp" +#define F_WRITE_PACKED "wp" +#define F_WRITE_NOPACK "w!" + +#define F_BUF_SIZE 4096 /* 4K buffer for caching data */ +#define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ +#define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ +#define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ + +#define PACKFILE_FLAG_WRITE 1 /* the file is being written */ +#define PACKFILE_FLAG_PACK 2 /* data is compressed */ +#define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ +#define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ +#define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ +#define PACKFILE_FLAG_OLD_CRYPT 32 /* backward compatibility mode */ +#define PACKFILE_FLAG_EXEDAT 64 /* reading from our executable */ + + +typedef struct PACKFILE_VTABLE PACKFILE_VTABLE; +typedef struct PACKFILE PACKFILE; + +struct LZSS_PACK_DATA; +struct LZSS_UNPACK_DATA; + + +struct _al_normal_packfile_details +{ + int hndl; /* DOS file handle */ + int flags; /* PACKFILE_FLAG_* constants */ + unsigned char *buf_pos; /* position in buffer */ + int buf_size; /* number of bytes in the buffer */ + long todo; /* number of bytes still on the disk */ + struct PACKFILE *parent; /* nested, parent file */ + struct LZSS_PACK_DATA *pack_data; /* for LZSS compression */ + struct LZSS_UNPACK_DATA *unpack_data; /* for LZSS decompression */ + char *filename; /* name of the file */ + char *passdata; /* encryption key data */ + char *passpos; /* current key position */ + unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ +}; + + +struct PACKFILE /* our very own FILE structure... */ +{ + AL_CONST PACKFILE_VTABLE *vtable; + void *userdata; + int is_normal_packfile; + + /* The following is only to be used for the "normal" PACKFILE vtable, + * i.e. what is implemented by Allegro itself. If is_normal_packfile is + * false then the following is not even allocated. This must be the last + * member in the structure. + */ + struct _al_normal_packfile_details normal; +}; + + +struct PACKFILE_VTABLE +{ + AL_METHOD(int, pf_fclose, (void *userdata)); + AL_METHOD(int, pf_getc, (void *userdata)); + AL_METHOD(int, pf_ungetc, (int c, void *userdata)); + AL_METHOD(long, pf_fread, (void *p, long n, void *userdata)); + AL_METHOD(int, pf_putc, (int c, void *userdata)); + AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata)); + AL_METHOD(int, pf_fseek, (void *userdata, int offset)); + AL_METHOD(int, pf_feof, (void *userdata)); + AL_METHOD(int, pf_ferror, (void *userdata)); +}; + + +#define uconvert_tofilename(s, buf) uconvert(s, U_CURRENT, buf, get_file_encoding(), sizeof(buf)) + +AL_FUNC(void, set_file_encoding, (int encoding)); +AL_FUNC(int, get_file_encoding, (void)); + +AL_FUNC(void, packfile_password, (AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode)); +AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata)); +AL_FUNC(int, pack_fclose, (PACKFILE *f)); +AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset)); +AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack)); +AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f)); +AL_FUNC(int, pack_getc, (PACKFILE *f)); +AL_FUNC(int, pack_putc, (int c, PACKFILE *f)); +AL_FUNC(int, pack_feof, (PACKFILE *f)); +AL_FUNC(int, pack_ferror, (PACKFILE *f)); +AL_FUNC(int, pack_igetw, (PACKFILE *f)); +AL_FUNC(long, pack_igetl, (PACKFILE *f)); +AL_FUNC(int, pack_iputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_iputl, (long l, PACKFILE *f)); +AL_FUNC(int, pack_mgetw, (PACKFILE *f)); +AL_FUNC(long, pack_mgetl, (PACKFILE *f)); +AL_FUNC(int, pack_mputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_mputl, (long l, PACKFILE *f)); +AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f)); +AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f)); +AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f)); +AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f)); +AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f)); +AL_FUNC(void *, pack_get_userdata, (PACKFILE *f)); + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FILE_H */ + + diff --git a/allegro/allegro/fix.h b/allegro/allegro/fix.h new file mode 100644 index 0000000000..41f3d654f4 --- /dev/null +++ b/allegro/allegro/fix.h @@ -0,0 +1,210 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * C++ wrapper for fixed point math type. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FIX_H +#define ALLEGRO_FIX_H + +#include "fixed.h" +#include "fmaths.h" + +#ifdef __cplusplus + +class fix /* C++ wrapper for the fixed point routines */ +{ +public: + fixed v; + + fix() : v(0) {} + fix(const fix &x) : v(x.v) {} + explicit fix(const int x) : v(itofix(x)) {} + explicit fix(const long x) : v(itofix(x)) {} + explicit fix(const unsigned int x) : v(itofix(x)) {} + explicit fix(const unsigned long x) : v(itofix(x)) {} + explicit fix(const float x) : v(ftofix(x)) {} + explicit fix(const double x) : v(ftofix(x)) {} + + operator int() const { return fixtoi(v); } + operator long() const { return fixtoi(v); } + operator unsigned int() const { return fixtoi(v); } + operator unsigned long() const { return fixtoi(v); } + operator float() const { return fixtof(v); } + operator double() const { return fixtof(v); } + + fix& operator = (const fix &x) { v = x.v; return *this; } + fix& operator = (const int x) { v = itofix(x); return *this; } + fix& operator = (const long x) { v = itofix(x); return *this; } + fix& operator = (const unsigned int x) { v = itofix(x); return *this; } + fix& operator = (const unsigned long x) { v = itofix(x); return *this; } + fix& operator = (const float x) { v = ftofix(x); return *this; } + fix& operator = (const double x) { v = ftofix(x); return *this; } + + fix& operator += (const fix x) { v += x.v; return *this; } + fix& operator += (const int x) { v += itofix(x); return *this; } + fix& operator += (const long x) { v += itofix(x); return *this; } + fix& operator += (const float x) { v += ftofix(x); return *this; } + fix& operator += (const double x) { v += ftofix(x); return *this; } + + fix& operator -= (const fix x) { v -= x.v; return *this; } + fix& operator -= (const int x) { v -= itofix(x); return *this; } + fix& operator -= (const long x) { v -= itofix(x); return *this; } + fix& operator -= (const float x) { v -= ftofix(x); return *this; } + fix& operator -= (const double x) { v -= ftofix(x); return *this; } + + fix& operator *= (const fix x) { v = fixmul(v, x.v); return *this; } + fix& operator *= (const int x) { v *= x; return *this; } + fix& operator *= (const long x) { v *= x; return *this; } + fix& operator *= (const float x) { v = ftofix(fixtof(v) * x); return *this; } + fix& operator *= (const double x) { v = ftofix(fixtof(v) * x); return *this; } + + fix& operator /= (const fix x) { v = fixdiv(v, x.v); return *this; } + fix& operator /= (const int x) { v /= x; return *this; } + fix& operator /= (const long x) { v /= x; return *this; } + fix& operator /= (const float x) { v = ftofix(fixtof(v) / x); return *this; } + fix& operator /= (const double x) { v = ftofix(fixtof(v) / x); return *this; } + + fix& operator <<= (const int x) { v <<= x; return *this; } + fix& operator >>= (const int x) { v >>= x; return *this; } + + fix& operator ++ () { v += itofix(1); return *this; } + fix& operator -- () { v -= itofix(1); return *this; } + + fix operator ++ (int) { fix t; t.v = v; v += itofix(1); return t; } + fix operator -- (int) { fix t; t.v = v; v -= itofix(1); return t; } + + fix operator - () const { fix t; t.v = -v; return t; } + + inline friend fix operator + (const fix x, const fix y); + inline friend fix operator + (const fix x, const int y); + inline friend fix operator + (const int x, const fix y); + inline friend fix operator + (const fix x, const long y); + inline friend fix operator + (const long x, const fix y); + inline friend fix operator + (const fix x, const float y); + inline friend fix operator + (const float x, const fix y); + inline friend fix operator + (const fix x, const double y); + inline friend fix operator + (const double x, const fix y); + + inline friend fix operator - (const fix x, const fix y); + inline friend fix operator - (const fix x, const int y); + inline friend fix operator - (const int x, const fix y); + inline friend fix operator - (const fix x, const long y); + inline friend fix operator - (const long x, const fix y); + inline friend fix operator - (const fix x, const float y); + inline friend fix operator - (const float x, const fix y); + inline friend fix operator - (const fix x, const double y); + inline friend fix operator - (const double x, const fix y); + + inline friend fix operator * (const fix x, const fix y); + inline friend fix operator * (const fix x, const int y); + inline friend fix operator * (const int x, const fix y); + inline friend fix operator * (const fix x, const long y); + inline friend fix operator * (const long x, const fix y); + inline friend fix operator * (const fix x, const float y); + inline friend fix operator * (const float x, const fix y); + inline friend fix operator * (const fix x, const double y); + inline friend fix operator * (const double x, const fix y); + + inline friend fix operator / (const fix x, const fix y); + inline friend fix operator / (const fix x, const int y); + inline friend fix operator / (const int x, const fix y); + inline friend fix operator / (const fix x, const long y); + inline friend fix operator / (const long x, const fix y); + inline friend fix operator / (const fix x, const float y); + inline friend fix operator / (const float x, const fix y); + inline friend fix operator / (const fix x, const double y); + inline friend fix operator / (const double x, const fix y); + + inline friend fix operator << (const fix x, const int y); + inline friend fix operator >> (const fix x, const int y); + + inline friend int operator == (const fix x, const fix y); + inline friend int operator == (const fix x, const int y); + inline friend int operator == (const int x, const fix y); + inline friend int operator == (const fix x, const long y); + inline friend int operator == (const long x, const fix y); + inline friend int operator == (const fix x, const float y); + inline friend int operator == (const float x, const fix y); + inline friend int operator == (const fix x, const double y); + inline friend int operator == (const double x, const fix y); + + inline friend int operator != (const fix x, const fix y); + inline friend int operator != (const fix x, const int y); + inline friend int operator != (const int x, const fix y); + inline friend int operator != (const fix x, const long y); + inline friend int operator != (const long x, const fix y); + inline friend int operator != (const fix x, const float y); + inline friend int operator != (const float x, const fix y); + inline friend int operator != (const fix x, const double y); + inline friend int operator != (const double x, const fix y); + + inline friend int operator < (const fix x, const fix y); + inline friend int operator < (const fix x, const int y); + inline friend int operator < (const int x, const fix y); + inline friend int operator < (const fix x, const long y); + inline friend int operator < (const long x, const fix y); + inline friend int operator < (const fix x, const float y); + inline friend int operator < (const float x, const fix y); + inline friend int operator < (const fix x, const double y); + inline friend int operator < (const double x, const fix y); + + inline friend int operator > (const fix x, const fix y); + inline friend int operator > (const fix x, const int y); + inline friend int operator > (const int x, const fix y); + inline friend int operator > (const fix x, const long y); + inline friend int operator > (const long x, const fix y); + inline friend int operator > (const fix x, const float y); + inline friend int operator > (const float x, const fix y); + inline friend int operator > (const fix x, const double y); + inline friend int operator > (const double x, const fix y); + + inline friend int operator <= (const fix x, const fix y); + inline friend int operator <= (const fix x, const int y); + inline friend int operator <= (const int x, const fix y); + inline friend int operator <= (const fix x, const long y); + inline friend int operator <= (const long x, const fix y); + inline friend int operator <= (const fix x, const float y); + inline friend int operator <= (const float x, const fix y); + inline friend int operator <= (const fix x, const double y); + inline friend int operator <= (const double x, const fix y); + + inline friend int operator >= (const fix x, const fix y); + inline friend int operator >= (const fix x, const int y); + inline friend int operator >= (const int x, const fix y); + inline friend int operator >= (const fix x, const long y); + inline friend int operator >= (const long x, const fix y); + inline friend int operator >= (const fix x, const float y); + inline friend int operator >= (const float x, const fix y); + inline friend int operator >= (const fix x, const double y); + inline friend int operator >= (const double x, const fix y); + + inline friend fix sqrt(fix x); + inline friend fix cos(fix x); + inline friend fix sin(fix x); + inline friend fix tan(fix x); + inline friend fix acos(fix x); + inline friend fix asin(fix x); + inline friend fix atan(fix x); + inline friend fix atan2(fix x, fix y); +}; + +#endif /* ifdef __cplusplus */ + +#include "inline/fix.inl" + +#endif /* ifndef ALLEGRO_FIX_H */ + + diff --git a/allegro/allegro/fixed.h b/allegro/allegro/fixed.h new file mode 100644 index 0000000000..1b8b5001fa --- /dev/null +++ b/allegro/allegro/fixed.h @@ -0,0 +1,39 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point type. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FIXED_H +#define ALLEGRO_FIXED_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef int32_t fixed; + +AL_VAR(AL_CONST fixed, fixtorad_r); +AL_VAR(AL_CONST fixed, radtofix_r); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FIXED_H */ + + diff --git a/allegro/allegro/fli.h b/allegro/allegro/fli.h new file mode 100644 index 0000000000..fb70c1a579 --- /dev/null +++ b/allegro/allegro/fli.h @@ -0,0 +1,63 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * FLI/FLC routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FLI_H +#define ALLEGRO_FLI_H + +#include "base.h" +#include "palette.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +#define FLI_OK 0 /* FLI player return values */ +#define FLI_EOF -1 +#define FLI_ERROR -2 +#define FLI_NOT_OPEN -3 + +AL_FUNC(int, play_fli, (AL_CONST char *filename, struct BITMAP *bmp, int loop, AL_METHOD(int, callback, (void)))); +AL_FUNC(int, play_memory_fli, (void *fli_data, struct BITMAP *bmp, int loop, AL_METHOD(int, callback, (void)))); + +AL_FUNC(int, open_fli, (AL_CONST char *filename)); +AL_FUNC(int, open_memory_fli, (void *fli_data)); +AL_FUNC(void, close_fli, (void)); +AL_FUNC(int, next_fli_frame, (int loop)); +AL_FUNC(void, reset_fli_variables, (void)); + +AL_VAR(struct BITMAP *, fli_bitmap); /* current frame of the FLI */ +AL_VAR(PALETTE, fli_palette); /* current FLI palette */ + +AL_VAR(int, fli_bmp_dirty_from); /* what part of fli_bitmap is dirty */ +AL_VAR(int, fli_bmp_dirty_to); +AL_VAR(int, fli_pal_dirty_from); /* what part of fli_palette is dirty */ +AL_VAR(int, fli_pal_dirty_to); + +AL_VAR(int, fli_frame); /* current frame number */ + +AL_VAR(volatile int, fli_timer); /* for timing FLI playback */ + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FLI_H */ + + diff --git a/allegro/allegro/fmaths.h b/allegro/allegro/fmaths.h new file mode 100644 index 0000000000..4a72d8966c --- /dev/null +++ b/allegro/allegro/fmaths.h @@ -0,0 +1,46 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point math routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FMATH_H +#define ALLEGRO_FMATH_H + +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(fixed, fixsqrt, (fixed x)); +AL_FUNC(fixed, fixhypot, (fixed x, fixed y)); +AL_FUNC(fixed, fixatan, (fixed x)); +AL_FUNC(fixed, fixatan2, (fixed y, fixed x)); + +AL_ARRAY(fixed, _cos_tbl); +AL_ARRAY(fixed, _tan_tbl); +AL_ARRAY(fixed, _acos_tbl); + +#ifdef __cplusplus + } +#endif + +#include "inline/fmaths.inl" + +#endif /* ifndef ALLEGRO_FMATH_H */ + + diff --git a/allegro/allegro/font.h b/allegro/allegro/font.h new file mode 100644 index 0000000000..ebfef90ec1 --- /dev/null +++ b/allegro/allegro/font.h @@ -0,0 +1,76 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Font loading routines. + * + * By Evert Glebbeek. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FONT_H +#define ALLEGRO_FONT_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct FONT_GLYPH /* a single monochrome font character */ +{ + short w, h; + ZERO_SIZE_ARRAY(unsigned char, dat); +} FONT_GLYPH; + + +struct FONT_VTABLE; + +typedef struct FONT +{ + void *data; + int height; + struct FONT_VTABLE *vtable; +} FONT; + +AL_FUNC(int, font_has_alpha, (FONT *f)); +AL_FUNC(void, make_trans_font, (FONT *f)); + +AL_FUNC(int, is_trans_font, (FONT *f)); +AL_FUNC(int, is_color_font, (FONT *f)); +AL_FUNC(int, is_mono_font, (FONT *f)); +AL_FUNC(int, is_compatible_font, (FONT *f1, FONT *f2)); + +AL_FUNC(void, register_font_file_type, (AL_CONST char *ext, FONT *(*load)(AL_CONST char *filename, RGB *pal, void *param))); +AL_FUNC(FONT *, load_font, (AL_CONST char *filename, RGB *pal, void *param)); + +AL_FUNC(FONT *, load_dat_font, (AL_CONST char *filename, RGB *pal, void *param)); +AL_FUNC(FONT *, load_bios_font, (AL_CONST char *filename, RGB *pal, void *param)); +AL_FUNC(FONT *, load_grx_font, (AL_CONST char *filename, RGB *pal, void *param)); +AL_FUNC(FONT *, load_grx_or_bios_font, (AL_CONST char *filename, RGB *pal, void *param)); +AL_FUNC(FONT *, load_bitmap_font, (AL_CONST char *fname, RGB *pal, void *param)); +AL_FUNC(FONT *, load_txt_font, (AL_CONST char *fname, RGB *pal, void *param)); + +AL_FUNC(FONT *, grab_font_from_bitmap, (BITMAP *bmp)); + +AL_FUNC(int, get_font_ranges, (FONT *f)); +AL_FUNC(int, get_font_range_begin, (FONT *f, int range)); +AL_FUNC(int, get_font_range_end, (FONT *f, int range)); +AL_FUNC(FONT *, extract_font_range, (FONT *f, int begin, int end)); +AL_FUNC(FONT *, merge_fonts, (FONT *f1, FONT *f2)); +AL_FUNC(int, transpose_font, (FONT *f, int drange)); +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FONT_H */ + + diff --git a/allegro/allegro/gfx.h b/allegro/allegro/gfx.h new file mode 100644 index 0000000000..d46a4d6c4b --- /dev/null +++ b/allegro/allegro/gfx.h @@ -0,0 +1,443 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Basic graphics support routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GFX_H +#define ALLEGRO_GFX_H + +#include "3d.h" +#include "base.h" +#include "fixed.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct RLE_SPRITE; +struct FONT_GLYPH; +struct RGB; + +#define GFX_TEXT -1 +#define GFX_AUTODETECT 0 +#define GFX_AUTODETECT_FULLSCREEN 1 +#define GFX_AUTODETECT_WINDOWED 2 +#define GFX_SAFE AL_ID('S','A','F','E') + + +/* Blender mode defines, for the gfx_driver->set_blender_mode() function */ +#define blender_mode_none 0 +#define blender_mode_trans 1 +#define blender_mode_add 2 +#define blender_mode_burn 3 +#define blender_mode_color 4 +#define blender_mode_difference 5 +#define blender_mode_dissolve 6 +#define blender_mode_dodge 7 +#define blender_mode_hue 8 +#define blender_mode_invert 9 +#define blender_mode_luminance 10 +#define blender_mode_multiply 11 +#define blender_mode_saturation 12 +#define blender_mode_screen 13 +#define blender_mode_alpha 14 + +typedef struct GFX_MODE +{ + int width, height, bpp; +} GFX_MODE; + +typedef struct GFX_MODE_LIST +{ + int num_modes; /* number of gfx modes */ + GFX_MODE *mode; /* pointer to the actual mode list array */ +} GFX_MODE_LIST; + +typedef struct GFX_DRIVER /* creates and manages the screen bitmap */ +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + AL_METHOD(struct BITMAP *, init, (int w, int h, int v_w, int v_h, int color_depth)); + AL_METHOD(void, exit, (struct BITMAP *b)); + AL_METHOD(int, scroll, (int x, int y)); + AL_METHOD(void, vsync, (void)); + AL_METHOD(void, set_palette, (AL_CONST struct RGB *p, int from, int to, int retracesync)); + AL_METHOD(int, request_scroll, (int x, int y)); + AL_METHOD(int, poll_scroll, (void)); + AL_METHOD(void, enable_triple_buffer, (void)); + AL_METHOD(struct BITMAP *, create_video_bitmap, (int width, int height)); + AL_METHOD(void, destroy_video_bitmap, (struct BITMAP *bitmap)); + AL_METHOD(int, show_video_bitmap, (struct BITMAP *bitmap)); + AL_METHOD(int, request_video_bitmap, (struct BITMAP *bitmap)); + AL_METHOD(struct BITMAP *, create_system_bitmap, (int width, int height)); + AL_METHOD(void, destroy_system_bitmap, (struct BITMAP *bitmap)); + AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus)); + AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y)); + AL_METHOD(void, hide_mouse, (void)); + AL_METHOD(void, move_mouse, (int x, int y)); + AL_METHOD(void, drawing_mode, (void)); + AL_METHOD(void, save_video_state, (void)); + AL_METHOD(void, restore_video_state, (void)); + AL_METHOD(void, set_blender_mode, (int mode, int r, int g, int b, int a)); + AL_METHOD(GFX_MODE_LIST *, fetch_mode_list, (void)); + int w, h; /* physical (not virtual!) screen size */ + int linear; /* true if video memory is linear */ + long bank_size; /* bank size, in bytes */ + long bank_gran; /* bank granularity, in bytes */ + long vid_mem; /* video memory size, in bytes */ + long vid_phys_base; /* physical address of video memory */ + int windowed; /* true if driver runs windowed */ +} GFX_DRIVER; + + +AL_VAR(GFX_DRIVER *, gfx_driver); +AL_ARRAY(_DRIVER_INFO, _gfx_driver_list); + + +/* macros for constructing the driver list */ +#define BEGIN_GFX_DRIVER_LIST \ + _DRIVER_INFO _gfx_driver_list[] = \ + { + +#define END_GFX_DRIVER_LIST \ + { 0, NULL, 0 } \ + }; + + +#define GFX_CAN_SCROLL 0x00000001 +#define GFX_CAN_TRIPLE_BUFFER 0x00000002 +#define GFX_HW_CURSOR 0x00000004 +#define GFX_HW_HLINE 0x00000008 +#define GFX_HW_HLINE_XOR 0x00000010 +#define GFX_HW_HLINE_SOLID_PATTERN 0x00000020 +#define GFX_HW_HLINE_COPY_PATTERN 0x00000040 +#define GFX_HW_FILL 0x00000080 +#define GFX_HW_FILL_XOR 0x00000100 +#define GFX_HW_FILL_SOLID_PATTERN 0x00000200 +#define GFX_HW_FILL_COPY_PATTERN 0x00000400 +#define GFX_HW_LINE 0x00000800 +#define GFX_HW_LINE_XOR 0x00001000 +#define GFX_HW_TRIANGLE 0x00002000 +#define GFX_HW_TRIANGLE_XOR 0x00004000 +#define GFX_HW_GLYPH 0x00008000 +#define GFX_HW_VRAM_BLIT 0x00010000 +#define GFX_HW_VRAM_BLIT_MASKED 0x00020000 +#define GFX_HW_MEM_BLIT 0x00040000 +#define GFX_HW_MEM_BLIT_MASKED 0x00080000 +#define GFX_HW_SYS_TO_VRAM_BLIT 0x00100000 +#define GFX_HW_SYS_TO_VRAM_BLIT_MASKED 0x00200000 +#define GFX_SYSTEM_CURSOR 0x00400000 +#define GFX_HW_VRAM_STRETCH_BLIT 0x00800000 +#define GFX_HW_VRAM_STRETCH_BLIT_MASKED 0x01000000 +#define GFX_HW_SYS_STRETCH_BLIT 0x02000000 +#define GFX_HW_SYS_STRETCH_BLIT_MASKED 0x04000000 + + +AL_VAR(int, gfx_capabilities); /* current driver capabilities */ + + +typedef struct GFX_VTABLE /* functions for drawing onto bitmaps */ +{ + int color_depth; + int mask_color; + void *unwrite_bank; /* C function on some machines, asm on i386 */ + AL_METHOD(void, set_clip, (struct BITMAP *bmp)); + AL_METHOD(void, acquire, (struct BITMAP *bmp)); + AL_METHOD(void, release, (struct BITMAP *bmp)); + AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); + AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); + AL_METHOD(int, getpixel, (struct BITMAP *bmp, int x, int y)); + AL_METHOD(void, putpixel, (struct BITMAP *bmp, int x, int y, int color)); + AL_METHOD(void, vline, (struct BITMAP *bmp, int x, int y_1, int y2, int color)); + AL_METHOD(void, hline, (struct BITMAP *bmp, int x1, int y, int x2, int color)); + AL_METHOD(void, hfill, (struct BITMAP *bmp, int x1, int y, int x2, int color)); + AL_METHOD(void, line, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, fastline, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, rectfill, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, triangle, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color)); + AL_METHOD(void, draw_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_256_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_v_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_h_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_sprite_vh_flip, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_trans_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rgba_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y)); + AL_METHOD(void, draw_lit_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color)); + AL_METHOD(void, draw_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_trans_rgba_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); + AL_METHOD(void, draw_lit_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + AL_METHOD(void, draw_character, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg)); + AL_METHOD(void, draw_glyph, (struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg)); + AL_METHOD(void, blit_from_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_memory, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_from_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_system, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self_forward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_to_self_backward, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, blit_between_formats, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, masked_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); + AL_METHOD(void, clear_to_color, (struct BITMAP *bitmap, int color)); + AL_METHOD(void, pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + AL_METHOD(void, do_stretch_blit, (struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int source_width, int source_height, int dest_x, int dest_y, int dest_width, int dest_height, int masked)); + AL_METHOD(void, draw_gouraud_sprite, (struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4)); + AL_METHOD(void, draw_sprite_end, (void)); + AL_METHOD(void, blit_end, (void)); + AL_METHOD(void, polygon, (struct BITMAP *bmp, int vertices, AL_CONST int *points, int color)); + AL_METHOD(void, rect, (struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + AL_METHOD(void, circle, (struct BITMAP *bmp, int x, int y, int radius, int color)); + AL_METHOD(void, circlefill, (struct BITMAP *bmp, int x, int y, int radius, int color)); + AL_METHOD(void, ellipse, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); + AL_METHOD(void, ellipsefill, (struct BITMAP *bmp, int x, int y, int rx, int ry, int color)); + AL_METHOD(void, arc, (struct BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color)); + AL_METHOD(void, spline, (struct BITMAP *bmp, AL_CONST int points[8], int color)); + AL_METHOD(void, floodfill, (struct BITMAP *bmp, int x, int y, int color)); + AL_METHOD(void, polygon3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D *vtx[])); + AL_METHOD(void, polygon3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, int vc, V3D_f *vtx[])); + AL_METHOD(void, triangle3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)); + AL_METHOD(void, triangle3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)); + AL_METHOD(void, quad3d, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)); + AL_METHOD(void, quad3d_f, (struct BITMAP *bmp, int type, struct BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)); +} GFX_VTABLE; + + +AL_VAR(GFX_VTABLE, __linear_vtable8); +AL_VAR(GFX_VTABLE, __linear_vtable15); +AL_VAR(GFX_VTABLE, __linear_vtable16); +AL_VAR(GFX_VTABLE, __linear_vtable24); +AL_VAR(GFX_VTABLE, __linear_vtable32); + + +typedef struct _VTABLE_INFO +{ + int color_depth; + GFX_VTABLE *vtable; +} _VTABLE_INFO; + +AL_ARRAY(_VTABLE_INFO, _vtable_list); + + +/* macros for constructing the vtable list */ +#define BEGIN_COLOR_DEPTH_LIST \ + _VTABLE_INFO _vtable_list[] = \ + { + +#define END_COLOR_DEPTH_LIST \ + { 0, NULL } \ + }; + +#define COLOR_DEPTH_8 \ + { 8, &__linear_vtable8 }, + +#define COLOR_DEPTH_15 \ + { 15, &__linear_vtable15 }, + +#define COLOR_DEPTH_16 \ + { 16, &__linear_vtable16 }, + +#define COLOR_DEPTH_24 \ + { 24, &__linear_vtable24 }, + +#define COLOR_DEPTH_32 \ + { 32, &__linear_vtable32 }, + + +typedef struct BITMAP /* a bitmap structure */ +{ + int w, h; /* width and height in pixels */ + int clip; /* flag if clipping is turned on */ + int cl, cr, ct, cb; /* clip left, right, top and bottom values */ + GFX_VTABLE *vtable; /* drawing functions */ + void *write_bank; /* C func on some machines, asm on i386 */ + void *read_bank; /* C func on some machines, asm on i386 */ + void *dat; /* the memory we allocated for the bitmap */ + unsigned long id; /* for identifying sub-bitmaps */ + void *extra; /* points to a structure with more info */ + int x_ofs; /* horizontal offset (for sub-bitmaps) */ + int y_ofs; /* vertical offset (for sub-bitmaps) */ + int seg; /* bitmap segment */ + ZERO_SIZE_ARRAY(unsigned char *, line); +} BITMAP; + + +#define BMP_ID_VIDEO 0x80000000 +#define BMP_ID_SYSTEM 0x40000000 +#define BMP_ID_SUB 0x20000000 +#define BMP_ID_PLANAR 0x10000000 +#define BMP_ID_NOBLIT 0x08000000 +#define BMP_ID_LOCKED 0x04000000 +#define BMP_ID_AUTOLOCK 0x02000000 +#define BMP_ID_MASK 0x01FFFFFF + + +AL_VAR(BITMAP *, screen); + +#define SCREEN_W (gfx_driver ? gfx_driver->w : 0) +#define SCREEN_H (gfx_driver ? gfx_driver->h : 0) + +#define VIRTUAL_W (screen ? screen->w : 0) +#define VIRTUAL_H (screen ? screen->h : 0) + +#define COLORCONV_NONE 0 + +#define COLORCONV_8_TO_15 1 +#define COLORCONV_8_TO_16 2 +#define COLORCONV_8_TO_24 4 +#define COLORCONV_8_TO_32 8 + +#define COLORCONV_15_TO_8 0x10 +#define COLORCONV_15_TO_16 0x20 +#define COLORCONV_15_TO_24 0x40 +#define COLORCONV_15_TO_32 0x80 + +#define COLORCONV_16_TO_8 0x100 +#define COLORCONV_16_TO_15 0x200 +#define COLORCONV_16_TO_24 0x400 +#define COLORCONV_16_TO_32 0x800 + +#define COLORCONV_24_TO_8 0x1000 +#define COLORCONV_24_TO_15 0x2000 +#define COLORCONV_24_TO_16 0x4000 +#define COLORCONV_24_TO_32 0x8000 + +#define COLORCONV_32_TO_8 0x10000 +#define COLORCONV_32_TO_15 0x20000 +#define COLORCONV_32_TO_16 0x40000 +#define COLORCONV_32_TO_24 0x80000 + +#define COLORCONV_32A_TO_8 0x100000 +#define COLORCONV_32A_TO_15 0x200000 +#define COLORCONV_32A_TO_16 0x400000 +#define COLORCONV_32A_TO_24 0x800000 + +#define COLORCONV_DITHER_PAL 0x1000000 +#define COLORCONV_DITHER_HI 0x2000000 +#define COLORCONV_KEEP_TRANS 0x4000000 + +#define COLORCONV_DITHER (COLORCONV_DITHER_PAL | \ + COLORCONV_DITHER_HI) + +#define COLORCONV_EXPAND_256 (COLORCONV_8_TO_15 | \ + COLORCONV_8_TO_16 | \ + COLORCONV_8_TO_24 | \ + COLORCONV_8_TO_32) + +#define COLORCONV_REDUCE_TO_256 (COLORCONV_15_TO_8 | \ + COLORCONV_16_TO_8 | \ + COLORCONV_24_TO_8 | \ + COLORCONV_32_TO_8 | \ + COLORCONV_32A_TO_8) + +#define COLORCONV_EXPAND_15_TO_16 COLORCONV_15_TO_16 + +#define COLORCONV_REDUCE_16_TO_15 COLORCONV_16_TO_15 + +#define COLORCONV_EXPAND_HI_TO_TRUE (COLORCONV_15_TO_24 | \ + COLORCONV_15_TO_32 | \ + COLORCONV_16_TO_24 | \ + COLORCONV_16_TO_32) + +#define COLORCONV_REDUCE_TRUE_TO_HI (COLORCONV_24_TO_15 | \ + COLORCONV_24_TO_16 | \ + COLORCONV_32_TO_15 | \ + COLORCONV_32_TO_16) + +#define COLORCONV_24_EQUALS_32 (COLORCONV_24_TO_32 | \ + COLORCONV_32_TO_24) + +#define COLORCONV_TOTAL (COLORCONV_EXPAND_256 | \ + COLORCONV_REDUCE_TO_256 | \ + COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_EXPAND_HI_TO_TRUE | \ + COLORCONV_REDUCE_TRUE_TO_HI | \ + COLORCONV_24_EQUALS_32 | \ + COLORCONV_32A_TO_15 | \ + COLORCONV_32A_TO_16 | \ + COLORCONV_32A_TO_24) + +#define COLORCONV_PARTIAL (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_24_EQUALS_32) + +#define COLORCONV_MOST (COLORCONV_EXPAND_15_TO_16 | \ + COLORCONV_REDUCE_16_TO_15 | \ + COLORCONV_EXPAND_HI_TO_TRUE | \ + COLORCONV_REDUCE_TRUE_TO_HI | \ + COLORCONV_24_EQUALS_32) + +#define COLORCONV_KEEP_ALPHA (COLORCONV_TOTAL \ + & ~(COLORCONV_32A_TO_8 | \ + COLORCONV_32A_TO_15 | \ + COLORCONV_32A_TO_16 | \ + COLORCONV_32A_TO_24)) + +AL_FUNC(GFX_MODE_LIST *, get_gfx_mode_list, (int card)); +AL_FUNC(void, destroy_gfx_mode_list, (GFX_MODE_LIST *gfx_mode_list)); +AL_FUNC(void, set_color_depth, (int depth)); +AL_FUNC(int, get_color_depth, (void)); +AL_FUNC(void, set_color_conversion, (int mode)); +AL_FUNC(int, get_color_conversion, (void)); +AL_FUNC(void, request_refresh_rate, (int rate)); +AL_FUNC(int, get_refresh_rate, (void)); +AL_FUNC(int, set_gfx_mode, (int card, int w, int h, int v_w, int v_h)); +AL_FUNC(int, scroll_screen, (int x, int y)); +AL_FUNC(int, request_scroll, (int x, int y)); +AL_FUNC(int, poll_scroll, (void)); +AL_FUNC(int, show_video_bitmap, (BITMAP *bitmap)); +AL_FUNC(int, request_video_bitmap, (BITMAP *bitmap)); +AL_FUNC(int, enable_triple_buffer, (void)); +AL_FUNC(BITMAP *, create_bitmap, (int width, int height)); +AL_FUNC(BITMAP *, create_bitmap_ex, (int color_depth, int width, int height)); +AL_FUNC(BITMAP *, create_sub_bitmap, (BITMAP *parent, int x, int y, int width, int height)); +AL_FUNC(BITMAP *, create_video_bitmap, (int width, int height)); +AL_FUNC(BITMAP *, create_system_bitmap, (int width, int height)); +AL_FUNC(void, destroy_bitmap, (BITMAP *bitmap)); +AL_FUNC(void, set_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); +AL_FUNC(void, add_clip_rect, (BITMAP *bitmap, int x1, int y_1, int x2, int y2)); +AL_FUNC(void, clear_bitmap, (BITMAP *bitmap)); +AL_FUNC(void, vsync, (void)); + + + +#define SWITCH_NONE 0 +#define SWITCH_PAUSE 1 +#define SWITCH_AMNESIA 2 +#define SWITCH_BACKGROUND 3 +#define SWITCH_BACKAMNESIA 4 + +#define SWITCH_IN 0 +#define SWITCH_OUT 1 + +AL_FUNC(int, set_display_switch_mode, (int mode)); +AL_FUNC(int, get_display_switch_mode, (void)); +AL_FUNC(int, set_display_switch_callback, (int dir, AL_METHOD(void, cb, (void)))); +AL_FUNC(void, remove_display_switch_callback, (AL_METHOD(void, cb, (void)))); + +AL_FUNC(void, lock_bitmap, (struct BITMAP *bmp)); + +#ifdef __cplusplus + } +#endif + +#include "inline/gfx.inl" + +#endif /* ifndef ALLEGRO_GFX_H */ + + diff --git a/allegro/allegro/graphics.h b/allegro/allegro/graphics.h new file mode 100644 index 0000000000..f92c2a2f1e --- /dev/null +++ b/allegro/allegro/graphics.h @@ -0,0 +1,33 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Container for all graphics related routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GRAPHICS_H +#define ALLEGRO_GRAPHICS_H + +#include "base.h" +#include "gfx.h" +#include "text.h" +#include "3d.h" +#include "draw.h" +#include "color.h" +#include "palette.h" +#include "rle.h" +#include "compiled.h" + +#endif /* ifndef ALLEGRO_GRAPHICS_H */ + diff --git a/allegro/allegro/gui.h b/allegro/allegro/gui.h new file mode 100644 index 0000000000..896faf1250 --- /dev/null +++ b/allegro/allegro/gui.h @@ -0,0 +1,231 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * GUI routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GUI_H +#define ALLEGRO_GUI_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; +struct DIALOG; + +typedef AL_METHOD(int, DIALOG_PROC, (int msg, struct DIALOG *d, int c)); + +typedef struct DIALOG +{ + DIALOG_PROC proc; + int x, y, w, h; /* position and size of the object */ + int fg, bg; /* foreground and background colors */ + int key; /* keyboard shortcut (ASCII code) */ + int flags; /* flags about the object state */ + int d1, d2; /* any data the object might require */ + void *dp, *dp2, *dp3; /* pointers to more object data */ +} DIALOG; + + +/* a popup menu */ +typedef struct MENU +{ + char *text; /* menu item text */ + AL_METHOD(int, proc, (void)); /* callback function */ + struct MENU *child; /* to allow nested menus */ + int flags; /* flags about the menu state */ + void *dp; /* any data the menu might require */ +} MENU; + + +/* stored information about the state of an active GUI dialog */ +typedef struct DIALOG_PLAYER +{ + int obj; + int res; + int mouse_obj; + int focus_obj; + int joy_on; + int click_wait; + int mouse_ox, mouse_oy; + int mouse_oz; + int mouse_b; + DIALOG *dialog; +} DIALOG_PLAYER; + + +/* stored information about the state of an active GUI menu */ +typedef struct MENU_PLAYER +{ + MENU *menu; /* the menu itself */ + int bar; /* set if it is a top level menu bar */ + int size; /* number of items in the menu */ + int sel; /* selected item */ + int x, y, w, h; /* screen position of the menu */ + int (*proc)(void); /* callback function */ + BITMAP *saved; /* saved what was underneath it */ + + int mouse_button_was_pressed; /* set if mouse button pressed on last iteration */ + int back_from_child; /* set if a child was activated on last iteration */ + int timestamp; /* timestamp for gui_timer events */ + int mouse_sel; /* item the mouse is currently over */ + int redraw; /* set if redrawing is required */ + int auto_open; /* set if menu auto-opening is activated */ + int ret; /* return value */ + + DIALOG *dialog; /* d_menu_proc() parent dialog (if any) */ + + struct MENU_PLAYER *parent; /* the parent menu, or NULL for root */ + struct MENU_PLAYER *child; /* the child menu, or NULL for none */ +} MENU_PLAYER; + + +/* bits for the flags field */ +#define D_EXIT 1 /* object makes the dialog exit */ +#define D_SELECTED 2 /* object is selected */ +#define D_GOTFOCUS 4 /* object has the input focus */ +#define D_GOTMOUSE 8 /* mouse is on top of object */ +#define D_HIDDEN 16 /* object is not visible */ +#define D_DISABLED 32 /* object is visible but inactive */ +#define D_DIRTY 64 /* object needs to be redrawn */ +#define D_INTERNAL 128 /* reserved for internal use */ +#define D_USER 256 /* from here on is free for your own use */ + + +/* return values for the dialog procedures */ +#define D_O_K 0 /* normal exit status */ +#define D_CLOSE 1 /* request to close the dialog */ +#define D_REDRAW 2 /* request to redraw the dialog */ +#define D_REDRAWME 4 /* request to redraw this object */ +#define D_WANTFOCUS 8 /* this object wants the input focus */ +#define D_USED_CHAR 16 /* object has used the keypress */ +#define D_REDRAW_ALL 32 /* request to redraw all active dialogs */ +#define D_DONTWANTMOUSE 64 /* this object does not want mouse focus */ + + +/* messages for the dialog procedures */ +#define MSG_START 1 /* start the dialog, initialise */ +#define MSG_END 2 /* dialog is finished - cleanup */ +#define MSG_DRAW 3 /* draw the object */ +#define MSG_CLICK 4 /* mouse click on the object */ +#define MSG_DCLICK 5 /* double click on the object */ +#define MSG_KEY 6 /* keyboard shortcut */ +#define MSG_CHAR 7 /* other keyboard input */ +#define MSG_UCHAR 8 /* unicode keyboard input */ +#define MSG_XCHAR 9 /* broadcast character to all objects */ +#define MSG_WANTFOCUS 10 /* does object want the input focus? */ +#define MSG_GOTFOCUS 11 /* got the input focus */ +#define MSG_LOSTFOCUS 12 /* lost the input focus */ +#define MSG_GOTMOUSE 13 /* mouse on top of object */ +#define MSG_LOSTMOUSE 14 /* mouse moved away from object */ +#define MSG_IDLE 15 /* update any background stuff */ +#define MSG_RADIO 16 /* clear radio buttons */ +#define MSG_WHEEL 17 /* mouse wheel moved */ +#define MSG_LPRESS 18 /* mouse left button pressed */ +#define MSG_LRELEASE 19 /* mouse left button released */ +#define MSG_MPRESS 20 /* mouse middle button pressed */ +#define MSG_MRELEASE 21 /* mouse middle button released */ +#define MSG_RPRESS 22 /* mouse right button pressed */ +#define MSG_RRELEASE 23 /* mouse right button released */ +#define MSG_WANTMOUSE 24 /* does object want the mouse? */ +#define MSG_USER 25 /* from here on are free... */ + + +/* some dialog procedures */ +AL_FUNC(int, d_yield_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_clear_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_box_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_shadow_box_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_bitmap_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_text_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_ctext_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_rtext_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_button_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_check_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_radio_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_icon_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_keyboard_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_edit_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_list_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_text_list_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_textbox_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_slider_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, d_menu_proc, (int msg, DIALOG *d, int c)); + +AL_VAR(DIALOG_PROC, gui_shadow_box_proc); +AL_VAR(DIALOG_PROC, gui_ctext_proc); +AL_VAR(DIALOG_PROC, gui_button_proc); +AL_VAR(DIALOG_PROC, gui_edit_proc); +AL_VAR(DIALOG_PROC, gui_list_proc); +AL_VAR(DIALOG_PROC, gui_text_list_proc); + +AL_FUNCPTR(void, gui_menu_draw_menu, (int x, int y, int w, int h)); +AL_FUNCPTR(void, gui_menu_draw_menu_item, (MENU *m, int x, int y, int w, int h, int bar, int sel)); + +AL_VAR(DIALOG *, active_dialog); +AL_VAR(MENU *, active_menu); + +AL_VAR(int, gui_mouse_focus); + +AL_VAR(int, gui_fg_color); +AL_VAR(int, gui_mg_color); +AL_VAR(int, gui_bg_color); + +AL_VAR(int, gui_font_baseline); + +AL_FUNCPTR(int, gui_mouse_x, (void)); +AL_FUNCPTR(int, gui_mouse_y, (void)); +AL_FUNCPTR(int, gui_mouse_z, (void)); +AL_FUNCPTR(int, gui_mouse_b, (void)); + +AL_FUNC(void, gui_set_screen, (BITMAP *bmp)); +AL_FUNC(BITMAP *, gui_get_screen, (void)); +AL_FUNC(int, gui_textout_ex, (struct BITMAP *bmp, AL_CONST char *s, int x, int y, int color, int bg, int centre)); +AL_FUNC(int, gui_strlen, (AL_CONST char *s)); +AL_FUNC(void, position_dialog, (DIALOG *dialog, int x, int y)); +AL_FUNC(void, centre_dialog, (DIALOG *dialog)); +AL_FUNC(void, set_dialog_color, (DIALOG *dialog, int fg, int bg)); +AL_FUNC(int, find_dialog_focus, (DIALOG *dialog)); +AL_FUNC(int, offer_focus, (DIALOG *dialog, int obj, int *focus_obj, int force)); +AL_FUNC(int, object_message, (DIALOG *dialog, int msg, int c)); +AL_FUNC(int, dialog_message, (DIALOG *dialog, int msg, int c, int *obj)); +AL_FUNC(int, broadcast_dialog_message, (int msg, int c)); +AL_FUNC(int, do_dialog, (DIALOG *dialog, int focus_obj)); +AL_FUNC(int, popup_dialog, (DIALOG *dialog, int focus_obj)); +AL_FUNC(DIALOG_PLAYER *, init_dialog, (DIALOG *dialog, int focus_obj)); +AL_FUNC(int, update_dialog, (DIALOG_PLAYER *player)); +AL_FUNC(int, shutdown_dialog, (DIALOG_PLAYER *player)); +AL_FUNC(int, do_menu, (MENU *menu, int x, int y)); +AL_FUNC(MENU_PLAYER *, init_menu, (MENU *menu, int x, int y)); +AL_FUNC(int, update_menu, (MENU_PLAYER *player)); +AL_FUNC(int, shutdown_menu, (MENU_PLAYER *player)); +AL_FUNC(int, alert, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, int c1, int c2)); +AL_FUNC(int, alert3, (AL_CONST char *s1, AL_CONST char *s2, AL_CONST char *s3, AL_CONST char *b1, AL_CONST char *b2, AL_CONST char *b3, int c1, int c2, int c3)); +AL_FUNC(int, file_select_ex, (AL_CONST char *message, char *path, AL_CONST char *ext, int size, int w, int h)); + +AL_FUNC(int, gfx_mode_select, (int *card, int *w, int *h)); +AL_FUNC(int, gfx_mode_select_ex, (int *card, int *w, int *h, int *color_depth)); +AL_FUNC(int, gfx_mode_select_filter, (int *card, int *w, int *h, int *color_depth, int (*filter)(int, int, int, int))); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_GUI_H */ + + diff --git a/allegro/allegro/inline/3dmaths.inl b/allegro/allegro/inline/3dmaths.inl new file mode 100644 index 0000000000..614f269a59 --- /dev/null +++ b/allegro/allegro/inline/3dmaths.inl @@ -0,0 +1,60 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * 3D maths inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_3DMATHS_INL +#define ALLEGRO_3DMATHS_INL + +#ifdef __cplusplus + extern "C" { +#endif + + +AL_INLINE(fixed, dot_product, (fixed x1, fixed y_1, fixed z1, fixed x2, fixed y2, fixed z2), +{ + return fixmul(x1, x2) + fixmul(y_1, y2) + fixmul(z1, z2); +}) + + +AL_INLINE(float, dot_product_f, (float x1, float y_1, float z1, float x2, float y2, float z2), +{ + return (x1 * x2) + (y_1 * y2) + (z1 * z2); +}) + + +AL_INLINE(void, persp_project, (fixed x, fixed y, fixed z, fixed *xout, fixed *yout), +{ + *xout = fixmul(fixdiv(x, z), _persp_xscale) + _persp_xoffset; + *yout = fixmul(fixdiv(y, z), _persp_yscale) + _persp_yoffset; +}) + + +AL_INLINE(void, persp_project_f, (float x, float y, float z, float *xout, float *yout), +{ + float z1 = 1.0f / z; + *xout = ((x * z1) * _persp_xscale_f) + _persp_xoffset_f; + *yout = ((y * z1) * _persp_yscale_f) + _persp_yoffset_f; +}) + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_3DMATHS_INL */ + + diff --git a/allegro/allegro/inline/asm.inl b/allegro/allegro/inline/asm.inl new file mode 100644 index 0000000000..4177da1ff2 --- /dev/null +++ b/allegro/allegro/inline/asm.inl @@ -0,0 +1,59 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Imports asm definitions of various inline functions. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifndef ALLEGRO_NO_ASM + +#if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386) + + /* use i386 asm, GCC syntax */ + #include "allegro/platform/al386gcc.h" + +#elif (defined ALLEGRO_MSVC) && (defined ALLEGRO_I386) + + /* use i386 asm, MSVC syntax */ + #include "allegro/platform/al386vc.h" + +#elif (defined ALLEGRO_WATCOM) && (defined ALLEGRO_I386) + + /* use i386 asm, Watcom syntax */ + #include "allegro/platform/al386wat.h" + +#else + + /* asm not supported */ + #define ALLEGRO_NO_ASM + +#endif + +#endif + +/* Define ALLEGRO_USE_C for backwards compatibility. It should not be used + * anywhere else in the sources for now. + */ +#ifdef ALLEGRO_NO_ASM +#define ALLEGRO_USE_C +#endif + +#ifdef __cplusplus + } +#endif + diff --git a/allegro/allegro/inline/color.inl b/allegro/allegro/inline/color.inl new file mode 100644 index 0000000000..6bd4406324 --- /dev/null +++ b/allegro/allegro/inline/color.inl @@ -0,0 +1,179 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Color inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_COLOR_INL +#define ALLEGRO_COLOR_INL + +#ifdef __cplusplus + extern "C" { +#endif + +AL_INLINE(int, makecol15, (int r, int g, int b), +{ + return (((r >> 3) << _rgb_r_shift_15) | + ((g >> 3) << _rgb_g_shift_15) | + ((b >> 3) << _rgb_b_shift_15)); +}) + + +AL_INLINE(int, makecol16, (int r, int g, int b), +{ + return (((r >> 3) << _rgb_r_shift_16) | + ((g >> 2) << _rgb_g_shift_16) | + ((b >> 3) << _rgb_b_shift_16)); +}) + + +AL_INLINE(int, makecol24, (int r, int g, int b), +{ + return ((r << _rgb_r_shift_24) | + (g << _rgb_g_shift_24) | + (b << _rgb_b_shift_24)); +}) + + +AL_INLINE(int, makecol32, (int r, int g, int b), +{ + return ((r << _rgb_r_shift_32) | + (g << _rgb_g_shift_32) | + (b << _rgb_b_shift_32)); +}) + + +AL_INLINE(int, makeacol32, (int r, int g, int b, int a), +{ + return ((r << _rgb_r_shift_32) | + (g << _rgb_g_shift_32) | + (b << _rgb_b_shift_32) | + (a << _rgb_a_shift_32)); +}) + + +AL_INLINE(int, getr8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].r]; +}) + + +AL_INLINE(int, getg8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].g]; +}) + + +AL_INLINE(int, getb8, (int c), +{ + return _rgb_scale_6[(int)_current_palette[c].b]; +}) + + +AL_INLINE(int, getr15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_r_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getg15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_g_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getb15, (int c), +{ + return _rgb_scale_5[(c >> _rgb_b_shift_15) & 0x1F]; +}) + + +AL_INLINE(int, getr16, (int c), +{ + return _rgb_scale_5[(c >> _rgb_r_shift_16) & 0x1F]; +}) + + +AL_INLINE(int, getg16, (int c), +{ + return _rgb_scale_6[(c >> _rgb_g_shift_16) & 0x3F]; +}) + + +AL_INLINE(int, getb16, (int c), +{ + return _rgb_scale_5[(c >> _rgb_b_shift_16) & 0x1F]; +}) + + +AL_INLINE(int, getr24, (int c), +{ + return ((c >> _rgb_r_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getg24, (int c), +{ + return ((c >> _rgb_g_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getb24, (int c), +{ + return ((c >> _rgb_b_shift_24) & 0xFF); +}) + + +AL_INLINE(int, getr32, (int c), +{ + return ((c >> _rgb_r_shift_32) & 0xFF); +}) + + +AL_INLINE(int, getg32, (int c), +{ + return ((c >> _rgb_g_shift_32) & 0xFF); +}) + + +AL_INLINE(int, getb32, (int c), +{ + return ((c >> _rgb_b_shift_32) & 0xFF); +}) + + +AL_INLINE(int, geta32, (int c), +{ + return ((c >> _rgb_a_shift_32) & 0xFF); +}) + + +#ifndef ALLEGRO_DOS + +AL_INLINE(void, _set_color, (int idx, AL_CONST RGB *p), +{ + set_color(idx, p); +}) + +#endif + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_COLOR_INL */ + + diff --git a/allegro/allegro/inline/draw.inl b/allegro/allegro/inline/draw.inl new file mode 100644 index 0000000000..504eb22fa7 --- /dev/null +++ b/allegro/allegro/inline/draw.inl @@ -0,0 +1,543 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Draw inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DRAW_INL +#define ALLEGRO_DRAW_INL + +#include "allegro/debug.h" +#include "allegro/3d.h" +#include "gfx.inl" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_INLINE(int, getpixel, (BITMAP *bmp, int x, int y), +{ + ASSERT(bmp); + + return bmp->vtable->getpixel(bmp, x, y); +}) + + +AL_INLINE(void, putpixel, (BITMAP *bmp, int x, int y, int color), +{ + ASSERT(bmp); + + bmp->vtable->putpixel(bmp, x, y, color); +}) + + +AL_INLINE(void, _allegro_vline, (BITMAP *bmp, int x, int y_1, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->vline(bmp, x, y_1, y2, color); +}) + + +AL_INLINE(void, _allegro_hline, (BITMAP *bmp, int x1, int y, int x2, int color), +{ + ASSERT(bmp); + + bmp->vtable->hline(bmp, x1, y, x2, color); +}) + + +/* The curses API also contains functions called vline and hline so we have + * called our functions _allegro_vline and _allegro_hline. User programs + * should use the vline/hline aliases as they are the official names. + */ +#ifndef ALLEGRO_NO_VHLINE_ALIAS + AL_ALIAS_VOID_RET(vline(BITMAP *bmp, int x, int y_1, int y2, int color), _allegro_vline(bmp, x, y_1, y2, color)) + AL_ALIAS_VOID_RET(hline(BITMAP *bmp, int x1, int y, int x2, int color), _allegro_hline(bmp, x1, y, x2, color)) +#endif + + +AL_INLINE(void, line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->line(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, fastline, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->fastline(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->rectfill(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, triangle, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color), +{ + ASSERT(bmp); + + bmp->vtable->triangle(bmp, x1, y_1, x2, y2, x3, y3, color); +}) + + +AL_INLINE(void, polygon, (BITMAP *bmp, int vertices, AL_CONST int *points, int color), +{ + ASSERT(bmp); + + bmp->vtable->polygon(bmp, vertices, points, color); +}) + + +AL_INLINE(void, rect, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color), +{ + ASSERT(bmp); + + bmp->vtable->rect(bmp, x1, y_1, x2, y2, color); +}) + + +AL_INLINE(void, circle, (BITMAP *bmp, int x, int y, int radius, int color), +{ + ASSERT(bmp); + + bmp->vtable->circle(bmp, x, y, radius, color); +}) + + +AL_INLINE(void, circlefill, (BITMAP *bmp, int x, int y, int radius, int color), +{ + ASSERT(bmp); + + bmp->vtable->circlefill(bmp, x, y, radius, color); +}) + + + +AL_INLINE(void, ellipse, (BITMAP *bmp, int x, int y, int rx, int ry, int color), +{ + ASSERT(bmp); + + bmp->vtable->ellipse(bmp, x, y, rx, ry, color); +}) + + + +AL_INLINE(void, ellipsefill, (BITMAP *bmp, int x, int y, int rx, int ry, int color), +{ + ASSERT(bmp); + + bmp->vtable->ellipsefill(bmp, x, y, rx, ry, color); +}) + + + +AL_INLINE(void, arc, (BITMAP *bmp, int x, int y, fixed ang1, fixed ang2, int r, int color), +{ + ASSERT(bmp); + + bmp->vtable->arc(bmp, x, y, ang1, ang2, r, color); +}) + + + +AL_INLINE(void, spline, (BITMAP *bmp, AL_CONST int points[8], int color), +{ + ASSERT(bmp); + + bmp->vtable->spline(bmp, points, color); +}) + + + +AL_INLINE(void, floodfill, (BITMAP *bmp, int x, int y, int color), +{ + ASSERT(bmp); + + bmp->vtable->floodfill(bmp, x, y, color); +}) + + + +AL_INLINE(void, polygon3d, (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]), +{ + ASSERT(bmp); + + bmp->vtable->polygon3d(bmp, type, texture, vc, vtx); +}) + + + +AL_INLINE(void, polygon3d_f, (BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]), +{ + ASSERT(bmp); + + bmp->vtable->polygon3d_f(bmp, type, texture, vc, vtx); +}) + + + +AL_INLINE(void, triangle3d, (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3), +{ + ASSERT(bmp); + + bmp->vtable->triangle3d(bmp, type, texture, v1, v2, v3); +}) + + + +AL_INLINE(void, triangle3d_f, (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3), +{ + ASSERT(bmp); + + bmp->vtable->triangle3d_f(bmp, type, texture, v1, v2, v3); +}) + + + +AL_INLINE(void, quad3d, (BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4), +{ + ASSERT(bmp); + + bmp->vtable->quad3d(bmp, type, texture, v1, v2, v3, v4); +}) + + + +AL_INLINE(void, quad3d_f, (BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4), +{ + ASSERT(bmp); + + bmp->vtable->quad3d_f(bmp, type, texture, v1, v2, v3, v4); +}) + + + + + +AL_INLINE(void, draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + + if (sprite->vtable->color_depth == 8) { + bmp->vtable->draw_256_sprite(bmp, sprite, x, y); + } + else { + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + bmp->vtable->draw_sprite(bmp, sprite, x, y); + } +}) + + +AL_INLINE(void, draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_v_flip(bmp, sprite, x, y); +}) + + +AL_INLINE(void, draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y),{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_h_flip(bmp, sprite, x, y); +}) + + +AL_INLINE(void, draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_sprite_vh_flip(bmp, sprite, x, y); +}) + + +AL_INLINE(void, draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + + if (sprite->vtable->color_depth == 32) { + ASSERT(bmp->vtable->draw_trans_rgba_sprite); + bmp->vtable->draw_trans_rgba_sprite(bmp, sprite, x, y); + } + else { + ASSERT((bmp->vtable->color_depth == sprite->vtable->color_depth) || + ((bmp->vtable->color_depth == 32) && + (sprite->vtable->color_depth == 8))); + bmp->vtable->draw_trans_sprite(bmp, sprite, x, y); + } +}) + + +AL_INLINE(void, draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_lit_sprite(bmp, sprite, x, y, color); +}) + + +AL_INLINE(void, draw_gouraud_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int c1, int c2, int c3, int c4), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->vtable->color_depth); + + bmp->vtable->draw_gouraud_sprite(bmp, sprite, x, y, c1, c2, c3, c4); +}) + + +AL_INLINE(void, draw_character_ex, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(sprite->vtable->color_depth == 8); + + bmp->vtable->draw_character(bmp, sprite, x, y, color, bg); +}) + + +AL_INLINE(void, rotate_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, + (y<<16) + (sprite->h * 0x10000) / 2, + sprite->w << 15, sprite->h << 15, + angle, 0x10000, FALSE); +}) + + +AL_INLINE(void, rotate_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * 0x10000) / 2, + (y<<16) + (sprite->h * 0x10000) / 2, + sprite->w << 15, sprite->h << 15, + angle, 0x10000, TRUE); +}) + + +AL_INLINE(void, rotate_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, + (y<<16) + (sprite->h * scale) / 2, + sprite->w << 15, sprite->h << 15, + angle, scale, FALSE); +}) + + +AL_INLINE(void, rotate_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, (x<<16) + (sprite->w * scale) / 2, + (y<<16) + (sprite->h * scale) / 2, + sprite->w << 15, sprite->h << 15, + angle, scale, TRUE); +}) + + +AL_INLINE(void, pivot_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, FALSE); +}) + + +AL_INLINE(void, pivot_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, 0x10000, TRUE); +}) + + +AL_INLINE(void, pivot_scaled_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, FALSE); +}) + + +AL_INLINE(void, pivot_scaled_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y, int cx, int cy, fixed angle, fixed scale), +{ + ASSERT(bmp); + ASSERT(sprite); + + bmp->vtable->pivot_scaled_sprite_flip(bmp, sprite, x<<16, y<<16, cx<<16, cy<<16, angle, scale, TRUE); +}) + + +AL_INLINE(void, _putpixel, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write8(addr+x, color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read8(addr+x); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel15, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write15(addr+x*sizeof(short), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel15, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read15(addr+x*sizeof(short)); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel16, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write16(addr+x*sizeof(short), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel16, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read16(addr+x*sizeof(short)); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel24, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write24(addr+x*3, color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel24, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read24(addr+x*3); + bmp_unwrite_line(bmp); + + return c; +}) + + +AL_INLINE(void, _putpixel32, (BITMAP *bmp, int x, int y, int color), +{ + uintptr_t addr; + + bmp_select(bmp); + addr = bmp_write_line(bmp, y); + bmp_write32(addr+x*sizeof(int32_t), color); + bmp_unwrite_line(bmp); +}) + + +AL_INLINE(int, _getpixel32, (BITMAP *bmp, int x, int y), +{ + uintptr_t addr; + int c; + + bmp_select(bmp); + addr = bmp_read_line(bmp, y); + c = bmp_read32(addr+x*sizeof(int32_t)); + bmp_unwrite_line(bmp); + + return c; +}) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_DRAW_INL */ + + diff --git a/allegro/allegro/inline/file.inl b/allegro/allegro/inline/file.inl new file mode 100644 index 0000000000..a1c87791ac --- /dev/null +++ b/allegro/allegro/inline/file.inl @@ -0,0 +1,6 @@ +#ifndef ALLEGRO_FILE_INL +#define ALLEGRO_FILE_INL + +#warning file.inl should no longer be referenced. + +#endif /* ifndef ALLEGRO_FILE_INL */ diff --git a/allegro/allegro/inline/fix.inl b/allegro/allegro/inline/fix.inl new file mode 100644 index 0000000000..7f105814a5 --- /dev/null +++ b/allegro/allegro/inline/fix.inl @@ -0,0 +1,254 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fix class inline functions. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FIX_INL +#define ALLEGRO_FIX_INL + +#ifdef __cplusplus + + +inline fix operator + (const fix x, const fix y) { fix t; t.v = x.v + y.v; return t; } +inline fix operator + (const fix x, const int y) { fix t; t.v = x.v + itofix(y); return t; } +inline fix operator + (const int x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } +inline fix operator + (const fix x, const long y) { fix t; t.v = x.v + itofix(y); return t; } +inline fix operator + (const long x, const fix y) { fix t; t.v = itofix(x) + y.v; return t; } +inline fix operator + (const fix x, const float y) { fix t; t.v = x.v + ftofix(y); return t; } +inline fix operator + (const float x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } +inline fix operator + (const fix x, const double y) { fix t; t.v = x.v + ftofix(y); return t; } +inline fix operator + (const double x, const fix y) { fix t; t.v = ftofix(x) + y.v; return t; } + +inline fix operator - (const fix x, const fix y) { fix t; t.v = x.v - y.v; return t; } +inline fix operator - (const fix x, const int y) { fix t; t.v = x.v - itofix(y); return t; } +inline fix operator - (const int x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } +inline fix operator - (const fix x, const long y) { fix t; t.v = x.v - itofix(y); return t; } +inline fix operator - (const long x, const fix y) { fix t; t.v = itofix(x) - y.v; return t; } +inline fix operator - (const fix x, const float y) { fix t; t.v = x.v - ftofix(y); return t; } +inline fix operator - (const float x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } +inline fix operator - (const fix x, const double y) { fix t; t.v = x.v - ftofix(y); return t; } +inline fix operator - (const double x, const fix y) { fix t; t.v = ftofix(x) - y.v; return t; } + +inline fix operator * (const fix x, const fix y) { fix t; t.v = fixmul(x.v, y.v); return t; } +inline fix operator * (const fix x, const int y) { fix t; t.v = x.v * y; return t; } +inline fix operator * (const int x, const fix y) { fix t; t.v = x * y.v; return t; } +inline fix operator * (const fix x, const long y) { fix t; t.v = x.v * y; return t; } +inline fix operator * (const long x, const fix y) { fix t; t.v = x * y.v; return t; } +inline fix operator * (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } +inline fix operator * (const float x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } +inline fix operator * (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) * y); return t; } +inline fix operator * (const double x, const fix y) { fix t; t.v = ftofix(x * fixtof(y.v)); return t; } + +inline fix operator / (const fix x, const fix y) { fix t; t.v = fixdiv(x.v, y.v); return t; } +inline fix operator / (const fix x, const int y) { fix t; t.v = x.v / y; return t; } +inline fix operator / (const int x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } +inline fix operator / (const fix x, const long y) { fix t; t.v = x.v / y; return t; } +inline fix operator / (const long x, const fix y) { fix t; t.v = fixdiv(itofix(x), y.v); return t; } +inline fix operator / (const fix x, const float y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } +inline fix operator / (const float x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } +inline fix operator / (const fix x, const double y) { fix t; t.v = ftofix(fixtof(x.v) / y); return t; } +inline fix operator / (const double x, const fix y) { fix t; t.v = ftofix(x / fixtof(y.v)); return t; } + +inline fix operator << (const fix x, const int y) { fix t; t.v = x.v << y; return t; } +inline fix operator >> (const fix x, const int y) { fix t; t.v = x.v >> y; return t; } + +inline int operator == (const fix x, const fix y) { return (x.v == y.v); } +inline int operator == (const fix x, const int y) { return (x.v == itofix(y)); } +inline int operator == (const int x, const fix y) { return (itofix(x) == y.v); } +inline int operator == (const fix x, const long y) { return (x.v == itofix(y)); } +inline int operator == (const long x, const fix y) { return (itofix(x) == y.v); } +inline int operator == (const fix x, const float y) { return (x.v == ftofix(y)); } +inline int operator == (const float x, const fix y) { return (ftofix(x) == y.v); } +inline int operator == (const fix x, const double y) { return (x.v == ftofix(y)); } +inline int operator == (const double x, const fix y) { return (ftofix(x) == y.v); } + +inline int operator != (const fix x, const fix y) { return (x.v != y.v); } +inline int operator != (const fix x, const int y) { return (x.v != itofix(y)); } +inline int operator != (const int x, const fix y) { return (itofix(x) != y.v); } +inline int operator != (const fix x, const long y) { return (x.v != itofix(y)); } +inline int operator != (const long x, const fix y) { return (itofix(x) != y.v); } +inline int operator != (const fix x, const float y) { return (x.v != ftofix(y)); } +inline int operator != (const float x, const fix y) { return (ftofix(x) != y.v); } +inline int operator != (const fix x, const double y) { return (x.v != ftofix(y)); } +inline int operator != (const double x, const fix y) { return (ftofix(x) != y.v); } + +inline int operator < (const fix x, const fix y) { return (x.v < y.v); } +inline int operator < (const fix x, const int y) { return (x.v < itofix(y)); } +inline int operator < (const int x, const fix y) { return (itofix(x) < y.v); } +inline int operator < (const fix x, const long y) { return (x.v < itofix(y)); } +inline int operator < (const long x, const fix y) { return (itofix(x) < y.v); } +inline int operator < (const fix x, const float y) { return (x.v < ftofix(y)); } +inline int operator < (const float x, const fix y) { return (ftofix(x) < y.v); } +inline int operator < (const fix x, const double y) { return (x.v < ftofix(y)); } +inline int operator < (const double x, const fix y) { return (ftofix(x) < y.v); } + +inline int operator > (const fix x, const fix y) { return (x.v > y.v); } +inline int operator > (const fix x, const int y) { return (x.v > itofix(y)); } +inline int operator > (const int x, const fix y) { return (itofix(x) > y.v); } +inline int operator > (const fix x, const long y) { return (x.v > itofix(y)); } +inline int operator > (const long x, const fix y) { return (itofix(x) > y.v); } +inline int operator > (const fix x, const float y) { return (x.v > ftofix(y)); } +inline int operator > (const float x, const fix y) { return (ftofix(x) > y.v); } +inline int operator > (const fix x, const double y) { return (x.v > ftofix(y)); } +inline int operator > (const double x, const fix y) { return (ftofix(x) > y.v); } + +inline int operator <= (const fix x, const fix y) { return (x.v <= y.v); } +inline int operator <= (const fix x, const int y) { return (x.v <= itofix(y)); } +inline int operator <= (const int x, const fix y) { return (itofix(x) <= y.v); } +inline int operator <= (const fix x, const long y) { return (x.v <= itofix(y)); } +inline int operator <= (const long x, const fix y) { return (itofix(x) <= y.v); } +inline int operator <= (const fix x, const float y) { return (x.v <= ftofix(y)); } +inline int operator <= (const float x, const fix y) { return (ftofix(x) <= y.v); } +inline int operator <= (const fix x, const double y) { return (x.v <= ftofix(y)); } +inline int operator <= (const double x, const fix y) { return (ftofix(x) <= y.v); } + +inline int operator >= (const fix x, const fix y) { return (x.v >= y.v); } +inline int operator >= (const fix x, const int y) { return (x.v >= itofix(y)); } +inline int operator >= (const int x, const fix y) { return (itofix(x) >= y.v); } +inline int operator >= (const fix x, const long y) { return (x.v >= itofix(y)); } +inline int operator >= (const long x, const fix y) { return (itofix(x) >= y.v); } +inline int operator >= (const fix x, const float y) { return (x.v >= ftofix(y)); } +inline int operator >= (const float x, const fix y) { return (ftofix(x) >= y.v); } +inline int operator >= (const fix x, const double y) { return (x.v >= ftofix(y)); } +inline int operator >= (const double x, const fix y) { return (ftofix(x) >= y.v); } + +inline fix sqrt(fix x) { fix t; t.v = fixsqrt(x.v); return t; } +inline fix cos(fix x) { fix t; t.v = fixcos(x.v); return t; } +inline fix sin(fix x) { fix t; t.v = fixsin(x.v); return t; } +inline fix tan(fix x) { fix t; t.v = fixtan(x.v); return t; } +inline fix acos(fix x) { fix t; t.v = fixacos(x.v); return t; } +inline fix asin(fix x) { fix t; t.v = fixasin(x.v); return t; } +inline fix atan(fix x) { fix t; t.v = fixatan(x.v); return t; } +inline fix atan2(fix x, fix y) { fix t; t.v = fixatan2(x.v, y.v); return t; } + + +inline void get_translation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_translation_matrix(m, x.v, y.v, z.v); +} + + +inline void get_scaling_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_scaling_matrix(m, x.v, y.v, z.v); +} + + +inline void get_x_rotate_matrix(MATRIX *m, fix r) +{ + get_x_rotate_matrix(m, r.v); +} + + +inline void get_y_rotate_matrix(MATRIX *m, fix r) +{ + get_y_rotate_matrix(m, r.v); +} + + +inline void get_z_rotate_matrix(MATRIX *m, fix r) +{ + get_z_rotate_matrix(m, r.v); +} + + +inline void get_rotation_matrix(MATRIX *m, fix x, fix y, fix z) +{ + get_rotation_matrix(m, x.v, y.v, z.v); +} + + +inline void get_align_matrix(MATRIX *m, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup) +{ + get_align_matrix(m, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v); +} + + +inline void get_vector_rotation_matrix(MATRIX *m, fix x, fix y, fix z, fix a) +{ + get_vector_rotation_matrix(m, x.v, y.v, z.v, a.v); +} + + +inline void get_transformation_matrix(MATRIX *m, fix scale, fix xrot, fix yrot, fix zrot, fix x, fix y, fix z) +{ + get_transformation_matrix(m, scale.v, xrot.v, yrot.v, zrot.v, x.v, y.v, z.v); +} + + +inline void get_camera_matrix(MATRIX *m, fix x, fix y, fix z, fix xfront, fix yfront, fix zfront, fix xup, fix yup, fix zup, fix fov, fix aspect) +{ + get_camera_matrix(m, x.v, y.v, z.v, xfront.v, yfront.v, zfront.v, xup.v, yup.v, zup.v, fov.v, aspect.v); +} + + +inline void qtranslate_matrix(MATRIX *m, fix x, fix y, fix z) +{ + qtranslate_matrix(m, x.v, y.v, z.v); +} + + +inline void qscale_matrix(MATRIX *m, fix scale) +{ + qscale_matrix(m, scale.v); +} + + +inline fix vector_length(fix x, fix y, fix z) +{ + fix t; + t.v = vector_length(x.v, y.v, z.v); + return t; +} + + +inline void normalize_vector(fix *x, fix *y, fix *z) +{ + normalize_vector(&x->v, &y->v, &z->v); +} + + +inline void cross_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2, fix *xout, fix *yout, fix *zout) +{ + cross_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v, &xout->v, &yout->v, &zout->v); +} + + +inline fix dot_product(fix x1, fix y_1, fix z1, fix x2, fix y2, fix z2) +{ + fix t; + t.v = dot_product(x1.v, y_1.v, z1.v, x2.v, y2.v, z2.v); + return t; +} + + +inline void apply_matrix(MATRIX *m, fix x, fix y, fix z, fix *xout, fix *yout, fix *zout) +{ + apply_matrix(m, x.v, y.v, z.v, &xout->v, &yout->v, &zout->v); +} + + +inline void persp_project(fix x, fix y, fix z, fix *xout, fix *yout) +{ + persp_project(x.v, y.v, z.v, &xout->v, &yout->v); +} + + +#endif /* ifdef __cplusplus */ + +#endif /* ifndef ALLEGRO_FIX_INL */ + + diff --git a/allegro/allegro/inline/fmaths.inl b/allegro/allegro/inline/fmaths.inl new file mode 100644 index 0000000000..cf679601c7 --- /dev/null +++ b/allegro/allegro/inline/fmaths.inl @@ -0,0 +1,238 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Fixed point math inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FMATHS_INL +#define ALLEGRO_FMATHS_INL + +#define ALLEGRO_IMPORT_MATH_ASM +#include "asm.inl" +#undef ALLEGRO_IMPORT_MATH_ASM + +#ifdef __cplusplus + extern "C" { +#endif + + +/* ftofix and fixtof are used in generic C versions of fixmul and fixdiv */ +AL_INLINE(fixed, ftofix, (double x), +{ + if (x > 32767.0) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + + if (x < -32767.0) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + + return (fixed)(x * 65536.0 + (x < 0 ? -0.5 : 0.5)); +}) + + +AL_INLINE(double, fixtof, (fixed x), +{ + return (double)x / 65536.0; +}) + + +#ifdef ALLEGRO_NO_ASM + +/* use generic C versions */ + +AL_INLINE(fixed, fixadd, (fixed x, fixed y), +{ + fixed result = x + y; + + if (result >= 0) { + if ((x < 0) && (y < 0)) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + else + return result; + } + else { + if ((x > 0) && (y > 0)) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else + return result; + } +}) + + +AL_INLINE(fixed, fixsub, (fixed x, fixed y), +{ + fixed result = x - y; + + if (result >= 0) { + if ((x < 0) && (y > 0)) { + *allegro_errno = ERANGE; + return -0x7FFFFFFF; + } + else + return result; + } + else { + if ((x > 0) && (y < 0)) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else + return result; + } +}) + + +/* In benchmarks conducted circa May 2005 we found that, in the main: + * - IA32 machines performed faster with one implementation; + * - AMD64 and G4 machines performed faster with another implementation. + * + * Benchmarks were mainly done with differing versions of gcc. + * Results varied with other compilers, optimisation levels, etc. + * so this is not optimal, though a tenable compromise. + * + * Note that the following implementation are NOT what were benchmarked. + * We had forgotten to put in overflow detection in those versions. + * If you don't need overflow detection then previous versions in the + * CVS tree might be worth looking at. + * + * PS. Don't move the #ifs inside the AL_INLINE; BCC doesn't like it. + */ +#if (defined ALLEGRO_I386) || (!defined LONG_LONG) + AL_INLINE(fixed, fixmul, (fixed x, fixed y), + { + return ftofix(fixtof(x) * fixtof(y)); + }) +#else + AL_INLINE(fixed, fixmul, (fixed x, fixed y), + { + LONG_LONG lx = x; + LONG_LONG ly = y; + LONG_LONG lres = (lx*ly); + + if (lres > 0x7FFFFFFF0000LL) { + *allegro_errno = ERANGE; + return 0x7FFFFFFF; + } + else if (lres < -0x7FFFFFFF0000LL) { + *allegro_errno = ERANGE; + return 0x80000000; + } + else { + int res = lres >> 16; + return res; + } + }) +#endif /* fixmul() C implementations */ + + +AL_INLINE(fixed, fixdiv, (fixed x, fixed y), +{ + if (y == 0) { + *allegro_errno = ERANGE; + return (x < 0) ? -0x7FFFFFFF : 0x7FFFFFFF; + } + else + return ftofix(fixtof(x) / fixtof(y)); +}) + + +AL_INLINE(int, fixfloor, (fixed x), +{ + /* (x >> 16) is not portable */ + if (x >= 0) + return (x >> 16); + else + return ~((~x) >> 16); +}) + + +AL_INLINE(int, fixceil, (fixed x), +{ + if (x > 0x7FFF0000) { + *allegro_errno = ERANGE; + return 0x7FFF; + } + + return fixfloor(x + 0xFFFF); +}) + +#endif /* C vs. inline asm */ + + +AL_INLINE(fixed, itofix, (int x), +{ + return x << 16; +}) + + +AL_INLINE(int, fixtoi, (fixed x), +{ + return fixfloor(x) + ((x & 0x8000) >> 15); +}) + + +AL_INLINE(fixed, fixcos, (fixed x), +{ + return _cos_tbl[((x + 0x4000) >> 15) & 0x1FF]; +}) + + +AL_INLINE(fixed, fixsin, (fixed x), +{ + return _cos_tbl[((x - 0x400000 + 0x4000) >> 15) & 0x1FF]; +}) + + +AL_INLINE(fixed, fixtan, (fixed x), +{ + return _tan_tbl[((x + 0x4000) >> 15) & 0xFF]; +}) + + +AL_INLINE(fixed, fixacos, (fixed x), +{ + if ((x < -65536) || (x > 65536)) { + *allegro_errno = EDOM; + return 0; + } + + return _acos_tbl[(x+65536+127)>>8]; +}) + + +AL_INLINE(fixed, fixasin, (fixed x), +{ + if ((x < -65536) || (x > 65536)) { + *allegro_errno = EDOM; + return 0; + } + + return 0x00400000 - _acos_tbl[(x+65536+127)>>8]; +}) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FMATHS_INL */ + + diff --git a/allegro/allegro/inline/gfx.inl b/allegro/allegro/inline/gfx.inl new file mode 100644 index 0000000000..5fefbc449e --- /dev/null +++ b/allegro/allegro/inline/gfx.inl @@ -0,0 +1,284 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Graphics inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_GFX_INL +#define ALLEGRO_GFX_INL + +#include "allegro/debug.h" + +#define ALLEGRO_IMPORT_GFX_ASM +#include "asm.inl" +#undef ALLEGRO_IMPORT_GFX_ASM + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef ALLEGRO_NO_ASM + + /* use generic C versions */ + +AL_INLINE(int, _default_ds, (void), +{ + return 0; +}) + +#ifdef ALLEGRO_BCC32 + + /* BCC32 is a somewhat unusual platform because it mixes a MSVC/MinGW generated DLL + * (for which ALLEGRO_NO_ASM is not defined) with Borland C++ compiled programs for + * which ALLEGRO_NO_ASM is defined. As a result, Borland C++ compiled programs can't + * use the inlined version of bmp_write_line(), bmp_read_line() and bmp_unwrite_line() + * because the write_bank() and read_bank() methods of the BITMAP class don't expect + * the same calling convention on both sides. + */ + +AL_FUNC(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne)); +AL_FUNC(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne)); +AL_FUNC(void, bmp_unwrite_line, (BITMAP *bmp)); + +#else + +typedef AL_METHOD(uintptr_t, _BMP_BANK_SWITCHER, (BITMAP *bmp, int lyne)); +typedef AL_METHOD(void, _BMP_UNBANK_SWITCHER, (BITMAP *bmp)); + + +AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne), +{ + _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->write_bank; + return switcher(bmp, lyne); +}) + + +AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne), +{ + _BMP_BANK_SWITCHER switcher = (_BMP_BANK_SWITCHER)bmp->read_bank; + return switcher(bmp, lyne); +}) + + +AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp), +{ + _BMP_UNBANK_SWITCHER switcher = (_BMP_UNBANK_SWITCHER)bmp->vtable->unwrite_bank; + switcher(bmp); +}) + +#endif /* defined ALLEGRO_BCC32 */ + +#endif /* C vs. inline asm */ + + +AL_INLINE(int, is_windowed_mode, (void), +{ + ASSERT (gfx_driver); + + return gfx_driver->windowed; +}) + + + +AL_INLINE(void, clear_to_color, (BITMAP *bitmap, int color), +{ + ASSERT(bitmap); + + bitmap->vtable->clear_to_color(bitmap, color); +}) + + +AL_INLINE(int, bitmap_color_depth, (BITMAP *bmp), +{ + ASSERT(bmp); + + return bmp->vtable->color_depth; +}) + + +AL_INLINE(int, bitmap_mask_color, (BITMAP *bmp), +{ + ASSERT(bmp); + + return bmp->vtable->mask_color; +}) + + +AL_INLINE(int, is_same_bitmap, (BITMAP *bmp1, BITMAP *bmp2), +{ + unsigned long m1; + unsigned long m2; + + if ((!bmp1) || (!bmp2)) + return FALSE; + + if (bmp1 == bmp2) + return TRUE; + + m1 = bmp1->id & BMP_ID_MASK; + m2 = bmp2->id & BMP_ID_MASK; + + return ((m1) && (m1 == m2)); +}) + + +AL_INLINE(int, is_linear_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_PLANAR) == 0; +}) + + +AL_INLINE(int, is_planar_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_PLANAR) != 0; +}) + + +AL_INLINE(int, is_memory_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & (BMP_ID_VIDEO | BMP_ID_SYSTEM)) == 0; +}) + + +AL_INLINE(int, is_screen_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return is_same_bitmap(bmp, screen); +}) + + +AL_INLINE(int, is_video_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_VIDEO) != 0; +}) + + +AL_INLINE(int, is_system_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_SYSTEM) != 0; +}) + + +AL_INLINE(int, is_sub_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + return (bmp->id & BMP_ID_SUB) != 0; +}) + + +#ifdef ALLEGRO_MPW + + #define acquire_bitmap(bmp) + #define release_bitmap(bmp) + #define acquire_screen() + #define release_screen() + +#else + +AL_INLINE(void, acquire_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + if (bmp->vtable->acquire) + bmp->vtable->acquire(bmp); +}) + + +AL_INLINE(void, release_bitmap, (BITMAP *bmp), +{ + ASSERT(bmp); + + if (bmp->vtable->release) + bmp->vtable->release(bmp); +}) + + +AL_INLINE(void, acquire_screen, (void), +{ + acquire_bitmap(screen); +}) + + +AL_INLINE(void, release_screen, (void), +{ + release_bitmap(screen); +}) + +#endif + + +AL_INLINE(int, is_inside_bitmap, (BITMAP *bmp, int x, int y, int clip), +{ + ASSERT(bmp); + + if (clip) { + if (bmp->clip) + /* internal clipping is inclusive-exclusive */ + return (x >= bmp->cl) && (y >= bmp->ct) && (x < bmp->cr) && (y < bmp->cb); + else + return TRUE; + } + else + /* bitmap dimensions are always non-negative */ + return (unsigned int)x < (unsigned int)bmp->w && (unsigned int)y < (unsigned int)bmp->h; +}) + + +AL_INLINE(void, get_clip_rect, (BITMAP *bitmap, int *x1, int *y_1, int *x2, int *y2), +{ + ASSERT(bitmap); + + /* internal clipping is inclusive-exclusive */ + *x1 = bitmap->cl; + *y_1 = bitmap->ct; + *x2 = bitmap->cr-1; + *y2 = bitmap->cb-1; +}) + +AL_INLINE(void, set_clip_state, (BITMAP *bitmap, int state), +{ + ASSERT(bitmap); + + bitmap->clip = state; +}) + +AL_INLINE(int, get_clip_state, (BITMAP *bitmap), +{ + ASSERT(bitmap); + + return bitmap->clip; +}) + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_GFX_INL */ + + diff --git a/allegro/allegro/inline/matrix.inl b/allegro/allegro/inline/matrix.inl new file mode 100644 index 0000000000..3dbdecfd82 --- /dev/null +++ b/allegro/allegro/inline/matrix.inl @@ -0,0 +1,48 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Matrix math inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_MATRIX_INL +#define ALLEGRO_MATRIX_INL + +#ifdef __cplusplus + extern "C" { +#endif + + +#define CALC_ROW(n) (fixmul(x, m->v[n][0]) + \ + fixmul(y, m->v[n][1]) + \ + fixmul(z, m->v[n][2]) + \ + m->t[n]) + +AL_INLINE(void, apply_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed *xout, fixed *yout, fixed *zout), +{ + *xout = CALC_ROW(0); + *yout = CALC_ROW(1); + *zout = CALC_ROW(2); +}) + +#undef CALC_ROW + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_MATRIX_INL */ + + diff --git a/allegro/allegro/inline/rle.inl b/allegro/allegro/inline/rle.inl new file mode 100644 index 0000000000..52730db46f --- /dev/null +++ b/allegro/allegro/inline/rle.inl @@ -0,0 +1,70 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * RLE sprite inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_RLE_INL +#define ALLEGRO_RLE_INL + +#include "allegro/debug.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +AL_INLINE(void, draw_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->color_depth); + + bmp->vtable->draw_rle_sprite(bmp, sprite, x, y); +}) + + +AL_INLINE(void, draw_trans_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y), +{ + ASSERT(bmp); + ASSERT(sprite); + + if (sprite->color_depth == 32) { + ASSERT(bmp->vtable->draw_trans_rgba_rle_sprite); + bmp->vtable->draw_trans_rgba_rle_sprite(bmp, sprite, x, y); + } + else { + ASSERT(bmp->vtable->color_depth == sprite->color_depth); + bmp->vtable->draw_trans_rle_sprite(bmp, sprite, x, y); + } +}) + + +AL_INLINE(void, draw_lit_rle_sprite, (struct BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color), +{ + ASSERT(bmp); + ASSERT(sprite); + ASSERT(bmp->vtable->color_depth == sprite->color_depth); + + bmp->vtable->draw_lit_rle_sprite(bmp, sprite, x, y, color); +}) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_RLE_INL */ + + diff --git a/allegro/allegro/inline/system.inl b/allegro/allegro/inline/system.inl new file mode 100644 index 0000000000..0fa7a79163 --- /dev/null +++ b/allegro/allegro/inline/system.inl @@ -0,0 +1,67 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * System inline functions (generic C). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_SYSTEM_INL +#define ALLEGRO_SYSTEM_INL + +#include "allegro/debug.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +AL_INLINE(void, set_window_title, (AL_CONST char *name), +{ + ASSERT(system_driver); + + if (system_driver->set_window_title) + system_driver->set_window_title(name); +}) + + +AL_INLINE(int, desktop_color_depth, (void), +{ + ASSERT(system_driver); + + if (system_driver->desktop_color_depth) + return system_driver->desktop_color_depth(); + else + return 0; +}) + + +AL_INLINE(int, get_desktop_resolution, (int *width, int *height), +{ + ASSERT(system_driver); + + if (system_driver->get_desktop_resolution) + return system_driver->get_desktop_resolution(width, height); + else + return -1; +}) + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_SYSTEM_INL */ + + diff --git a/allegro/allegro/internal/aintern.h b/allegro/allegro/internal/aintern.h new file mode 100644 index 0000000000..f8ef9f2141 --- /dev/null +++ b/allegro/allegro/internal/aintern.h @@ -0,0 +1,1260 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTERN_H +#define AINTERN_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* length in bytes of the cpu_vendor string */ +#define _AL_CPU_VENDOR_SIZE 32 + + +/* flag for how many times we have been initialised */ +AL_VAR(int, _allegro_count); + + +/* flag to know whether we are being called by the exit mechanism */ +AL_VAR(int, _allegro_in_exit); + + +/* These functions are referenced by 4.2.0 binaries, but should no longer be + * used by newer versions directly. + * _get_allegro_version would be marked deprecated except that misc/fixdll.* + * would complain about it being missing. + */ +AL_FUNC(int, _get_allegro_version, (void)); +AL_FUNC(int, _install_allegro, (int system_id, int *errno_ptr, AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))))); + + +/* flag to decide whether to disable the screensaver */ +enum { + NEVER_DISABLED, + FULLSCREEN_DISABLED, + ALWAYS_DISABLED +}; + +AL_VAR(int, _screensaver_policy); + + +AL_FUNCPTR(int, _al_trace_handler, (AL_CONST char *msg)); + + +/* malloc wrappers */ +/* The 4.3 branch uses the following macro names to allow the user to customise + * the memory management routines. We don't have that feature in 4.2, but we + * use the same macros names in order to reduce divergence of the codebases. + */ +#define _AL_MALLOC(SIZE) (_al_malloc(SIZE)) +#define _AL_MALLOC_ATOMIC(SIZE) (_al_malloc(SIZE)) +#define _AL_FREE(PTR) (_al_free(PTR)) +#define _AL_REALLOC(PTR, SIZE) (_al_realloc(PTR, SIZE)) + +AL_FUNC(void *, _al_malloc, (size_t size)); +AL_FUNC(void, _al_free, (void *mem)); +AL_FUNC(void *, _al_realloc, (void *mem, size_t size)); + + + +/* some Allegro functions need a block of scratch memory */ +AL_VAR(void *, _scratch_mem); +AL_VAR(int, _scratch_mem_size); + + +AL_INLINE(void, _grow_scratch_mem, (int size), +{ + if (size > _scratch_mem_size) { + size = (size+1023) & 0xFFFFFC00; + _scratch_mem = _AL_REALLOC(_scratch_mem, size); + _scratch_mem_size = size; + } +}) + + +/* list of functions to call at program cleanup */ +AL_FUNC(void, _add_exit_func, (AL_METHOD(void, func, (void)), AL_CONST char *desc)); +AL_FUNC(void, _remove_exit_func, (AL_METHOD(void, func, (void)))); + + +/* helper structure for talking to Unicode strings */ +typedef struct UTYPE_INFO +{ + int id; + AL_METHOD(int, u_getc, (AL_CONST char *s)); + AL_METHOD(int, u_getx, (char **s)); + AL_METHOD(int, u_setc, (char *s, int c)); + AL_METHOD(int, u_width, (AL_CONST char *s)); + AL_METHOD(int, u_cwidth, (int c)); + AL_METHOD(int, u_isok, (int c)); + int u_width_max; +} UTYPE_INFO; + +AL_FUNC(UTYPE_INFO *, _find_utype, (int type)); + + +/* message stuff */ +#define ALLEGRO_MESSAGE_SIZE 4096 + + +/* wrappers for implementing disk I/O on different platforms */ +AL_FUNC(int, _al_file_isok, (AL_CONST char *filename)); +AL_FUNC(uint64_t, _al_file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, _al_file_time, (AL_CONST char *filename)); +AL_FUNC(int, _al_drive_exists, (int drive)); +AL_FUNC(int, _al_getdrive, (void)); +AL_FUNC(void, _al_getdcwd, (int drive, char *buf, int size)); + +/* obsolete; only exists for binary compatibility with 4.2.0 */ +AL_FUNC(long, _al_file_size, (AL_CONST char *filename)); + + +/* packfile stuff */ +AL_VAR(int, _packfile_filesize); +AL_VAR(int, _packfile_datasize); +AL_VAR(int, _packfile_type); +AL_FUNC(PACKFILE *, _pack_fdopen, (int fd, AL_CONST char *mode, AL_CONST char *password)); + +AL_FUNC(int, _al_lzss_incomplete_state, (AL_CONST LZSS_UNPACK_DATA *dat)); + + +/* config stuff */ +void _reload_config(void); + + +/* various bits of mouse stuff */ +AL_FUNC(void, _handle_mouse_input, (void)); + +AL_VAR(int, _mouse_x); +AL_VAR(int, _mouse_y); +AL_VAR(int, _mouse_z); +AL_VAR(int, _mouse_w); +AL_VAR(int, _mouse_b); +AL_VAR(int, _mouse_on); + +AL_VAR(int, _mouse_installed); + +AL_VAR(int, _mouse_type); +AL_VAR(BITMAP *, _mouse_screen); +AL_VAR(BITMAP *, _mouse_pointer); + + +/* various bits of timer stuff */ +AL_FUNC(long, _handle_timer_tick, (int interval)); + +#define MAX_TIMERS 16 + +/* list of active timer handlers */ +typedef struct TIMER_QUEUE +{ + AL_METHOD(void, proc, (void)); /* timer handler functions */ + AL_METHOD(void, param_proc, (void *param)); + void *param; /* param for param_proc if used */ + long speed; /* timer speed */ + long counter; /* counts down to zero=blastoff */ +} TIMER_QUEUE; + +AL_ARRAY(TIMER_QUEUE, _timer_queue); + +AL_VAR(int, _timer_installed); + +AL_VAR(int, _timer_use_retrace); +AL_VAR(volatile int, _retrace_hpp_value); + +AL_VAR(long, _vsync_speed); + + +/* various bits of keyboard stuff */ +AL_FUNC(void, _handle_key_press, (int keycode, int scancode)); +AL_FUNC(void, _handle_key_release, (int scancode)); + +AL_VAR(int, _keyboard_installed); +AL_ARRAY(AL_CONST char *, _keyboard_common_names); +AL_ARRAY(volatile char, _key); +AL_VAR(volatile int, _key_shifts); + + +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_DJGPP) || (defined ALLEGRO_WATCOM) || \ + (defined ALLEGRO_QNX) || (defined ALLEGRO_BEOS) + +AL_ARRAY(char *, _pckeys_names); + +AL_FUNC(void, _pckeys_init, (void)); +AL_FUNC(void, _handle_pckey, (int code)); +AL_FUNC(int, _pckey_scancode_to_ascii, (int scancode)); +AL_FUNC(AL_CONST char *, _pckey_scancode_to_name, (int scancode)); + +AL_VAR(unsigned short *, _key_ascii_table); +AL_VAR(unsigned short *, _key_capslock_table); +AL_VAR(unsigned short *, _key_shift_table); +AL_VAR(unsigned short *, _key_control_table); +AL_VAR(unsigned short *, _key_altgr_lower_table); +AL_VAR(unsigned short *, _key_altgr_upper_table); +AL_VAR(unsigned short *, _key_accent1_lower_table); +AL_VAR(unsigned short *, _key_accent1_upper_table); +AL_VAR(unsigned short *, _key_accent2_lower_table); +AL_VAR(unsigned short *, _key_accent2_upper_table); +AL_VAR(unsigned short *, _key_accent3_lower_table); +AL_VAR(unsigned short *, _key_accent3_upper_table); +AL_VAR(unsigned short *, _key_accent4_lower_table); +AL_VAR(unsigned short *, _key_accent4_upper_table); + +AL_VAR(int, _key_accent1); +AL_VAR(int, _key_accent2); +AL_VAR(int, _key_accent3); +AL_VAR(int, _key_accent4); +AL_VAR(int, _key_accent1_flag); +AL_VAR(int, _key_accent2_flag); +AL_VAR(int, _key_accent3_flag); +AL_VAR(int, _key_accent4_flag); + +AL_VAR(int, _key_standard_kb); + +AL_VAR(char *, _keyboard_layout); + +#endif + +#if (defined ALLEGRO_WINDOWS) + + AL_FUNC(int, _al_win_open, (const char *filename, int mode, int perm)); + AL_FUNC(int, _al_win_unlink, (const char *filename)); + + + #define _al_open(filename, mode, perm) _al_win_open(filename, mode, perm) + #define _al_unlink(filename) _al_win_unlink(filename) + +#else + + #define _al_open(filename, mode, perm) open(filename, mode, perm) + #define _al_unlink(filename) unlink(filename) + +#endif + + +/* various bits of joystick stuff */ +AL_VAR(int, _joy_type); + +AL_VAR(int, _joystick_installed); + + +/* some GUI innards that other people need to use */ +AL_FUNC(int, _gui_shadow_box_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_ctext_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_button_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_edit_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_list_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_text_list_proc, (int msg, DIALOG *d, int c)); + +AL_FUNC(void, _handle_scrollable_scroll_click, (DIALOG *d, int listsize, int *offset, int height)); +AL_FUNC(void, _handle_scrollable_scroll, (DIALOG *d, int listsize, int *idx, int *offset)); +AL_FUNC(void, _handle_listbox_click, (DIALOG *d)); +AL_FUNC(void, _draw_scrollable_frame, (DIALOG *d, int listsize, int offset, int height, int fg_color, int bg)); +AL_FUNC(void, _draw_listbox, (DIALOG *d)); +AL_FUNC(void, _draw_textbox, (char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, int disabled, int fore, int deselect, int disable)); + + +/* text- and font-related stuff */ +typedef struct FONT_VTABLE +{ + AL_METHOD(int, font_height, (AL_CONST FONT *f)); + AL_METHOD(int, char_length, (AL_CONST FONT *f, int ch)); + AL_METHOD(int, text_length, (AL_CONST FONT *f, AL_CONST char *text)); + AL_METHOD(int, render_char, (AL_CONST FONT *f, int ch, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, render, (AL_CONST FONT *f, AL_CONST char *text, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, destroy, (FONT *f)); + + AL_METHOD(int, get_font_ranges, (FONT *f)); + AL_METHOD(int, get_font_range_begin, (FONT *f, int range)); + AL_METHOD(int, get_font_range_end, (FONT *f, int range)); + AL_METHOD(FONT *, extract_font_range, (FONT *f, int begin, int end)); + AL_METHOD(FONT *, merge_fonts, (FONT *f1, FONT *f2)); + AL_METHOD(int, transpose_font, (FONT *f, int drange)); +} FONT_VTABLE; + +AL_VAR(FONT_VTABLE, _font_vtable_mono); +AL_VAR(FONT_VTABLE *, font_vtable_mono); +AL_VAR(FONT_VTABLE, _font_vtable_color); +AL_VAR(FONT_VTABLE *, font_vtable_color); +AL_VAR(FONT_VTABLE, _font_vtable_trans); +AL_VAR(FONT_VTABLE *, font_vtable_trans); + +AL_FUNC(FONT_GLYPH *, _mono_find_glyph, (AL_CONST FONT *f, int ch)); +AL_FUNC(BITMAP *, _color_find_glyph, (AL_CONST FONT *f, int ch)); + +typedef struct FONT_MONO_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + FONT_GLYPH **glyphs; /* our glyphs */ + struct FONT_MONO_DATA *next; /* linked list structure */ +} FONT_MONO_DATA; + +typedef struct FONT_COLOR_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + BITMAP **bitmaps; /* our glyphs */ + struct FONT_COLOR_DATA *next; /* linked list structure */ +} FONT_COLOR_DATA; + + +/* caches and tables for svga bank switching */ +AL_VAR(int, _last_bank_1); +AL_VAR(int, _last_bank_2); + +AL_VAR(int *, _gfx_bank); + +/* bank switching routines (these use a non-C calling convention on i386!) */ +AL_FUNC(uintptr_t, _stub_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _stub_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _stub_bank_switch_end, (void)); + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(uintptr_t, _x_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _x_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _x_bank_switch_end, (void)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VBEAF + +AL_FUNC(void, _accel_bank_stub, (void)); +AL_FUNC(void, _accel_bank_stub_end, (void)); +AL_FUNC(void, _accel_bank_switch, (void)); +AL_FUNC(void, _accel_bank_switch_end, (void)); + +AL_VAR(void *, _accel_driver); + +AL_VAR(int, _accel_active); + +AL_VAR(void *, _accel_set_bank); +AL_VAR(void *, _accel_idle); + +AL_FUNC(void, _fill_vbeaf_libc_exports, (void *ptr)); +AL_FUNC(void, _fill_vbeaf_pmode_exports, (void *ptr)); + +#endif + + +/* stuff for setting up bitmaps */ +AL_FUNC(BITMAP *, _make_bitmap, (int w, int h, uintptr_t addr, GFX_DRIVER *driver, int color_depth, int bpl)); +AL_FUNC(void, _sort_out_virtual_width, (int *width, GFX_DRIVER *driver)); + +AL_FUNC(GFX_VTABLE *, _get_vtable, (int color_depth)); + +AL_VAR(GFX_VTABLE, _screen_vtable); + +AL_VAR(int, _gfx_mode_set_count); + +AL_VAR(int, _refresh_rate_request); +AL_FUNC(void, _set_current_refresh_rate, (int rate)); + +AL_VAR(int, _wait_for_vsync); + +AL_VAR(int, _sub_bitmap_id_count); + +AL_VAR(int, _screen_split_position); + +AL_VAR(int, _safe_gfx_mode_change); + +#ifdef ALLEGRO_I386 + #define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) +#else + #ifdef ALLEGRO_MPW + /* in Mac 24 bit is a unsigned long */ + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : 4)) + #else + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : (((bpp) <= 24) ? 3 : 4))) + #endif +#endif + +AL_FUNC(int, _color_load_depth, (int depth, int hasalpha)); + +AL_VAR(int, _color_conv); + +AL_FUNC(BITMAP *, _fixup_loaded_bitmap, (BITMAP *bmp, PALETTE pal, int bpp)); + +AL_FUNC(int, _bitmap_has_alpha, (BITMAP *bmp)); + +/* default truecolor pixel format */ +#define DEFAULT_RGB_R_SHIFT_15 0 +#define DEFAULT_RGB_G_SHIFT_15 5 +#define DEFAULT_RGB_B_SHIFT_15 10 +#define DEFAULT_RGB_R_SHIFT_16 0 +#define DEFAULT_RGB_G_SHIFT_16 5 +#define DEFAULT_RGB_B_SHIFT_16 11 +#define DEFAULT_RGB_R_SHIFT_24 0 +#define DEFAULT_RGB_G_SHIFT_24 8 +#define DEFAULT_RGB_B_SHIFT_24 16 +#define DEFAULT_RGB_R_SHIFT_32 0 +#define DEFAULT_RGB_G_SHIFT_32 8 +#define DEFAULT_RGB_B_SHIFT_32 16 +#define DEFAULT_RGB_A_SHIFT_32 24 + + +/* display switching support */ +AL_FUNC(void, _switch_in, (void)); +AL_FUNC(void, _switch_out, (void)); + +AL_FUNC(void, _register_switch_bitmap, (BITMAP *bmp, BITMAP *parent)); +AL_FUNC(void, _unregister_switch_bitmap, (BITMAP *bmp)); +AL_FUNC(void, _save_switch_state, (int switch_mode)); +AL_FUNC(void, _restore_switch_state, (void)); + +AL_VAR(int, _dispsw_status); + + +/* current drawing mode */ +AL_VAR(int, _drawing_mode); +AL_VAR(BITMAP *, _drawing_pattern); +AL_VAR(int, _drawing_x_anchor); +AL_VAR(int, _drawing_y_anchor); +AL_VAR(unsigned int, _drawing_x_mask); +AL_VAR(unsigned int, _drawing_y_mask); + +AL_FUNCPTR(int *, _palette_expansion_table, (int bpp)); + +AL_VAR(int, _color_depth); + +AL_VAR(int, _current_palette_changed); +AL_VAR(PALETTE, _prev_current_palette); +AL_VAR(int, _got_prev_current_palette); + +AL_ARRAY(int, _palette_color8); +AL_ARRAY(int, _palette_color15); +AL_ARRAY(int, _palette_color16); +AL_ARRAY(int, _palette_color24); +AL_ARRAY(int, _palette_color32); + +/* truecolor blending functions */ +AL_VAR(BLENDER_FUNC, _blender_func15); +AL_VAR(BLENDER_FUNC, _blender_func16); +AL_VAR(BLENDER_FUNC, _blender_func24); +AL_VAR(BLENDER_FUNC, _blender_func32); + +AL_VAR(BLENDER_FUNC, _blender_func15x); +AL_VAR(BLENDER_FUNC, _blender_func16x); +AL_VAR(BLENDER_FUNC, _blender_func24x); + +AL_VAR(int, _blender_col_15); +AL_VAR(int, _blender_col_16); +AL_VAR(int, _blender_col_24); +AL_VAR(int, _blender_col_32); + +AL_VAR(int, _blender_alpha); + +AL_FUNC(unsigned long, _blender_black, (unsigned long x, unsigned long y, unsigned long n)); + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(unsigned long, _blender_trans15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen15, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_trans16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen16, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + +AL_FUNC(unsigned long, _blender_trans24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen24, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +AL_FUNC(unsigned long, _blender_alpha15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha32, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_write_alpha, (unsigned long x, unsigned long y, unsigned long n)); + + +/* graphics drawing routines */ +AL_FUNC(void, _normal_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _fast_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _normal_rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(int, _linear_getpixel8, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel8, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline8, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline8, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph8, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color8, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _linear_putpixel15, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline15, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline15, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_trans_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + +AL_FUNC(int, _linear_getpixel16, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel16, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline16, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline16, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph16, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color16, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(int, _linear_getpixel24, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel24, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline24, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline24, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph24, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color24, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(int, _linear_getpixel32, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel32, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline32, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline32, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph32, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color32, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(int, _x_getpixel, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _x_putpixel, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _x_vline, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _x_hline, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _x_draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _x_draw_glyph, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _x_blit_from_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_to_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_forward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_backward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_masked_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_clear_to_color, (BITMAP *bitmap, int color)); + +#endif + + +/* color conversion routines */ +typedef struct GRAPHICS_RECT { + int width; + int height; + int pitch; + void *data; +} GRAPHICS_RECT; + +typedef void (COLORCONV_BLITTER_FUNC)(GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect); + +AL_FUNC(COLORCONV_BLITTER_FUNC *, _get_colorconv_blitter, (int from_depth, int to_depth)); +AL_FUNC(void, _release_colorconv_blitter, (COLORCONV_BLITTER_FUNC *blitter)); +AL_FUNC(void, _set_colorconv_palette, (AL_CONST struct RGB *p, int from, int to)); +AL_FUNC(unsigned char *, _get_colorconv_map, (void)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _colorconv_blit_8_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _colorconv_blit_15_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +AL_FUNC(void, _colorconv_blit_16_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _colorconv_blit_24_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _colorconv_blit_32_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + + +/* color copy routines */ +#ifndef ALLEGRO_NO_COLORCOPY + +#ifdef ALLEGRO_COLOR16 +AL_FUNC(void, _colorcopy_blit_15_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorcopy_blit_16_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR24 +AL_FUNC(void, _colorcopy_blit_24_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR32 +AL_FUNC(void, _colorcopy_blit_32_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#endif + + +/* generic color conversion blitter */ +AL_FUNC(void, _blit_between_formats, (BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)); + + +/* asm helper for stretch_blit() */ +#ifndef SCAN_EXPORT +AL_FUNC(void, _do_stretch, (BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth)); +#endif + + +/* lower level functions for rotation */ +AL_FUNC(void, _parallelogram_map, (BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy)); +AL_FUNC(void, _parallelogram_map_standard, (BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _rotate_scale_flip_coordinates, (fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + + +/* number of fractional bits used by the polygon rasteriser */ +#define POLYGON_FIX_SHIFT 18 + + +/* bitfield specifying which polygon attributes need interpolating */ +#define INTERP_FLAT 1 /* no interpolation */ +#define INTERP_1COL 2 /* gcol or alpha */ +#define INTERP_3COL 4 /* grgb */ +#define INTERP_FIX_UV 8 /* atex */ +#define INTERP_Z 16 /* always in scene3d */ +#define INTERP_FLOAT_UV 32 /* ptex */ +#define OPT_FLOAT_UV_TO_FIX 64 /* translate ptex to atex */ +#define COLOR_TO_RGB 128 /* grgb to gcol for truecolor */ +#define INTERP_ZBUF 256 /* z-buffered */ +#define INTERP_THRU 512 /* any kind of transparent */ +#define INTERP_NOSOLID 1024 /* non-solid modes for 8-bit flat */ +#define INTERP_BLEND 2048 /* lit for truecolor */ +#define INTERP_TRANS 4096 /* trans for truecolor */ + + +/* information for polygon scanline fillers */ +typedef struct POLYGON_SEGMENT +{ + fixed u, v, du, dv; /* fixed point u/v coordinates */ + fixed c, dc; /* single color gouraud shade values */ + fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ + float z, dz; /* polygon depth (1/z) */ + float fu, fv, dfu, dfv; /* floating point u/v coordinates */ + unsigned char *texture; /* the texture map */ + int umask, vmask, vshift; /* texture map size information */ + int seg; /* destination bitmap selector */ + uintptr_t zbuf_addr; /* Z-buffer address */ + uintptr_t read_addr; /* reading address for transparency modes */ +} POLYGON_SEGMENT; + + +/* prototype for the scanline filler functions */ +typedef AL_METHOD(void, SCANLINE_FILLER, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + + +/* an active polygon edge */ +typedef struct POLYGON_EDGE +{ + int top; /* top y position */ + int bottom; /* bottom y position */ + fixed x, dx; /* fixed point x position and gradient */ + fixed w; /* width of line segment */ + POLYGON_SEGMENT dat; /* texture/gouraud information */ + struct POLYGON_EDGE *prev; /* doubly linked list */ + struct POLYGON_EDGE *next; + struct POLYGON_INFO *poly; /* father polygon */ +} POLYGON_EDGE; + + +typedef struct POLYGON_INFO /* a polygon waiting rendering */ +{ + struct POLYGON_INFO *next, *prev;/* double linked list */ + int inside; /* flag for "scanlining" */ + int flags; /* INTERP_* flags */ + int color; /* vtx[0]->c */ + float a, b, c; /* plane's coefficients -a/d, -b/d, -c/d */ + int dmode; /* drawing mode */ + BITMAP *dpat; /* drawing pattern */ + int xanchor, yanchor; /* for dpat */ + int alpha; /* blender alpha */ + int b15, b16, b24, b32; /* blender colors */ + COLOR_MAP *cmap; /* trans color map */ + SCANLINE_FILLER drawer; /* scanline drawing functions */ + SCANLINE_FILLER alt_drawer; + POLYGON_EDGE *left_edge; /* true edges used in interpolation */ + POLYGON_EDGE *right_edge; + POLYGON_SEGMENT info; /* base information for scanline functions */ +} POLYGON_INFO; + + +/* global variable for z-buffer */ +AL_VAR(BITMAP *, _zbuffer); + + +/* polygon helper functions */ +AL_VAR(SCANLINE_FILLER, _optim_alternative_drawer); +AL_FUNC(POLYGON_EDGE *, _add_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)); +AL_FUNC(POLYGON_EDGE *, _remove_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge)); +AL_FUNC(int, _fill_3d_edge_structure, (POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp)); +AL_FUNC(int, _fill_3d_edge_structure_f, (POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp)); +AL_FUNC(SCANLINE_FILLER, _get_scanline_filler, (int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp)); +AL_FUNC(void, _clip_polygon_segment, (POLYGON_SEGMENT *info, fixed gap, int flags)); +AL_FUNC(void, _clip_polygon_segment_f, (POLYGON_SEGMENT *info, int gap, int flags)); + + +/* polygon scanline filler functions */ +AL_FUNC(void, _poly_scanline_dummy, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _poly_scanline_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb8x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _poly_scanline_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _poly_scanline_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _poly_scanline_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + + +/* sound lib stuff */ +AL_VAR(MIDI_DRIVER, _midi_none); +AL_VAR(int, _digi_volume); +AL_VAR(int, _midi_volume); +AL_VAR(int, _sound_flip_pan); +AL_VAR(int, _sound_hq); +AL_VAR(int, _sound_stereo); +AL_VAR(int, _sound_bits); +AL_VAR(int, _sound_freq); +AL_VAR(int, _sound_port); +AL_VAR(int, _sound_dma); +AL_VAR(int, _sound_irq); + +AL_VAR(int, _sound_installed); +AL_VAR(int, _sound_input_installed); + +AL_FUNC(int, _midi_allocate_voice, (int min, int max)); + +AL_VAR(volatile long, _midi_tick); + +AL_FUNC(int, _digmid_find_patches, (char *dir, int dir_size, char *file, int size_of_file)); + +#define VIRTUAL_VOICES 256 + + +typedef struct /* a virtual (as seen by the user) soundcard voice */ +{ + AL_CONST SAMPLE *sample; /* which sample are we playing? (NULL = free) */ + int num; /* physical voice number (-1 = been killed off) */ + int autokill; /* set to free the voice when the sample finishes */ + long time; /* when we were started (for voice allocation) */ + int priority; /* how important are we? */ +} VOICE; + + +typedef struct /* a physical (as used by hardware) soundcard voice */ +{ + int num; /* the virtual voice currently using me (-1 = free) */ + int playmode; /* are we looping? */ + int vol; /* current volume (fixed point .12) */ + int dvol; /* volume delta, for ramping */ + int target_vol; /* target volume, for ramping */ + int pan; /* current pan (fixed point .12) */ + int dpan; /* pan delta, for sweeps */ + int target_pan; /* target pan, for sweeps */ + int freq; /* current frequency (fixed point .12) */ + int dfreq; /* frequency delta, for sweeps */ + int target_freq; /* target frequency, for sweeps */ +} PHYS_VOICE; + +AL_ARRAY(PHYS_VOICE, _phys_voice); + + +#define MIXER_DEF_SFX 8 +#define MIXER_MAX_SFX 64 + +AL_FUNC(int, _mixer_init, (int bufsize, int freq, int stereo, int is16bit, int *voices)); +AL_FUNC(void, _mixer_exit, (void)); +AL_FUNC(void, _mix_some_samples, (uintptr_t buf, unsigned short seg, int issigned)); +AL_FUNC(void, _mixer_init_voice, (int voice, AL_CONST SAMPLE *sample)); +AL_FUNC(void, _mixer_release_voice, (int voice)); +AL_FUNC(void, _mixer_start_voice, (int voice)); +AL_FUNC(void, _mixer_stop_voice, (int voice)); +AL_FUNC(void, _mixer_loop_voice, (int voice, int loopmode)); +AL_FUNC(int, _mixer_get_position, (int voice)); +AL_FUNC(void, _mixer_set_position, (int voice, int position)); +AL_FUNC(int, _mixer_get_volume, (int voice)); +AL_FUNC(void, _mixer_set_volume, (int voice, int volume)); +AL_FUNC(void, _mixer_ramp_volume, (int voice, int tyme, int endvol)); +AL_FUNC(void, _mixer_stop_volume_ramp, (int voice)); +AL_FUNC(int, _mixer_get_frequency, (int voice)); +AL_FUNC(void, _mixer_set_frequency, (int voice, int frequency)); +AL_FUNC(void, _mixer_sweep_frequency, (int voice, int tyme, int endfreq)); +AL_FUNC(void, _mixer_stop_frequency_sweep, (int voice)); +AL_FUNC(int, _mixer_get_pan, (int voice)); +AL_FUNC(void, _mixer_set_pan, (int voice, int pan)); +AL_FUNC(void, _mixer_sweep_pan, (int voice, int tyme, int endpan)); +AL_FUNC(void, _mixer_stop_pan_sweep, (int voice)); +AL_FUNC(void, _mixer_set_echo, (int voice, int strength, int delay)); +AL_FUNC(void, _mixer_set_tremolo, (int voice, int rate, int depth)); +AL_FUNC(void, _mixer_set_vibrato, (int voice, int rate, int depth)); + +AL_FUNC(void, _dummy_noop1, (int p)); +AL_FUNC(void, _dummy_noop2, (int p1, int p2)); +AL_FUNC(void, _dummy_noop3, (int p1, int p2, int p3)); +AL_FUNC(int, _dummy_load_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan)); + + +/* datafile ID's for compatibility with the old datafile format */ +#define V1_DAT_MAGIC 0x616C6C2EL + +#define V1_DAT_DATA 0 +#define V1_DAT_FONT 1 +#define V1_DAT_BITMAP_16 2 +#define V1_DAT_BITMAP_256 3 +#define V1_DAT_SPRITE_16 4 +#define V1_DAT_SPRITE_256 5 +#define V1_DAT_PALETTE_16 6 +#define V1_DAT_PALETTE_256 7 +#define V1_DAT_FONT_8x8 8 +#define V1_DAT_FONT_PROP 9 +#define V1_DAT_BITMAP 10 +#define V1_DAT_PALETTE 11 +#define V1_DAT_SAMPLE 12 +#define V1_DAT_MIDI 13 +#define V1_DAT_RLE_SPRITE 14 +#define V1_DAT_FLI 15 +#define V1_DAT_C_SPRITE 16 +#define V1_DAT_XC_SPRITE 17 + +#define OLD_FONT_SIZE 95 +#define LESS_OLD_FONT_SIZE 224 + + +/* datafile object loading functions */ +AL_FUNC(void, _unload_datafile_object, (DATAFILE *dat)); + + +/* information about a datafile object */ +typedef struct DATAFILE_TYPE +{ + int type; + AL_METHOD(void *, load, (PACKFILE *f, long size)); + AL_METHOD(void, destroy, (void *)); +} DATAFILE_TYPE; + + +#define MAX_DATAFILE_TYPES 32 + +AL_ARRAY(DATAFILE_TYPE, _datafile_type); + +AL_VAR(int, _compile_sprites); + +AL_FUNC(void, _construct_datafile, (DATAFILE *data)); + + +/* for readbmp.c */ +AL_FUNC(void, _register_bitmap_file_type_init, (void)); + +/* for readsmp.c */ +AL_FUNC(void, _register_sample_file_type_init, (void)); + +/* for readfont.c */ +AL_FUNC(void, _register_font_file_type_init, (void)); + + +/* for module linking system; see comment in allegro.c */ +struct _AL_LINKER_MIDI +{ + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); +}; + +AL_VAR(struct _AL_LINKER_MIDI *, _al_linker_midi); + +struct _AL_LINKER_MOUSE +{ + AL_METHOD(void, set_mouse_etc, (void)); + AL_METHOD(void, show_mouse, (BITMAP *)); + BITMAP **mouse_screen_ptr; +}; + +AL_VAR(struct _AL_LINKER_MOUSE *, _al_linker_mouse); + + +/* dynamic driver lists */ +AL_FUNC(_DRIVER_INFO *, _create_driver_list, (void)); +AL_FUNC(void, _destroy_driver_list, (_DRIVER_INFO *drvlist)); +AL_FUNC(void, _driver_list_append_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_prepend_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_append_list, (_DRIVER_INFO **drvlist, _DRIVER_INFO *srclist)); + + +/* various libc stuff */ +AL_FUNC(void *, _al_sane_realloc, (void *ptr, size_t size)); +AL_FUNC(char *, _al_sane_strncpy, (char *dest, const char *src, size_t n)); + + +#define _AL_RAND_MAX 0xFFFF +AL_FUNC(void, _al_srand, (int seed)); +AL_FUNC(int, _al_rand, (void)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef AINTERN_H */ diff --git a/allegro/allegro/internal/aintern.h.old b/allegro/allegro/internal/aintern.h.old new file mode 100644 index 0000000000..30dca5e856 --- /dev/null +++ b/allegro/allegro/internal/aintern.h.old @@ -0,0 +1,1260 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTERN_H +#define AINTERN_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* length in bytes of the cpu_vendor string */ +#define _AL_CPU_VENDOR_SIZE 32 + + +/* flag for how many times we have been initialised */ +AL_VAR(int, _allegro_count); + + +/* flag to know whether we are being called by the exit mechanism */ +AL_VAR(int, _allegro_in_exit); + + +/* These functions are referenced by 4.2.0 binaries, but should no longer be + * used by newer versions directly. + * _get_allegro_version would be marked deprecated except that misc/fixdll.* + * would complain about it being missing. + */ +AL_FUNC(int, _get_allegro_version, (void)); +AL_FUNC(int, _install_allegro, (int system_id, int *errno_ptr, AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))))); + + +/* flag to decide whether to disable the screensaver */ +enum { + NEVER_DISABLED, + FULLSCREEN_DISABLED, + ALWAYS_DISABLED +}; + +AL_VAR(int, _screensaver_policy); + + +AL_FUNCPTR(int, _al_trace_handler, (AL_CONST char *msg)); + + +/* malloc wrappers */ +/* The 4.3 branch uses the following macro names to allow the user to customise + * the memory management routines. We don't have that feature in 4.2, but we + * use the same macros names in order to reduce divergence of the codebases. + */ +#define _AL_MALLOC(SIZE) (_al_malloc(SIZE)) +#define _AL_MALLOC_ATOMIC(SIZE) (_al_malloc(SIZE)) +#define _AL_FREE(PTR) (_al_free(PTR)) +#define _AL_REALLOC(PTR, SIZE) (_al_realloc(PTR, SIZE)) + +AL_FUNC(void *, _al_malloc, (size_t size)); +AL_FUNC(void, _al_free, (void *mem)); +AL_FUNC(void *, _al_realloc, (void *mem, size_t size)); + + + +/* some Allegro functions need a block of scratch memory */ +AL_VAR(void *, _scratch_mem); +AL_VAR(int, _scratch_mem_size); + + +AL_INLINE(void, _grow_scratch_mem, (int size), +{ + if (size > _scratch_mem_size) { + size = (size+1023) & 0xFFFFFC00; + _scratch_mem = _AL_REALLOC(_scratch_mem, size); + _scratch_mem_size = size; + } +}) + + +/* list of functions to call at program cleanup */ +AL_FUNC(void, _add_exit_func, (AL_METHOD(void, func, (void)), AL_CONST char *desc)); +AL_FUNC(void, _remove_exit_func, (AL_METHOD(void, func, (void)))); + + +/* helper structure for talking to Unicode strings */ +typedef struct UTYPE_INFO +{ + int id; + AL_METHOD(int, u_getc, (AL_CONST char *s)); + AL_METHOD(int, u_getx, (char **s)); + AL_METHOD(int, u_setc, (char *s, int c)); + AL_METHOD(int, u_width, (AL_CONST char *s)); + AL_METHOD(int, u_cwidth, (int c)); + AL_METHOD(int, u_isok, (int c)); + int u_width_max; +} UTYPE_INFO; + +AL_FUNC(UTYPE_INFO *, _find_utype, (int type)); + + +/* message stuff */ +#define ALLEGRO_MESSAGE_SIZE 4096 + + +/* wrappers for implementing disk I/O on different platforms */ +AL_FUNC(int, _al_file_isok, (AL_CONST char *filename)); +AL_FUNC(uint64_t, _al_file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, _al_file_time, (AL_CONST char *filename)); +AL_FUNC(int, _al_drive_exists, (int drive)); +AL_FUNC(int, _al_getdrive, (void)); +AL_FUNC(void, _al_getdcwd, (int drive, char *buf, int size)); + +/* obsolete; only exists for binary compatibility with 4.2.0 */ +AL_FUNC(long, _al_file_size, (AL_CONST char *filename)); + + +/* packfile stuff */ +AL_VAR(int, _packfile_filesize); +AL_VAR(int, _packfile_datasize); +AL_VAR(int, _packfile_type); +AL_FUNC(PACKFILE *, _pack_fdopen, (int fd, AL_CONST char *mode)); + +AL_FUNC(int, _al_lzss_incomplete_state, (AL_CONST LZSS_UNPACK_DATA *dat)); + + +/* config stuff */ +void _reload_config(void); + + +/* various bits of mouse stuff */ +AL_FUNC(void, _handle_mouse_input, (void)); + +AL_VAR(int, _mouse_x); +AL_VAR(int, _mouse_y); +AL_VAR(int, _mouse_z); +AL_VAR(int, _mouse_w); +AL_VAR(int, _mouse_b); +AL_VAR(int, _mouse_on); + +AL_VAR(int, _mouse_installed); + +AL_VAR(int, _mouse_type); +AL_VAR(BITMAP *, _mouse_screen); +AL_VAR(BITMAP *, _mouse_pointer); + + +/* various bits of timer stuff */ +AL_FUNC(long, _handle_timer_tick, (int interval)); + +#define MAX_TIMERS 16 + +/* list of active timer handlers */ +typedef struct TIMER_QUEUE +{ + AL_METHOD(void, proc, (void)); /* timer handler functions */ + AL_METHOD(void, param_proc, (void *param)); + void *param; /* param for param_proc if used */ + long speed; /* timer speed */ + long counter; /* counts down to zero=blastoff */ +} TIMER_QUEUE; + +AL_ARRAY(TIMER_QUEUE, _timer_queue); + +AL_VAR(int, _timer_installed); + +AL_VAR(int, _timer_use_retrace); +AL_VAR(volatile int, _retrace_hpp_value); + +AL_VAR(long, _vsync_speed); + + +/* various bits of keyboard stuff */ +AL_FUNC(void, _handle_key_press, (int keycode, int scancode)); +AL_FUNC(void, _handle_key_release, (int scancode)); + +AL_VAR(int, _keyboard_installed); +AL_ARRAY(AL_CONST char *, _keyboard_common_names); +AL_ARRAY(volatile char, _key); +AL_VAR(volatile int, _key_shifts); + + +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_DJGPP) || (defined ALLEGRO_WATCOM) || \ + (defined ALLEGRO_QNX) || (defined ALLEGRO_BEOS) + +AL_ARRAY(char *, _pckeys_names); + +AL_FUNC(void, _pckeys_init, (void)); +AL_FUNC(void, _handle_pckey, (int code)); +AL_FUNC(int, _pckey_scancode_to_ascii, (int scancode)); +AL_FUNC(AL_CONST char *, _pckey_scancode_to_name, (int scancode)); + +AL_VAR(unsigned short *, _key_ascii_table); +AL_VAR(unsigned short *, _key_capslock_table); +AL_VAR(unsigned short *, _key_shift_table); +AL_VAR(unsigned short *, _key_control_table); +AL_VAR(unsigned short *, _key_altgr_lower_table); +AL_VAR(unsigned short *, _key_altgr_upper_table); +AL_VAR(unsigned short *, _key_accent1_lower_table); +AL_VAR(unsigned short *, _key_accent1_upper_table); +AL_VAR(unsigned short *, _key_accent2_lower_table); +AL_VAR(unsigned short *, _key_accent2_upper_table); +AL_VAR(unsigned short *, _key_accent3_lower_table); +AL_VAR(unsigned short *, _key_accent3_upper_table); +AL_VAR(unsigned short *, _key_accent4_lower_table); +AL_VAR(unsigned short *, _key_accent4_upper_table); + +AL_VAR(int, _key_accent1); +AL_VAR(int, _key_accent2); +AL_VAR(int, _key_accent3); +AL_VAR(int, _key_accent4); +AL_VAR(int, _key_accent1_flag); +AL_VAR(int, _key_accent2_flag); +AL_VAR(int, _key_accent3_flag); +AL_VAR(int, _key_accent4_flag); + +AL_VAR(int, _key_standard_kb); + +AL_VAR(char *, _keyboard_layout); + +#endif + +#if (defined ALLEGRO_WINDOWS) + + AL_FUNC(int, _al_win_open, (const char *filename, int mode, int perm)); + AL_FUNC(int, _al_win_unlink, (const char *filename)); + + + #define _al_open(filename, mode, perm) _al_win_open(filename, mode, perm) + #define _al_unlink(filename) _al_win_unlink(filename) + +#else + + #define _al_open(filename, mode, perm) open(filename, mode, perm) + #define _al_unlink(filename) unlink(filename) + +#endif + + +/* various bits of joystick stuff */ +AL_VAR(int, _joy_type); + +AL_VAR(int, _joystick_installed); + + +/* some GUI innards that other people need to use */ +AL_FUNC(int, _gui_shadow_box_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_ctext_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_button_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_edit_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_list_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_text_list_proc, (int msg, DIALOG *d, int c)); + +AL_FUNC(void, _handle_scrollable_scroll_click, (DIALOG *d, int listsize, int *offset, int height)); +AL_FUNC(void, _handle_scrollable_scroll, (DIALOG *d, int listsize, int *idx, int *offset)); +AL_FUNC(void, _handle_listbox_click, (DIALOG *d)); +AL_FUNC(void, _draw_scrollable_frame, (DIALOG *d, int listsize, int offset, int height, int fg_color, int bg)); +AL_FUNC(void, _draw_listbox, (DIALOG *d)); +AL_FUNC(void, _draw_textbox, (char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, int disabled, int fore, int deselect, int disable)); + + +/* text- and font-related stuff */ +typedef struct FONT_VTABLE +{ + AL_METHOD(int, font_height, (AL_CONST FONT *f)); + AL_METHOD(int, char_length, (AL_CONST FONT *f, int ch)); + AL_METHOD(int, text_length, (AL_CONST FONT *f, AL_CONST char *text)); + AL_METHOD(int, render_char, (AL_CONST FONT *f, int ch, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, render, (AL_CONST FONT *f, AL_CONST char *text, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, destroy, (FONT *f)); + + AL_METHOD(int, get_font_ranges, (FONT *f)); + AL_METHOD(int, get_font_range_begin, (FONT *f, int range)); + AL_METHOD(int, get_font_range_end, (FONT *f, int range)); + AL_METHOD(FONT *, extract_font_range, (FONT *f, int begin, int end)); + AL_METHOD(FONT *, merge_fonts, (FONT *f1, FONT *f2)); + AL_METHOD(int, transpose_font, (FONT *f, int drange)); +} FONT_VTABLE; + +AL_VAR(FONT_VTABLE, _font_vtable_mono); +AL_VAR(FONT_VTABLE *, font_vtable_mono); +AL_VAR(FONT_VTABLE, _font_vtable_color); +AL_VAR(FONT_VTABLE *, font_vtable_color); +AL_VAR(FONT_VTABLE, _font_vtable_trans); +AL_VAR(FONT_VTABLE *, font_vtable_trans); + +AL_FUNC(FONT_GLYPH *, _mono_find_glyph, (AL_CONST FONT *f, int ch)); +AL_FUNC(BITMAP *, _color_find_glyph, (AL_CONST FONT *f, int ch)); + +typedef struct FONT_MONO_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + FONT_GLYPH **glyphs; /* our glyphs */ + struct FONT_MONO_DATA *next; /* linked list structure */ +} FONT_MONO_DATA; + +typedef struct FONT_COLOR_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + BITMAP **bitmaps; /* our glyphs */ + struct FONT_COLOR_DATA *next; /* linked list structure */ +} FONT_COLOR_DATA; + + +/* caches and tables for svga bank switching */ +AL_VAR(int, _last_bank_1); +AL_VAR(int, _last_bank_2); + +AL_VAR(int *, _gfx_bank); + +/* bank switching routines (these use a non-C calling convention on i386!) */ +AL_FUNC(uintptr_t, _stub_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _stub_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _stub_bank_switch_end, (void)); + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(uintptr_t, _x_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _x_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _x_bank_switch_end, (void)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VBEAF + +AL_FUNC(void, _accel_bank_stub, (void)); +AL_FUNC(void, _accel_bank_stub_end, (void)); +AL_FUNC(void, _accel_bank_switch, (void)); +AL_FUNC(void, _accel_bank_switch_end, (void)); + +AL_VAR(void *, _accel_driver); + +AL_VAR(int, _accel_active); + +AL_VAR(void *, _accel_set_bank); +AL_VAR(void *, _accel_idle); + +AL_FUNC(void, _fill_vbeaf_libc_exports, (void *ptr)); +AL_FUNC(void, _fill_vbeaf_pmode_exports, (void *ptr)); + +#endif + + +/* stuff for setting up bitmaps */ +AL_FUNC(BITMAP *, _make_bitmap, (int w, int h, uintptr_t addr, GFX_DRIVER *driver, int color_depth, int bpl)); +AL_FUNC(void, _sort_out_virtual_width, (int *width, GFX_DRIVER *driver)); + +AL_FUNC(GFX_VTABLE *, _get_vtable, (int color_depth)); + +AL_VAR(GFX_VTABLE, _screen_vtable); + +AL_VAR(int, _gfx_mode_set_count); + +AL_VAR(int, _refresh_rate_request); +AL_FUNC(void, _set_current_refresh_rate, (int rate)); + +AL_VAR(int, _wait_for_vsync); + +AL_VAR(int, _sub_bitmap_id_count); + +AL_VAR(int, _screen_split_position); + +AL_VAR(int, _safe_gfx_mode_change); + +#ifdef ALLEGRO_I386 + #define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) +#else + #ifdef ALLEGRO_MPW + /* in Mac 24 bit is a unsigned long */ + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : 4)) + #else + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : (((bpp) <= 24) ? 3 : 4))) + #endif +#endif + +AL_FUNC(int, _color_load_depth, (int depth, int hasalpha)); + +AL_VAR(int, _color_conv); + +AL_FUNC(BITMAP *, _fixup_loaded_bitmap, (BITMAP *bmp, PALETTE pal, int bpp)); + +AL_FUNC(int, _bitmap_has_alpha, (BITMAP *bmp)); + +/* default truecolor pixel format */ +#define DEFAULT_RGB_R_SHIFT_15 0 +#define DEFAULT_RGB_G_SHIFT_15 5 +#define DEFAULT_RGB_B_SHIFT_15 10 +#define DEFAULT_RGB_R_SHIFT_16 0 +#define DEFAULT_RGB_G_SHIFT_16 5 +#define DEFAULT_RGB_B_SHIFT_16 11 +#define DEFAULT_RGB_R_SHIFT_24 0 +#define DEFAULT_RGB_G_SHIFT_24 8 +#define DEFAULT_RGB_B_SHIFT_24 16 +#define DEFAULT_RGB_R_SHIFT_32 0 +#define DEFAULT_RGB_G_SHIFT_32 8 +#define DEFAULT_RGB_B_SHIFT_32 16 +#define DEFAULT_RGB_A_SHIFT_32 24 + + +/* display switching support */ +AL_FUNC(void, _switch_in, (void)); +AL_FUNC(void, _switch_out, (void)); + +AL_FUNC(void, _register_switch_bitmap, (BITMAP *bmp, BITMAP *parent)); +AL_FUNC(void, _unregister_switch_bitmap, (BITMAP *bmp)); +AL_FUNC(void, _save_switch_state, (int switch_mode)); +AL_FUNC(void, _restore_switch_state, (void)); + +AL_VAR(int, _dispsw_status); + + +/* current drawing mode */ +AL_VAR(int, _drawing_mode); +AL_VAR(BITMAP *, _drawing_pattern); +AL_VAR(int, _drawing_x_anchor); +AL_VAR(int, _drawing_y_anchor); +AL_VAR(unsigned int, _drawing_x_mask); +AL_VAR(unsigned int, _drawing_y_mask); + +AL_FUNCPTR(int *, _palette_expansion_table, (int bpp)); + +AL_VAR(int, _color_depth); + +AL_VAR(int, _current_palette_changed); +AL_VAR(PALETTE, _prev_current_palette); +AL_VAR(int, _got_prev_current_palette); + +AL_ARRAY(int, _palette_color8); +AL_ARRAY(int, _palette_color15); +AL_ARRAY(int, _palette_color16); +AL_ARRAY(int, _palette_color24); +AL_ARRAY(int, _palette_color32); + +/* truecolor blending functions */ +AL_VAR(BLENDER_FUNC, _blender_func15); +AL_VAR(BLENDER_FUNC, _blender_func16); +AL_VAR(BLENDER_FUNC, _blender_func24); +AL_VAR(BLENDER_FUNC, _blender_func32); + +AL_VAR(BLENDER_FUNC, _blender_func15x); +AL_VAR(BLENDER_FUNC, _blender_func16x); +AL_VAR(BLENDER_FUNC, _blender_func24x); + +AL_VAR(int, _blender_col_15); +AL_VAR(int, _blender_col_16); +AL_VAR(int, _blender_col_24); +AL_VAR(int, _blender_col_32); + +AL_VAR(int, _blender_alpha); + +AL_FUNC(unsigned long, _blender_black, (unsigned long x, unsigned long y, unsigned long n)); + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(unsigned long, _blender_trans15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen15, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_trans16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen16, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + +AL_FUNC(unsigned long, _blender_trans24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen24, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +AL_FUNC(unsigned long, _blender_alpha15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha32, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_write_alpha, (unsigned long x, unsigned long y, unsigned long n)); + + +/* graphics drawing routines */ +AL_FUNC(void, _normal_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _fast_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _normal_rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(int, _linear_getpixel8, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel8, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline8, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline8, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph8, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color8, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _linear_putpixel15, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline15, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline15, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_trans_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + +AL_FUNC(int, _linear_getpixel16, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel16, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline16, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline16, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph16, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color16, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(int, _linear_getpixel24, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel24, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline24, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline24, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph24, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color24, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(int, _linear_getpixel32, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel32, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline32, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline32, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph32, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color32, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(int, _x_getpixel, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _x_putpixel, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _x_vline, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _x_hline, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _x_draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _x_draw_glyph, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _x_blit_from_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_to_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_forward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_backward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_masked_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_clear_to_color, (BITMAP *bitmap, int color)); + +#endif + + +/* color conversion routines */ +typedef struct GRAPHICS_RECT { + int width; + int height; + int pitch; + void *data; +} GRAPHICS_RECT; + +typedef void (COLORCONV_BLITTER_FUNC)(GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect); + +AL_FUNC(COLORCONV_BLITTER_FUNC *, _get_colorconv_blitter, (int from_depth, int to_depth)); +AL_FUNC(void, _release_colorconv_blitter, (COLORCONV_BLITTER_FUNC *blitter)); +AL_FUNC(void, _set_colorconv_palette, (AL_CONST struct RGB *p, int from, int to)); +AL_FUNC(unsigned char *, _get_colorconv_map, (void)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _colorconv_blit_8_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _colorconv_blit_15_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +AL_FUNC(void, _colorconv_blit_16_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _colorconv_blit_24_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _colorconv_blit_32_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + + +/* color copy routines */ +#ifndef ALLEGRO_NO_COLORCOPY + +#ifdef ALLEGRO_COLOR16 +AL_FUNC(void, _colorcopy_blit_15_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorcopy_blit_16_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR24 +AL_FUNC(void, _colorcopy_blit_24_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR32 +AL_FUNC(void, _colorcopy_blit_32_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#endif + + +/* generic color conversion blitter */ +AL_FUNC(void, _blit_between_formats, (BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)); + + +/* asm helper for stretch_blit() */ +#ifndef SCAN_EXPORT +AL_FUNC(void, _do_stretch, (BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth)); +#endif + + +/* lower level functions for rotation */ +AL_FUNC(void, _parallelogram_map, (BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy)); +AL_FUNC(void, _parallelogram_map_standard, (BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _rotate_scale_flip_coordinates, (fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + + +/* number of fractional bits used by the polygon rasteriser */ +#define POLYGON_FIX_SHIFT 18 + + +/* bitfield specifying which polygon attributes need interpolating */ +#define INTERP_FLAT 1 /* no interpolation */ +#define INTERP_1COL 2 /* gcol or alpha */ +#define INTERP_3COL 4 /* grgb */ +#define INTERP_FIX_UV 8 /* atex */ +#define INTERP_Z 16 /* always in scene3d */ +#define INTERP_FLOAT_UV 32 /* ptex */ +#define OPT_FLOAT_UV_TO_FIX 64 /* translate ptex to atex */ +#define COLOR_TO_RGB 128 /* grgb to gcol for truecolor */ +#define INTERP_ZBUF 256 /* z-buffered */ +#define INTERP_THRU 512 /* any kind of transparent */ +#define INTERP_NOSOLID 1024 /* non-solid modes for 8-bit flat */ +#define INTERP_BLEND 2048 /* lit for truecolor */ +#define INTERP_TRANS 4096 /* trans for truecolor */ + + +/* information for polygon scanline fillers */ +typedef struct POLYGON_SEGMENT +{ + fixed u, v, du, dv; /* fixed point u/v coordinates */ + fixed c, dc; /* single color gouraud shade values */ + fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ + float z, dz; /* polygon depth (1/z) */ + float fu, fv, dfu, dfv; /* floating point u/v coordinates */ + unsigned char *texture; /* the texture map */ + int umask, vmask, vshift; /* texture map size information */ + int seg; /* destination bitmap selector */ + uintptr_t zbuf_addr; /* Z-buffer address */ + uintptr_t read_addr; /* reading address for transparency modes */ +} POLYGON_SEGMENT; + + +/* prototype for the scanline filler functions */ +typedef AL_METHOD(void, SCANLINE_FILLER, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + + +/* an active polygon edge */ +typedef struct POLYGON_EDGE +{ + int top; /* top y position */ + int bottom; /* bottom y position */ + fixed x, dx; /* fixed point x position and gradient */ + fixed w; /* width of line segment */ + POLYGON_SEGMENT dat; /* texture/gouraud information */ + struct POLYGON_EDGE *prev; /* doubly linked list */ + struct POLYGON_EDGE *next; + struct POLYGON_INFO *poly; /* father polygon */ +} POLYGON_EDGE; + + +typedef struct POLYGON_INFO /* a polygon waiting rendering */ +{ + struct POLYGON_INFO *next, *prev;/* double linked list */ + int inside; /* flag for "scanlining" */ + int flags; /* INTERP_* flags */ + int color; /* vtx[0]->c */ + float a, b, c; /* plane's coefficients -a/d, -b/d, -c/d */ + int dmode; /* drawing mode */ + BITMAP *dpat; /* drawing pattern */ + int xanchor, yanchor; /* for dpat */ + int alpha; /* blender alpha */ + int b15, b16, b24, b32; /* blender colors */ + COLOR_MAP *cmap; /* trans color map */ + SCANLINE_FILLER drawer; /* scanline drawing functions */ + SCANLINE_FILLER alt_drawer; + POLYGON_EDGE *left_edge; /* true edges used in interpolation */ + POLYGON_EDGE *right_edge; + POLYGON_SEGMENT info; /* base information for scanline functions */ +} POLYGON_INFO; + + +/* global variable for z-buffer */ +AL_VAR(BITMAP *, _zbuffer); + + +/* polygon helper functions */ +AL_VAR(SCANLINE_FILLER, _optim_alternative_drawer); +AL_FUNC(POLYGON_EDGE *, _add_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)); +AL_FUNC(POLYGON_EDGE *, _remove_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge)); +AL_FUNC(int, _fill_3d_edge_structure, (POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp)); +AL_FUNC(int, _fill_3d_edge_structure_f, (POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp)); +AL_FUNC(SCANLINE_FILLER, _get_scanline_filler, (int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp)); +AL_FUNC(void, _clip_polygon_segment, (POLYGON_SEGMENT *info, fixed gap, int flags)); +AL_FUNC(void, _clip_polygon_segment_f, (POLYGON_SEGMENT *info, int gap, int flags)); + + +/* polygon scanline filler functions */ +AL_FUNC(void, _poly_scanline_dummy, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _poly_scanline_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb8x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _poly_scanline_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _poly_scanline_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _poly_scanline_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + + +/* sound lib stuff */ +AL_VAR(MIDI_DRIVER, _midi_none); +AL_VAR(int, _digi_volume); +AL_VAR(int, _midi_volume); +AL_VAR(int, _sound_flip_pan); +AL_VAR(int, _sound_hq); +AL_VAR(int, _sound_stereo); +AL_VAR(int, _sound_bits); +AL_VAR(int, _sound_freq); +AL_VAR(int, _sound_port); +AL_VAR(int, _sound_dma); +AL_VAR(int, _sound_irq); + +AL_VAR(int, _sound_installed); +AL_VAR(int, _sound_input_installed); + +AL_FUNC(int, _midi_allocate_voice, (int min, int max)); + +AL_VAR(volatile long, _midi_tick); + +AL_FUNC(int, _digmid_find_patches, (char *dir, int dir_size, char *file, int size_of_file)); + +#define VIRTUAL_VOICES 256 + + +typedef struct /* a virtual (as seen by the user) soundcard voice */ +{ + AL_CONST SAMPLE *sample; /* which sample are we playing? (NULL = free) */ + int num; /* physical voice number (-1 = been killed off) */ + int autokill; /* set to free the voice when the sample finishes */ + long time; /* when we were started (for voice allocation) */ + int priority; /* how important are we? */ +} VOICE; + + +typedef struct /* a physical (as used by hardware) soundcard voice */ +{ + int num; /* the virtual voice currently using me (-1 = free) */ + int playmode; /* are we looping? */ + int vol; /* current volume (fixed point .12) */ + int dvol; /* volume delta, for ramping */ + int target_vol; /* target volume, for ramping */ + int pan; /* current pan (fixed point .12) */ + int dpan; /* pan delta, for sweeps */ + int target_pan; /* target pan, for sweeps */ + int freq; /* current frequency (fixed point .12) */ + int dfreq; /* frequency delta, for sweeps */ + int target_freq; /* target frequency, for sweeps */ +} PHYS_VOICE; + +AL_ARRAY(PHYS_VOICE, _phys_voice); + + +#define MIXER_DEF_SFX 8 +#define MIXER_MAX_SFX 64 + +AL_FUNC(int, _mixer_init, (int bufsize, int freq, int stereo, int is16bit, int *voices)); +AL_FUNC(void, _mixer_exit, (void)); +AL_FUNC(void, _mix_some_samples, (uintptr_t buf, unsigned short seg, int issigned)); +AL_FUNC(void, _mixer_init_voice, (int voice, AL_CONST SAMPLE *sample)); +AL_FUNC(void, _mixer_release_voice, (int voice)); +AL_FUNC(void, _mixer_start_voice, (int voice)); +AL_FUNC(void, _mixer_stop_voice, (int voice)); +AL_FUNC(void, _mixer_loop_voice, (int voice, int loopmode)); +AL_FUNC(int, _mixer_get_position, (int voice)); +AL_FUNC(void, _mixer_set_position, (int voice, int position)); +AL_FUNC(int, _mixer_get_volume, (int voice)); +AL_FUNC(void, _mixer_set_volume, (int voice, int volume)); +AL_FUNC(void, _mixer_ramp_volume, (int voice, int tyme, int endvol)); +AL_FUNC(void, _mixer_stop_volume_ramp, (int voice)); +AL_FUNC(int, _mixer_get_frequency, (int voice)); +AL_FUNC(void, _mixer_set_frequency, (int voice, int frequency)); +AL_FUNC(void, _mixer_sweep_frequency, (int voice, int tyme, int endfreq)); +AL_FUNC(void, _mixer_stop_frequency_sweep, (int voice)); +AL_FUNC(int, _mixer_get_pan, (int voice)); +AL_FUNC(void, _mixer_set_pan, (int voice, int pan)); +AL_FUNC(void, _mixer_sweep_pan, (int voice, int tyme, int endpan)); +AL_FUNC(void, _mixer_stop_pan_sweep, (int voice)); +AL_FUNC(void, _mixer_set_echo, (int voice, int strength, int delay)); +AL_FUNC(void, _mixer_set_tremolo, (int voice, int rate, int depth)); +AL_FUNC(void, _mixer_set_vibrato, (int voice, int rate, int depth)); + +AL_FUNC(void, _dummy_noop1, (int p)); +AL_FUNC(void, _dummy_noop2, (int p1, int p2)); +AL_FUNC(void, _dummy_noop3, (int p1, int p2, int p3)); +AL_FUNC(int, _dummy_load_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan)); + + +/* datafile ID's for compatibility with the old datafile format */ +#define V1_DAT_MAGIC 0x616C6C2EL + +#define V1_DAT_DATA 0 +#define V1_DAT_FONT 1 +#define V1_DAT_BITMAP_16 2 +#define V1_DAT_BITMAP_256 3 +#define V1_DAT_SPRITE_16 4 +#define V1_DAT_SPRITE_256 5 +#define V1_DAT_PALETTE_16 6 +#define V1_DAT_PALETTE_256 7 +#define V1_DAT_FONT_8x8 8 +#define V1_DAT_FONT_PROP 9 +#define V1_DAT_BITMAP 10 +#define V1_DAT_PALETTE 11 +#define V1_DAT_SAMPLE 12 +#define V1_DAT_MIDI 13 +#define V1_DAT_RLE_SPRITE 14 +#define V1_DAT_FLI 15 +#define V1_DAT_C_SPRITE 16 +#define V1_DAT_XC_SPRITE 17 + +#define OLD_FONT_SIZE 95 +#define LESS_OLD_FONT_SIZE 224 + + +/* datafile object loading functions */ +AL_FUNC(void, _unload_datafile_object, (DATAFILE *dat)); + + +/* information about a datafile object */ +typedef struct DATAFILE_TYPE +{ + int type; + AL_METHOD(void *, load, (PACKFILE *f, long size)); + AL_METHOD(void, destroy, (void *)); +} DATAFILE_TYPE; + + +#define MAX_DATAFILE_TYPES 32 + +AL_ARRAY(DATAFILE_TYPE, _datafile_type); + +AL_VAR(int, _compile_sprites); + +AL_FUNC(void, _construct_datafile, (DATAFILE *data)); + + +/* for readbmp.c */ +AL_FUNC(void, _register_bitmap_file_type_init, (void)); + +/* for readsmp.c */ +AL_FUNC(void, _register_sample_file_type_init, (void)); + +/* for readfont.c */ +AL_FUNC(void, _register_font_file_type_init, (void)); + + +/* for module linking system; see comment in allegro.c */ +struct _AL_LINKER_MIDI +{ + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); +}; + +AL_VAR(struct _AL_LINKER_MIDI *, _al_linker_midi); + +struct _AL_LINKER_MOUSE +{ + AL_METHOD(void, set_mouse_etc, (void)); + AL_METHOD(void, show_mouse, (BITMAP *)); + BITMAP **mouse_screen_ptr; +}; + +AL_VAR(struct _AL_LINKER_MOUSE *, _al_linker_mouse); + + +/* dynamic driver lists */ +AL_FUNC(_DRIVER_INFO *, _create_driver_list, (void)); +AL_FUNC(void, _destroy_driver_list, (_DRIVER_INFO *drvlist)); +AL_FUNC(void, _driver_list_append_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_prepend_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_append_list, (_DRIVER_INFO **drvlist, _DRIVER_INFO *srclist)); + + +/* various libc stuff */ +AL_FUNC(void *, _al_sane_realloc, (void *ptr, size_t size)); +AL_FUNC(char *, _al_sane_strncpy, (char *dest, const char *src, size_t n)); + + +#define _AL_RAND_MAX 0xFFFF +AL_FUNC(void, _al_srand, (int seed)); +AL_FUNC(int, _al_rand, (void)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef AINTERN_H */ diff --git a/allegro/allegro/internal/aintvga.h b/allegro/allegro/internal/aintvga.h new file mode 100644 index 0000000000..9a21f314ed --- /dev/null +++ b/allegro/allegro/internal/aintvga.h @@ -0,0 +1,139 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Helpers for accessing the VGA hardware registers. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTVGA_H +#define AINTVGA_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifdef ALLEGRO_GFX_HAS_VGA + +#ifdef __cplusplus + extern "C" { +#endif + + +AL_VAR(int, _crtc); + +AL_FUNC(void, _vga_regs_init, (void)); +AL_FUNC(void, _vga_vsync, (void)); +AL_FUNC(void, _vga_set_palette_range, (AL_CONST PALETTE p, int from, int to, int do_sync)); +AL_FUNC(void, _set_vga_virtual_width, (int old_width, int new_width)); +AL_FUNC(uintptr_t, _set_vga_mode, (int modenum)); +AL_FUNC(void, _unset_vga_mode, (void)); +AL_FUNC(void, _save_vga_mode, (void)); +AL_FUNC(void, _restore_vga_mode, (void)); + + +/* reads the current value of a VGA hardware register */ +AL_INLINE(int, _read_vga_register, (int port, int idx), +{ + if (port==0x3C0) + inportb(_crtc+6); + + outportb(port, idx); + return inportb(port+1); +}) + + +/* writes to a VGA hardware register */ +AL_INLINE(void, _write_vga_register, (int port, int idx, int v), +{ + if (port==0x3C0) { + inportb(_crtc+6); + outportb(port, idx); + outportb(port, v); + } + else { + outportb(port, idx); + outportb(port+1, v); + } +}) + + +/* alters specific bits of a VGA hardware register */ +AL_INLINE(void, _alter_vga_register, (int port, int idx, int mask, int v), +{ + int temp; + temp = _read_vga_register(port, idx); + temp &= (~mask); + temp |= (v & mask); + _write_vga_register(port, idx, temp); +}) + + +/* waits until the VGA isn't in a horizontal blank */ +AL_INLINE(void, _vsync_out_h, (void), +{ + do { + } while (inportb(0x3DA) & 1); +}) + + +/* waits until the VGA isn't in a vertical blank */ +AL_INLINE(void, _vsync_out_v, (void), +{ + do { + } while (inportb(0x3DA) & 8); +}) + + +/* waits until the VGA is in a vertical blank */ +AL_INLINE(void, _vsync_in, (void), +{ + if (_timer_use_retrace) { + int t = retrace_count; + + do { + } while (t == retrace_count); + } + else { + do { + } while (!(inportb(0x3DA) & 8)); + } +}) + + +/* modifies the VGA pelpan register */ +AL_INLINE(void, _write_hpp, (int value), +{ + if (_timer_use_retrace) { + _retrace_hpp_value = value; + + do { + } while (_retrace_hpp_value == value); + } + else { + do { + } while (!(inportb(0x3DA) & 8)); + + _write_vga_register(0x3C0, 0x33, value); + } +}) + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifdef ALLEGRO_GFX_HAS_VGA */ + +#endif /* ifndef AINTVGA_H */ diff --git a/allegro/allegro/internal/alconfig.h b/allegro/allegro/internal/alconfig.h new file mode 100644 index 0000000000..5dc9e6a94d --- /dev/null +++ b/allegro/allegro/internal/alconfig.h @@ -0,0 +1,424 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +/* which color depths to include? */ +#define ALLEGRO_COLOR8 +#define ALLEGRO_COLOR16 +#define ALLEGRO_COLOR24 +#define ALLEGRO_COLOR32 + + +/* for backward compatibility */ +#ifdef USE_CONSOLE + #define ALLEGRO_NO_MAGIC_MAIN + #define ALLEGRO_USE_CONSOLE +#endif + + +/* include platform-specific stuff */ +#ifndef SCAN_EXPORT + #ifndef SCAN_DEPEND + #include "allegro/platform/alplatf.h" + #endif + + #if defined ALLEGRO_DJGPP + #include "allegro/platform/aldjgpp.h" + #elif defined ALLEGRO_WATCOM + #include "allegro/platform/alwatcom.h" + #elif defined ALLEGRO_MINGW32 + #include "allegro/platform/almngw32.h" + #elif defined ALLEGRO_DMC + #include "allegro/platform/aldmc.h" + #elif defined ALLEGRO_BCC32 + #include "allegro/platform/albcc32.h" + #elif defined ALLEGRO_MSVC + #include "allegro/platform/almsvc.h" + #elif defined ALLEGRO_BEOS + #include "allegro/platform/albecfg.h" + #elif defined ALLEGRO_MPW + #include "allegro/platform/almaccfg.h" + #elif defined ALLEGRO_MACOSX + #include "allegro/platform/alosxcfg.h" + #elif defined ALLEGRO_QNX + #include "allegro/platform/alqnxcfg.h" + #elif defined ALLEGRO_UNIX + #include "allegro/platform/alucfg.h" + #else + #error platform not supported + #endif + + #ifndef SCAN_DEPEND + #include "allegro/platform/astdint.h" + #endif +#endif + + +/* special definitions for the GCC compiler */ +#ifdef __GNUC__ + #define ALLEGRO_GCC + + #ifndef AL_INLINE + #ifdef __cplusplus + #define AL_INLINE(type, name, args, code) \ + static inline type name args; \ + static inline type name args code + #else + #define AL_INLINE(type, name, args, code) \ + extern __inline__ type name args; \ + extern __inline__ type name args code + #endif + #endif + + #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) __attribute__ ((format (printf, a, b))) + + #ifndef INLINE + #define INLINE __inline__ + #endif + + #if __GNUC__ >= 3 + /* SET: According to gcc volatile is ignored for a return type. + * I think the code should just ensure that inportb is declared as an + * __asm__ __volatile__ macro. If that's the case the extra volatile + * doesn't have any sense. + */ + #define RET_VOLATILE + #else + #define RET_VOLATILE volatile + #endif + + #ifndef ZERO_SIZE_ARRAY + #if __GNUC__ < 3 + #define ZERO_SIZE_ARRAY(type, name) __extension__ type name[0] + #else + #define ZERO_SIZE_ARRAY(type, name) type name[] /* ISO C99 flexible array members */ + #endif + #endif + + #ifndef LONG_LONG + #define LONG_LONG long long + #ifdef ALLEGRO_GUESS_INTTYPES_OK + #define int64_t signed long long + #define uint64_t unsigned long long + #endif + #endif + + #ifdef __i386__ + #define ALLEGRO_I386 + #ifndef ALLEGRO_NO_ASM + #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) + #endif + #endif + + #ifdef __amd64__ + #define ALLEGRO_AMD64 + #ifndef ALLEGRO_NO_ASM + #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) + #endif + #endif + + #ifdef __arm__ + #define ALLEGRO_ARM + #endif + + #ifndef AL_CONST + #define AL_CONST const + #endif + + #ifndef AL_FUNC_DEPRECATED + #if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) + #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(__attribute__ ((deprecated)) type, name, args) + #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(__attribute__ ((deprecated)) type, name, args, a, b) + #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(__attribute__ ((deprecated)) type, name, args, code) + #endif + #endif + + #ifndef AL_ALIAS + #define AL_ALIAS(DECL, CALL) \ + static __attribute__((unused)) __inline__ DECL \ + { \ + return CALL; \ + } + #endif + + #ifndef AL_ALIAS_VOID_RET + #define AL_ALIAS_VOID_RET(DECL, CALL) \ + static __attribute__((unused)) __inline__ void DECL \ + { \ + CALL; \ + } + #endif +#endif + + +/* use constructor functions, if supported */ +#ifdef ALLEGRO_USE_CONSTRUCTOR + #define CONSTRUCTOR_FUNCTION(func) func __attribute__ ((constructor)) + #define DESTRUCTOR_FUNCTION(func) func __attribute__ ((destructor)) +#endif + + +/* the rest of this file fills in some default definitions of language + * features and helper functions, which are conditionalised so they will + * only be included if none of the above headers defined custom versions. + */ + +#ifndef _AL_SINCOS + #define _AL_SINCOS(x, s, c) do { (c) = cos(x); (s) = sin(x); } while (0) +#endif + +#ifndef INLINE + #define INLINE +#endif + +#ifndef RET_VOLATILE + #define RET_VOLATILE volatile +#endif + +#ifndef ZERO_SIZE_ARRAY + #define ZERO_SIZE_ARRAY(type, name) type name[] +#endif + +#ifndef AL_CONST + #define AL_CONST +#endif + +#ifndef AL_VAR + #define AL_VAR(type, name) extern type name +#endif + +#ifndef AL_ARRAY + #define AL_ARRAY(type, name) extern type name[] +#endif + +#ifndef AL_FUNC + #define AL_FUNC(type, name, args) type name args +#endif + +#ifndef AL_PRINTFUNC + #define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) +#endif + +#ifndef AL_METHOD + #define AL_METHOD(type, name, args) type (*name) args +#endif + +#ifndef AL_FUNCPTR + #define AL_FUNCPTR(type, name, args) extern type (*name) args +#endif + +#ifndef AL_FUNCPTRARRAY + #define AL_FUNCPTRARRAY(type, name, args) extern type (*name[]) args +#endif + +#ifndef AL_INLINE + #define AL_INLINE(type, name, args, code) type name args; +#endif + +#ifndef AL_FUNC_DEPRECATED + #define AL_FUNC_DEPRECATED(type, name, args) AL_FUNC(type, name, args) + #define AL_PRINTFUNC_DEPRECATED(type, name, args, a, b) AL_PRINTFUNC(type, name, args, a, b) + #define AL_INLINE_DEPRECATED(type, name, args, code) AL_INLINE(type, name, args, code) +#endif + +#ifndef AL_ALIAS + #define AL_ALIAS(DECL, CALL) \ + static INLINE DECL \ + { \ + return CALL; \ + } +#endif + +#ifndef AL_ALIAS_VOID_RET + #define AL_ALIAS_VOID_RET(DECL, CALL) \ + static INLINE void DECL \ + { \ + CALL; \ + } +#endif + +#ifndef END_OF_MAIN + #define END_OF_MAIN() +#endif + + +/* fill in default memory locking macros */ +#ifndef END_OF_FUNCTION + #define END_OF_FUNCTION(x) + #define END_OF_STATIC_FUNCTION(x) + #define LOCK_DATA(d, s) + #define LOCK_CODE(c, s) + #define UNLOCK_DATA(d, s) + #define LOCK_VARIABLE(x) + #define LOCK_FUNCTION(x) +#endif + + +/* fill in default filename behaviour */ +#ifndef ALLEGRO_LFN + #define ALLEGRO_LFN 1 +#endif + +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + #define OTHER_PATH_SEPARATOR '\\' + #define DEVICE_SEPARATOR ':' +#else + #define OTHER_PATH_SEPARATOR '/' + #define DEVICE_SEPARATOR '\0' +#endif + + +/* emulate the FA_* flags for platforms that don't already have them */ +#ifndef FA_RDONLY + #define FA_RDONLY 1 + #define FA_HIDDEN 2 + #define FA_SYSTEM 4 + #define FA_LABEL 8 + #define FA_DIREC 16 + #define FA_ARCH 32 +#endif + #define FA_NONE 0 + #define FA_ALL (~FA_NONE) + + +#ifdef __cplusplus + extern "C" { +#endif + +/* emulate missing library functions */ +#ifdef ALLEGRO_NO_STRICMP + AL_FUNC(int, _alemu_stricmp, (AL_CONST char *s1, AL_CONST char *s2)); + #define stricmp _alemu_stricmp +#endif + +#ifdef ALLEGRO_NO_STRLWR + AL_FUNC(char *, _alemu_strlwr, (char *string)); + #define strlwr _alemu_strlwr +#endif + +#ifdef ALLEGRO_NO_STRUPR + AL_FUNC(char *, _alemu_strupr, (char *string)); + #define strupr _alemu_strupr +#endif + +#ifdef ALLEGRO_NO_MEMCMP + AL_FUNC(int, _alemu_memcmp, (AL_CONST void *s1, AL_CONST void *s2, size_t num)); + #define memcmp _alemu_memcmp +#endif + + +/* if nobody put them elsewhere, video bitmaps go in regular memory */ +#ifndef _video_ds + #define _video_ds() _default_ds() +#endif + + +/* not many places actually use these, but still worth emulating */ +#ifndef ALLEGRO_DJGPP + #define _farsetsel(seg) + #define _farnspokeb(addr, val) (*((uint8_t *)(addr)) = (val)) + #define _farnspokew(addr, val) (*((uint16_t *)(addr)) = (val)) + #define _farnspokel(addr, val) (*((uint32_t *)(addr)) = (val)) + #define _farnspeekb(addr) (*((uint8_t *)(addr))) + #define _farnspeekw(addr) (*((uint16_t *)(addr))) + #define _farnspeekl(addr) (*((uint32_t *)(addr))) +#endif + + +/* endian-independent 3-byte accessor macros */ +#ifdef ALLEGRO_LITTLE_ENDIAN + + #define READ3BYTES(p) ((*(unsigned char *)(p)) \ + | (*((unsigned char *)(p) + 1) << 8) \ + | (*((unsigned char *)(p) + 2) << 16)) + + #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c)), \ + (*((unsigned char *)(p) + 1) = (c) >> 8), \ + (*((unsigned char *)(p) + 2) = (c) >> 16)) + +#elif defined ALLEGRO_BIG_ENDIAN + + #define READ3BYTES(p) ((*(unsigned char *)(p) << 16) \ + | (*((unsigned char *)(p) + 1) << 8) \ + | (*((unsigned char *)(p) + 2))) + + #define WRITE3BYTES(p,c) ((*(unsigned char *)(p) = (c) >> 16), \ + (*((unsigned char *)(p) + 1) = (c) >> 8), \ + (*((unsigned char *)(p) + 2) = (c))) + +#elif defined SCAN_DEPEND + + #define READ3BYTES(p) + #define WRITE3BYTES(p,c) + +#else + #error endianess not defined +#endif + + +/* generic versions of the video memory access helpers */ +#ifndef bmp_select + #define bmp_select(bmp) +#endif + +#ifndef bmp_write8 + #define bmp_write8(addr, c) (*((uint8_t *)(addr)) = (c)) + #define bmp_write15(addr, c) (*((uint16_t *)(addr)) = (c)) + #define bmp_write16(addr, c) (*((uint16_t *)(addr)) = (c)) + #define bmp_write32(addr, c) (*((uint32_t *)(addr)) = (c)) + + #define bmp_read8(addr) (*((uint8_t *)(addr))) + #define bmp_read15(addr) (*((uint16_t *)(addr))) + #define bmp_read16(addr) (*((uint16_t *)(addr))) + #define bmp_read32(addr) (*((uint32_t *)(addr))) + + AL_INLINE(int, bmp_read24, (uintptr_t addr), + { + unsigned char *p = (unsigned char *)addr; + int c; + + c = READ3BYTES(p); + + return c; + }) + + AL_INLINE(void, bmp_write24, (uintptr_t addr, int c), + { + unsigned char *p = (unsigned char *)addr; + + WRITE3BYTES(p, c); + }) + +#endif + + +/* default random function definition */ +#ifndef AL_RAND + #define AL_RAND() (rand()) +#endif + +#ifdef __cplusplus + } +#endif + + +/* parameters for the color conversion code */ +#if (defined ALLEGRO_WINDOWS) || (defined ALLEGRO_QNX) + #define ALLEGRO_COLORCONV_ALIGNED_WIDTH + #define ALLEGRO_NO_COLORCOPY +#endif + diff --git a/allegro/allegro/joystick.h b/allegro/allegro/joystick.h new file mode 100644 index 0000000000..76c7aca3b8 --- /dev/null +++ b/allegro/allegro/joystick.h @@ -0,0 +1,145 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Joystick routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_JOYSTICK_H +#define ALLEGRO_JOYSTICK_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define JOY_TYPE_AUTODETECT -1 +#define JOY_TYPE_NONE 0 + + +#define MAX_JOYSTICKS 8 +#define MAX_JOYSTICK_AXIS 3 +#define MAX_JOYSTICK_STICKS 5 +#define MAX_JOYSTICK_BUTTONS 32 + + +/* information about a single joystick axis */ +typedef struct JOYSTICK_AXIS_INFO +{ + int pos; + int d1, d2; + AL_CONST char *name; +} JOYSTICK_AXIS_INFO; + + +/* information about one or more axis (a slider or directional control) */ +typedef struct JOYSTICK_STICK_INFO +{ + int flags; + int num_axis; + JOYSTICK_AXIS_INFO axis[MAX_JOYSTICK_AXIS]; + AL_CONST char *name; +} JOYSTICK_STICK_INFO; + + +/* information about a joystick button */ +typedef struct JOYSTICK_BUTTON_INFO +{ + int b; + AL_CONST char *name; +} JOYSTICK_BUTTON_INFO; + + +/* information about an entire joystick */ +typedef struct JOYSTICK_INFO +{ + int flags; + int num_sticks; + int num_buttons; + JOYSTICK_STICK_INFO stick[MAX_JOYSTICK_STICKS]; + JOYSTICK_BUTTON_INFO button[MAX_JOYSTICK_BUTTONS]; +} JOYSTICK_INFO; + + +/* joystick status flags */ +#define JOYFLAG_DIGITAL 1 +#define JOYFLAG_ANALOGUE 2 +#define JOYFLAG_CALIB_DIGITAL 4 +#define JOYFLAG_CALIB_ANALOGUE 8 +#define JOYFLAG_CALIBRATE 16 +#define JOYFLAG_SIGNED 32 +#define JOYFLAG_UNSIGNED 64 + + +/* alternative spellings */ +#define JOYFLAG_ANALOG JOYFLAG_ANALOGUE +#define JOYFLAG_CALIB_ANALOG JOYFLAG_CALIB_ANALOGUE + + +/* global joystick information */ +AL_ARRAY(JOYSTICK_INFO, joy); +AL_VAR(int, num_joysticks); + + +typedef struct JOYSTICK_DRIVER /* driver for reading joystick input */ +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); + AL_METHOD(int, poll, (void)); + AL_METHOD(int, save_data, (void)); + AL_METHOD(int, load_data, (void)); + AL_METHOD(AL_CONST char *, calibrate_name, (int n)); + AL_METHOD(int, calibrate, (int n)); +} JOYSTICK_DRIVER; + + +AL_VAR(JOYSTICK_DRIVER, joystick_none); +AL_VAR(JOYSTICK_DRIVER *, joystick_driver); +AL_ARRAY(_DRIVER_INFO, _joystick_driver_list); + + +/* macros for constructing the driver list */ +#define BEGIN_JOYSTICK_DRIVER_LIST \ + _DRIVER_INFO _joystick_driver_list[] = \ + { + +#define END_JOYSTICK_DRIVER_LIST \ + { JOY_TYPE_NONE, &joystick_none, TRUE }, \ + { 0, NULL, 0 } \ + }; + + +AL_FUNC(int, install_joystick, (int type)); +AL_FUNC(void, remove_joystick, (void)); + +AL_FUNC(int, poll_joystick, (void)); + +AL_FUNC(int, save_joystick_data, (AL_CONST char *filename)); +AL_FUNC(int, load_joystick_data, (AL_CONST char *filename)); + +AL_FUNC(AL_CONST char *, calibrate_joystick_name, (int n)); +AL_FUNC(int, calibrate_joystick, (int n)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_JOYSTICK_H */ + + diff --git a/allegro/allegro/keyboard.h b/allegro/allegro/keyboard.h new file mode 100644 index 0000000000..a76b9727f7 --- /dev/null +++ b/allegro/allegro/keyboard.h @@ -0,0 +1,421 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Keyboard routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_KEYBOARD_H +#define ALLEGRO_KEYBOARD_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + + +//Win7 keyboard callback stuff; +//AL_FUNCPTR(void, al_zc_win_key_press_fix, (unsigned char*)); +//AL_FUNCPTR(void, al_zc_win_key_release_fix, (unsigned char*)); +//AL_FUNC(void, al_zc_set_key_press_fix, (AL_METHOD(void, funcPtr, (unsigned char*)))); +//AL_FUNC(void, al_zc_set_key_release_fix, (AL_METHOD(void, funcPtr, (unsigned char*)))); +//AL_FUNC(void, al_zc_set_key_press_fix, (void (*funcPtr)(unsigned char*))); +//AL_FUNC(void, al_zc_set_key_release_fix, (void (*funcPtr)(unsigned char*))); + +typedef void (*alzckeyfuncptr)(unsigned char*); + +static alzckeyfuncptr al_zc_win_key_press_fix = NULL; +static alzckeyfuncptr al_zc_win_key_release_fix = NULL; + + +/* +static void al_zc_set_key_press_fix(void (*funcPtr)(unsigned char*)) +{ + al_zc_win_key_press_fix = funcPtr; +} + +static void al_zc_set_key_release_fix(void (*funcPtr)(unsigned char*)) +{ + al_zc_win_key_release_fix = funcPtr; +} +*/ +typedef struct KEYBOARD_DRIVER +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + int autorepeat; + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); + AL_METHOD(void, poll, (void)); + AL_METHOD(void, set_leds, (int leds)); + AL_METHOD(void, set_rate, (int delay, int rate)); + AL_METHOD(void, wait_for_input, (void)); + AL_METHOD(void, stop_waiting_for_input, (void)); + AL_METHOD(int, scancode_to_ascii, (int scancode)); + AL_METHOD(AL_CONST char *, scancode_to_name, (int scancode)); +} KEYBOARD_DRIVER; + + +AL_VAR(KEYBOARD_DRIVER *, keyboard_driver); +AL_ARRAY(_DRIVER_INFO, _keyboard_driver_list); + +AL_FUNC(int, install_keyboard, (void)); +AL_FUNC(void, remove_keyboard, (void)); + +AL_FUNC(int, poll_keyboard, (void)); +AL_FUNC(int, keyboard_needs_poll, (void)); + +AL_FUNCPTR(int, keyboard_callback, (int key)); +AL_FUNCPTR(int, keyboard_ucallback, (int key, int *scancode)); +AL_FUNCPTR(void, keyboard_lowlevel_callback, (int scancode)); + +AL_FUNC(void, install_keyboard_hooks, (AL_METHOD(int, keypressed, (void)), AL_METHOD(int, readkey, (void)))); + +AL_ARRAY(volatile char, key); +AL_VAR(volatile int, key_shifts); + +AL_VAR(int, three_finger_flag); +AL_VAR(int, key_led_flag); + +AL_FUNC(int, keypressed, (void)); +AL_FUNC(int, readkey, (void)); +AL_FUNC(int, ureadkey, (int *scancode)); +AL_FUNC(void, simulate_keypress, (int keycode)); +AL_FUNC(void, simulate_ukeypress, (int keycode, int scancode)); +AL_FUNC(void, clear_keybuf, (void)); +AL_FUNC(void, set_leds, (int leds)); +AL_FUNC(void, set_keyboard_rate, (int delay, int repeat)); +AL_FUNC(int, scancode_to_ascii, (int scancode)); +AL_FUNC(AL_CONST char *, scancode_to_name, (int scancode)); + +/* The KEY_ macros are no longer #defined directly to avoid conflicting with + * linux (which has its own KEY_ constants). "__allegro_"-prefixed constants + * are used by the Allegro-Linux keyboard driver, but everyone else should + * continue to use the KEY_ constants. + */ + +enum { + __allegro_KB_SHIFT_FLAG = 0x0001, + __allegro_KB_CTRL_FLAG = 0x0002, + __allegro_KB_ALT_FLAG = 0x0004, + __allegro_KB_LWIN_FLAG = 0x0008, + __allegro_KB_RWIN_FLAG = 0x0010, + __allegro_KB_MENU_FLAG = 0x0020, + __allegro_KB_COMMAND_FLAG = 0x0040, + __allegro_KB_SCROLOCK_FLAG = 0x0100, + __allegro_KB_NUMLOCK_FLAG = 0x0200, + __allegro_KB_CAPSLOCK_FLAG = 0x0400, + __allegro_KB_INALTSEQ_FLAG = 0x0800, + __allegro_KB_ACCENT1_FLAG = 0x1000, + __allegro_KB_ACCENT2_FLAG = 0x2000, + __allegro_KB_ACCENT3_FLAG = 0x4000, + __allegro_KB_ACCENT4_FLAG = 0x8000 +}; + +enum { + __allegro_KEY_A = 1, + __allegro_KEY_B = 2, + __allegro_KEY_C = 3, + __allegro_KEY_D = 4, + __allegro_KEY_E = 5, + __allegro_KEY_F = 6, + __allegro_KEY_G = 7, + __allegro_KEY_H = 8, + __allegro_KEY_I = 9, + __allegro_KEY_J = 10, + __allegro_KEY_K = 11, + __allegro_KEY_L = 12, + __allegro_KEY_M = 13, + __allegro_KEY_N = 14, + __allegro_KEY_O = 15, + __allegro_KEY_P = 16, + __allegro_KEY_Q = 17, + __allegro_KEY_R = 18, + __allegro_KEY_S = 19, + __allegro_KEY_T = 20, + __allegro_KEY_U = 21, + __allegro_KEY_V = 22, + __allegro_KEY_W = 23, + __allegro_KEY_X = 24, + __allegro_KEY_Y = 25, + __allegro_KEY_Z = 26, + __allegro_KEY_0 = 27, + __allegro_KEY_1 = 28, + __allegro_KEY_2 = 29, + __allegro_KEY_3 = 30, + __allegro_KEY_4 = 31, + __allegro_KEY_5 = 32, + __allegro_KEY_6 = 33, + __allegro_KEY_7 = 34, + __allegro_KEY_8 = 35, + __allegro_KEY_9 = 36, + __allegro_KEY_0_PAD = 37, + __allegro_KEY_1_PAD = 38, + __allegro_KEY_2_PAD = 39, + __allegro_KEY_3_PAD = 40, + __allegro_KEY_4_PAD = 41, + __allegro_KEY_5_PAD = 42, + __allegro_KEY_6_PAD = 43, + __allegro_KEY_7_PAD = 44, + __allegro_KEY_8_PAD = 45, + __allegro_KEY_9_PAD = 46, + __allegro_KEY_F1 = 47, + __allegro_KEY_F2 = 48, + __allegro_KEY_F3 = 49, + __allegro_KEY_F4 = 50, + __allegro_KEY_F5 = 51, + __allegro_KEY_F6 = 52, + __allegro_KEY_F7 = 53, + __allegro_KEY_F8 = 54, + __allegro_KEY_F9 = 55, + __allegro_KEY_F10 = 56, + __allegro_KEY_F11 = 57, + __allegro_KEY_F12 = 58, + __allegro_KEY_ESC = 59, + __allegro_KEY_TILDE = 60, + __allegro_KEY_MINUS = 61, + __allegro_KEY_EQUALS = 62, + __allegro_KEY_BACKSPACE = 63, + __allegro_KEY_TAB = 64, + __allegro_KEY_OPENBRACE = 65, + __allegro_KEY_CLOSEBRACE = 66, + __allegro_KEY_ENTER = 67, + __allegro_KEY_COLON = 68, + __allegro_KEY_QUOTE = 69, + __allegro_KEY_BACKSLASH = 70, + __allegro_KEY_BACKSLASH2 = 71, + __allegro_KEY_COMMA = 72, + __allegro_KEY_STOP = 73, + __allegro_KEY_SLASH = 74, + __allegro_KEY_SPACE = 75, + __allegro_KEY_INSERT = 76, + __allegro_KEY_DEL = 77, + __allegro_KEY_HOME = 78, + __allegro_KEY_END = 79, + __allegro_KEY_PGUP = 80, + __allegro_KEY_PGDN = 81, + __allegro_KEY_LEFT = 82, + __allegro_KEY_RIGHT = 83, + __allegro_KEY_UP = 84, + __allegro_KEY_DOWN = 85, + __allegro_KEY_SLASH_PAD = 86, + __allegro_KEY_ASTERISK = 87, + __allegro_KEY_MINUS_PAD = 88, + __allegro_KEY_PLUS_PAD = 89, + __allegro_KEY_DEL_PAD = 90, + __allegro_KEY_ENTER_PAD = 91, + __allegro_KEY_PRTSCR = 92, + __allegro_KEY_PAUSE = 93, + __allegro_KEY_ABNT_C1 = 94, + __allegro_KEY_YEN = 95, + __allegro_KEY_KANA = 96, + __allegro_KEY_CONVERT = 97, + __allegro_KEY_NOCONVERT = 98, + __allegro_KEY_AT = 99, + __allegro_KEY_CIRCUMFLEX = 100, + __allegro_KEY_COLON2 = 101, + __allegro_KEY_KANJI = 102, + __allegro_KEY_EQUALS_PAD = 103, /* MacOS X */ + __allegro_KEY_BACKQUOTE = 104, /* MacOS X */ + __allegro_KEY_SEMICOLON = 105, /* MacOS X */ + __allegro_KEY_COMMAND = 106, /* MacOS X */ + __allegro_KEY_UNKNOWN1 = 107, + __allegro_KEY_UNKNOWN2 = 108, + __allegro_KEY_UNKNOWN3 = 109, + __allegro_KEY_UNKNOWN4 = 110, + __allegro_KEY_UNKNOWN5 = 111, + __allegro_KEY_UNKNOWN6 = 112, + __allegro_KEY_UNKNOWN7 = 113, + __allegro_KEY_UNKNOWN8 = 114, + + __allegro_KEY_MODIFIERS = 115, + + __allegro_KEY_LSHIFT = 115, + __allegro_KEY_RSHIFT = 116, + __allegro_KEY_LCONTROL = 117, + __allegro_KEY_RCONTROL = 118, + __allegro_KEY_ALT = 119, + __allegro_KEY_ALTGR = 120, + __allegro_KEY_LWIN = 121, + __allegro_KEY_RWIN = 122, + __allegro_KEY_MENU = 123, + __allegro_KEY_SCRLOCK = 124, + __allegro_KEY_NUMLOCK = 125, + __allegro_KEY_CAPSLOCK = 126, + + __allegro_KEY_MAX = 127 +}; + +#ifndef ALLEGRO_NO_KEY_DEFINES + +#define KB_SHIFT_FLAG __allegro_KB_SHIFT_FLAG +#define KB_CTRL_FLAG __allegro_KB_CTRL_FLAG +#define KB_ALT_FLAG __allegro_KB_ALT_FLAG +#define KB_LWIN_FLAG __allegro_KB_LWIN_FLAG +#define KB_RWIN_FLAG __allegro_KB_RWIN_FLAG +#define KB_MENU_FLAG __allegro_KB_MENU_FLAG +#define KB_COMMAND_FLAG __allegro_KB_COMMAND_FLAG +#define KB_SCROLOCK_FLAG __allegro_KB_SCROLOCK_FLAG +#define KB_NUMLOCK_FLAG __allegro_KB_NUMLOCK_FLAG +#define KB_CAPSLOCK_FLAG __allegro_KB_CAPSLOCK_FLAG +#define KB_INALTSEQ_FLAG __allegro_KB_INALTSEQ_FLAG +#define KB_ACCENT1_FLAG __allegro_KB_ACCENT1_FLAG +#define KB_ACCENT2_FLAG __allegro_KB_ACCENT2_FLAG +#define KB_ACCENT3_FLAG __allegro_KB_ACCENT3_FLAG +#define KB_ACCENT4_FLAG __allegro_KB_ACCENT4_FLAG + +#define KEY_A __allegro_KEY_A +#define KEY_B __allegro_KEY_B +#define KEY_C __allegro_KEY_C +#define KEY_D __allegro_KEY_D +#define KEY_E __allegro_KEY_E +#define KEY_F __allegro_KEY_F +#define KEY_G __allegro_KEY_G +#define KEY_H __allegro_KEY_H +#define KEY_I __allegro_KEY_I +#define KEY_J __allegro_KEY_J +#define KEY_K __allegro_KEY_K +#define KEY_L __allegro_KEY_L +#define KEY_M __allegro_KEY_M +#define KEY_N __allegro_KEY_N +#define KEY_O __allegro_KEY_O +#define KEY_P __allegro_KEY_P +#define KEY_Q __allegro_KEY_Q +#define KEY_R __allegro_KEY_R +#define KEY_S __allegro_KEY_S +#define KEY_T __allegro_KEY_T +#define KEY_U __allegro_KEY_U +#define KEY_V __allegro_KEY_V +#define KEY_W __allegro_KEY_W +#define KEY_X __allegro_KEY_X +#define KEY_Y __allegro_KEY_Y +#define KEY_Z __allegro_KEY_Z +#define KEY_0 __allegro_KEY_0 +#define KEY_1 __allegro_KEY_1 +#define KEY_2 __allegro_KEY_2 +#define KEY_3 __allegro_KEY_3 +#define KEY_4 __allegro_KEY_4 +#define KEY_5 __allegro_KEY_5 +#define KEY_6 __allegro_KEY_6 +#define KEY_7 __allegro_KEY_7 +#define KEY_8 __allegro_KEY_8 +#define KEY_9 __allegro_KEY_9 +#define KEY_0_PAD __allegro_KEY_0_PAD +#define KEY_1_PAD __allegro_KEY_1_PAD +#define KEY_2_PAD __allegro_KEY_2_PAD +#define KEY_3_PAD __allegro_KEY_3_PAD +#define KEY_4_PAD __allegro_KEY_4_PAD +#define KEY_5_PAD __allegro_KEY_5_PAD +#define KEY_6_PAD __allegro_KEY_6_PAD +#define KEY_7_PAD __allegro_KEY_7_PAD +#define KEY_8_PAD __allegro_KEY_8_PAD +#define KEY_9_PAD __allegro_KEY_9_PAD +#define KEY_F1 __allegro_KEY_F1 +#define KEY_F2 __allegro_KEY_F2 +#define KEY_F3 __allegro_KEY_F3 +#define KEY_F4 __allegro_KEY_F4 +#define KEY_F5 __allegro_KEY_F5 +#define KEY_F6 __allegro_KEY_F6 +#define KEY_F7 __allegro_KEY_F7 +#define KEY_F8 __allegro_KEY_F8 +#define KEY_F9 __allegro_KEY_F9 +#define KEY_F10 __allegro_KEY_F10 +#define KEY_F11 __allegro_KEY_F11 +#define KEY_F12 __allegro_KEY_F12 +#define KEY_ESC __allegro_KEY_ESC +#define KEY_TILDE __allegro_KEY_TILDE +#define KEY_MINUS __allegro_KEY_MINUS +#define KEY_EQUALS __allegro_KEY_EQUALS +#define KEY_BACKSPACE __allegro_KEY_BACKSPACE +#define KEY_TAB __allegro_KEY_TAB +#define KEY_OPENBRACE __allegro_KEY_OPENBRACE +#define KEY_CLOSEBRACE __allegro_KEY_CLOSEBRACE +#define KEY_ENTER __allegro_KEY_ENTER +#define KEY_COLON __allegro_KEY_COLON +#define KEY_QUOTE __allegro_KEY_QUOTE +#define KEY_BACKSLASH __allegro_KEY_BACKSLASH +#define KEY_BACKSLASH2 __allegro_KEY_BACKSLASH2 +#define KEY_COMMA __allegro_KEY_COMMA +#define KEY_STOP __allegro_KEY_STOP +#define KEY_SLASH __allegro_KEY_SLASH +#define KEY_SPACE __allegro_KEY_SPACE +#define KEY_INSERT __allegro_KEY_INSERT +#define KEY_DEL __allegro_KEY_DEL +#define KEY_HOME __allegro_KEY_HOME +#define KEY_END __allegro_KEY_END +#define KEY_PGUP __allegro_KEY_PGUP +#define KEY_PGDN __allegro_KEY_PGDN +#define KEY_LEFT __allegro_KEY_LEFT +#define KEY_RIGHT __allegro_KEY_RIGHT +#define KEY_UP __allegro_KEY_UP +#define KEY_DOWN __allegro_KEY_DOWN +#define KEY_SLASH_PAD __allegro_KEY_SLASH_PAD +#define KEY_ASTERISK __allegro_KEY_ASTERISK +#define KEY_MINUS_PAD __allegro_KEY_MINUS_PAD +#define KEY_PLUS_PAD __allegro_KEY_PLUS_PAD +#define KEY_DEL_PAD __allegro_KEY_DEL_PAD +#define KEY_ENTER_PAD __allegro_KEY_ENTER_PAD +#define KEY_PRTSCR __allegro_KEY_PRTSCR +#define KEY_PAUSE __allegro_KEY_PAUSE +#define KEY_ABNT_C1 __allegro_KEY_ABNT_C1 +#define KEY_YEN __allegro_KEY_YEN +#define KEY_KANA __allegro_KEY_KANA +#define KEY_CONVERT __allegro_KEY_CONVERT +#define KEY_NOCONVERT __allegro_KEY_NOCONVERT +#define KEY_AT __allegro_KEY_AT +#define KEY_CIRCUMFLEX __allegro_KEY_CIRCUMFLEX +#define KEY_COLON2 __allegro_KEY_COLON2 +#define KEY_KANJI __allegro_KEY_KANJI +#define KEY_EQUALS_PAD __allegro_KEY_EQUALS_PAD +#define KEY_BACKQUOTE __allegro_KEY_BACKQUOTE +#define KEY_SEMICOLON __allegro_KEY_SEMICOLON +#define KEY_COMMAND __allegro_KEY_COMMAND +#define KEY_UNKNOWN1 __allegro_KEY_UNKNOWN1 +#define KEY_UNKNOWN2 __allegro_KEY_UNKNOWN2 +#define KEY_UNKNOWN3 __allegro_KEY_UNKNOWN3 +#define KEY_UNKNOWN4 __allegro_KEY_UNKNOWN4 +#define KEY_UNKNOWN5 __allegro_KEY_UNKNOWN5 +#define KEY_UNKNOWN6 __allegro_KEY_UNKNOWN6 +#define KEY_UNKNOWN7 __allegro_KEY_UNKNOWN7 +#define KEY_UNKNOWN8 __allegro_KEY_UNKNOWN8 + +#define KEY_MODIFIERS __allegro_KEY_MODIFIERS + +#define KEY_LSHIFT __allegro_KEY_LSHIFT +#define KEY_RSHIFT __allegro_KEY_RSHIFT +#define KEY_LCONTROL __allegro_KEY_LCONTROL +#define KEY_RCONTROL __allegro_KEY_RCONTROL +#define KEY_ALT __allegro_KEY_ALT +#define KEY_ALTGR __allegro_KEY_ALTGR +#define KEY_LWIN __allegro_KEY_LWIN +#define KEY_RWIN __allegro_KEY_RWIN +#define KEY_MENU __allegro_KEY_MENU +#define KEY_SCRLOCK __allegro_KEY_SCRLOCK +#define KEY_NUMLOCK __allegro_KEY_NUMLOCK +#define KEY_CAPSLOCK __allegro_KEY_CAPSLOCK + +#define KEY_MAX __allegro_KEY_MAX + +#endif /* ALLEGRO_NO_KEY_DEFINES */ + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_KEYBOARD_H */ + + diff --git a/allegro/allegro/lzss.h b/allegro/allegro/lzss.h new file mode 100644 index 0000000000..f6bc91dd87 --- /dev/null +++ b/allegro/allegro/lzss.h @@ -0,0 +1,47 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Compression routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_LZSS_H +#define ALLEGRO_LZSS_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct LZSS_PACK_DATA LZSS_PACK_DATA; +typedef struct LZSS_UNPACK_DATA LZSS_UNPACK_DATA; + + +AL_FUNC(LZSS_PACK_DATA *, create_lzss_pack_data, (void)); +AL_FUNC(void, free_lzss_pack_data, (LZSS_PACK_DATA *dat)); +AL_FUNC(int, lzss_write, (PACKFILE *file, LZSS_PACK_DATA *dat, int size, unsigned char *buf, int last)); + +AL_FUNC(LZSS_UNPACK_DATA *, create_lzss_unpack_data, (void)); +AL_FUNC(void, free_lzss_unpack_data, (LZSS_UNPACK_DATA *dat)); +AL_FUNC(int, lzss_read, (PACKFILE *file, LZSS_UNPACK_DATA *dat, int s, unsigned char *buf)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_LZSS_H */ + + diff --git a/allegro/allegro/matrix.h b/allegro/allegro/matrix.h new file mode 100644 index 0000000000..3b24b6421b --- /dev/null +++ b/allegro/allegro/matrix.h @@ -0,0 +1,96 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Matrix math routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_MATRIX_H +#define ALLEGRO_MATRIX_H + +#include "base.h" +#include "fixed.h" +#include "fmaths.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct MATRIX /* transformation matrix (fixed point) */ +{ + fixed v[3][3]; /* scaling and rotation */ + fixed t[3]; /* translation */ +} MATRIX; + + +typedef struct MATRIX_f /* transformation matrix (floating point) */ +{ + float v[3][3]; /* scaling and rotation */ + float t[3]; /* translation */ +} MATRIX_f; + + +AL_VAR(MATRIX, identity_matrix); +AL_VAR(MATRIX_f, identity_matrix_f); + +AL_FUNC(void, get_translation_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); +AL_FUNC(void, get_translation_matrix_f, (MATRIX_f *m, float x, float y, float z)); + +AL_FUNC(void, get_scaling_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); +AL_FUNC(void, get_scaling_matrix_f, (MATRIX_f *m, float x, float y, float z)); + +AL_FUNC(void, get_x_rotate_matrix, (MATRIX *m, fixed r)); +AL_FUNC(void, get_x_rotate_matrix_f, (MATRIX_f *m, float r)); + +AL_FUNC(void, get_y_rotate_matrix, (MATRIX *m, fixed r)); +AL_FUNC(void, get_y_rotate_matrix_f, (MATRIX_f *m, float r)); + +AL_FUNC(void, get_z_rotate_matrix, (MATRIX *m, fixed r)); +AL_FUNC(void, get_z_rotate_matrix_f, (MATRIX_f *m, float r)); + +AL_FUNC(void, get_rotation_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); +AL_FUNC(void, get_rotation_matrix_f, (MATRIX_f *m, float x, float y, float z)); + +AL_FUNC(void, get_align_matrix, (MATRIX *m, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup)); +AL_FUNC(void, get_align_matrix_f, (MATRIX_f *m, float xfront, float yfront, float zfront, float xup, float yup, float zup)); + +AL_FUNC(void, get_vector_rotation_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed a)); +AL_FUNC(void, get_vector_rotation_matrix_f, (MATRIX_f *m, float x, float y, float z, float a)); + +AL_FUNC(void, get_transformation_matrix, (MATRIX *m, fixed scale, fixed xrot, fixed yrot, fixed zrot, fixed x, fixed y, fixed z)); +AL_FUNC(void, get_transformation_matrix_f, (MATRIX_f *m, float scale, float xrot, float yrot, float zrot, float x, float y, float z)); + +AL_FUNC(void, get_camera_matrix, (MATRIX *m, fixed x, fixed y, fixed z, fixed xfront, fixed yfront, fixed zfront, fixed xup, fixed yup, fixed zup, fixed fov, fixed aspect)); +AL_FUNC(void, get_camera_matrix_f, (MATRIX_f *m, float x, float y, float z, float xfront, float yfront, float zfront, float xup, float yup, float zup, float fov, float aspect)); + +AL_FUNC(void, qtranslate_matrix, (MATRIX *m, fixed x, fixed y, fixed z)); +AL_FUNC(void, qtranslate_matrix_f, (MATRIX_f *m, float x, float y, float z)); + +AL_FUNC(void, qscale_matrix, (MATRIX *m, fixed scale)); +AL_FUNC(void, qscale_matrix_f, (MATRIX_f *m, float scale)); + +AL_FUNC(void, matrix_mul, (AL_CONST MATRIX *m1, AL_CONST MATRIX *m2, MATRIX *out)); +AL_FUNC(void, matrix_mul_f, (AL_CONST MATRIX_f *m1, AL_CONST MATRIX_f *m2, MATRIX_f *out)); + +AL_FUNC(void, apply_matrix_f, (AL_CONST MATRIX_f *m, float x, float y, float z, float *xout, float *yout, float *zout)); + +#ifdef __cplusplus + } +#endif + +#include "inline/matrix.inl" + +#endif /* ifndef ALLEGRO_MATRIX_H */ + + diff --git a/allegro/allegro/midi.h b/allegro/allegro/midi.h new file mode 100644 index 0000000000..26c7a81c0f --- /dev/null +++ b/allegro/allegro/midi.h @@ -0,0 +1,144 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * MIDI music routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_MIDI_H +#define ALLEGRO_MIDI_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + /* Theoretical maximums: */ +#define MIDI_VOICES 64 /* actual drivers may not be */ +#define MIDI_TRACKS 32 /* able to handle this many */ + + + +typedef struct MIDI /* a midi file */ +{ + int divisions; /* number of ticks per quarter note */ + struct { + unsigned char *data; /* MIDI message stream */ + int len; /* length of the track data */ + } track[MIDI_TRACKS]; +} MIDI; + + + +#define MIDI_AUTODETECT -1 +#define MIDI_NONE 0 +#define MIDI_DIGMID AL_ID('D','I','G','I') + +typedef struct MIDI_DRIVER /* driver for playing midi music */ +{ + int id; /* driver ID code */ + AL_CONST char *name; /* driver name */ + AL_CONST char *desc; /* description string */ + AL_CONST char *ascii_name; /* ASCII format name string */ + int voices; /* available voices */ + int basevoice; /* voice number offset */ + int max_voices; /* maximum voices we can support */ + int def_voices; /* default number of voices to use */ + int xmin, xmax; /* reserved voice range */ + + /* setup routines */ + AL_METHOD(int, detect, (int input)); + AL_METHOD(int, init, (int input, int voices)); + AL_METHOD(void, exit, (int input)); + AL_METHOD(int, set_mixer_volume, (int volume)); + AL_METHOD(int, get_mixer_volume, (void)); + + /* raw MIDI output to MPU-401, etc. */ + AL_METHOD(void, raw_midi, (int data)); + + /* dynamic patch loading routines */ + AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); + AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); + + /* note control functions */ + AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); + AL_METHOD(void, key_off, (int voice)); + AL_METHOD(void, set_volume, (int voice, int vol)); + AL_METHOD(void, set_pitch, (int voice, int note, int bend)); + AL_METHOD(void, set_pan, (int voice, int pan)); + AL_METHOD(void, set_vibrato, (int voice, int amount)); +} MIDI_DRIVER; + + +AL_VAR(MIDI_DRIVER, midi_digmid); + +AL_ARRAY(_DRIVER_INFO, _midi_driver_list); + + +/* macros for constructing the driver lists */ +#define BEGIN_MIDI_DRIVER_LIST \ + _DRIVER_INFO _midi_driver_list[] = \ + { + +#define END_MIDI_DRIVER_LIST \ + { 0, NULL, 0 } \ + }; + +#define MIDI_DRIVER_DIGMID \ + { MIDI_DIGMID, &midi_digmid, TRUE }, + + +AL_VAR(MIDI_DRIVER *, midi_driver); + +AL_VAR(MIDI_DRIVER *, midi_input_driver); + +AL_VAR(int, midi_card); + +AL_VAR(int, midi_input_card); + +AL_VAR(volatile long, midi_pos); /* current position in the midi file, in beats */ +AL_VAR(volatile long, midi_time); /* current position in the midi file, in seconds */ + +AL_VAR(long, midi_loop_start); /* where to loop back to at EOF */ +AL_VAR(long, midi_loop_end); /* loop when we hit this position */ + +AL_FUNC(int, detect_midi_driver, (int driver_id)); + +AL_FUNC(MIDI *, load_midi, (AL_CONST char *filename)); +AL_FUNC(void, destroy_midi, (MIDI *midi)); +AL_FUNC(int, play_midi, (MIDI *midi, int loop)); +AL_FUNC(int, play_looped_midi, (MIDI *midi, int loop_start, int loop_end)); +AL_FUNC(void, stop_midi, (void)); +AL_FUNC(void, midi_pause, (void)); +AL_FUNC(void, midi_resume, (void)); +AL_FUNC(int, midi_seek, (int target)); +AL_FUNC(int, get_midi_length, (MIDI *midi)); +AL_FUNC(void, midi_out, (unsigned char *data, int length)); +AL_FUNC(int, load_midi_patches, (void)); + +AL_FUNCPTR(void, midi_msg_callback, (int msg, int byte1, int byte2)); +AL_FUNCPTR(void, midi_meta_callback, (int type, AL_CONST unsigned char *data, int length)); +AL_FUNCPTR(void, midi_sysex_callback, (AL_CONST unsigned char *data, int length)); + +AL_FUNCPTR(void, midi_recorder, (unsigned char data)); + +AL_FUNC(void, lock_midi, (struct MIDI *midi)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_MIDI_H */ + + diff --git a/allegro/allegro/mouse.h b/allegro/allegro/mouse.h new file mode 100644 index 0000000000..a4093984e5 --- /dev/null +++ b/allegro/allegro/mouse.h @@ -0,0 +1,120 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Mouse routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_MOUSE_H +#define ALLEGRO_MOUSE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define MOUSEDRV_AUTODETECT -1 +#define MOUSEDRV_NONE 0 + + +typedef struct MOUSE_DRIVER +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); + AL_METHOD(void, poll, (void)); + AL_METHOD(void, timer_poll, (void)); + AL_METHOD(void, position, (int x, int y)); + AL_METHOD(void, set_range, (int x1, int y_1, int x2, int y2)); + AL_METHOD(void, set_speed, (int xspeed, int yspeed)); + AL_METHOD(void, get_mickeys, (int *mickeyx, int *mickeyy)); + AL_METHOD(int, analyse_data, (AL_CONST char *buffer, int size)); + AL_METHOD(void, enable_hardware_cursor, (int mode)); + AL_METHOD(int, select_system_cursor, (int cursor)); +} MOUSE_DRIVER; + + +AL_VAR(MOUSE_DRIVER, mousedrv_none); +AL_VAR(MOUSE_DRIVER *, mouse_driver); +AL_ARRAY(_DRIVER_INFO, _mouse_driver_list); + +AL_FUNC(int, install_mouse, (void)); +AL_FUNC(void, remove_mouse, (void)); + +AL_FUNC(int, poll_mouse, (void)); +AL_FUNC(int, mouse_needs_poll, (void)); + +AL_FUNC(void, enable_hardware_cursor, (void)); +AL_FUNC(void, disable_hardware_cursor, (void)); + +/* Mouse cursors */ +#define MOUSE_CURSOR_NONE 0 +#define MOUSE_CURSOR_ALLEGRO 1 +#define MOUSE_CURSOR_ARROW 2 +#define MOUSE_CURSOR_BUSY 3 +#define MOUSE_CURSOR_QUESTION 4 +#define MOUSE_CURSOR_EDIT 5 +#define AL_NUM_MOUSE_CURSORS 6 + +AL_VAR(struct BITMAP *, mouse_sprite); +AL_VAR(int, mouse_x_focus); +AL_VAR(int, mouse_y_focus); + +AL_VAR(volatile int, mouse_x); +AL_VAR(volatile int, mouse_y); +AL_VAR(volatile int, mouse_z); +AL_VAR(volatile int, mouse_w); +AL_VAR(volatile int, mouse_b); +AL_VAR(volatile int, mouse_pos); + +AL_VAR(volatile int, freeze_mouse_flag); + +#define MOUSE_FLAG_MOVE 1 +#define MOUSE_FLAG_LEFT_DOWN 2 +#define MOUSE_FLAG_LEFT_UP 4 +#define MOUSE_FLAG_RIGHT_DOWN 8 +#define MOUSE_FLAG_RIGHT_UP 16 +#define MOUSE_FLAG_MIDDLE_DOWN 32 +#define MOUSE_FLAG_MIDDLE_UP 64 +#define MOUSE_FLAG_MOVE_Z 128 +#define MOUSE_FLAG_MOVE_W 256 + +AL_FUNCPTR(void, mouse_callback, (int flags)); + +AL_FUNC(void, show_mouse, (struct BITMAP *bmp)); +AL_FUNC(void, scare_mouse, (void)); +AL_FUNC(void, scare_mouse_area, (int x, int y, int w, int h)); +AL_FUNC(void, unscare_mouse, (void)); +AL_FUNC(void, position_mouse, (int x, int y)); +AL_FUNC(void, position_mouse_z, (int z)); +AL_FUNC(void, position_mouse_w, (int w)); +AL_FUNC(void, set_mouse_range, (int x1, int y_1, int x2, int y2)); +AL_FUNC(void, set_mouse_speed, (int xspeed, int yspeed)); +AL_FUNC(void, select_mouse_cursor, (int cursor)); +AL_FUNC(void, set_mouse_cursor_bitmap, (int cursor, struct BITMAP *bmp)); +AL_FUNC(void, set_mouse_sprite_focus, (int x, int y)); +AL_FUNC(void, get_mouse_mickeys, (int *mickeyx, int *mickeyy)); +AL_FUNC(void, set_mouse_sprite, (struct BITMAP *sprite)); +AL_FUNC(int, show_os_cursor, (int cursor)); +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_MOUSE_H */ + + diff --git a/allegro/allegro/palette.h b/allegro/allegro/palette.h new file mode 100644 index 0000000000..7843421a06 --- /dev/null +++ b/allegro/allegro/palette.h @@ -0,0 +1,42 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Palette type. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_PALETTE_H +#define ALLEGRO_PALETTE_H + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct RGB +{ + unsigned char r, g, b; + unsigned char filler; +} RGB; + +#define PAL_SIZE 256 + +typedef RGB PALETTE[PAL_SIZE]; + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_PALETTE_H */ + + diff --git a/allegro/allegro/platform/aintbeos.h b/allegro/allegro/platform/aintbeos.h new file mode 100644 index 0000000000..72e33854b2 --- /dev/null +++ b/allegro/allegro/platform/aintbeos.h @@ -0,0 +1,151 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Definitions for internal use by the BeOS configuration. + * + * By Jason Wilkins. + * + * See readme.txt for copyright information. + */ + + +#include "bealleg.h" + +#ifdef __cplusplus +extern status_t ignore_result; + +extern volatile int32 focus_count; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define WND_TITLE_SIZE 128 + +AL_ARRAY(char, wnd_title); + +int be_key_init(void); +void be_key_exit(void); +void be_key_set_leds(int leds); +void be_key_set_rate(int delay, int repeat); +void be_key_wait_for_input(void); +void be_key_stop_waiting_for_input(void); +void be_key_suspend(void); +void be_key_resume(void); + +int be_sys_init(void); +void be_sys_exit(void); +void _be_sys_get_executable_name(char *output, int size); +void be_sys_get_executable_name(char *output, int size); +int be_sys_find_resource(char *dest, AL_CONST char *resource, int size); +void be_sys_set_window_title(AL_CONST char *name); +int be_sys_set_close_button_callback(void (*proc)(void)); +void be_sys_message(AL_CONST char *msg); +int be_sys_set_display_switch_mode(int mode); +int be_sys_desktop_color_depth(void); +int be_sys_get_desktop_resolution(int *width, int *height); +void be_sys_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode); +void be_sys_yield_timeslice(void); +void *be_sys_create_mutex(void); +void be_sys_destroy_mutex(void *handle); +void be_sys_lock_mutex(void *handle); +void be_sys_unlock_mutex(void *handle); +void be_sys_suspend(void); +void be_sys_resume(void); +void be_main_suspend(void); +void be_main_resume(void); + +struct BITMAP *be_gfx_bwindowscreen_accel_init(int w, int h, int v_w, int v_h, int color_depth); +struct BITMAP *be_gfx_bwindowscreen_init(int w, int h, int v_w, int v_h, int color_depth); +void be_gfx_bwindowscreen_exit(struct BITMAP *b); +void be_gfx_bwindowscreen_acquire(struct BITMAP *b); +void be_gfx_bwindowscreen_release(struct BITMAP *b); +void be_gfx_bwindowscreen_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); +int be_gfx_bwindowscreen_scroll(int x, int y); +int be_gfx_bwindowscreen_request_scroll(int x, int y); +int be_gfx_bwindowscreen_poll_scroll(void); +int be_gfx_bwindowscreen_request_video_bitmap(struct BITMAP *bitmap); +void be_gfx_vsync(void); +struct GFX_MODE_LIST *be_gfx_bwindowscreen_fetch_mode_list(void); +void be_gfx_bwindowscreen_accelerate(int color_depth); +#ifdef ALLEGRO_NO_ASM +uintptr_t be_gfx_bwindowscreen_read_write_bank(BITMAP *bmp, int lyne); +void be_gfx_bwindowscreen_unwrite_bank(BITMAP *bmp); +#else +uintptr_t _be_gfx_bwindowscreen_read_write_bank_asm(BITMAP *bmp, int lyne); +void _be_gfx_bwindowscreen_unwrite_bank_asm(BITMAP *bmp); +#endif + +struct BITMAP *be_gfx_bdirectwindow_init(int w, int h, int v_w, int v_h, int color_depth); +void be_gfx_bdirectwindow_exit(struct BITMAP *b); +void be_gfx_bdirectwindow_acquire(struct BITMAP *bmp); +void be_gfx_bdirectwindow_release(struct BITMAP *bmp); +void be_gfx_bdirectwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); + +struct BITMAP *be_gfx_bwindow_init(int w, int h, int v_w, int v_h, int color_depth); +void be_gfx_bwindow_exit(struct BITMAP *b); +void be_gfx_bwindow_acquire(struct BITMAP *bmp); +void be_gfx_bwindow_release(struct BITMAP *bmp); +void be_gfx_bwindow_set_palette(AL_CONST struct RGB *p, int from, int to, int vsync); + +#ifdef ALLEGRO_NO_ASM +void _be_gfx_bwindow_unwrite_bank(BITMAP *bmp); +uintptr_t _be_gfx_bwindow_read_write_bank(BITMAP *bmp, int lyne); +#else +void _be_gfx_bwindow_unwrite_bank_asm(BITMAP *bmp); +uintptr_t _be_gfx_bwindow_read_write_bank_asm(BITMAP *bmp, int lyne); +#endif + +struct BITMAP *be_gfx_overlay_init(int w, int h, int v_w, int v_h, int color_depth); +void be_gfx_overlay_exit(struct BITMAP *b); + +int be_time_init(void); +void be_time_exit(void); +void be_time_rest(unsigned int tyme, AL_METHOD(void, callback, (void))); +void be_time_suspend(void); +void be_time_resume(void); + +int be_mouse_init(void); +void be_mouse_exit(void); +void be_mouse_position(int x, int y); +void be_mouse_set_range(int x1, int y_1, int x2, int y2); +void be_mouse_set_speed(int xspeed, int yspeed); +void be_mouse_get_mickeys(int *mickeyx, int *mickeyy); + +int be_joy_init(void); +void be_joy_exit(void); +int be_joy_poll(void); + +int be_sound_detect(int input); +int be_sound_init(int input, int voices); +void be_sound_exit(int input); +void *be_sound_lock_voice(int voice, int start, int end); +void be_sound_unlock_voice(int voice); +int be_sound_buffer_size(void); +int be_sound_set_mixer_volume(int volume); +int be_sound_get_mixer_volume(void); +void be_sound_suspend(void); +void be_sound_resume(void); + +int be_midi_detect(int input); +int be_midi_init(int input, int voices); +void be_midi_exit(int input); +int be_midi_set_mixer_volume(int volume); +int be_midi_get_mixer_volume(void); +void be_midi_key_on(int inst, int note, int bend, int vol, int pan); +void be_midi_key_off(int voice); +void be_midi_set_volume(int voice, int vol); +void be_midi_set_pitch(int voice, int note, int bend); +void be_midi_set_pan(int voice, int pan); + +#ifdef __cplusplus +} +#endif diff --git a/allegro/allegro/platform/aintdos.h b/allegro/allegro/platform/aintdos.h new file mode 100644 index 0000000000..c01b254f71 --- /dev/null +++ b/allegro/allegro/platform/aintdos.h @@ -0,0 +1,184 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the DOS library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTDOS_H +#define AINTDOS_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifndef ALLEGRO_DOS + #error bad include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* macros to enable and disable interrupts */ +#if defined ALLEGRO_GCC + + #define DISABLE() asm volatile ("cli") + #define ENABLE() asm volatile ("sti") + +#elif defined ALLEGRO_WATCOM + + void DISABLE(void); + void ENABLE(void); + + #pragma aux DISABLE = "cli"; + #pragma aux ENABLE = "sti"; + +#else + + #define DISABLE() asm { cli } + #define ENABLE() asm { sti } + +#endif + + +AL_INLINE(void, _enter_critical, (void), +{ + /* check if windows is running */ + if ((os_type == OSTYPE_WIN3) || (os_type == OSTYPE_WIN95) || + (os_type == OSTYPE_WIN98) || (os_type == OSTYPE_WINME) || + (os_type == OSTYPE_WINNT) || (os_type == OSTYPE_WIN2000)) { + __dpmi_regs r; + r.x.ax = 0x1681; + __dpmi_int(0x2F, &r); + } + + DISABLE(); +}) + + +AL_INLINE(void, _exit_critical, (void), +{ + /* check if windows is running */ + if ((os_type == OSTYPE_WIN3) || (os_type == OSTYPE_WIN95) || + (os_type == OSTYPE_WIN98) || (os_type == OSTYPE_WINME) || + (os_type == OSTYPE_WINNT) || (os_type == OSTYPE_WIN2000)) { + __dpmi_regs r; + r.x.ax = 0x1682; + __dpmi_int(0x2F, &r); + } + + ENABLE(); +}) + + +/* interrupt hander stuff */ +AL_FUNC(void, _dos_irq_init, (void)); +AL_FUNC(void, _dos_irq_exit, (void)); + +#define _map_irq(irq) (((irq)>7) ? ((irq)+104) : ((irq)+8)) + +AL_FUNC(int, _install_irq, (int num, AL_METHOD(int, handler, (void)))); +AL_FUNC(void, _remove_irq, (int num)); +AL_FUNC(void, _restore_irq, (int irq)); +AL_FUNC(void, _enable_irq, (int irq)); +AL_FUNC(void, _disable_irq, (int irq)); + +#define _eoi(irq) { outportb(0x20, 0x20); if ((irq)>7) outportb(0xA0, 0x20); } + +typedef struct _IRQ_HANDLER +{ + AL_METHOD(int, handler, (void)); /* our C handler */ + int number; /* irq number */ + + #ifdef ALLEGRO_DJGPP + __dpmi_paddr old_vector; /* original protected mode vector */ + #else + void (__interrupt __far *old_vector)(); + #endif +} _IRQ_HANDLER; + + +/* sound lib stuff */ +AL_VAR(int, _fm_port); +AL_VAR(int, _mpu_port); +AL_VAR(int, _mpu_irq); + + +/* DPMI memory mapping routines */ +AL_FUNC(int, _create_physical_mapping, (unsigned long *linear, int *segment, unsigned long physaddr, int size)); +AL_FUNC(void, _remove_physical_mapping, (unsigned long *linear, int *segment)); +AL_FUNC(int, _create_linear_mapping, (unsigned long *linear, unsigned long physaddr, int size)); +AL_FUNC(void, _remove_linear_mapping, (unsigned long *linear)); +AL_FUNC(int, _create_selector, (int *segment, unsigned long linear, int size)); +AL_FUNC(void, _remove_selector, (int *segment)); +AL_FUNC(void, _unlock_dpmi_data, (void *addr, int size)); + + +/* bank switching routines (these use a non-C calling convention on i386!) */ +AL_FUNC(void, _vesa_window_1, (void)); +AL_FUNC(void, _vesa_window_1_end, (void)); + +AL_FUNC(void, _vesa_window_2, (void)); +AL_FUNC(void, _vesa_window_2_end, (void)); + +AL_FUNC(void, _vesa_pm_window_1, (void)); +AL_FUNC(void, _vesa_pm_window_1_end, (void)); + +AL_FUNC(void, _vesa_pm_window_2, (void)); +AL_FUNC(void, _vesa_pm_window_2_end, (void)); + +AL_FUNC(void, _vesa_pm_es_window_1, (void)); +AL_FUNC(void, _vesa_pm_es_window_1_end, (void)); + +AL_FUNC(void, _vesa_pm_es_window_2, (void)); +AL_FUNC(void, _vesa_pm_es_window_2_end, (void)); + + +/* stuff for the VESA driver */ +AL_VAR(__dpmi_regs, _dpmi_reg); + +AL_VAR(int, _window_2_offset); + +AL_VAR(int, _mmio_segment); + +AL_FUNCPTR(void, _pm_vesa_switcher, (void)); +AL_FUNCPTR(void, _pm_vesa_scroller, (void)); +AL_FUNCPTR(void, _pm_vesa_palette, (void)); + + +AL_FUNC(int, _sb_read_dsp_version, (void)); +AL_FUNC(int, _sb_reset_dsp, (int data)); +AL_FUNC(void, _sb_voice, (int state)); +AL_FUNC(int, _sb_set_mixer, (int digi_volume, int midi_volume)); + +AL_FUNC(void, _mpu_poll, (void)); + +AL_FUNC(int, _dma_allocate_mem, (int bytes, int *sel, unsigned long *phys)); +AL_FUNC(void, _dma_start, (int channel, unsigned long addr, int size, int auto_init, int input)); +AL_FUNC(void, _dma_stop, (int channel)); +AL_FUNC(unsigned long, _dma_todo, (int channel)); +AL_FUNC(void, _dma_lock_mem, (void)); + + + +#ifdef __cplusplus + } +#endif + +/* VGA register access helpers */ +#include "allegro/internal/aintvga.h" + +#endif /* ifndef AINTDOS_H */ diff --git a/allegro/allegro/platform/aintlnx.h b/allegro/allegro/platform/aintlnx.h new file mode 100644 index 0000000000..3be5df8133 --- /dev/null +++ b/allegro/allegro/platform/aintlnx.h @@ -0,0 +1,258 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the Linux console code. + * + * By George Foot. + * + * See readme.txt for copyright information. + */ + +#ifndef AINTLNX_H +#define AINTLNX_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/**************************************/ +/************ Driver lists ************/ +/**************************************/ + +extern _DRIVER_INFO _linux_gfx_driver_list[]; +extern _DRIVER_INFO _linux_keyboard_driver_list[]; +extern _DRIVER_INFO _linux_mouse_driver_list[]; +extern _DRIVER_INFO _linux_timer_driver_list[]; +extern _DRIVER_INFO _linux_joystick_driver_list[]; + + +/****************************************/ +/************ Memory mapping ************/ /* (src/linux/lmemory.c) */ +/****************************************/ + +/* struct MAPPED_MEMORY: Used to describe a block of memory mapped + * into our address space (in particular, the video memory). + */ +struct MAPPED_MEMORY { + unsigned int base, size; /* linear address and size of block */ + int perms; /* PROT_READ | PROT_WRITE, etc */ + void *data; /* pointer to block after mapping */ +}; + +extern int __al_linux_have_ioperms; + +int __al_linux_init_memory (void); +int __al_linux_shutdown_memory (void); +int __al_linux_map_memory (struct MAPPED_MEMORY *info); +int __al_linux_unmap_memory (struct MAPPED_MEMORY *info); + + +/******************************************/ +/************ Standard drivers ************/ /* (src/linux/lstddrv.c) */ +/******************************************/ + +/* This "standard drivers" business is mostly a historical artifact. + * It was highly over-engineered, now simplified. It has been mostly + * superseded by the newer, shinier, better bg_man. But hey, at least + * it didn't suffer the fate of its cousin lasyncio.c, now dead, + * buried, and without a tombstone to show for it. --pw + */ + +typedef struct STD_DRIVER { + unsigned type; /* One of the below STD_ constants */ + + int (*update) (void); + void (*resume) (void); + void (*suspend) (void); + + int fd; /* Descriptor of the opened device */ +} STD_DRIVER; + +#define STD_MOUSE 0 +#define STD_KBD 1 + +#define N_STD_DRIVERS 2 + +/* List of standard drivers */ +extern STD_DRIVER *__al_linux_std_drivers[]; + +/* Exported functions */ +int __al_linux_add_standard_driver (STD_DRIVER *spec); +int __al_linux_remove_standard_driver (STD_DRIVER *spec); +void __al_linux_update_standard_drivers (int threaded); +void __al_linux_suspend_standard_drivers (void); +void __al_linux_resume_standard_drivers (void); + + +/******************************************/ +/************ Console routines ************/ /* (src/linux/lconsole.c) */ +/******************************************/ + +#define N_CRTC_REGS 24 +#define N_ATC_REGS 21 +#define N_GC_REGS 9 +#define N_SEQ_REGS 5 + +#define MISC_REG_R 0x03CC +#define MISC_REG_W 0x03C2 +#define ATC_REG_IW 0x03C0 +#define ATC_REG_R 0x03C1 +#define GC_REG_I 0x03CE +#define GC_REG_RW 0x03CF +#define SEQ_REG_I 0x03C4 +#define SEQ_REG_RW 0x03C5 +#define PEL_REG_IW 0x03C8 +#define PEL_REG_IR 0x03C7 +#define PEL_REG_D 0x03C9 + +#define _is1 0x03DA + +#define ATC_DELAY 10 /* microseconds - for usleep() */ + +#define VGA_MEMORY_BASE 0xA0000 +#define VGA_MEMORY_SIZE 0x10000 +#define VGA_FONT_SIZE 0x02000 + +/* This structure is also used for video state saving/restoring, therefore it + * contains fields that are used only when saving/restoring the text mode. */ +typedef struct MODE_REGISTERS +{ + unsigned char crt[N_CRTC_REGS]; + unsigned char seq[N_SEQ_REGS]; + unsigned char atc[N_ATC_REGS]; + unsigned char gc[N_GC_REGS]; + unsigned char misc; + unsigned char *ext; + unsigned short ext_count; + unsigned char *text_font1; + unsigned char *text_font2; + unsigned long flags; + union { + unsigned char vga[768]; + PALETTE allegro; + } palette; +} MODE_REGISTERS; + +extern int __al_linux_vt; +extern int __al_linux_console_fd; +extern int __al_linux_prev_vt; +extern int __al_linux_got_text_message; +extern struct termios __al_linux_startup_termio; +extern struct termios __al_linux_work_termio; + +int __al_linux_use_console (void); +int __al_linux_leave_console (void); + +int __al_linux_console_graphics (void); +int __al_linux_console_text (void); + +int __al_linux_wait_for_display (void); + + +/*************************************/ +/************ VGA helpers ************/ /* (src/linux/lvgahelp.c) */ +/*************************************/ + +int __al_linux_init_vga_helpers (void); +int __al_linux_shutdown_vga_helpers (void); + +void __al_linux_screen_off (void); +void __al_linux_screen_on (void); + +void __al_linux_clear_vram (void); + +void __al_linux_set_vga_regs (MODE_REGISTERS *regs); +void __al_linux_get_vga_regs (MODE_REGISTERS *regs); + +void __al_linux_save_gfx_mode (void); +void __al_linux_restore_gfx_mode (void); +void __al_linux_save_text_mode (void); +void __al_linux_restore_text_mode (void); + +#define __just_a_moment() usleep(ATC_DELAY) + + +/**************************************/ +/************ VT switching ************/ /* (src/linux/vtswitch.c) */ +/**************************************/ + +/* signals for VT switching */ +#define SIGRELVT SIGUSR1 +#define SIGACQVT SIGUSR2 + +int __al_linux_init_vtswitch (void); +int __al_linux_done_vtswitch (void); + +void __al_linux_acquire_bitmap (BITMAP *bmp); +void __al_linux_release_bitmap (BITMAP *bmp); + +int __al_linux_set_display_switch_mode (int mode); +void __al_linux_display_switch_lock (int lock, int foreground); + +extern volatile int __al_linux_switching_blocked; + + +/**************************************/ +/************ Mode setting ************/ /* (src/linux/lgraph.c) */ +/**************************************/ + +typedef struct GFX_MODE_INFO { + int w,h,c; /* width, height, colour depth */ + int id; /* ID code, for driver's reference */ + void *data; /* data for driver's use in setting the mode */ +} GFX_MODE_INFO; + +BITMAP *__al_linux_gfx_mode_set_helper ( + int w, int h, int v_w, int v_h, int c, + GFX_DRIVER *driver, GFX_MODE_INFO *mode, + int (*set_video_mode) (GFX_MODE_INFO *mode), + void (*set_width) (int w) +); + + +/*******************************/ +/************ Mouse ************/ /* (src/linux/lmouse.c) */ +/*******************************/ + +typedef struct INTERNAL_MOUSE_DRIVER { + int device; + int (*process) (unsigned char *buf, int buf_size); + int num_buttons; +} INTERNAL_MOUSE_DRIVER; + +int __al_linux_mouse_init (INTERNAL_MOUSE_DRIVER *drv); +void __al_linux_mouse_exit (void); +void __al_linux_mouse_position (int x, int y); +void __al_linux_mouse_set_range (int x1, int y_1, int x2, int y2); +void __al_linux_mouse_set_speed (int xspeed, int yspeed); +void __al_linux_mouse_get_mickeys (int *mickeyx, int *mickeyy); +void __al_linux_mouse_handler (int x, int y, int z, int b); + + +#ifdef __cplusplus +} +#endif + +/* VGA register access helpers */ +/* This is conditional because configure may have disabled VGA support */ +#ifdef ALLEGRO_LINUX_VGA + #include "allegro/internal/aintern.h" + #include "allegro/internal/aintvga.h" +#endif + +/* Functions for querying the framebuffer, for the fbcon driver */ +#if (defined ALLEGRO_LINUX_FBCON) && (!defined ALLEGRO_WITH_MODULES) + extern int __al_linux_get_fb_color_depth(void); + extern int __al_linux_get_fb_resolution(int *width, int *height); +#endif + +#endif /* ifndef AINTLNX_H */ + diff --git a/allegro/allegro/platform/aintmac.h b/allegro/allegro/platform/aintmac.h new file mode 100644 index 0000000000..0625ce17f3 --- /dev/null +++ b/allegro/allegro/platform/aintmac.h @@ -0,0 +1,95 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the MacOs library code. + * + * By Ronaldo Hideki Yamada. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTMAC_H +#define AINTMAC_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifndef ALLEGRO_MPW + #error bad include +#endif + +#include "macalleg.h" +#include "allegro/aintern.h" + +#ifdef __cplusplus + extern "C" { +#endif + +/*macsbmp.c*/ +extern void _mac_init_system_bitmap(void); +extern BITMAP *_mac_create_system_bitmap(int w, int h); +extern void _mac_destroy_system_bitmap(BITMAP *bmp); +extern void _mac_sys_set_clip(struct BITMAP *dst); +extern void _mac_sys_clear_to_color8(BITMAP *bmp, int color); +extern void _mac_sys_blit8(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h); +extern void _mac_sys_selfblit8(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h); +extern int _mac_sys_triangle(struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int x3, int y3, int color); +extern void _mac_sys_rectfill8(struct BITMAP *bmp, int x1, int y_1, int x2, int y2, int color); +extern void _mac_sys_hline8(struct BITMAP *bmp, int x1, int y, int x2, int color); +extern void _mac_sys_vline8(struct BITMAP *bmp, int x, int y_1, int y2, int color); +extern BITMAP *_CGrafPtr_to_system_bitmap(CGrafPtr cg); + +/*macdraw.c*/ +extern GDHandle MainGDevice; +extern CTabHandle MainCTable; +extern short dspr_depth; +extern volatile short _sync; +extern const RGBColor ForeDef; +extern const RGBColor BackDef; +extern int _dspr_sys_init(); +extern void _dspr_sys_exit(); + +enum{kRDDNull =0, + kRDDStarted =1, + kRDDReserved =2, + kRDDFadeOut =4, + kRDDActive =8, + kRDDPaused =16, + kRDDUnder =32, + kRDDOver =64, + kRDDouble =128, +}; + +/*macsys.c*/ +extern void _mac_get_executable_name(char *output, int size); +extern void _mac_message(const char *msg); +extern int _tm_sys_init(); +extern void _tm_sys_exit(); + +/*macfile.c*/ +extern int _al_open(const char *filename, int mode); +extern int _mac_file_sys_init(); + +/*macallegro.c*/ +extern QDGlobals qd; /*The our QuickDraw globals */ +extern char *strdup(const char *p); +extern void ptoc(StringPtr pstr, char *cstr); +extern Boolean RTrapAvailable(short tNumber, TrapType tType); +extern void MacEntry(); + +#ifdef __cplusplus + } +#endif + + +#endif /* ifndef AINTMAC_H */ + diff --git a/allegro/allegro/platform/aintosx.h b/allegro/allegro/platform/aintosx.h new file mode 100644 index 0000000000..cb086a2023 --- /dev/null +++ b/allegro/allegro/platform/aintosx.h @@ -0,0 +1,191 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Internal header file for the MacOS X Allegro library port. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTOSX_H +#define AINTOSX_H + +#ifdef __OBJC__ + +#include "allegro/platform/aintunix.h" + +#include +#include +#include +#include +#include +#include + + +#ifndef NSAppKitVersionNumber10_1 +#define NSAppKitVersionNumber10_1 620 +#endif +#ifndef NSAppKitVersionNumber10_2 +#define NSAppKitVersionNumber10_2 663 +#endif + + +#define OSX_GFX_NONE 0 +#define OSX_GFX_WINDOW 1 +#define OSX_GFX_FULL 2 + +#define BMP_EXTRA(bmp) ((BMP_EXTRA_INFO *)((bmp)->extra)) + +#define HID_MAX_DEVICES MAX_JOYSTICKS +#define HID_MOUSE 0 +#define HID_JOYSTICK 1 +#define HID_GAMEPAD 2 + +#define HID_MAX_DEVICE_ELEMENTS ((MAX_JOYSTICK_AXIS * MAX_JOYSTICK_STICKS) + MAX_JOYSTICK_BUTTONS) +#define HID_ELEMENT_BUTTON 0 +#define HID_ELEMENT_AXIS 1 +#define HID_ELEMENT_AXIS_PRIMARY_X 2 +#define HID_ELEMENT_AXIS_PRIMARY_Y 3 +#define HID_ELEMENT_STANDALONE_AXIS 4 +#define HID_ELEMENT_HAT 5 + + + +@interface AllegroAppDelegate : NSObject +- (BOOL)application: (NSApplication *)theApplication openFile: (NSString *)filename; +- (void)applicationDidFinishLaunching: (NSNotification *)aNotification; +- (void)applicationDidChangeScreenParameters: (NSNotification *)aNotification; ++ (void)app_main: (id)arg; +- (NSApplicationTerminateReply) applicationShouldTerminate: (id)sender; +- (void) quitAction: (id) sender; +@end + + +@interface AllegroWindow : NSWindow +- (void)display; +- (void)miniaturize: (id)sender; +@end + + +@interface AllegroWindowDelegate : NSObject +- (BOOL)windowShouldClose: (id)sender; +- (void)windowDidDeminiaturize: (NSNotification *)aNotification; +@end + + +@interface AllegroView: NSQuickDrawView +- (void)resetCursorRects; +@end + + +typedef void RETSIGTYPE; + + +typedef struct BMP_EXTRA_INFO +{ + GrafPtr port; +} BMP_EXTRA_INFO; + + +typedef struct HID_ELEMENT +{ + int type; + IOHIDElementCookie cookie; + int max, min; + int app; + int col; + int index; + char *name; +} HID_ELEMENT; + + +typedef struct HID_DEVICE +{ + int type; + char *manufacturer; + char *product; + int num_elements; + int capacity; + HID_ELEMENT *element; + IOHIDDeviceInterface **interface; + int cur_app; +} HID_DEVICE; + +typedef struct +{ + int count; + int capacity; + HID_DEVICE* devices; +} HID_DEVICE_COLLECTION; + + +void osx_event_handler(void); +int osx_bootstrap_ok(void); + +void setup_direct_shifts(void); +void osx_init_fade_system(void); +void osx_fade_screen(int fade_in, double seconds); +void osx_qz_blit_to_self(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); +void osx_qz_created_sub_bitmap(BITMAP *bmp, BITMAP *parent); +BITMAP *osx_qz_create_video_bitmap(int width, int height); +BITMAP *osx_qz_create_system_bitmap(int width, int height); +void osx_qz_destroy_video_bitmap(BITMAP *bmp); +int osx_setup_colorconv_blitter(void); +void osx_update_dirty_lines(void); + +uintptr_t osx_qz_write_line(BITMAP *bmp, int lyne); +void osx_qz_unwrite_line(BITMAP *bmp); +void osx_qz_acquire(BITMAP *bmp); +void osx_qz_release(BITMAP *bmp); + +void osx_keyboard_handler(int pressed, NSEvent *event); +void osx_keyboard_modifiers(unsigned int new_mods); +void osx_keyboard_focused(int focused, int state); + +void osx_mouse_handler(int x, int y, int dx, int dy, int dz, int buttons); +int osx_mouse_set_sprite(BITMAP *sprite, int x, int y); +int osx_mouse_show(BITMAP *bmp, int x, int y); +void osx_mouse_hide(void); +void osx_mouse_move(int x, int y); + +HID_DEVICE_COLLECTION *osx_hid_scan(int type, HID_DEVICE_COLLECTION*); +void osx_hid_free(HID_DEVICE_COLLECTION *); + + +AL_VAR(NSBundle *, osx_bundle); +AL_VAR(void *, osx_event_mutex); +AL_VAR(void *, osx_window_mutex); +AL_VAR(int, osx_gfx_mode); +AL_VAR(int, osx_screen_used); +AL_VAR(NSCursor *, osx_blank_cursor); +AL_VAR(NSCursor *, osx_cursor); +AL_VAR(AllegroWindow *, osx_window); +AL_ARRAY(char, osx_window_title); +AL_VAR(int, osx_window_first_expose); +AL_VAR(CGDirectPaletteRef, osx_palette); +AL_VAR(int, osx_palette_dirty); +AL_VAR(int, osx_mouse_warped); +AL_VAR(int, osx_skip_mouse_move); +AL_VAR(int, osx_emulate_mouse_buttons); +AL_VAR(NSTrackingRectTag, osx_mouse_tracking_rect); +extern AL_METHOD(void, osx_window_close_hook, (void)); + + +#endif + +#endif + +/* Local variables: */ +/* mode: objc */ +/* c-basic-offset: 3 */ +/* indent-tabs-mode: nil */ +/* End: */ diff --git a/allegro/allegro/platform/aintqnx.h b/allegro/allegro/platform/aintqnx.h new file mode 100644 index 0000000000..b3b61a6c89 --- /dev/null +++ b/allegro/allegro/platform/aintqnx.h @@ -0,0 +1,113 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Internal header for the QNX Allegro library. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTQNX_H +#define AINTQNX_H + +#include "allegro/platform/aintunix.h" + +#ifndef SCAN_DEPEND + #include + #include + #include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* from qphaccel.c */ +AL_FUNC(void, enable_acceleration, (GFX_DRIVER * drv)); +AL_FUNC(void, enable_triple_buffering, (GFX_DRIVER *drv)); + + +/* from qphbmp.c */ +typedef struct BMP_EXTRA_INFO { + PdOffscreenContext_t *context; +} BMP_EXTRA_INFO; + +#define BMP_EXTRA(bmp) ((BMP_EXTRA_INFO *)(bmp->extra)) + +AL_VAR(BITMAP *, ph_frontbuffer); + +AL_FUNC(uintptr_t, ph_write_line, (BITMAP *bmp, int lyne)); +AL_FUNC(uintptr_t, ph_write_line_asm, (BITMAP *bmp, int lyne)); +AL_FUNC(void, ph_unwrite_line, (BITMAP *bmp, int lyne)); +AL_FUNC(void, ph_unwrite_line_asm, (BITMAP *bmp, int lyne)); +AL_FUNC(void, ph_acquire, (BITMAP *bmp)); +AL_FUNC(void, ph_release, (BITMAP *bmp)); +AL_FUNC(BITMAP *, make_photon_bitmap, (PdOffscreenContext_t *context, int w, int h, int id)); +AL_FUNC(void, destroy_photon_bitmap, (BITMAP *bmp)); +AL_FUNC(void, qnx_ph_created_sub_bitmap, (BITMAP *bmp, BITMAP *parent)); +AL_FUNC(BITMAP *, qnx_ph_create_video_bitmap, (int width, int height)); +AL_FUNC(void, qnx_ph_destroy_video_bitmap, (BITMAP *bmp)); +AL_FUNC(int, qnx_ph_show_video_bitmap, (BITMAP *bmp)); +AL_FUNC(int, qnx_ph_request_video_bitmap, (BITMAP *bmp)); + + +/* from qphoton.c */ +#define PH_GFX_NONE 0 +#define PH_GFX_WINDOW 1 +#define PH_GFX_DIRECT 2 +#define PH_GFX_OVERLAY 3 + +AL_VAR(int, ph_gfx_mode); +AL_VAR(PgVideoModeInfo_t, ph_gfx_mode_info); +AL_ARRAY(PgColor_t, ph_palette); + +AL_FUNC(void, setup_direct_shifts, (void)); +AL_FUNC(void, setup_driver, (GFX_DRIVER *drv, int w, int h, int color_depth)); + + +/* from qphwin.c */ +AL_VAR(BITMAP *, pseudo_screen); + +AL_FUNCPTR(void, ph_update_window, (PhRect_t* rect)); + + +/* from qsystem.c */ +AL_VAR(PtWidget_t, *ph_window); +AL_VAR(pthread_mutex_t, qnx_event_mutex); +AL_VAR(pthread_mutex_t, qnx_gfx_mutex); + + +/* from qkeydrv.c */ +AL_FUNC(void, qnx_keyboard_handler, (int, int)); +AL_FUNC(void, qnx_keyboard_focused, (int, int)); + + +/* from qmouse.c */ +AL_VAR(int, qnx_mouse_warped); +AL_FUNC(void, qnx_mouse_handler, (int, int, int, int)); + + +/* A very strange thing: PgWaitHWIdle() cannot be found in any system + * header file, but it is explained in the QNX docs, and it actually + * exists in the Photon library... So until QNX fixes the missing declaration, + * we will declare it here. + */ +int PgWaitHWIdle(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/allegro/allegro/platform/aintunix.h b/allegro/allegro/platform/aintunix.h new file mode 100644 index 0000000000..8ada820c5e --- /dev/null +++ b/allegro/allegro/platform/aintunix.h @@ -0,0 +1,194 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the Unix library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + +#ifndef AINTUNIX_H +#define AINTUNIX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef ALLEGRO_HAVE_LIBPTHREAD + /* Synchronization routines using POSIX threads */ + AL_FUNC(void *, _unix_create_mutex, (void)); + AL_FUNC(void, _unix_destroy_mutex, (void *handle)); + AL_FUNC(void, _unix_lock_mutex, (void *handle)); + AL_FUNC(void, _unix_unlock_mutex, (void *handle)); +#else + /* Asynchronous event processing with SIGALRM */ + AL_FUNC(void, _sigalrm_request_abort, (void)); + AL_FUNCPTR(void, _sigalrm_timer_interrupt_handler, (unsigned long interval)); +#endif + + /* Macros to enable and disable interrupts */ + #define DISABLE() _unix_bg_man->disable_interrupts() + #define ENABLE() _unix_bg_man->enable_interrupts() + + + /* Helper for locating config files */ + AL_FUNC(int, _unix_find_resource, (char *dest, AL_CONST char *resource, int size)); + + + /* Generic system driver entry for finding the executable */ + AL_FUNC(void, _unix_get_executable_name, (char *output, int size)); + + + /* Helper for setting os_type */ + AL_FUNC(void, _unix_read_os_type, (void)); + + + /* Helper for yield CPU */ + AL_FUNC(void, _unix_yield_timeslice, (void)); + + + /* Unix rest function */ + AL_FUNC(void, _unix_rest, (unsigned int, AL_METHOD(void, callback, (void)))); + + + /* Module support */ + AL_FUNC(void, _unix_load_modules, (int system_driver_id)); + AL_FUNC(void, _unix_unload_modules, (void)); + + + /* Dynamic driver lists, for modules */ + AL_VAR(_DRIVER_INFO *, _unix_gfx_driver_list); + AL_VAR(_DRIVER_INFO *, _unix_digi_driver_list); + AL_VAR(_DRIVER_INFO *, _unix_midi_driver_list); + AL_FUNC(void, _unix_driver_lists_init, (void)); + AL_FUNC(void, _unix_driver_lists_shutdown, (void)); + AL_FUNC(void, _unix_register_gfx_driver, (int id, GFX_DRIVER *driver, int autodetect, int priority)); + AL_FUNC(void, _unix_register_digi_driver, (int id, DIGI_DRIVER *driver, int autodetect, int priority)); + AL_FUNC(void, _unix_register_midi_driver, (int id, MIDI_DRIVER *driver, int autodetect, int priority)); + + + /* File system helpers */ + AL_FUNC(void, _unix_guess_file_encoding, (void)); + + + /* Get size of a memory page in bytes */ + AL_FUNC(size_t, _unix_get_page_size, (void)); + + +#ifdef ALLEGRO_WITH_XWINDOWS + AL_FUNCPTR(void, _xwin_keyboard_interrupt, (int pressed, int code)); + AL_FUNCPTR(void, _xwin_keyboard_focused, (int focused, int state)); + AL_FUNCPTR(void, _xwin_mouse_interrupt, (int x, int y, int z, int w, int buttons)); + AL_FUNCPTR(void, _xwin_timer_interrupt, (unsigned long interval)); + + AL_ARRAY(_DRIVER_INFO, _xwin_gfx_driver_list); + AL_ARRAY(_DRIVER_INFO, _xwin_keyboard_driver_list); + AL_ARRAY(_DRIVER_INFO, _xwin_mouse_driver_list); + AL_ARRAY(_DRIVER_INFO, _xwin_timer_driver_list); + + AL_FUNC(void, _xwin_handle_input, (void)); + AL_FUNC(void, _xwin_private_handle_input, (void)); + +#ifndef ALLEGRO_MULTITHREADED + + AL_VAR(int, _xwin_missed_input); + + #define XLOCK() \ + do { \ + _xwin.lock_count++; \ + } while (0) + + #define XUNLOCK() \ + do { \ + if (_xwin.lock_count == 1) { \ + while(_xwin_missed_input) { \ + if (_xwin_input_handler) \ + _xwin_input_handler(); \ + else \ + _xwin_private_handle_input(); \ + --_xwin_missed_input; \ + } \ + } \ + _xwin.lock_count--; \ + } while (0) + +#else + + #define XLOCK() \ + do { \ + if (_xwin.mutex) \ + _unix_lock_mutex (_xwin.mutex); \ + _xwin.lock_count++; \ + } while (0) + + #define XUNLOCK() \ + do { \ + if (_xwin.mutex) \ + _unix_unlock_mutex (_xwin.mutex); \ + _xwin.lock_count--; \ + } while (0) + +#endif + +#endif + + +#ifdef ALLEGRO_WITH_OSSDIGI + /* So the setup program can read what we detected */ + AL_VAR(int, _oss_fragsize); + AL_VAR(int, _oss_numfrags); +#endif + + +#ifdef __cplusplus +} +#endif + + +#ifdef ALLEGRO_LINUX + #include "aintlnx.h" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Typedef for background functions, called frequently in the background. + * `threaded' is nonzero if the function is being called from a thread. + */ +typedef void (*bg_func) (int threaded); + +/* Background function manager -- responsible for calling background + * functions. `int' methods return -1 on failure, 0 on success. */ +struct bg_manager +{ + int multi_threaded; + int (*init) (void); + void (*exit) (void); + int (*register_func) (bg_func f); + int (*unregister_func) (bg_func f); + void (*enable_interrupts) (void); + void (*disable_interrupts) (void); + int (*interrupts_disabled) (void); +}; + +extern struct bg_manager _bg_man_pthreads; +extern struct bg_manager _bg_man_sigalrm; + +extern struct bg_manager *_unix_bg_man; + + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef AINTUNIX_H */ diff --git a/allegro/allegro/platform/aintwin.h b/allegro/allegro/platform/aintwin.h new file mode 100644 index 0000000000..8d1bb778bc --- /dev/null +++ b/allegro/allegro/platform/aintwin.h @@ -0,0 +1,220 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the Windows library code. + * + * By Stefan Schimanski. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTWIN_H +#define AINTWIN_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifndef ALLEGRO_WINDOWS + #error bad include +#endif + + +#include "winalleg.h" + +#ifndef SCAN_DEPEND + /* workaround for buggy MinGW32 headers */ + #ifdef ALLEGRO_MINGW32 + #ifndef HMONITOR_DECLARED + #define HMONITOR_DECLARED + #endif + #if (defined _HRESULT_DEFINED) && (defined WINNT) + #undef WINNT + #endif + #endif + + #include /* for LPGUID */ +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +/* generals */ +AL_VAR(HINSTANCE, allegro_inst); +AL_VAR(HANDLE, allegro_thread); +AL_VAR(CRITICAL_SECTION, allegro_critical_section); +AL_VAR(int, _dx_ver); + +#define _enter_critical() EnterCriticalSection(&allegro_critical_section) +#define _exit_critical() LeaveCriticalSection(&allegro_critical_section) + +AL_FUNC(int, init_directx_window, (void)); +AL_FUNC(void, exit_directx_window, (void)); +AL_FUNC(int, get_dx_ver, (void)); +AL_FUNC(int, adjust_window, (int w, int h)); +AL_FUNC(void, restore_window_style, (void)); +AL_FUNC(void, save_window_pos, (void)); + + +/* main window */ +#define WND_TITLE_SIZE 128 + +AL_ARRAY(char, wnd_title); +AL_VAR(int, wnd_x); +AL_VAR(int, wnd_y); +AL_VAR(int, wnd_width); +AL_VAR(int, wnd_height); +AL_VAR(int, wnd_sysmenu); + +AL_FUNCPTR(void, user_close_proc, (void)); + + +/* gfx synchronization */ +AL_VAR(CRITICAL_SECTION, gfx_crit_sect); +AL_VAR(int, gfx_crit_sect_nesting); + +#define _enter_gfx_critical() EnterCriticalSection(&gfx_crit_sect); \ + gfx_crit_sect_nesting++ +#define _exit_gfx_critical() LeaveCriticalSection(&gfx_crit_sect); \ + gfx_crit_sect_nesting-- +#define GFX_CRITICAL_RELEASED (!gfx_crit_sect_nesting) + + +/* switch routines */ +AL_VAR(int, _win_app_foreground); + +AL_FUNC(void, sys_directx_display_switch_init, (void)); +AL_FUNC(void, sys_directx_display_switch_exit, (void)); +AL_FUNC(int, sys_directx_set_display_switch_mode, (int mode)); + +AL_FUNC(void, _win_switch_in, (void)); +AL_FUNC(void, _win_switch_out, (void)); +AL_FUNC(void, _win_reset_switch_mode, (void)); + +AL_FUNC(int, _win_thread_switch_out, (void)); + + +/* main window routines */ +AL_FUNC(int, wnd_call_proc, (int (*proc)(void))); +AL_FUNC(void, wnd_schedule_proc, (int (*proc)(void))); + + +/* input routines */ +AL_VAR(int, _win_input_events); +AL_ARRAY(HANDLE, _win_input_event_id); +AL_FUNCPTRARRAY(void, _win_input_event_handler, (void)); + +AL_FUNC(void, _win_input_init, (int need_thread)); +AL_FUNC(void, _win_input_exit, (void)); +AL_FUNC(int, _win_input_register_event, (HANDLE event_id, void (*event_handler)(void))); +AL_FUNC(void, _win_input_unregister_event, (HANDLE event_id)); + + +/* keyboard routines */ +AL_FUNC(int, key_dinput_acquire, (void)); +AL_FUNC(int, key_dinput_unacquire, (void)); + + +/* mouse routines */ +AL_VAR(HCURSOR, _win_hcursor); +AL_FUNC(int, mouse_dinput_acquire, (void)); +AL_FUNC(int, mouse_dinput_unacquire, (void)); +AL_FUNC(int, mouse_dinput_grab, (void)); +AL_FUNC(int, mouse_set_syscursor, (void)); +AL_FUNC(int, mouse_set_sysmenu, (int state)); + + +/* joystick routines */ +#define WINDOWS_MAX_AXES 6 + +#define WINDOWS_JOYSTICK_INFO_MEMBERS \ + int caps; \ + int num_axes; \ + int axis[WINDOWS_MAX_AXES]; \ + char *axis_name[WINDOWS_MAX_AXES]; \ + int hat; \ + char *hat_name; \ + int num_buttons; \ + int button[MAX_JOYSTICK_BUTTONS]; \ + char *button_name[MAX_JOYSTICK_BUTTONS]; + +typedef struct WINDOWS_JOYSTICK_INFO { + WINDOWS_JOYSTICK_INFO_MEMBERS +} WINDOWS_JOYSTICK_INFO; + +AL_FUNC(int, win_add_joystick, (WINDOWS_JOYSTICK_INFO *win_joy)); +AL_FUNC(void, win_remove_all_joysticks, (void)); +AL_FUNC(int, win_update_joystick_status, (int n, WINDOWS_JOYSTICK_INFO *win_joy)); + +AL_FUNC(int, joystick_dinput_acquire, (void)); +AL_FUNC(int, joystick_dinput_unacquire, (void)); + + +/* thread routines */ +AL_FUNC(void, _win_thread_init, (void)); +AL_FUNC(void, _win_thread_exit, (void)); + + +/* synchronization routines */ +AL_FUNC(void *, sys_directx_create_mutex, (void)); +AL_FUNC(void, sys_directx_destroy_mutex, (void *handle)); +AL_FUNC(void, sys_directx_lock_mutex, (void *handle)); +AL_FUNC(void, sys_directx_unlock_mutex, (void *handle)); + + +/* sound routines */ +AL_FUNC(_DRIVER_INFO *, _get_win_digi_driver_list, (void)); +AL_FUNC(void, _free_win_digi_driver_list, (void)); + +AL_FUNC(DIGI_DRIVER *, _get_dsalmix_driver, (char *name, LPGUID guid, int num)); +AL_FUNC(DIGI_DRIVER *, _get_woalmix_driver, (int num)); + +AL_FUNC(int, digi_directsound_capture_init, (LPGUID guid)); +AL_FUNC(void, digi_directsound_capture_exit, (void)); +AL_FUNC(int, digi_directsound_capture_detect, (LPGUID guid)); +AL_FUNC(int, digi_directsound_rec_cap_rate, (int bits, int stereo)); +AL_FUNC(int, digi_directsound_rec_cap_param, (int rate, int bits, int stereo)); +AL_FUNC(int, digi_directsound_rec_source, (int source)); +AL_FUNC(int, digi_directsound_rec_start, (int rate, int bits, int stereo)); +AL_FUNC(void, digi_directsound_rec_stop, (void)); +AL_FUNC(int, digi_directsound_rec_read, (void *buf)); + + +/* midi routines */ +AL_FUNC(_DRIVER_INFO *, _get_win_midi_driver_list, (void)); +AL_FUNC(void, _free_win_midi_driver_list, (void)); + +AL_FUNC(void, midi_switch_out, (void)); + + +/* file routines */ +AL_VAR(int, _al_win_unicode_filenames); + + +/* error handling */ +AL_FUNC(char* , win_err_str, (long err)); +AL_FUNC(void, thread_safe_trace, (char *msg, ...)); + +#if DEBUGMODE >= 2 + #define _TRACE thread_safe_trace +#else + #define _TRACE 1 ? (void) 0 : thread_safe_trace +#endif + + +#ifdef __cplusplus + } +#endif + +#endif /* !defined AINTWIN_H */ + diff --git a/allegro/allegro/platform/al386gcc.h b/allegro/allegro/platform/al386gcc.h new file mode 100644 index 0000000000..136f064a73 --- /dev/null +++ b/allegro/allegro/platform/al386gcc.h @@ -0,0 +1,402 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Inline functions (gcc style 386 asm). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#if (!defined ALLEGRO_GCC) || (!defined ALLEGRO_I386) + #error bad include +#endif + +#ifdef ALLEGRO_IMPORT_GFX_ASM + +/* _default_ds: + * Return a copy of the current %ds selector. + */ +AL_INLINE(int, _default_ds, (void), +{ + short result; + + __asm__ ( + " movw %%ds, %0 " + + : "=r" (result) + ); + + return result; +}) + + + +/* bmp_write_line: + * Bank switch function. + */ +AL_INLINE(uintptr_t, bmp_write_line, (BITMAP *bmp, int lyne), +{ + uintptr_t result; + + __asm__ volatile ( + " call *%3 " + + : "=a" (result) /* result in eax */ + + : "d" (bmp), /* bitmap in edx */ + "0" (lyne), /* line number in eax */ + "r" (bmp->write_bank) /* the bank switch routine */ + ); + + return result; +}) + + + +/* bmp_read_line: + * Bank switch function. + */ +AL_INLINE(uintptr_t, bmp_read_line, (BITMAP *bmp, int lyne), +{ + uintptr_t result; + + __asm__ volatile ( + " call *%3 " + + : "=a" (result) /* result in eax */ + + : "d" (bmp), /* bitmap in edx */ + "0" (lyne), /* line number in eax */ + "r" (bmp->read_bank) /* the bank switch routine */ + ); + + return result; +}) + + + +/* bmp_unwrite_line: + * Terminate bank switch function. + */ +AL_INLINE(void, bmp_unwrite_line, (BITMAP *bmp), +{ + __asm__ volatile ( + " call *%1 " + : + : "d" (bmp), /* bitmap in edx */ + "r" (bmp->vtable->unwrite_bank) /* the bank switch routine */ + ); +}) + +#endif /* ALLEGRO_IMPORT_GFX_ASM */ + + +#ifdef ALLEGRO_IMPORT_MATH_ASM + +/* Helper macro that makes the compiler reduce fixadd(), fixsub(), fixmul() and + fixdiv() calls to a single constant if both operands are constant. Since + this doesn't work unless we compile with optimization, it's better to skip + the test then. */ +#if (defined __OPTIMIZE__) && ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 95))) + #define __PRECALCULATE_CONSTANTS(calc) \ + if(__builtin_constant_p(x) && __builtin_constant_p(y)) { \ + if((calc) > (double)0x7FFFFFFF) { \ + *allegro_errno = ERANGE; \ + return 0x7FFFFFFF; \ + } \ + else if(-(calc) > (double)0x7FFFFFFF) { \ + *allegro_errno = ERANGE; \ + return -0x7FFFFFFF; \ + } \ + else \ + return (fixed)(calc); \ + } \ + else +#else + #define __PRECALCULATE_CONSTANTS(calc) +#endif + + + +/* fixadd: + * Fixed point (16.16) addition. + */ +AL_INLINE(fixed, fixadd, (fixed x, fixed y), +{ + fixed result; + + __PRECALCULATE_CONSTANTS(x + (double)y) + { + __asm__ ( + " addl %2, %0 ; " /* do the addition */ + " jno 0f ; " /* check for overflow */ + + " movl %4, %0 ; " /* on overflow, set errno */ + " movl %3, (%0) ; " + " movl $0x7FFFFFFF, %0 ; " /* and return MAXINT */ + " cmpl $0, %2 ; " + " jg 0f ; " + " negl %0 ; " + + " 0: " /* finished */ + + : "=r" (result) /* result in a register */ + + : "0" (x), /* x in the output register */ + "rm" (y), /* y can go in register or memory */ + "i" (ERANGE), + "m" (allegro_errno) + + : "%cc", "memory" /* clobbers flags and errno */ + ); + + return result; + } +}) + + + +/* fixsub: + * Fixed point (16.16) subtraction. + */ +AL_INLINE(fixed, fixsub, (fixed x, fixed y), +{ + fixed result; + + __PRECALCULATE_CONSTANTS(x - (double)y) + { + __asm__ ( + " subl %2, %0 ; " /* do the subtraction */ + " jno 0f ; " /* check for overflow */ + + " movl %4, %0 ; " /* on overflow, set errno */ + " movl %3, (%0) ; " + " movl $0x7FFFFFFF, %0 ; " /* and return MAXINT */ + " cmpl $0, %2 ; " + " jl 0f ; " + " negl %0 ; " + + " 0: " /* finished */ + + : "=r" (result) /* result in a register */ + + : "0" (x), /* x in the output register */ + "rm" (y), /* y can go in register or memory */ + "i" (ERANGE), + "m" (allegro_errno) + + : "%cc", "memory" /* clobbers flags and errno */ + ); + + return result; + } +}) + + + +/* fixmul: + * Fixed point (16.16) multiplication. + */ +AL_INLINE(fixed, fixmul, (fixed x, fixed y), +{ + fixed edx __attribute__ ((__unused__)); + fixed result; + + __PRECALCULATE_CONSTANTS(x / 65536.0 * y) + { + __asm__ ( + " movl %2, %%eax ; " + " imull %3 ; " /* do the multiply */ + " shrdl $16, %%edx, %%eax ; " + + " sarl $15, %%edx ; " /* check for overflow */ + " jz 0f ; " + " cmpl $-1, %%edx ; " + " je 0f ; " + + " movl %5, %%eax ; " /* on overflow, set errno */ + " movl %4, (%%eax) ; " + " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ + " cmpl $0, %2 ; " + " jge 1f ; " + " negl %%eax ; " + " 1: " + " cmpl $0, %3 ; " + " jge 0f ; " + " negl %%eax ; " + + " .balign 4, 0x90 ; " + + " 0: " /* finished */ + + : "=&a" (result), /* the result has to go in eax */ + "=&d" (edx) /* reliably reserve edx */ + + : "mr" (x), /* x and y can be regs or mem */ + "mr" (y), + "i" (ERANGE), + "m" (allegro_errno) + + : "%cc", "memory" /* clobbers flags and errno */ + ); + + return result; + } +}) + + + +/* fixdiv: + * Fixed point (16.16) division. + */ +AL_INLINE(fixed, fixdiv, (fixed x, fixed y), +{ + fixed edx __attribute__ ((__unused__)); + fixed reg __attribute__ ((__unused__)); + fixed result; + + __PRECALCULATE_CONSTANTS(x * 65536.0 / y) + { + __asm__ ( + " testl %%eax, %%eax ; " /* test sign of x */ + " js 3f ; " + + " testl %2, %2 ; " /* test sign of y */ + " jns 4f ; " + " negl %2 ; " + + " 0: " /* result will be negative */ + " movl %%eax, %%edx ; " /* check the range is ok */ + " shrl $16, %%edx ; " + " shll $16, %%eax ; " + " cmpl %2, %%edx ; " + " jae 1f ; " + + " divl %2 ; " /* do the divide */ + " testl %%eax, %%eax ; " + " jns 2f ; " + + " 1: " + " movl %6, %%eax ; " /* on overflow, set errno */ + " movl %5, (%%eax) ; " + " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ + + " 2: " + " negl %%eax ; " /* fix up the sign of the result */ + " jmp 6f ; " + + " .balign 4, 0x90 ; " + + " 3: " /* x is negative */ + " negl %%eax ; " + " testl %2, %2 ; " /* test sign of y */ + " jns 0b ; " + " negl %2 ; " + + " 4: " /* result will be positive */ + " movl %%eax, %%edx ; " /* check the range is ok */ + " shrl $16, %%edx ; " + " shll $16, %%eax ; " + " cmpl %2, %%edx ; " + " jae 5f ; " + + " divl %2 ; " /* do the divide */ + " testl %%eax, %%eax ; " + " jns 6f ; " + + " 5: " + " movl %6, %%eax ; " /* on overflow, set errno */ + " movl %5, (%%eax) ; " + " movl $0x7FFFFFFF, %%eax ; " /* and return MAXINT */ + + " 6: " /* finished */ + + : "=a" (result), /* the result has to go in eax */ + "=&d" (edx), /* reliably reserve edx */ + "=r" (reg) /* input operand will be clobbered */ + + : "0" (x), /* x in eax */ + "2" (y), /* y in register */ + "i" (ERANGE), + "m" (allegro_errno) + + : "%cc", "memory" /* clobbers flags and memory */ + ); + + return result; + } +}) + + + +/* fixfloor: + * Fixed point version of floor(). + * Note that it returns an integer result (not a fixed one) + */ +AL_INLINE(int, fixfloor, (fixed x), +{ + int result; + + __asm__ ( + " sarl $16, %0 " /* convert to int */ + + : "=r" (result) /* result in a register */ + + : "0" (x) /* x in the output register */ + ); + + return result; +}) + + + +/* fixceil: + * Fixed point version of ceil(). + * Note that it returns an integer result (not a fixed one) + */ +AL_INLINE(int, fixceil, (fixed x), +{ + int result; + + __asm__ ( + " addl $0xFFFF, %0 ;" /* ceil () */ + " jns 0f ;" + " jo 1f ;" + + "0:" + " sarl $16, %0 ;" /* convert to int */ + " jmp 2f ;" + + "1:" + " movl %3, %0 ;" /* on overflow, set errno */ + " movl %2, (%0) ;" + " movl $0x7FFF, %0 ;" /* and return large int */ + + "2:" + : "=r" (result) /* result in a register */ + + : "0" (x), /* x in the output register */ + "i" (ERANGE), + "m" (allegro_errno) + + : "%cc", "memory" /* clobbers flags and errno */ + ); + + return result; +}) + + + +#undef __PRECALCULATE_CONSTANTS + +#endif /* ALLEGRO_IMPORT_MATH_ASM */ + diff --git a/allegro/allegro/platform/al386vc.h b/allegro/allegro/platform/al386vc.h new file mode 100644 index 0000000000..63e75b056e --- /dev/null +++ b/allegro/allegro/platform/al386vc.h @@ -0,0 +1,269 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Inline functions (MSVC style 386 asm). + * + * By Stefan Schimanski. + * + * See readme.txt for copyright information. + */ + + +#if (!defined ALLEGRO_MSVC) || (!defined ALLEGRO_I386) + #error bad include +#endif + + +#pragma warning (disable: 4035) + + +#ifdef ALLEGRO_IMPORT_GFX_ASM + +/* _default_ds: + * Return a copy of the current %ds selector. + */ +INLINE _AL_DLL int _default_ds(void) +{ + _asm { + mov eax, 0 + mov ax, ds + } +} + +END_OF_INLINE(_default_ds); + + + +/* bmp_write_line: + * Bank switch function. + */ +INLINE _AL_DLL uintptr_t bmp_write_line(BITMAP *bmp, int lyne) +{ + _asm { + mov edx, bmp + mov ecx, [edx]BITMAP.write_bank + mov eax, lyne + call ecx + } +} + +END_OF_INLINE(bmp_write_line); + + + +/* bmp_read_line: + * Bank switch function. + */ +INLINE _AL_DLL uintptr_t bmp_read_line(BITMAP *bmp, int lyne) +{ + _asm { + mov edx, bmp + mov ecx, [edx]BITMAP.read_bank + mov eax, lyne + call ecx + } +} + +END_OF_INLINE(bmp_read_line); + + + +/* bmp_unwrite_line: + * Terminate bank switch function. + */ +INLINE _AL_DLL void bmp_unwrite_line(BITMAP *bmp) +{ + _asm { + mov edx, bmp + mov ecx, [edx]BITMAP.vtable + mov ecx, [ecx]GFX_VTABLE.unwrite_bank + call ecx + } +} + +END_OF_INLINE(bmp_unwrite_line); + + +#endif /* ALLEGRO_IMPORT_GFX_ASM */ + + +#ifdef ALLEGRO_IMPORT_MATH_ASM + +/* _set_errno_erange: + */ +INLINE void _set_errno_erange(void) +{ + *allegro_errno = ERANGE; +} + +END_OF_INLINE(_set_errno_erange); + + + +/* fixadd: + * Fixed point (16.16) addition. + */ +INLINE _AL_DLL fixed fixadd(fixed x, fixed y) +{ + _asm { + mov eax, x + add eax, y + jno Out1 + call _set_errno_erange + mov eax, 0x7FFFFFFF + cmp y, 0 + jg Out1 + neg eax + Out1: + } +} + +END_OF_INLINE(fixadd); + + + +/* fixsub: + * Fixed point (16.16) subtraction. + */ +INLINE _AL_DLL fixed fixsub(fixed x, fixed y) +{ + _asm { + mov eax, x + sub eax, y + jno Out1 + call _set_errno_erange + mov eax, 0x7FFFFFFF + cmp y, 0 + jl Out1 + neg eax + Out1: + } +} + +END_OF_INLINE(fixsub); + + + +/* fixmul: + * Fixed point (16.16) multiplication. + */ +INLINE _AL_DLL fixed fixmul(fixed x, fixed y) +{ + _asm { + mov eax, x + imul y + shrd eax, edx, 16 + sar edx, 15 + jz Out2 + cmp edx, -1 + jz Out2 + call _set_errno_erange + mov eax, 0x7FFFFFFF + cmp x, 0 + jge Out1 + neg eax + Out1: + cmp y, 0 + jge Out2 + neg eax + Out2: + } +} + +END_OF_INLINE(fixmul); + + + +/* fixdiv: + * Fixed point (16.16) division. + */ +INLINE _AL_DLL fixed fixdiv(fixed x, fixed y) +{ + _asm { + mov ecx, y + xor ebx, ebx + mov eax, x + or eax, eax + jns Out1 + neg eax + inc ebx + Out1: + or ecx, ecx + jns Out2 + neg ecx + inc ebx + Out2: + mov edx, eax + shr edx, 0x10 + shl eax, 0x10 + cmp edx, ecx + jae Out3 + div ecx + or eax, eax + jns Out4 + Out3: + call _set_errno_erange + mov eax, 0x7FFFFFFF + Out4: + test ebx, 1 + je Out5 + neg eax + Out5: + } +} + +END_OF_INLINE(fixdiv); + + + +/* fixfloor : + * Fixed point version of floor(). + * Note that it returns an integer result (not a fixed one) + */ +INLINE _AL_DLL int fixfloor(fixed x) +{ + _asm { + mov eax, x + sar eax, 0x10 + } +} + +END_OF_INLINE(fixfloor); + + + +/* fixceil: + * Fixed point version of ceil(). + * Note that it returns an integer result (not a fixed one) + */ +INLINE _AL_DLL int fixceil(fixed x) +{ + _asm { + mov eax, x + add eax, 0xFFFF + jns Out1 + jo Out2 + Out1: + sar eax, 0x10 + jmp Out3 + Out2: + call _set_errno_erange + mov eax, 0x7FFF + Out3: + } +} + +END_OF_INLINE(fixceil); + +#endif /* ALLEGRO_IMPORT_MATH_ASM */ + + +#pragma warning (default: 4035) + diff --git a/allegro/allegro/platform/al386wat.h b/allegro/allegro/platform/al386wat.h new file mode 100644 index 0000000000..1647744779 --- /dev/null +++ b/allegro/allegro/platform/al386wat.h @@ -0,0 +1,241 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Inline functions (Watcom style 386 asm). + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#if (!defined ALLEGRO_WATCOM) || (!defined ALLEGRO_I386) + #error bad include +#endif + + +#ifdef ALLEGRO_IMPORT_GFX_ASM + +/* _default_ds: + * Return a copy of the current %ds selector. + */ +int _default_ds(void); + +#pragma aux _default_ds = \ + " mov eax, 0 " \ + " mov ax, ds " \ + \ + value [eax]; + + + +/* _my_cs: + * Return a copy of the current %cs selector. + */ +int _my_cs(void); + +#pragma aux _my_cs = \ + " mov eax, 0 " \ + " mov ax, cs " \ + \ + value [eax]; + + + +/* bmp_write_line/bmp_read_line: + * Bank switch functions. + */ +uintptr_t _bmp_bank_switcher(BITMAP *bmp, int lyne, void *bank_switch); + +#pragma aux _bmp_bank_switcher = \ + " call ecx " \ + \ + parm [edx] [eax] [ecx] \ + value [eax]; + +#define bmp_write_line(bmp, lyne) _bmp_bank_switcher(bmp, lyne, (void *)bmp->write_bank) +#define bmp_read_line(bmp, lyne) _bmp_bank_switcher(bmp, lyne, (void *)bmp->read_bank) + + + +/* bmp_unwrite_line: + * Terminate bank switch function. + */ +void _bmp_unbank_switcher(BITMAP *bmp, void *bank_unswitcher); + +#pragma aux _bmp_unbank_switcher = \ + " call ecx " \ + \ + parm [edx] [ecx]; + +#define bmp_unwrite_line(bmp) _bmp_unbank_switcher(bmp, (void *)bmp->vtable->unwrite_bank) + +#endif /* ALLEGRO_IMPORT_GFX_ASM */ + + +#ifdef ALLEGRO_IMPORT_MATH_ASM + +/* _set_errno_erange: + * Watcom's asm syntax doesn't provide any nice way to do this inline... + */ +AL_INLINE(void, _set_errno_erange, (void), +{ + *allegro_errno = ERANGE; +}) + + + +/* fixadd: + * Fixed point (16.16) addition. + */ +fixed fixadd(fixed x, fixed y); + +#pragma aux fixadd = \ + " add eax, edx " \ + " jno Out1 " \ + " call _set_errno_erange " \ + " mov eax, 0x7FFFFFFF " \ + " cmp edx, 0 " \ + " jg Out1 " \ + " neg eax " \ + " Out1: " \ + \ + parm [eax] [edx] \ + value [eax]; + + + +/* fixsub: + * Fixed point (16.16) subtraction. + */ +fixed fixsub(fixed x, fixed y); + +#pragma aux fixsub = \ + " sub eax, edx " \ + " jno Out1 " \ + " call _set_errno_erange " \ + " mov eax, 0x7FFFFFFF " \ + " cmp edx, 0 " \ + " jl Out1 " \ + " neg eax " \ + " Out1: " \ + \ + parm [eax] [edx] \ + value [eax]; + + + +/* fixmul: + * Fixed point (16.16) multiplication. + */ +fixed fixmul(fixed x, fixed y); + +#pragma aux fixmul = \ + " mov eax, ebx " \ + " imul ecx " \ + " shrd eax, edx, 16 " \ + " sar edx, 15 " \ + " jz Out2 " \ + " cmp edx, -1 " \ + " jz Out2 " \ + " call _set_errno_erange " \ + " mov eax, 0x7FFFFFFF " \ + " cmp ebx, 0 " \ + " jge Out1 " \ + " neg eax " \ + " Out1: " \ + " cmp ecx, 0 " \ + " jge Out2 " \ + " neg eax " \ + " Out2: " \ + \ + parm [ebx] [ecx] \ + modify [edx] \ + value [eax]; + + + +/* fixdiv: + * Fixed point (16.16) division. + */ +fixed fixdiv(fixed x, fixed y); + +#pragma aux fixdiv = \ + " xor ebx, ebx " \ + " or eax, eax " \ + " jns Out1 " \ + " neg eax " \ + " inc ebx " \ + " Out1: " \ + " or ecx, ecx " \ + " jns Out2 " \ + " neg ecx " \ + " inc ebx " \ + " Out2: " \ + " mov edx, eax " \ + " shr edx, 0x10 " \ + " shl eax, 0x10 " \ + " cmp edx, ecx " \ + " jae Out3 " \ + " div ecx " \ + " or eax, eax " \ + " jns Out4 " \ + " Out3: " \ + " call _set_errno_erange " \ + " mov eax, 0x7FFFFFFF " \ + " Out4: " \ + " test ebx, 1 " \ + " je Out5 " \ + " neg eax " \ + " Out5: " \ + \ + parm [eax] [ecx] \ + modify [ebx edx] \ + value [eax]; + + + +/* fixfloor : + * Fixed point version of floor(). + * Note that it returns an integer result (not a fixed one) + */ +int fixfloor(fixed x); + +#pragma aux fixfloor = \ + " sar eax, 0x10 " \ + \ + parm [eax] \ + value [eax]; + + + +/* fixceil : + * Fixed point version of ceil(). + * Note that it returns an integer result (not a fixed one) + */ +int fixceil(fixed x); + +#pragma aux fixceil = \ + " add eax, 0xFFFF " \ + " jns Out1 " \ + " jo Out2 " \ + " Out1: " \ + " sar eax, 0x10 " \ + " jmp Out3 " \ + " Out2: " \ + " call _set_errno_erange " \ + " mov eax, 0x7FFF " \ + " Out3: " \ + \ + parm [eax] \ + value [eax]; + +#endif /* ALLEGRO_IMPORT_MATH_ASM */ + diff --git a/allegro/allegro/platform/albcc32.h b/allegro/allegro/platform/albcc32.h new file mode 100644 index 0000000000..f28c1a4254 --- /dev/null +++ b/allegro/allegro/platform/albcc32.h @@ -0,0 +1,85 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with Borland C++Builder. + * + * By Greg Hackmann. + * + * See readme.txt for copyright information. + */ + + +#ifdef ALLEGRO_SRC + #error Currently BCC32 cannot build the library +#endif + +#ifndef SCAN_DEPEND + #include + #include + #include + #include +#endif + + +#pragma warn -8004 /* unused assigned value */ +#pragma warn -8008 /* condition always met */ +#pragma warn -8057 /* unused parameter */ +#pragma warn -8066 /* unreachable code */ + + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "BCC32" +#define ALLEGRO_WINDOWS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_GUESS_INTTYPES_OK + /* TODO: check if BCC has inttypes.h and/or stdint.h */ +#define ALLEGRO_MULTITHREADED + +#ifdef ALLEGRO_USE_CONSOLE + #define ALLEGRO_CONSOLE_OK + #define ALLEGRO_NO_MAGIC_MAIN +#endif + + +/* describe how function prototypes look to BCC32 */ +#if (defined ALLEGRO_STATICLINK) || (defined ALLEGRO_SRC) + #define _AL_DLL +#else + #define _AL_DLL __declspec(dllimport) +#endif + +#define AL_VAR(type, name) extern _AL_DLL type name +#define AL_ARRAY(type, name) extern _AL_DLL type name[] +#define AL_FUNC(type, name, args) _AL_DLL type __cdecl name args +#define AL_METHOD(type, name, args) type (__cdecl *name) args +#define AL_FUNCPTR(type, name, args) extern _AL_DLL type (__cdecl *name) args + + +#define END_OF_INLINE(name) +#define AL_INLINE(type, name, args, code) extern __inline type __cdecl name args code END_OF_INLINE(name) + +#define INLINE __inline + +#define LONG_LONG __int64 +#define int64_t signed __int64 +#define uint64_t unsigned __int64 + +#define AL_CONST const + +/* windows specific defines */ +#ifdef NONAMELESSUNION + #undef NONAMELESSUNION +#endif +/* This fixes 99.999999% of Borland C++Builder's problems with structs. */ + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" diff --git a/allegro/allegro/platform/albecfg.h b/allegro/allegro/platform/albecfg.h new file mode 100644 index 0000000000..4ee08c9a2f --- /dev/null +++ b/allegro/allegro/platform/albecfg.h @@ -0,0 +1,43 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with BeOS. + * + * By Jason Wilkins. + * + * See readme.txt for copyright information. + */ + + +#include +#include + +/* provide implementations of missing functions */ +#define ALLEGRO_NO_STRICMP +#define ALLEGRO_NO_STRLWR +#define ALLEGRO_NO_STRUPR + +/* a static auto config */ +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_INTTYPES_H 1 /* TODO: check this */ +#define ALLEGRO_HAVE_STDINT_H 1 /* TODO: check this */ +#define ALLEGRO_HAVE_SYS_TIME_H 1 + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "BeOS" +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_USE_CONSTRUCTOR +#define ALLEGRO_MULTITHREADED + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/albeos.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintbeos.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/beos/asmcapa.h" diff --git a/allegro/allegro/platform/albeos.h b/allegro/allegro/platform/albeos.h new file mode 100644 index 0000000000..9af2dbfc78 --- /dev/null +++ b/allegro/allegro/platform/albeos.h @@ -0,0 +1,76 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * BeOS specific definitions header file. + * + * By Jason Wilkins. + * + * See readme.txt for copyright information. + */ + + +/* system driver */ +#define SYSTEM_BEOS AL_ID('B','S','Y','S') +AL_VAR(SYSTEM_DRIVER, system_beos); + +/* timer driver */ +#define TIMER_BEOS AL_ID('B','T','I','M') +AL_VAR(TIMER_DRIVER, timer_beos); + +/* keyboard driver */ +#define KEYBOARD_BEOS AL_ID('B','K','E','Y') +AL_VAR(KEYBOARD_DRIVER, keyboard_beos); + +/* mouse driver */ +#define MOUSE_BEOS AL_ID('B','M','O','U') +AL_VAR(MOUSE_DRIVER, mouse_beos); + +/* joystick driver */ +#define JOYSTICK_BEOS AL_ID('B','J','O','Y') +AL_VAR(JOYSTICK_DRIVER, joystick_beos); + +/* graphics drivers */ +#define GFX_BWINDOWSCREEN_ACCEL AL_ID('B','W','S','A') +#define GFX_BWINDOWSCREEN AL_ID('B','W','S',' ') +AL_VAR(GFX_DRIVER, gfx_beos_bwindowscreen_accel); +AL_VAR(GFX_DRIVER, gfx_beos_bwindowscreen); + +#define GFX_BDIRECTWINDOW AL_ID('B','D','W','N') +#define GFX_BWINDOW AL_ID('B','W','N',' ') +AL_VAR(GFX_DRIVER, gfx_beos_bdirectwindow); +AL_VAR(GFX_DRIVER, gfx_beos_bwindow); + +#define GFX_BWINDOW_OVERLAY AL_ID('B','O','V','L') +AL_VAR(GFX_DRIVER, gfx_beos_overlay); + +/* digi drivers */ +#define DIGI_BEOS AL_ID('B','D','I','G') +AL_VAR(DIGI_DRIVER, digi_beos); + +/* midi drivers */ +#define MIDI_BEOS AL_ID('B','M','I','D') +AL_VAR(MIDI_DRIVER, midi_beos); + +#define GFX_DRIVER_BEOS \ + { GFX_BWINDOWSCREEN_ACCEL, &gfx_beos_bwindowscreen_accel, TRUE }, \ + { GFX_BWINDOWSCREEN, &gfx_beos_bwindowscreen, TRUE }, \ + { GFX_BDIRECTWINDOW, &gfx_beos_bdirectwindow, TRUE }, \ + { GFX_BWINDOW, &gfx_beos_bwindow, TRUE }, \ + { GFX_BWINDOW_OVERLAY, &gfx_beos_overlay, TRUE }, + +#define DIGI_DRIVER_BEOS \ + { DIGI_BEOS, &digi_beos, TRUE }, + +#define MIDI_DRIVER_BEOS \ + { MIDI_BEOS, &midi_beos, TRUE }, + +#define JOYSTICK_DRIVER_BEOS \ + { JOYSTICK_BEOS, &joystick_beos, TRUE }, + diff --git a/allegro/allegro/platform/aldjgpp.h b/allegro/allegro/platform/aldjgpp.h new file mode 100644 index 0000000000..a9ea3f921f --- /dev/null +++ b/allegro/allegro/platform/aldjgpp.h @@ -0,0 +1,99 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with djgpp. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include + #include + #include + #include +#endif + + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "djgpp" +#define ALLEGRO_DOS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_GUESS_INTTYPES_OK + /* inttypes.h and stdint.h not available in djgpp 2.02 */ +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_VRAM_SINGLE_SURFACE +#define ALLEGRO_USE_CONSTRUCTOR + + +#ifdef __cplusplus +extern "C" { +#endif + +/* memory locking macros */ +void _unlock_dpmi_data(void *addr, int size); + +#define END_OF_FUNCTION(x) void x##_end(void) { } +#define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } +#define LOCK_DATA(d, s) _go32_dpmi_lock_data((void *)d, s) +#define LOCK_CODE(c, s) _go32_dpmi_lock_code((void *)c, s) +#define UNLOCK_DATA(d,s) _unlock_dpmi_data((void *)d, s) +#define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) +#define LOCK_FUNCTION(x) LOCK_CODE((void *)x, (intptr_t)x##_end - (intptr_t)x) + + +/* long filename status */ +#ifdef _USE_LFN + #define ALLEGRO_LFN _USE_LFN +#else + #define ALLEGRO_LFN 0 +#endif + + +/* selector for video memory bitmaps */ +#define _video_ds() _dos_ds + + +/* helpers for talking to video memory */ +#define bmp_select(bmp) _farsetsel((bmp)->seg) + +#define bmp_write8(addr, c) _farnspokeb(addr, c) +#define bmp_write15(addr, c) _farnspokew(addr, c) +#define bmp_write16(addr, c) _farnspokew(addr, c) +#define bmp_write24(addr, c) ({ _farnspokew(addr, c&0xFFFF); \ + _farnspokeb(addr+2, c>>16); }) +#define bmp_write32(addr, c) _farnspokel(addr, c) + +#define bmp_read8(addr) _farnspeekb(addr) +#define bmp_read15(addr) _farnspeekw(addr) +#define bmp_read16(addr) _farnspeekw(addr) +#define bmp_read32(addr) _farnspeekl(addr) +#define bmp_read24(addr) (_farnspeekl(addr) & 0xFFFFFF) + +#ifdef __cplusplus +} +#endif + + +/* describe the asm syntax for this platform */ +#define ALLEGRO_ASM_PREFIX "_" +#define ALLEGRO_ASM_USE_FS + + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/aldos.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintdos.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/djgpp/asmcapa.h" diff --git a/allegro/allegro/platform/aldmc.h b/allegro/allegro/platform/aldmc.h new file mode 100644 index 0000000000..1600436add --- /dev/null +++ b/allegro/allegro/platform/aldmc.h @@ -0,0 +1,93 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with Digital Mars C compiler. + * + * By Matthew Leverton. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include +#endif + +#include + + +/* a static auto config */ +#define ALLEGRO_HAVE_INTTYPES_H +#define ALLEGRO_HAVE_STDINT_H + +#define LONG_LONG long long + +/* describe this platform */ +#ifdef ALLEGRO_STATICLINK + #define ALLEGRO_PLATFORM_STR "DMC.s" +#else + #define ALLEGRO_PLATFORM_STR "DMC" +#endif + +#define ALLEGRO_WINDOWS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_MULTITHREADED + +#ifdef ALLEGRO_USE_CONSOLE + #define ALLEGRO_CONSOLE_OK + #define ALLEGRO_NO_MAGIC_MAIN +#endif + + +/* describe how function prototypes look to DMC */ +#if (defined ALLEGRO_STATICLINK) || (defined ALLEGRO_SRC) + #define _AL_DLL +#else + #define _AL_DLL __declspec(dllimport) +#endif + +#define AL_VAR(type, name) extern _AL_DLL type name +#define AL_ARRAY(type, name) extern _AL_DLL type name[] +#define AL_FUNC(type, name, args) extern type name args +#define AL_METHOD(type, name, args) type (*name) args +#define AL_FUNCPTR(type, name, args) extern _AL_DLL type (*name) args + + +/* Windows specific defines */ + +#if (defined ALLEGRO_SRC) + +#if (!defined S_IRUSR) && (!defined SCAN_DEPEND) + #define S_IRUSR S_IREAD + #define S_IWUSR S_IWRITE +#endif + +typedef unsigned long _fsize_t; + +struct _wfinddata_t { + unsigned attrib; + time_t time_create; /* -1 for FAT file systems */ + time_t time_access; /* -1 for FAT file systems */ + time_t time_write; + _fsize_t size; + wchar_t name[260]; /* may include spaces. */ +}; + +#endif /* ALLEGRO_SRC */ + +/* describe the asm syntax for this platform */ +#define ALLEGRO_ASM_PREFIX "_" + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/dmc/asmcapa.h" diff --git a/allegro/allegro/platform/aldos.h b/allegro/allegro/platform/aldos.h new file mode 100644 index 0000000000..ccb00f1dbf --- /dev/null +++ b/allegro/allegro/platform/aldos.h @@ -0,0 +1,354 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * DOS-specific header defines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_DOS + #error bad include +#endif + + +/********************************************/ +/************ Platform-specifics ************/ +/********************************************/ + +#define SYSTEM_DOS AL_ID('D','O','S',' ') + +AL_VAR(SYSTEM_DRIVER, system_dos); + +AL_VAR(int, i_love_bill); + + +#define KEYDRV_PCDOS AL_ID('P','C','K','B') + +AL_VAR(KEYBOARD_DRIVER, keydrv_pcdos); + + +#define TIMEDRV_FIXED_RATE AL_ID('F','I','X','T') +#define TIMEDRV_VARIABLE_RATE AL_ID('V','A','R','T') + +AL_VAR(TIMER_DRIVER, timedrv_fixed_rate); +AL_VAR(TIMER_DRIVER, timedrv_variable_rate); + + +#define MOUSEDRV_MICKEYS AL_ID('M','I','C','K') +#define MOUSEDRV_INT33 AL_ID('I','3','3',' ') +#define MOUSEDRV_POLLING AL_ID('P','O','L','L') +#define MOUSEDRV_WINNT AL_ID('W','N','T',' ') +#define MOUSEDRV_WIN2K AL_ID('W','2','K',' ') + +AL_VAR(MOUSE_DRIVER, mousedrv_mickeys); +AL_VAR(MOUSE_DRIVER, mousedrv_int33); +AL_VAR(MOUSE_DRIVER, mousedrv_polling); +AL_VAR(MOUSE_DRIVER, mousedrv_winnt); +AL_VAR(MOUSE_DRIVER, mousedrv_win2k); + + + +/*******************************************/ +/************ Joystick routines ************/ +/*******************************************/ + +#define JOY_TYPE_STANDARD AL_ID('S','T','D',' ') +#define JOY_TYPE_2PADS AL_ID('2','P','A','D') +#define JOY_TYPE_4BUTTON AL_ID('4','B','U','T') +#define JOY_TYPE_6BUTTON AL_ID('6','B','U','T') +#define JOY_TYPE_8BUTTON AL_ID('8','B','U','T') +#define JOY_TYPE_FSPRO AL_ID('F','P','R','O') +#define JOY_TYPE_WINGEX AL_ID('W','I','N','G') +#define JOY_TYPE_SIDEWINDER AL_ID('S','W',' ',' ') +#define JOY_TYPE_SIDEWINDER_AG AL_ID('S','W','A','G') +#define JOY_TYPE_SIDEWINDER_PP AL_ID('S','W','P','P') +#define JOY_TYPE_GAMEPAD_PRO AL_ID('G','P','R','O') +#define JOY_TYPE_GRIP AL_ID('G','R','I','P') +#define JOY_TYPE_GRIP4 AL_ID('G','R','I','4') +#define JOY_TYPE_SNESPAD_LPT1 AL_ID('S','N','E','1') +#define JOY_TYPE_SNESPAD_LPT2 AL_ID('S','N','E','2') +#define JOY_TYPE_SNESPAD_LPT3 AL_ID('S','N','E','3') +#define JOY_TYPE_PSXPAD_LPT1 AL_ID('P','S','X','1') +#define JOY_TYPE_PSXPAD_LPT2 AL_ID('P','S','X','2') +#define JOY_TYPE_PSXPAD_LPT3 AL_ID('P','S','X','3') +#define JOY_TYPE_N64PAD_LPT1 AL_ID('N','6','4','1') +#define JOY_TYPE_N64PAD_LPT2 AL_ID('N','6','4','2') +#define JOY_TYPE_N64PAD_LPT3 AL_ID('N','6','4','3') +#define JOY_TYPE_DB9_LPT1 AL_ID('D','B','9','1') +#define JOY_TYPE_DB9_LPT2 AL_ID('D','B','9','2') +#define JOY_TYPE_DB9_LPT3 AL_ID('D','B','9','3') +#define JOY_TYPE_TURBOGRAFX_LPT1 AL_ID('T','G','X','1') +#define JOY_TYPE_TURBOGRAFX_LPT2 AL_ID('T','G','X','2') +#define JOY_TYPE_TURBOGRAFX_LPT3 AL_ID('T','G','X','3') +#define JOY_TYPE_IFSEGA_ISA AL_ID('S','E','G','I') +#define JOY_TYPE_IFSEGA_PCI AL_ID('S','E','G','P') +#define JOY_TYPE_IFSEGA_PCI_FAST AL_ID('S','G','P','F') +#define JOY_TYPE_WINGWARRIOR AL_ID('W','W','A','R') + + +AL_VAR(JOYSTICK_DRIVER, joystick_standard); +AL_VAR(JOYSTICK_DRIVER, joystick_2pads); +AL_VAR(JOYSTICK_DRIVER, joystick_4button); +AL_VAR(JOYSTICK_DRIVER, joystick_6button); +AL_VAR(JOYSTICK_DRIVER, joystick_8button); +AL_VAR(JOYSTICK_DRIVER, joystick_fspro); +AL_VAR(JOYSTICK_DRIVER, joystick_wingex); +AL_VAR(JOYSTICK_DRIVER, joystick_sw); +AL_VAR(JOYSTICK_DRIVER, joystick_sw_ag); +AL_VAR(JOYSTICK_DRIVER, joystick_sw_pp); +AL_VAR(JOYSTICK_DRIVER, joystick_gpro); +AL_VAR(JOYSTICK_DRIVER, joystick_grip); +AL_VAR(JOYSTICK_DRIVER, joystick_grip4); +AL_VAR(JOYSTICK_DRIVER, joystick_sp1); +AL_VAR(JOYSTICK_DRIVER, joystick_sp2); +AL_VAR(JOYSTICK_DRIVER, joystick_sp3); +AL_VAR(JOYSTICK_DRIVER, joystick_psx1); +AL_VAR(JOYSTICK_DRIVER, joystick_psx2); +AL_VAR(JOYSTICK_DRIVER, joystick_psx3); +AL_VAR(JOYSTICK_DRIVER, joystick_n641); +AL_VAR(JOYSTICK_DRIVER, joystick_n642); +AL_VAR(JOYSTICK_DRIVER, joystick_n643); +AL_VAR(JOYSTICK_DRIVER, joystick_db91); +AL_VAR(JOYSTICK_DRIVER, joystick_db92); +AL_VAR(JOYSTICK_DRIVER, joystick_db93); +AL_VAR(JOYSTICK_DRIVER, joystick_tgx1); +AL_VAR(JOYSTICK_DRIVER, joystick_tgx2); +AL_VAR(JOYSTICK_DRIVER, joystick_tgx3); +AL_VAR(JOYSTICK_DRIVER, joystick_sg1); +AL_VAR(JOYSTICK_DRIVER, joystick_sg2); +AL_VAR(JOYSTICK_DRIVER, joystick_sg2f); +AL_VAR(JOYSTICK_DRIVER, joystick_ww); + + +#define JOYSTICK_DRIVER_STANDARD \ + { JOY_TYPE_STANDARD, &joystick_standard, TRUE }, \ + { JOY_TYPE_2PADS, &joystick_2pads, FALSE }, \ + { JOY_TYPE_4BUTTON, &joystick_4button, FALSE }, \ + { JOY_TYPE_6BUTTON, &joystick_6button, FALSE }, \ + { JOY_TYPE_8BUTTON, &joystick_8button, FALSE }, \ + { JOY_TYPE_FSPRO, &joystick_fspro, FALSE }, \ + { JOY_TYPE_WINGEX, &joystick_wingex, FALSE }, + +#define JOYSTICK_DRIVER_SIDEWINDER \ + { JOY_TYPE_SIDEWINDER, &joystick_sw, TRUE }, \ + { JOY_TYPE_SIDEWINDER_AG, &joystick_sw_ag, TRUE }, \ + { JOY_TYPE_SIDEWINDER_PP, &joystick_sw_pp, TRUE }, + +#define JOYSTICK_DRIVER_GAMEPAD_PRO \ + { JOY_TYPE_GAMEPAD_PRO, &joystick_gpro, TRUE }, + +#define JOYSTICK_DRIVER_GRIP \ + { JOY_TYPE_GRIP, &joystick_grip, TRUE }, \ + { JOY_TYPE_GRIP4, &joystick_grip4, TRUE }, + +#define JOYSTICK_DRIVER_SNESPAD \ + { JOY_TYPE_SNESPAD_LPT1, &joystick_sp1, FALSE }, \ + { JOY_TYPE_SNESPAD_LPT2, &joystick_sp2, FALSE }, \ + { JOY_TYPE_SNESPAD_LPT3, &joystick_sp3, FALSE }, + +#define JOYSTICK_DRIVER_PSXPAD \ + { JOY_TYPE_PSXPAD_LPT1, &joystick_psx1, FALSE }, \ + { JOY_TYPE_PSXPAD_LPT2, &joystick_psx2, FALSE }, \ + { JOY_TYPE_PSXPAD_LPT3, &joystick_psx3, FALSE }, + +#define JOYSTICK_DRIVER_N64PAD \ + { JOY_TYPE_N64PAD_LPT1, &joystick_n641, FALSE }, \ + { JOY_TYPE_N64PAD_LPT2, &joystick_n642, FALSE }, \ + { JOY_TYPE_N64PAD_LPT3, &joystick_n643, FALSE }, + +#define JOYSTICK_DRIVER_DB9 \ + { JOY_TYPE_DB9_LPT1, &joystick_db91, FALSE }, \ + { JOY_TYPE_DB9_LPT2, &joystick_db92, FALSE }, \ + { JOY_TYPE_DB9_LPT3, &joystick_db93, FALSE }, + +#define JOYSTICK_DRIVER_TURBOGRAFX \ + { JOY_TYPE_TURBOGRAFX_LPT1,&joystick_tgx1, FALSE }, \ + { JOY_TYPE_TURBOGRAFX_LPT2,&joystick_tgx2, FALSE }, \ + { JOY_TYPE_TURBOGRAFX_LPT3,&joystick_tgx3, FALSE }, + +#define JOYSTICK_DRIVER_IFSEGA_ISA \ + { JOY_TYPE_IFSEGA_ISA, &joystick_sg1, FALSE }, + +#define JOYSTICK_DRIVER_IFSEGA_PCI \ + { JOY_TYPE_IFSEGA_PCI, &joystick_sg2, FALSE }, + +#define JOYSTICK_DRIVER_IFSEGA_PCI_FAST \ + { JOY_TYPE_IFSEGA_PCI_FAST,&joystick_sg2f, FALSE }, + +#define JOYSTICK_DRIVER_WINGWARRIOR \ + { JOY_TYPE_WINGWARRIOR, &joystick_ww, TRUE }, + + +#define joy_FSPRO_trigger joy_b1 +#define joy_FSPRO_butleft joy_b2 +#define joy_FSPRO_butright joy_b3 +#define joy_FSPRO_butmiddle joy_b4 + +#define joy_WINGEX_trigger joy_b1 +#define joy_WINGEX_buttop joy_b2 +#define joy_WINGEX_butthumb joy_b3 +#define joy_WINGEX_butmiddle joy_b4 + + +AL_FUNC(int, calibrate_joystick_tl, (void)); +AL_FUNC(int, calibrate_joystick_br, (void)); +AL_FUNC(int, calibrate_joystick_throttle_min, (void)); +AL_FUNC(int, calibrate_joystick_throttle_max, (void)); +AL_FUNC(int, calibrate_joystick_hat, (int direction)); + + + +/*******************************************/ +/************ Graphics routines ************/ +/*******************************************/ + +#define ALLEGRO_GFX_HAS_VGA +#define ALLEGRO_GFX_HAS_VBEAF + +#define GFX_VGA AL_ID('V','G','A',' ') +#define GFX_MODEX AL_ID('M','O','D','X') +#define GFX_VESA1 AL_ID('V','B','E','1') +#define GFX_VESA2B AL_ID('V','B','2','B') +#define GFX_VESA2L AL_ID('V','B','2','L') +#define GFX_VESA3 AL_ID('V','B','E','3') +#define GFX_VBEAF AL_ID('V','B','A','F') +#define GFX_XTENDED AL_ID('X','T','N','D') + +AL_VAR(GFX_DRIVER, gfx_vga); +AL_VAR(GFX_DRIVER, gfx_modex); +AL_VAR(GFX_DRIVER, gfx_vesa_1); +AL_VAR(GFX_DRIVER, gfx_vesa_2b); +AL_VAR(GFX_DRIVER, gfx_vesa_2l); +AL_VAR(GFX_DRIVER, gfx_vesa_3); +AL_VAR(GFX_DRIVER, gfx_vbeaf); +AL_VAR(GFX_DRIVER, gfx_xtended); + + +#define GFX_DRIVER_VGA \ + { GFX_VGA, &gfx_vga, TRUE }, + +#define GFX_DRIVER_MODEX \ + { GFX_MODEX, &gfx_modex, TRUE }, + +#define GFX_DRIVER_VBEAF \ + { GFX_VBEAF, &gfx_vbeaf, TRUE }, + +#define GFX_DRIVER_VESA3 \ + { GFX_VESA3, &gfx_vesa_3, TRUE }, + +#define GFX_DRIVER_VESA2L \ + { GFX_VESA2L, &gfx_vesa_2l, TRUE }, + +#define GFX_DRIVER_VESA2B \ + { GFX_VESA2B, &gfx_vesa_2b, TRUE }, + +#define GFX_DRIVER_XTENDED \ + { GFX_XTENDED, &gfx_xtended, FALSE }, + +#define GFX_DRIVER_VESA1 \ + { GFX_VESA1, &gfx_vesa_1, TRUE }, + + +AL_FUNC_DEPRECATED(void, split_modex_screen, (int lyne)); + + +AL_INLINE(void, _set_color, (int index, AL_CONST RGB *p), +{ + outportb(0x3C8, index); + outportb(0x3C9, p->r); + outportb(0x3C9, p->g); + outportb(0x3C9, p->b); + + _current_palette[index] = *p; +}) + + + +/****************************************/ +/************ Sound routines ************/ +/****************************************/ + +#define DIGI_SB10 AL_ID('S','B','1','0') +#define DIGI_SB15 AL_ID('S','B','1','5') +#define DIGI_SB20 AL_ID('S','B','2','0') +#define DIGI_SBPRO AL_ID('S','B','P',' ') +#define DIGI_SB16 AL_ID('S','B','1','6') +#define DIGI_AUDIODRIVE AL_ID('E','S','S',' ') +#define DIGI_SOUNDSCAPE AL_ID('E','S','C',' ') +#define DIGI_WINSOUNDSYS AL_ID('W','S','S',' ') + +#define MIDI_OPL2 AL_ID('O','P','L','2') +#define MIDI_2XOPL2 AL_ID('O','P','L','X') +#define MIDI_OPL3 AL_ID('O','P','L','3') +#define MIDI_SB_OUT AL_ID('S','B',' ',' ') +#define MIDI_MPU AL_ID('M','P','U',' ') +#define MIDI_AWE32 AL_ID('A','W','E',' ') + + +AL_VAR(DIGI_DRIVER, digi_sb10); +AL_VAR(DIGI_DRIVER, digi_sb15); +AL_VAR(DIGI_DRIVER, digi_sb20); +AL_VAR(DIGI_DRIVER, digi_sbpro); +AL_VAR(DIGI_DRIVER, digi_sb16); +AL_VAR(DIGI_DRIVER, digi_audiodrive); +AL_VAR(DIGI_DRIVER, digi_soundscape); +AL_VAR(DIGI_DRIVER, digi_wss); + +AL_VAR(MIDI_DRIVER, midi_opl2); +AL_VAR(MIDI_DRIVER, midi_2xopl2); +AL_VAR(MIDI_DRIVER, midi_opl3); +AL_VAR(MIDI_DRIVER, midi_sb_out); +AL_VAR(MIDI_DRIVER, midi_mpu401); +AL_VAR(MIDI_DRIVER, midi_awe32); + + +#define DIGI_DRIVER_WINSOUNDSYS \ + { DIGI_WINSOUNDSYS, &digi_wss, FALSE }, + +#define DIGI_DRIVER_AUDIODRIVE \ + { DIGI_AUDIODRIVE, &digi_audiodrive, TRUE }, + +#define DIGI_DRIVER_SOUNDSCAPE \ + { DIGI_SOUNDSCAPE, &digi_soundscape, TRUE }, + +#define DIGI_DRIVER_SB \ + { DIGI_SB16, &digi_sb16, TRUE }, \ + { DIGI_SBPRO, &digi_sbpro, TRUE }, \ + { DIGI_SB20, &digi_sb20, TRUE }, \ + { DIGI_SB15, &digi_sb15, TRUE }, \ + { DIGI_SB10, &digi_sb10, TRUE }, + +#define MIDI_DRIVER_AWE32 \ + { MIDI_AWE32, &midi_awe32, TRUE }, + +#define MIDI_DRIVER_ADLIB \ + { MIDI_OPL3, &midi_opl3, TRUE }, \ + { MIDI_2XOPL2, &midi_2xopl2, TRUE }, \ + { MIDI_OPL2, &midi_opl2, TRUE }, + +#define MIDI_DRIVER_SB_OUT \ + { MIDI_SB_OUT, &midi_sb_out, FALSE }, + +#define MIDI_DRIVER_MPU \ + { MIDI_MPU, &midi_mpu401, FALSE }, + + +#ifdef __cplusplus +extern "C" { +#endif + +AL_FUNC(int, load_ibk, (AL_CONST char *filename, int drums)); + +#ifdef __cplusplus +} +#endif diff --git a/allegro/allegro/platform/almac.h b/allegro/allegro/platform/almac.h new file mode 100644 index 0000000000..374601ad5b --- /dev/null +++ b/allegro/allegro/platform/almac.h @@ -0,0 +1,68 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Mac-specific header defines. + * + * By Ronaldo Hideki Yamada. + * + * See readme.txt for copyright information. + */ + + +/*******************************************/ +/************* system drivers **************/ +/*******************************************/ +#define SYSTEM_MACOS AL_ID('M','C','O','S') +AL_VAR(SYSTEM_DRIVER, system_macos); + +/*******************************************/ +/************** timer drivers **************/ +/*******************************************/ +#define TIMER_MACOS AL_ID('M','C','O','S') +AL_VAR(TIMER_DRIVER, timer_macos); + +/*******************************************/ +/************ keyboard drivers *************/ +/*******************************************/ +#define KEYBOARD_MACOS AL_ID('M','C','O','S') +AL_VAR(KEYBOARD_DRIVER, keyboard_macos); +#define KEYBOARD_ADB AL_ID('M','A','D','B') +AL_VAR(KEYBOARD_DRIVER, keyboard_adb); + +/*******************************************/ +/************* mouse drivers ***************/ +/*******************************************/ +#define MOUSE_MACOS AL_ID('M','C','O','S') +AL_VAR(MOUSE_DRIVER, mouse_macos); +#define MOUSE_ADB AL_ID('M','A','D','B') +AL_VAR(MOUSE_DRIVER, mouse_adb); + + +/*******************************************/ +/*************** gfx drivers ***************/ +/*******************************************/ +#define GFX_DRAWSPROCKET AL_ID('D','S','P',' ') +AL_VAR(GFX_DRIVER,gfx_drawsprocket); + + +/********************************************/ +/*************** sound drivers **************/ +/********************************************/ +#define DIGI_MACOS AL_ID('M','C','O','S') +AL_VAR(DIGI_DRIVER, digi_macos); + +#define MIDI_QUICKTIME AL_ID('Q','T',' ',' ') +AL_VAR(MIDI_DRIVER, midi_quicktime); + +/*******************************************/ +/************ joystick drivers *************/ +/*******************************************/ +/*no yet */ + diff --git a/allegro/allegro/platform/almaccfg.h b/allegro/allegro/platform/almaccfg.h new file mode 100644 index 0000000000..f394246894 --- /dev/null +++ b/allegro/allegro/platform/almaccfg.h @@ -0,0 +1,78 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with MPW. + * + * By Ronaldo Hideki Yamada. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include +#endif +#define CALL_NOT_IN_CARBON 1 + +#include +#ifndef ENOSYS +#define ENOSYS ENOENT +#endif + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "mpw" +#define ALLEGRO_BIG_ENDIAN +#undef ALLEGRO_CONSOLE_OK + +#define INLINE +#define ZERO_SIZE_ARRAY(type, name) type name[64] +#define AL_CONST const +#define AL_VAR(type, name) extern type name +#define AL_ARRAY(type, name) extern type name[] +#define AL_FUNC(type, name, args) type name args +#define AL_PRINTFUNC(type, name, args, a, b) AL_FUNC(type, name, args) +#define AL_METHOD(type, name, args) type (*name) args +#define AL_FUNCPTR(type, name, args) extern type (*name) args + +#define END_OF_MAIN() void x##_end(void) { } + +#define END_OF_FUNCTION(x) void x##_end(void) { } +#define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } +#define LOCK_DATA(d, s) _mac_lock((void *)d, s) +#define LOCK_CODE(c, s) _mac_lock((void *)c, s) +#define UNLOCK_DATA(d,s) _mac_unlock((void *)d, s) +#define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) +#define LOCK_FUNCTION(x) LOCK_CODE((void *)x, (intptr_t)x##_end - (intptr_t)x) + +/* long filename status */ +#define ALLEGRO_LFN 0 + +#define ALLEGRO_NO_STRICMP 1 + +#define ALLEGRO_NO_STRUPR 1 + +//#define ALLEGRO_NO_STRDUP 1 +#ifdef __cplusplus +extern "C" +#endif +char *strdup(const char *); + +#ifndef AL_INLINE + #define AL_INLINE(type, name, args, code) static type name args code +#endif + + +// gm_time has an strange return +#define gmtime localtime + + +#define ALLEGRO_EXTRA_HEADER "allegro/platform/almac.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintmac.h" diff --git a/allegro/allegro/platform/almngw32.h b/allegro/allegro/platform/almngw32.h new file mode 100644 index 0000000000..64c5cf4028 --- /dev/null +++ b/allegro/allegro/platform/almngw32.h @@ -0,0 +1,96 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with Mingw32. + * + * By Michael Rickmann. + * + * Native build version by Henrik Stokseth. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include +#endif + + +/* a static auto config */ +/* older mingw's don't seem to have inttypes.h */ +/* #define ALLEGRO_HAVE_INTTYPES_H */ +#define ALLEGRO_HAVE_STDINT_H 1 + + +/* describe this platform */ +#ifdef ALLEGRO_STATICLINK + #define ALLEGRO_PLATFORM_STR "MinGW32.s" +#else + #define ALLEGRO_PLATFORM_STR "MinGW32" +#endif + +#define ALLEGRO_WINDOWS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_USE_CONSTRUCTOR +#define ALLEGRO_MULTITHREADED + +#ifdef ALLEGRO_USE_CONSOLE + #define ALLEGRO_CONSOLE_OK + #define ALLEGRO_NO_MAGIC_MAIN +#endif + + +/* describe how function prototypes look to MINGW32 */ +#if (defined ALLEGRO_STATICLINK) || (defined ALLEGRO_SRC) + #define _AL_DLL +#else + #define _AL_DLL __declspec(dllimport) +#endif + +#define AL_VAR(type, name) extern _AL_DLL type name +#define AL_ARRAY(type, name) extern _AL_DLL type name[] +#define AL_FUNC(type, name, args) extern type name args +#define AL_METHOD(type, name, args) type (*name) args +#define AL_FUNCPTR(type, name, args) extern _AL_DLL type (*name) args + + +/* windows specific defines */ + +#if (defined ALLEGRO_SRC) +/* pathches to handle DX7 headers on a win9x system */ + +/* should WINNT be defined on win9x systems? */ +#ifdef WINNT + #undef WINNT +#endif + +/* defined in windef.h */ +#ifndef HMONITOR_DECLARED + #define HMONITOR_DECLARED 1 +#endif + +#endif /* ALLEGRO_SRC */ + +/* another instance of missing constants in the mingw32 headers */ +#ifndef ENUM_CURRENT_SETTINGS + #define ENUM_CURRENT_SETTINGS ((DWORD)-1) +#endif + +/* describe the asm syntax for this platform */ +#define ALLEGRO_ASM_PREFIX "_" + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/mingw32/asmcapa.h" diff --git a/allegro/allegro/platform/almsvc.h b/allegro/allegro/platform/almsvc.h new file mode 100644 index 0000000000..12fb9888f1 --- /dev/null +++ b/allegro/allegro/platform/almsvc.h @@ -0,0 +1,99 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with MSVC. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include +#endif + + +#pragma warning (disable: 4200 4244 4305) + + +/* describe this platform */ +#ifdef ALLEGRO_STATICLINK + #define ALLEGRO_PLATFORM_STR "MSVC.s" +#else + #define ALLEGRO_PLATFORM_STR "MSVC" +#endif + +#define ALLEGRO_WINDOWS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_GUESS_INTTYPES_OK +#define ALLEGRO_MULTITHREADED + +#ifdef ALLEGRO_USE_CONSOLE + #define ALLEGRO_CONSOLE_OK + #define ALLEGRO_NO_MAGIC_MAIN +#endif + +#ifdef ALLEGRO_AND_MFC + #define ALLEGRO_NO_MAGIC_MAIN +#endif + + +/* describe how function prototypes look to MSVC */ +#if (defined ALLEGRO_STATICLINK) || (defined ALLEGRO_SRC) + #define _AL_DLL +#else + #define _AL_DLL __declspec(dllimport) +#endif + +#define AL_VAR(type, name) extern _AL_DLL type name +#define AL_ARRAY(type, name) extern _AL_DLL type name[] +#define AL_FUNC(type, name, args) _AL_DLL type __cdecl name args +#define AL_METHOD(type, name, args) type (__cdecl *name) args +#define AL_FUNCPTR(type, name, args) extern _AL_DLL type (__cdecl *name) args + +#ifdef AL_INLINE + #define END_OF_INLINE(name) void *_force_instantiate_##name = name; +#else + #define END_OF_INLINE(name) +#endif + +#undef AL_INLINE + +#define AL_INLINE(type, name, args, code) __inline _AL_DLL type __cdecl name args code END_OF_INLINE(name) + +#define INLINE __inline + +#define LONG_LONG __int64 +#define int64_t signed __int64 +#define uint64_t unsigned __int64 + +#define AL_CONST const + + +/* describe the asm syntax for this platform */ +#define ALLEGRO_ASM_PREFIX "_" + + +/* life would be so easy if compilers would all use the same names! */ +#if (!defined S_IRUSR) && (!defined SCAN_DEPEND) + #define S_IRUSR S_IREAD + #define S_IWUSR S_IWRITE +#endif + + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alwin.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintwin.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/msvc/asmcapa.h" diff --git a/allegro/allegro/platform/alosx.h b/allegro/allegro/platform/alosx.h new file mode 100644 index 0000000000..6f7061bbfe --- /dev/null +++ b/allegro/allegro/platform/alosx.h @@ -0,0 +1,115 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * MacOS X specific header defines. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALOSX_H +#define ALOSX_H + +#ifndef ALLEGRO_MACOSX + #error bad include +#endif + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include + #include + #include + #if defined __OBJC__ && defined ALLEGRO_SRC + #undef TRUE + #undef FALSE + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #import + #undef TRUE + #undef FALSE + #undef assert + #define TRUE -1 + #define FALSE 0 + #endif +#endif + + +/* The following code comes from alunix.h */ +/* Magic to capture name of executable file */ +extern int __crt0_argc; +extern char **__crt0_argv; + +#ifndef ALLEGRO_NO_MAGIC_MAIN + #define ALLEGRO_MAGIC_MAIN + #define main _mangled_main + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; +#else + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address; +#endif + + +/* System driver */ +#define SYSTEM_MACOSX AL_ID('O','S','X',' ') +AL_VAR(SYSTEM_DRIVER, system_macosx); + +/* Timer driver */ +#define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') +AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); + +/* Keyboard driver */ +#define KEYBOARD_MACOSX AL_ID('O','S','X','K') +AL_VAR(KEYBOARD_DRIVER, keyboard_macosx); + +/* Mouse driver */ +#define MOUSE_MACOSX AL_ID('O','S','X','M') +AL_VAR(MOUSE_DRIVER, mouse_macosx); + +/* Gfx drivers */ +#define GFX_QUARTZ_WINDOW AL_ID('Q','Z','W','N') +#define GFX_QUARTZ_FULLSCREEN AL_ID('Q','Z','F','L') +AL_VAR(GFX_DRIVER, gfx_quartz_window); +AL_VAR(GFX_DRIVER, gfx_quartz_full); + +/* Digital sound drivers */ +#define DIGI_CORE_AUDIO AL_ID('D','C','A',' ') +#define DIGI_SOUND_MANAGER AL_ID('S','N','D','M') +AL_VAR(DIGI_DRIVER, digi_core_audio); +AL_VAR(DIGI_DRIVER, digi_sound_manager); + +/* MIDI music drivers */ +#define MIDI_CORE_AUDIO AL_ID('M','C','A',' ') +#define MIDI_QUICKTIME AL_ID('Q','T','M',' ') +AL_VAR(MIDI_DRIVER, midi_core_audio); +AL_VAR(MIDI_DRIVER, midi_quicktime); + +/* Joystick drivers */ +#define JOYSTICK_HID AL_ID('H','I','D','J') +AL_VAR(JOYSTICK_DRIVER, joystick_hid); + + +#endif diff --git a/allegro/allegro/platform/alosxcfg.h b/allegro/allegro/platform/alosxcfg.h new file mode 100644 index 0000000000..6e2b8ad6a0 --- /dev/null +++ b/allegro/allegro/platform/alosxcfg.h @@ -0,0 +1,66 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with MacOS X. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALOSXCFG_H +#define ALOSXCFG_H + +/* Provide implementations of missing functions */ +#define ALLEGRO_NO_STRICMP +#define ALLEGRO_NO_STRLWR +#define ALLEGRO_NO_STRUPR + +/* Provide implementations of missing definitions */ +#define O_BINARY 0 + +/* Override default definitions for this platform */ +#define AL_RAND() ((rand() >> 16) & 0x7fff) + +/* A static auto config */ +#define ALLEGRO_HAVE_LIBPTHREAD 1 +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_INTTYPES_H 1 +#define ALLEGRO_HAVE_STDINT_H 1 +#define ALLEGRO_HAVE_SYS_TIME_H 1 +#define ALLEGRO_HAVE_SYS_STAT_H 1 +#define ALLEGRO_HAVE_MKSTEMP 1 + +/* Describe this platform */ +#define ALLEGRO_PLATFORM_STR "MacOS X" +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_USE_CONSTRUCTOR +#define ALLEGRO_MULTITHREADED + +/* Endianesse - different between Intel and PPC based Mac's */ +#ifdef __LITTLE_ENDIAN__ + #define ALLEGRO_LITTLE_ENDIAN +#endif +#ifdef __BIG_ENDIAN__ + #define ALLEGRO_BIG_ENDIAN +#endif + +/* Exclude ASM */ + +#ifndef ALLEGRO_NO_ASM + #define ALLEGRO_NO_ASM +#endif + +/* Arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alosx.h" + + +#endif diff --git a/allegro/allegro/platform/alplatf.h b/allegro/allegro/platform/alplatf.h new file mode 100644 index 0000000000..769d5200fa --- /dev/null +++ b/allegro/allegro/platform/alplatf.h @@ -0,0 +1,2 @@ +/* generated by fix.sh */ +#define ALLEGRO_MSVC diff --git a/allegro/allegro/platform/alqnx.h b/allegro/allegro/platform/alqnx.h new file mode 100644 index 0000000000..acce2bd05d --- /dev/null +++ b/allegro/allegro/platform/alqnx.h @@ -0,0 +1,74 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * QNX specific driver definitions. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +/* magic to capture name of executable file */ +extern int __crt0_argc; +extern char **__crt0_argv; + +#ifndef ALLEGRO_NO_MAGIC_MAIN + #define ALLEGRO_MAGIC_MAIN + #define main _mangled_main + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; +#else + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address; +#endif + + +/* System driver */ +#define SYSTEM_QNX AL_ID('Q','S','Y','S') +AL_VAR(SYSTEM_DRIVER, system_qnx); + + +/* Timer driver */ +#define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') +AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); + + +/* Keyboard driver */ +#define KEYBOARD_QNX AL_ID('Q','K','E','Y') +AL_VAR(KEYBOARD_DRIVER, keyboard_qnx); + + +/* Mouse driver */ +#define MOUSE_QNX AL_ID('Q','M','S','E') +AL_VAR(MOUSE_DRIVER, mouse_qnx); + + +/* Graphics drivers */ +#define GFX_PHOTON AL_ID('Q','P','A','C') +#define GFX_PHOTON_ACCEL AL_ID('Q','P','A','C') +#define GFX_PHOTON_SOFT AL_ID('Q','P','S','O') +#define GFX_PHOTON_SAFE AL_ID('Q','P','S','A') +#define GFX_PHOTON_WIN AL_ID('Q','P','W','N') +AL_VAR(GFX_DRIVER, gfx_photon); +AL_VAR(GFX_DRIVER, gfx_photon_accel); +AL_VAR(GFX_DRIVER, gfx_photon_soft); +AL_VAR(GFX_DRIVER, gfx_photon_safe); +AL_VAR(GFX_DRIVER, gfx_photon_win); + + +/* Sound driver */ +#define DIGI_ALSA AL_ID('A','L','S','A') +AL_VAR(DIGI_DRIVER, digi_alsa); + + +/* MIDI driver */ +#define MIDI_ALSA AL_ID('A','M','I','D') +AL_VAR(MIDI_DRIVER, midi_alsa); diff --git a/allegro/allegro/platform/alqnxcfg.h b/allegro/allegro/platform/alqnxcfg.h new file mode 100644 index 0000000000..a28a328b58 --- /dev/null +++ b/allegro/allegro/platform/alqnxcfg.h @@ -0,0 +1,51 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with QNX. + * + * By Angelo Mottola. + * + * See readme.txt for copyright information. + */ + + +#ifndef SCAN_DEPEND + #include + #include + #include + #include +#endif + + +/* a static auto config */ +#define ALLEGRO_HAVE_INTTYPES_H 1 +#define ALLEGRO_HAVE_STDINT_H 1 +#define ALLEGRO_HAVE_STRICMP 1 +#define ALLEGRO_HAVE_STRLWR 1 +#define ALLEGRO_HAVE_STRUPR 1 +#define ALLEGRO_HAVE_MEMCMP 1 +#define ALLEGRO_HAVE_MKSTEMP 1 +#define ALLEGRO_HAVE_DIRENT_H 1 +#define ALLEGRO_HAVE_SYS_UTSNAME_H 1 +#define ALLEGRO_HAVE_SYS_TIME_H 1 +#define ALLEGRO_HAVE_LIBPTHREAD 1 + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "QNX" +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_HAVE_SCHED_YIELD +#define ALLEGRO_USE_CONSTRUCTOR +#undef ALLEGRO_MULTITHREADED /* FIXME */ + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alqnx.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintqnx.h" +#define ALLEGRO_ASMCAPA_HEADER "obj/qnx/asmcapa.h" diff --git a/allegro/allegro/platform/alucfg.h b/allegro/allegro/platform/alucfg.h new file mode 100644 index 0000000000..abd269ae4e --- /dev/null +++ b/allegro/allegro/platform/alucfg.h @@ -0,0 +1,64 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use on Unix platforms. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#include +#include + +/* Describe this platform. */ +#define ALLEGRO_PLATFORM_STR "Unix" +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_VRAM_SINGLE_SURFACE + +#define ALLEGRO_EXTRA_HEADER "allegro/platform/alunix.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintunix.h" + +#ifndef O_BINARY +#define O_BINARY 0 +#define O_TEXT 0 +#endif + +/* These defines will be provided by configure script. */ +#undef ALLEGRO_COLOR8 +#undef ALLEGRO_COLOR16 +#undef ALLEGRO_COLOR24 +#undef ALLEGRO_COLOR32 + +/* Include configuration generated by configure script. */ +#include "alunixac.h" + +/* Enable multithreaded library */ +#ifdef ALLEGRO_HAVE_LIBPTHREAD +#define ALLEGRO_MULTITHREADED +#endif + +/* Provide implementations of missing functions. */ +#ifndef ALLEGRO_HAVE_STRICMP +#define ALLEGRO_NO_STRICMP +#endif + +#ifndef ALLEGRO_HAVE_STRLWR +#define ALLEGRO_NO_STRLWR +#endif + +#ifndef ALLEGRO_HAVE_STRUPR +#define ALLEGRO_NO_STRUPR +#endif + +#ifndef ALLEGRO_HAVE_MEMCMP +#define ALLEGRO_NO_MEMCMP +#endif diff --git a/allegro/allegro/platform/alunix.h b/allegro/allegro/platform/alunix.h new file mode 100644 index 0000000000..19707a8a29 --- /dev/null +++ b/allegro/allegro/platform/alunix.h @@ -0,0 +1,272 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Unix-specific header defines. + * + * By Michael Bukin. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_UNIX + #error bad include +#endif + + +/* magic to capture name of executable file */ +extern int __crt0_argc; +extern char **__crt0_argv; + +#ifdef ALLEGRO_WITH_MAGIC_MAIN + + #ifndef ALLEGRO_NO_MAGIC_MAIN + #define ALLEGRO_MAGIC_MAIN + #define main _mangled_main + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address = (void*) _mangled_main; + #else + #undef END_OF_MAIN + #define END_OF_MAIN() void *_mangled_main_address; + #endif + +#endif + + + +/**************************************/ +/************ General Unix ************/ +/**************************************/ + +#define TIMERDRV_UNIX_PTHREADS AL_ID('P','T','H','R') +#define TIMERDRV_UNIX_SIGALRM AL_ID('A','L','R','M') + + +#ifdef ALLEGRO_HAVE_LIBPTHREAD +AL_VAR(TIMER_DRIVER, timerdrv_unix_pthreads); +#else +AL_VAR(TIMER_DRIVER, timerdrv_unix_sigalrm); +#endif + + + +/************************************/ +/*********** Sound drivers **********/ +/************************************/ + +#define DIGI_OSS AL_ID('O','S','S','D') +#define MIDI_OSS AL_ID('O','S','S','M') +#define DIGI_ESD AL_ID('E','S','D','D') +#define DIGI_ARTS AL_ID('A','R','T','S') +#define DIGI_SGIAL AL_ID('S','G','I','A') +#define DIGI_ALSA AL_ID('A','L','S','A') +#define MIDI_ALSA AL_ID('A','M','I','D') +#define DIGI_JACK AL_ID('J','A','C','K') + + +#ifdef ALLEGRO_WITH_OSSDIGI +AL_VAR(DIGI_DRIVER, digi_oss); +#define DIGI_DRIVER_OSS \ + { DIGI_OSS, &digi_oss, TRUE }, +#endif /* ALLEGRO_WITH_OSSDIGI */ + +#ifdef ALLEGRO_WITH_OSSMIDI +AL_VAR(MIDI_DRIVER, midi_oss); +#define MIDI_DRIVER_OSS \ + { MIDI_OSS, &midi_oss, TRUE }, +#endif /* ALLEGRO_WITH_OSSMIDI */ + +#ifndef ALLEGRO_WITH_MODULES + +#ifdef ALLEGRO_WITH_ESDDIGI +AL_VAR(DIGI_DRIVER, digi_esd); +#define DIGI_DRIVER_ESD \ + { DIGI_ESD, &digi_esd, TRUE }, +#endif /* ALLEGRO_WITH_ESDDIGI */ + +#ifdef ALLEGRO_WITH_ARTSDIGI +AL_VAR(DIGI_DRIVER, digi_arts); +#define DIGI_DRIVER_ARTS \ + { DIGI_ARTS, &digi_arts, TRUE }, +#endif /* ALLEGRO_WITH_ARTSDIGI */ + +#ifdef ALLEGRO_WITH_SGIALDIGI +AL_VAR(DIGI_DRIVER, digi_sgial); +#define DIGI_DRIVER_SGIAL \ + { DIGI_SGIAL, &digi_sgial, TRUE }, +#endif /* ALLEGRO_WITH_SGIALDIGI */ + +#ifdef ALLEGRO_WITH_ALSADIGI +AL_VAR(DIGI_DRIVER, digi_alsa); +#define DIGI_DRIVER_ALSA \ + { DIGI_ALSA, &digi_alsa, TRUE }, +#endif /* ALLEGRO_WITH_ALSADIGI */ + + +#ifdef ALLEGRO_WITH_ALSAMIDI +AL_VAR(MIDI_DRIVER, midi_alsa); +#define MIDI_DRIVER_ALSA \ + { MIDI_ALSA, &midi_alsa, TRUE }, +#endif /* ALLEGRO_WITH_ALSAMIDI */ + + +#ifdef ALLEGRO_WITH_JACKDIGI +AL_VAR(DIGI_DRIVER, digi_jack); +#define DIGI_DRIVER_JACK \ + { DIGI_JACK, &digi_jack, TRUE }, +#endif /* ALLEGRO_WITH_JACKDIGI */ + +#endif + + + +/************************************/ +/************ X-specific ************/ +/************************************/ + +#define SYSTEM_XWINDOWS AL_ID('X','W','I','N') + +#define KEYBOARD_XWINDOWS AL_ID('X','W','I','N') +#define MOUSE_XWINDOWS AL_ID('X','W','I','N') + +#define GFX_XWINDOWS AL_ID('X','W','I','N') +#define GFX_XWINDOWS_FULLSCREEN AL_ID('X','W','F','S') +#define GFX_XDGA AL_ID('X','D','G','A') +#define GFX_XDGA_FULLSCREEN AL_ID('X','D','F','S') +#define GFX_XDGA2 AL_ID('D','G','A','2') +#define GFX_XDGA2_SOFT AL_ID('D','G','A','S') + + +#ifdef ALLEGRO_WITH_XWINDOWS +AL_VAR(SYSTEM_DRIVER, system_xwin); + +#ifdef ALLEGRO_XWINDOWS_WITH_XF86DGA2 +#ifndef ALLEGRO_WITH_MODULES +AL_VAR(GFX_DRIVER, gfx_xdga2); +AL_VAR(GFX_DRIVER, gfx_xdga2_soft); +#endif +#endif + +#endif /* ALLEGRO_WITH_XWINDOWS */ + + + +/****************************************/ +/************ Linux-specific ************/ +/****************************************/ + +#define SYSTEM_LINUX AL_ID('L','N','X','C') + +#define GFX_VGA AL_ID('V','G','A',' ') +#define GFX_MODEX AL_ID('M','O','D','X') +#define GFX_FBCON AL_ID('F','B',' ',' ') +#define GFX_VBEAF AL_ID('V','B','A','F') +#define GFX_SVGALIB AL_ID('S','V','G','A') + +#define KEYDRV_LINUX AL_ID('L','N','X','C') + +#define MOUSEDRV_LINUX_PS2 AL_ID('L','P','S','2') +#define MOUSEDRV_LINUX_IPS2 AL_ID('L','I','P','S') +#define MOUSEDRV_LINUX_GPMDATA AL_ID('G','P','M','D') +#define MOUSEDRV_LINUX_MS AL_ID('M','S',' ',' ') +#define MOUSEDRV_LINUX_IMS AL_ID('I','M','S',' ') +#define MOUSEDRV_LINUX_EVDEV AL_ID('E','V',' ',' ') + +#define JOY_TYPE_LINUX_ANALOGUE AL_ID('L','N','X','A') + + +#ifdef ALLEGRO_LINUX + +AL_VAR(SYSTEM_DRIVER, system_linux); + +#ifdef ALLEGRO_LINUX_VGA + AL_VAR(GFX_DRIVER, gfx_vga); + AL_VAR(GFX_DRIVER, gfx_modex); + #define ALLEGRO_GFX_HAS_VGA +#endif + +#ifndef ALLEGRO_WITH_MODULES + +#ifdef ALLEGRO_LINUX_FBCON + AL_VAR(GFX_DRIVER, gfx_fbcon); +#endif +#ifdef ALLEGRO_LINUX_SVGALIB + AL_VAR(GFX_DRIVER, gfx_svgalib); +#endif + +#endif + +#ifdef ALLEGRO_LINUX_VBEAF + AL_VAR(GFX_DRIVER, gfx_vbeaf); + #define ALLEGRO_GFX_HAS_VBEAF +#endif + +AL_VAR(MOUSE_DRIVER, mousedrv_linux_ps2); +AL_VAR(MOUSE_DRIVER, mousedrv_linux_ips2); +AL_VAR(MOUSE_DRIVER, mousedrv_linux_gpmdata); +AL_VAR(MOUSE_DRIVER, mousedrv_linux_ms); +AL_VAR(MOUSE_DRIVER, mousedrv_linux_ims); +AL_VAR(MOUSE_DRIVER, mousedrv_linux_evdev); + +AL_FUNC_DEPRECATED(void, split_modex_screen, (int lyne)); + + +/* Port I/O functions -- maybe these should be internal */ + +#ifdef ALLEGRO_LINUX_VGA + +#ifdef __cplusplus +extern "C" { +#endif + +static INLINE void outportb(unsigned short port, unsigned char value) +{ + __asm__ volatile ("outb %0, %1" : : "a" (value), "d" (port)); +} + +static INLINE void outportw(unsigned short port, unsigned short value) +{ + __asm__ volatile ("outw %0, %1" : : "a" (value), "d" (port)); +} + +static INLINE void outportl(unsigned short port, unsigned long value) +{ + __asm__ volatile ("outl %0, %1" : : "a" (value), "d" (port)); +} + +static INLINE unsigned char inportb(unsigned short port) +{ + unsigned char value; + __asm__ volatile ("inb %1, %0" : "=a" (value) : "d" (port)); + return value; +} + +static INLINE unsigned short inportw(unsigned short port) +{ + unsigned short value; + __asm__ volatile ("inw %1, %0" : "=a" (value) : "d" (port)); + return value; +} + +static INLINE unsigned long inportl(unsigned short port) +{ + unsigned long value; + __asm__ volatile ("inl %1, %0" : "=a" (value) : "d" (port)); + return value; +} + +#ifdef __cplusplus +} +#endif + +#endif /* ALLEGRO_LINUX_VGA */ + + +#endif /* ALLEGRO_LINUX */ diff --git a/allegro/allegro/platform/alunixac.hin b/allegro/allegro/platform/alunixac.hin new file mode 100644 index 0000000000..49e80760ab --- /dev/null +++ b/allegro/allegro/platform/alunixac.hin @@ -0,0 +1,177 @@ +/* + * Note that this file is no longer generated by autoheader as it results in + * too much namespace pollution. If you add define a new macro in + * configure.in or aclocal.m4, you must add an entry to this file. + */ + +/* Define if you want support for n bpp modes. */ +#undef ALLEGRO_COLOR8 +#undef ALLEGRO_COLOR16 +#undef ALLEGRO_COLOR24 +#undef ALLEGRO_COLOR32 + +/*---------------------------------------------------------------------------*/ + +/* Define to 1 if you have the corresponding header file. */ +#undef ALLEGRO_HAVE_DIRENT_H +#undef ALLEGRO_HAVE_INTTYPES_H +#undef ALLEGRO_HAVE_LINUX_AWE_VOICE_H +#undef ALLEGRO_HAVE_LINUX_INPUT_H +#undef ALLEGRO_HAVE_LINUX_JOYSTICK_H +#undef ALLEGRO_HAVE_LINUX_SOUNDCARD_H +#undef ALLEGRO_HAVE_MACHINE_SOUNDCARD_H +#undef ALLEGRO_HAVE_SOUNDCARD_H +#undef ALLEGRO_HAVE_STDINT_H +#undef ALLEGRO_HAVE_SV_PROCFS_H +#undef ALLEGRO_HAVE_SYS_IO_H +#undef ALLEGRO_HAVE_SYS_SOUNDCARD_H +#undef ALLEGRO_HAVE_SYS_STAT_H +#undef ALLEGRO_HAVE_SYS_TIME_H +#undef ALLEGRO_HAVE_SYS_UTSNAME_H + +/* Define to 1 if the corresponding functions are available. */ +#undef ALLEGRO_HAVE_GETEXECNAME +#undef ALLEGRO_HAVE_MEMCMP +#undef ALLEGRO_HAVE_MKSTEMP +#undef ALLEGRO_HAVE_MMAP +#undef ALLEGRO_HAVE_MPROTECT +#undef ALLEGRO_HAVE_SCHED_YIELD +#undef ALLEGRO_HAVE_STRICMP +#undef ALLEGRO_HAVE_STRLWR +#undef ALLEGRO_HAVE_STRUPR +#undef ALLEGRO_HAVE_SYSCONF + +/* Define to 1 if procfs reveals argc and argv */ +#undef ALLEGRO_HAVE_PROCFS_ARGCV + +/*---------------------------------------------------------------------------*/ + +/* Define if target machine is little endian. */ +#undef ALLEGRO_LITTLE_ENDIAN + +/* Define if target machine is big endian. */ +#undef ALLEGRO_BIG_ENDIAN + +/* Define for Unix platforms, to use C convention for bank switching. */ +#undef ALLEGRO_NO_ASM + +/* Define if compiler prepends underscore to symbols. */ +#undef ALLEGRO_ASM_PREFIX + +/* Define if assembler supports MMX. */ +#undef ALLEGRO_MMX + +/* Define if assembler supports SSE. */ +#undef ALLEGRO_SSE + +/* Define if target platform is Darwin. */ +#undef ALLEGRO_DARWIN + +/* Define if you have the pthread library. */ +#undef ALLEGRO_HAVE_LIBPTHREAD + +/* Define if constructor attribute is supported. */ +#undef ALLEGRO_USE_CONSTRUCTOR + +/* Define if you need to use a magic main. */ +#undef ALLEGRO_WITH_MAGIC_MAIN + +/* Define if dynamically loaded modules are supported. */ +#undef ALLEGRO_WITH_MODULES + +/*---------------------------------------------------------------------------*/ + +/* Define if you need support for X-Windows. */ +#undef ALLEGRO_WITH_XWINDOWS + +/* Define if MIT-SHM extension is supported. */ +#undef ALLEGRO_XWINDOWS_WITH_SHM + +/* Define if XCursor ARGB extension is available. */ +#undef ALLEGRO_XWINDOWS_WITH_XCURSOR + +/* Define if DGA version 2.0 or newer is supported */ +#undef ALLEGRO_XWINDOWS_WITH_XF86DGA2 + +/* Define if XF86VidMode extension is supported. */ +#undef ALLEGRO_XWINDOWS_WITH_XF86VIDMODE + +/* Define if XIM extension is supported. */ +#undef ALLEGRO_XWINDOWS_WITH_XIM + +/* Define if xpm bitmap support is available. */ +#undef ALLEGRO_XWINDOWS_WITH_XPM + +/*---------------------------------------------------------------------------*/ + +/* Define if target platform is linux. */ +#undef ALLEGRO_LINUX + +/* Define to enable Linux console fbcon driver. */ +#undef ALLEGRO_LINUX_FBCON + +/* Define to enable Linux console SVGAlib driver. */ +#undef ALLEGRO_LINUX_SVGALIB + +/* Define if SVGAlib driver can check vga_version. */ +#undef ALLEGRO_LINUX_SVGALIB_HAVE_VGA_VERSION + +/* Define to enable Linux console VBE/AF driver. */ +#undef ALLEGRO_LINUX_VBEAF + +/* Define to enable Linux console VGA driver. */ +#undef ALLEGRO_LINUX_VGA + +/*---------------------------------------------------------------------------*/ + +/* Define to the installed ALSA version. */ +#undef ALLEGRO_ALSA_VERSION + +/* Define if ALSA DIGI driver is supported. */ +#undef ALLEGRO_WITH_ALSADIGI + +/* Define if ALSA MIDI driver is supported. */ +#undef ALLEGRO_WITH_ALSAMIDI + +/* Define if aRts DIGI driver is supported. */ +#undef ALLEGRO_WITH_ARTSDIGI + +/* Define if ESD DIGI driver is supported. */ +#undef ALLEGRO_WITH_ESDDIGI + +/* Define if JACK DIGI driver is supported. */ +#undef ALLEGRO_WITH_JACKDIGI + +/* Define if OSS DIGI driver is supported. */ +#undef ALLEGRO_WITH_OSSDIGI + +/* Define if OSS MIDI driver is supported. */ +#undef ALLEGRO_WITH_OSSMIDI + +/* Define if SGI AL DIGI driver is supported. */ +#undef ALLEGRO_WITH_SGIALDIGI + +/*---------------------------------------------------------------------------*/ + +/* Define to (void *)-1, if MAP_FAILED is not defined. */ +/* TODO: rename this */ +#undef MAP_FAILED + +/* Define as the return type of signal handlers (`int' or `void'). */ +/* TODO: rename this */ +#undef RETSIGTYPE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/*---------------------------------------------------------------------------*/ +/* vi:set ft=c: */ diff --git a/allegro/allegro/platform/alwatcom.h b/allegro/allegro/platform/alwatcom.h new file mode 100644 index 0000000000..f308afef08 --- /dev/null +++ b/allegro/allegro/platform/alwatcom.h @@ -0,0 +1,195 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Configuration defines for use with Watcom. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + +#ifndef SCAN_DEPEND + #ifndef __SW_3S + #error Allegro only supports stack based calling convention + #endif + + #ifndef __SW_S + #error Stack overflow checking must be disabled + #endif + + #include + #include + #include + #include + #include + #include +#endif + + +#pragma disable_message (120 201 202) + + +/* these are available in OpenWatcom 1.3 (12.3) */ +#if __WATCOMC__ >= 1230 + #define ALLEGRO_HAVE_INTTYPES_H 1 + #define ALLEGRO_HAVE_STDINT_H 1 +#else + #define ALLEGRO_GUESS_INTTYPES_OK +#endif + + +/* describe this platform */ +#define ALLEGRO_PLATFORM_STR "Watcom" +#define ALLEGRO_DOS +#define ALLEGRO_I386 +#define ALLEGRO_LITTLE_ENDIAN +#define ALLEGRO_CONSOLE_OK +#define ALLEGRO_VRAM_SINGLE_SURFACE + +#define ALLEGRO_LFN 0 + +#define LONG_LONG long long +#ifdef ALLEGRO_GUESS_INTTYPES_OK + #define int64_t signed long long + #define uint64_t unsigned long long +#endif + +#if __WATCOMC__ >= 1100 + #define ALLEGRO_MMX +#endif + +#if __WATCOMC__ >= 1200 /* Open Watcom 1.0 */ + #define AL_CONST const +#endif + + +/* emulate some important djgpp routines */ +#define inportb(port) inp(port) +#define inportw(port) inpw(port) +#define outportb(port, val) outp(port, val) +#define outportw(port, val) outpw(port, val) + +#define ffblk find_t +#define ff_name name +#define ff_attrib attrib +#define ff_fsize size +#define ff_ftime wr_time +#define ff_fdate wr_date + +#define findfirst(name, dta, attrib) _dos_findfirst(name, attrib, dta) +#define findnext(dta) _dos_findnext(dta) + +#define random() rand() +#define srandom(n) srand(n) + +#define _dos_ds _default_ds() + +#define dosmemget(offset, length, buffer) memcpy(buffer, (void *)(offset), length) +#define dosmemput(buffer, length, offset) memcpy((void *)(offset), buffer, length) + +#define __djgpp_nearptr_enable() 1 +#define __djgpp_nearptr_disable() + +#define __djgpp_base_address 0 +#define __djgpp_conventional_base 0 + +#define _crt0_startup_flags 1 +#define _CRT0_FLAG_NEARPTR 1 + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef union __dpmi_regs +{ + struct { + unsigned long edi, esi, ebp, res, ebx, edx, ecx, eax; + } d; + struct { + unsigned short di, di_hi, si, si_hi, bp, bp_hi, res, res_hi; + unsigned short bx, bx_hi, dx, dx_hi, cx, cx_hi, ax, ax_hi; + unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss; + } x; + struct { + unsigned char edi[4], esi[4], ebp[4], res[4]; + unsigned char bl, bh, ebx_b2, ebx_b3, dl, dh, edx_b2, edx_b3; + unsigned char cl, ch, ecx_b2, ecx_b3, al, ah, eax_b2, eax_b3; + } h; +} __dpmi_regs; + + +typedef struct __dpmi_meminfo +{ + unsigned long handle; + unsigned long size; + unsigned long address; +} __dpmi_meminfo; + + +typedef struct __dpmi_free_mem_info +{ + unsigned long largest_available_free_block_in_bytes; + unsigned long maximum_unlocked_page_allocation_in_pages; + unsigned long maximum_locked_page_allocation_in_pages; + unsigned long linear_address_space_size_in_pages; + unsigned long total_number_of_unlocked_pages; + unsigned long total_number_of_free_pages; + unsigned long total_number_of_physical_pages; + unsigned long free_linear_address_space_in_pages; + unsigned long size_of_paging_file_partition_in_pages; + unsigned long reserved[3]; +} __dpmi_free_mem_info; + + +extern unsigned long __tb; + + +int __dpmi_int(int vector, __dpmi_regs *regs); +int __dpmi_allocate_dos_memory(int paragraphs, int *ret); +int __dpmi_free_dos_memory(int selector); +int __dpmi_physical_address_mapping(__dpmi_meminfo *info); +int __dpmi_free_physical_address_mapping(__dpmi_meminfo *info); +int __dpmi_lock_linear_region(__dpmi_meminfo *info); +int __dpmi_unlock_linear_region(__dpmi_meminfo *info); +int __dpmi_allocate_ldt_descriptors(int count); +int __dpmi_free_ldt_descriptor(int descriptor); +int __dpmi_get_segment_base_address(int selector, unsigned long *addr); +int __dpmi_set_segment_base_address(int selector, unsigned long address); +int __dpmi_set_segment_limit(int selector, unsigned long limit); +int __dpmi_get_free_memory_information(__dpmi_free_mem_info *info); +int __dpmi_simulate_real_mode_interrupt(int vector, __dpmi_regs *regs); +int __dpmi_simulate_real_mode_procedure_retf(__dpmi_regs *regs); +int _go32_dpmi_lock_data(void *lockaddr, unsigned long locksize); +int _go32_dpmi_lock_code(void *lockaddr, unsigned long locksize); + +long _allocate_real_mode_callback(void (*handler)(__dpmi_regs *r), __dpmi_regs *regs); + + +/* memory locking macros */ +void _unlock_dpmi_data(void *addr, int size); + +#ifdef __cplusplus +} +#endif + + +#define END_OF_FUNCTION(x) void x##_end(void) { } +#define END_OF_STATIC_FUNCTION(x) static void x##_end(void) { } +#define LOCK_DATA(d, s) _go32_dpmi_lock_data(d, s) +#define LOCK_CODE(c, s) _go32_dpmi_lock_code(c, s) +#define UNLOCK_DATA(d,s) _unlock_dpmi_data(d, s) +#define LOCK_VARIABLE(x) LOCK_DATA((void *)&x, sizeof(x)) +#define LOCK_FUNCTION(x) LOCK_CODE((void *)FP_OFF(x), (long)FP_OFF(x##_end) - (long)FP_OFF(x)) + + +/* arrange for other headers to be included later on */ +#define ALLEGRO_EXTRA_HEADER "allegro/platform/aldos.h" +#define ALLEGRO_INTERNAL_HEADER "allegro/platform/aintdos.h" diff --git a/allegro/allegro/platform/alwin.h b/allegro/allegro/platform/alwin.h new file mode 100644 index 0000000000..14ee64235a --- /dev/null +++ b/allegro/allegro/platform/alwin.h @@ -0,0 +1,147 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Windows-specific header defines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_WINDOWS + #error bad include +#endif + + + +/*******************************************/ +/********** magic main emulation ***********/ +/*******************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +AL_FUNC(int, _WinMain, (void *_main, void *hInst, void *hPrev, char *Cmd, int nShow)); + +#ifdef __cplusplus +} +#endif + + +#if (!defined ALLEGRO_NO_MAGIC_MAIN) && (!defined ALLEGRO_SRC) + + #define ALLEGRO_MAGIC_MAIN + #define main _mangled_main + #undef END_OF_MAIN + + /* disable strict pointer typing because of the vague prototype below */ + #define NO_STRICT + + #ifdef __cplusplus + extern "C" int __stdcall WinMain(void *hInst, void *hPrev, char *Cmd, int nShow); + #endif + + #define END_OF_MAIN() \ + \ + int __stdcall WinMain(void *hInst, void *hPrev, char *Cmd, int nShow) \ + { \ + return _WinMain((void *)_mangled_main, hInst, hPrev, Cmd, nShow); \ + } + +#endif + + + +/*******************************************/ +/************* system drivers **************/ +/*******************************************/ +#define SYSTEM_DIRECTX AL_ID('D','X',' ',' ') + +AL_VAR(SYSTEM_DRIVER, system_directx); + + + +/*******************************************/ +/************** timer drivers **************/ +/*******************************************/ +#define TIMER_WIN32_HIGH_PERF AL_ID('W','3','2','H') +#define TIMER_WIN32_LOW_PERF AL_ID('W','3','2','L') + + + +/*******************************************/ +/************ keyboard drivers *************/ +/*******************************************/ +#define KEYBOARD_DIRECTX AL_ID('D','X',' ',' ') + + + +/*******************************************/ +/************* mouse drivers ***************/ +/*******************************************/ +#define MOUSE_DIRECTX AL_ID('D','X',' ',' ') + + + +/*******************************************/ +/*************** gfx drivers ***************/ +/*******************************************/ +#define GFX_DIRECTX AL_ID('D','X','A','C') +#define GFX_DIRECTX_ACCEL AL_ID('D','X','A','C') +#define GFX_DIRECTX_SAFE AL_ID('D','X','S','A') +#define GFX_DIRECTX_SOFT AL_ID('D','X','S','O') +#define GFX_DIRECTX_WIN AL_ID('D','X','W','N') +#define GFX_DIRECTX_OVL AL_ID('D','X','O','V') +#define GFX_GDI AL_ID('G','D','I','B') + +AL_VAR(GFX_DRIVER, gfx_directx_accel); +AL_VAR(GFX_DRIVER, gfx_directx_safe); +AL_VAR(GFX_DRIVER, gfx_directx_soft); +AL_VAR(GFX_DRIVER, gfx_directx_win); +AL_VAR(GFX_DRIVER, gfx_directx_ovl); +AL_VAR(GFX_DRIVER, gfx_gdi); + +#define GFX_DRIVER_DIRECTX \ + { GFX_DIRECTX_ACCEL, &gfx_directx_accel, TRUE }, \ + { GFX_DIRECTX_SOFT, &gfx_directx_soft, TRUE }, \ + { GFX_DIRECTX_SAFE, &gfx_directx_safe, TRUE }, \ + { GFX_DIRECTX_WIN, &gfx_directx_win, TRUE }, \ + { GFX_DIRECTX_OVL, &gfx_directx_ovl, TRUE }, \ + { GFX_GDI, &gfx_gdi, FALSE }, + + + +/********************************************/ +/*************** sound drivers **************/ +/********************************************/ +#define DIGI_DIRECTX(n) AL_ID('D','X','A'+(n),' ') +#define DIGI_DIRECTAMX(n) AL_ID('A','X','A'+(n),' ') +#define DIGI_WAVOUTID(n) AL_ID('W','O','A'+(n),' ') +#define MIDI_WIN32MAPPER AL_ID('W','3','2','M') +#define MIDI_WIN32(n) AL_ID('W','3','2','A'+(n)) +#define MIDI_WIN32_IN(n) AL_ID('W','3','2','A'+(n)) + + + +/*******************************************/ +/************ joystick drivers *************/ +/*******************************************/ +#define JOY_TYPE_DIRECTX AL_ID('D','X',' ',' ') +#define JOY_TYPE_WIN32 AL_ID('W','3','2',' ') + +AL_VAR(JOYSTICK_DRIVER, joystick_directx); +AL_VAR(JOYSTICK_DRIVER, joystick_win32); + +#define JOYSTICK_DRIVER_DIRECTX \ + { JOY_TYPE_DIRECTX, &joystick_directx, TRUE }, + +#define JOYSTICK_DRIVER_WIN32 \ + { JOY_TYPE_WIN32, &joystick_win32, TRUE }, diff --git a/allegro/allegro/platform/astdint.h b/allegro/allegro/platform/astdint.h new file mode 100644 index 0000000000..296813be9e --- /dev/null +++ b/allegro/allegro/platform/astdint.h @@ -0,0 +1,49 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * A header file to get definitions of uint*_t and int*_t. + * + * By Peter Wang. + * + * See readme.txt for copyright information. + */ + +#ifndef ASTDINT_H +#define ASTDINT_H + +/* Please only include this file from include/allegro/internal/alconfig.h + * and don't add more than inttypes.h/stdint.h emulation here. Thanks. + */ + + + +#if defined ALLEGRO_HAVE_INTTYPES_H + #include +#elif defined ALLEGRO_HAVE_STDINT_H + #include +#elif defined ALLEGRO_I386 && defined ALLEGRO_LITTLE_ENDIAN + #ifndef ALLEGRO_GUESS_INTTYPES_OK + #warning Guessing the definitions of fixed-width integer types. + #endif + #define int8_t signed char + #define uint8_t unsigned char + #define int16_t signed short + #define uint16_t unsigned short + #define int32_t signed int + #define uint32_t unsigned int + #define intptr_t int32_t + #define uintptr_t uint32_t +#else + #error I dunno how to get the definitions of fixed-width integer types on your platform. Please report this to your friendly Allegro developer. +#endif + + + +#endif /* ifndef ASTDINT_H */ diff --git a/allegro/allegro/platform/macdef.h b/allegro/allegro/platform/macdef.h new file mode 100644 index 0000000000..22cfabef08 --- /dev/null +++ b/allegro/allegro/platform/macdef.h @@ -0,0 +1,7 @@ +#define rmac_message 128 /*message window ID*/ +#define rerror_str 128 /*errors str*/ + +#define kprefsize 16384 /* kbytes */ +#define kminsize 10000 +#define kStackNeeded 2048*1024 /*unsual stack requeriment? but allegro need*/ +#define kHeapNeeded 8192*1024 /*it's a game OK*/ \ No newline at end of file diff --git a/allegro/allegro/quat.h b/allegro/allegro/quat.h new file mode 100644 index 0000000000..82928b6bfe --- /dev/null +++ b/allegro/allegro/quat.h @@ -0,0 +1,60 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Quaternion routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_QUAT_H +#define ALLEGRO_QUAT_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct QUAT +{ + float w, x, y, z; +} QUAT; + + +AL_VAR(QUAT, identity_quat); + +AL_FUNC(void, quat_mul, (AL_CONST QUAT *p, AL_CONST QUAT *q, QUAT *out)); +AL_FUNC(void, get_x_rotate_quat, (QUAT *q, float r)); +AL_FUNC(void, get_y_rotate_quat, (QUAT *q, float r)); +AL_FUNC(void, get_z_rotate_quat, (QUAT *q, float r)); +AL_FUNC(void, get_rotation_quat, (QUAT *q, float x, float y, float z)); +AL_FUNC(void, get_vector_rotation_quat, (QUAT *q, float x, float y, float z, float a)); + +AL_FUNC(void, apply_quat, (AL_CONST QUAT *q, float x, float y, float z, float *xout, float *yout, float *zout)); +AL_FUNC(void, quat_slerp, (AL_CONST QUAT *from, AL_CONST QUAT *to, float t, QUAT *out, int how)); + +#define QUAT_SHORT 0 +#define QUAT_LONG 1 +#define QUAT_CW 2 +#define QUAT_CCW 3 +#define QUAT_USER 4 + +#define quat_interpolate(from, to, t, out) quat_slerp((from), (to), (t), (out), QUAT_SHORT) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_QUAT_H */ + + diff --git a/allegro/allegro/rle.h b/allegro/allegro/rle.h new file mode 100644 index 0000000000..3159f1d45f --- /dev/null +++ b/allegro/allegro/rle.h @@ -0,0 +1,49 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * RLE sprites. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_RLE_H +#define ALLEGRO_RLE_H + +#include "base.h" +#include "gfx.h" + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct RLE_SPRITE /* a RLE compressed sprite */ +{ + int w, h; /* width and height in pixels */ + int color_depth; /* color depth of the image */ + int size; /* size of sprite data in bytes */ + ZERO_SIZE_ARRAY(signed char, dat); +} RLE_SPRITE; + + +AL_FUNC(RLE_SPRITE *, get_rle_sprite, (struct BITMAP *bitmap)); +AL_FUNC(void, destroy_rle_sprite, (RLE_SPRITE *sprite)); + +#ifdef __cplusplus + } +#endif + +#include "inline/rle.inl" + +#endif /* ifndef ALLEGRO_RLE_H */ + + diff --git a/allegro/allegro/sound.h b/allegro/allegro/sound.h new file mode 100644 index 0000000000..c7bb50c836 --- /dev/null +++ b/allegro/allegro/sound.h @@ -0,0 +1,60 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Sound support routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_SOUND_H +#define ALLEGRO_SOUND_H + +#include "base.h" +#include "digi.h" +#include "stream.h" +#include "midi.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(void, reserve_voices, (int digi_voices, int midi_voices)); +AL_FUNC(void, set_volume_per_voice, (int scale)); + +AL_FUNC(int, install_sound, (int digi, int midi, AL_CONST char *cfg_path)); +AL_FUNC(void, remove_sound, (void)); + +AL_FUNC(int, install_sound_input, (int digi, int midi)); +AL_FUNC(void, remove_sound_input, (void)); + +AL_FUNC(void, set_volume, (int digi_volume, int midi_volume)); +AL_FUNC(void, set_hardware_volume, (int digi_volume, int midi_volume)); + +AL_FUNC(void, get_volume, (int *digi_volume, int *midi_volume)); +AL_FUNC(void, get_hardware_volume, (int *digi_volume, int *midi_volume)); + +AL_FUNC(void, set_mixer_quality, (int quality)); +AL_FUNC(int, get_mixer_quality, (void)); +AL_FUNC(int, get_mixer_frequency, (void)); +AL_FUNC(int, get_mixer_bits, (void)); +AL_FUNC(int, get_mixer_channels, (void)); +AL_FUNC(int, get_mixer_voices, (void)); +AL_FUNC(int, get_mixer_buffer_length, (void)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_SOUND_H */ + + diff --git a/allegro/allegro/stream.h b/allegro/allegro/stream.h new file mode 100644 index 0000000000..54d3ac2463 --- /dev/null +++ b/allegro/allegro/stream.h @@ -0,0 +1,52 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Streaming sound routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_STREAM_H +#define ALLEGRO_STREAM_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct SAMPLE; + +typedef struct AUDIOSTREAM +{ + int voice; /* the voice we are playing on */ + struct SAMPLE *samp; /* the sample we are using */ + int len; /* buffer length */ + int bufcount; /* number of buffers per sample half */ + int bufnum; /* current refill buffer */ + int active; /* which half is currently playing */ + void *locked; /* the locked buffer */ +} AUDIOSTREAM; + +AL_FUNC(AUDIOSTREAM *, play_audio_stream, (int len, int bits, int stereo, int freq, int vol, int pan)); +AL_FUNC(void, stop_audio_stream, (AUDIOSTREAM *stream)); +AL_FUNC(void *, get_audio_stream_buffer, (AUDIOSTREAM *stream)); +AL_FUNC(void, free_audio_stream_buffer, (AUDIOSTREAM *stream)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_STREAM_H */ + + diff --git a/allegro/allegro/system.h b/allegro/allegro/system.h new file mode 100644 index 0000000000..812fc41ae0 --- /dev/null +++ b/allegro/allegro/system.h @@ -0,0 +1,249 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * System level: initialization, cleanup, etc. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_SYSTEM_H +#define ALLEGRO_SYSTEM_H + +#include "base.h" +#include "unicode.h" +#include "config.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct RGB; +struct BITMAP; +struct GFX_VTABLE; +struct GFX_MODE; + +#define ALLEGRO_ERROR_SIZE 256 + +AL_ARRAY(char, allegro_id); +AL_ARRAY(char, allegro_error); + +#define OSTYPE_UNKNOWN 0 +#define OSTYPE_WIN3 AL_ID('W','I','N','3') +#define OSTYPE_WIN95 AL_ID('W','9','5',' ') +#define OSTYPE_WIN98 AL_ID('W','9','8',' ') +#define OSTYPE_WINME AL_ID('W','M','E',' ') +#define OSTYPE_WINNT AL_ID('W','N','T',' ') +#define OSTYPE_WIN2000 AL_ID('W','2','K',' ') +#define OSTYPE_WINXP AL_ID('W','X','P',' ') +#define OSTYPE_WIN2003 AL_ID('W','2','K','3') +#define OSTYPE_WINVISTA AL_ID('W','V','S','T') +#define OSTYPE_OS2 AL_ID('O','S','2',' ') +#define OSTYPE_WARP AL_ID('W','A','R','P') +#define OSTYPE_DOSEMU AL_ID('D','E','M','U') +#define OSTYPE_OPENDOS AL_ID('O','D','O','S') +#define OSTYPE_LINUX AL_ID('T','U','X',' ') +#define OSTYPE_SUNOS AL_ID('S','U','N',' ') +#define OSTYPE_FREEBSD AL_ID('F','B','S','D') +#define OSTYPE_NETBSD AL_ID('N','B','S','D') +#define OSTYPE_OPENBSD AL_ID('O','B','S','D') +#define OSTYPE_IRIX AL_ID('I','R','I','X') +#define OSTYPE_DARWIN AL_ID('D','A','R','W') +#define OSTYPE_QNX AL_ID('Q','N','X',' ') +#define OSTYPE_UNIX AL_ID('U','N','I','X') +#define OSTYPE_BEOS AL_ID('B','E','O','S') +#define OSTYPE_MACOS AL_ID('M','A','C',' ') +#define OSTYPE_MACOSX AL_ID('M','A','C','X') + +AL_VAR(int, os_type); +AL_VAR(int, os_version); +AL_VAR(int, os_revision); +AL_VAR(int, os_multitasking); + +#define SYSTEM_AUTODETECT 0 +#define SYSTEM_NONE AL_ID('N','O','N','E') + +#define MAKE_VERSION(a, b, c) (((a)<<16)|((b)<<8)|(c)) + +AL_FUNC(int, _install_allegro_version_check, (int system_id, int *errno_ptr, + AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))), int version)); + +AL_INLINE(int, install_allegro, (int system_id, int *errno_ptr, + AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void))))), +{ + return _install_allegro_version_check(system_id, errno_ptr, atexit_ptr, \ + MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)); +}) + +#define allegro_init() _install_allegro_version_check(SYSTEM_AUTODETECT, &errno, \ + (int (*)(void (*)(void)))atexit, \ + MAKE_VERSION(ALLEGRO_VERSION, ALLEGRO_SUB_VERSION, ALLEGRO_WIP_VERSION)) + +AL_FUNC(void, allegro_exit, (void)); + +AL_PRINTFUNC(void, allegro_message, (AL_CONST char *msg, ...), 1, 2); +AL_FUNC(void, get_executable_name, (char *output, int size)); +AL_FUNC(int, set_close_button_callback, (AL_METHOD(void, proc, (void)))); + + +AL_FUNC(void, check_cpu, (void)); + +/* CPU Capabilities flags for x86 capable chips */ +#define CPU_ID 0x0001 +#define CPU_FPU 0x0002 +#define CPU_MMX 0x0004 +#define CPU_MMXPLUS 0x0008 +#define CPU_SSE 0x0010 +#define CPU_SSE2 0x0020 +#define CPU_3DNOW 0x0040 +#define CPU_ENH3DNOW 0x0080 +#define CPU_CMOV 0x0100 +#define CPU_AMD64 0x0200 +#define CPU_IA64 0x0400 +#define CPU_SSE3 0x0800 + +/* CPU families - PC */ +#define CPU_FAMILY_UNKNOWN 0 +#define CPU_FAMILY_I386 3 +#define CPU_FAMILY_I486 4 +#define CPU_FAMILY_I586 5 +#define CPU_FAMILY_I686 6 +#define CPU_FAMILY_ITANIUM 7 +#define CPU_FAMILY_EXTENDED 15 +/* CPUID only returns 15 bits, we need extra information from the CPU */ +/* model to identify Pentium IV, Xeon and Athlon 64 processors. */ + +/* CPU families - Power PC */ +#define CPU_FAMILY_POWERPC 18 + +/* CPU models - PC */ +/* 486 */ +#define CPU_MODEL_I486DX 0 +#define CPU_MODEL_I486DX50 1 +#define CPU_MODEL_I486SX 2 +#define CPU_MODEL_I487SX 3 +#define CPU_MODEL_I486SL 4 +#define CPU_MODEL_I486SX2 5 +#define CPU_MODEL_I486DX2 7 +#define CPU_MODEL_I486DX4 8 + +/* Intel/586 */ +#define CPU_MODEL_PENTIUM 1 +#define CPU_MODEL_PENTIUMP54C 2 +#define CPU_MODEL_PENTIUMOVERDRIVE 3 +#define CPU_MODEL_PENTIUMOVERDRIVEDX4 4 +#define CPU_MODEL_CYRIX 14 +#define CPU_MODEL_UNKNOWN 15 + +/* AMD/586 */ +#define CPU_MODEL_K5 0 +#define CPU_MODEL_K6 6 + +/* Intel/686 */ +#define CPU_MODEL_PENTIUMPROA 0 +#define CPU_MODEL_PENTIUMPRO 1 +#define CPU_MODEL_PENTIUMIIKLAMATH 3 +#define CPU_MODEL_PENTIUMII 5 +#define CPU_MODEL_CELERON 6 +#define CPU_MODEL_PENTIUMIIIKATMAI 7 +#define CPU_MODEL_PENTIUMIIICOPPERMINE 8 +#define CPU_MODEL_PENTIUMIIIMOBILE 9 + +/* AMD/686 */ +#define CPU_MODEL_ATHLON 2 +#define CPU_MODEL_DURON 3 + + +/* Information when CPU_FAMILY is 15 */ +#define CPU_MODEL_PENTIUMIV 0 +#define CPU_MODEL_XEON 2 + +#define CPU_MODEL_ATHLON64 4 +#define CPU_MODEL_OPTERON 5 + +/* Information for Power PC processors */ +/* these defines are taken from */ +#define CPU_MODEL_POWERPC_601 1 +#define CPU_MODEL_POWERPC_602 2 +#define CPU_MODEL_POWERPC_603 3 +#define CPU_MODEL_POWERPC_603e 4 +#define CPU_MODEL_POWERPC_603ev 5 +#define CPU_MODEL_POWERPC_604 6 +#define CPU_MODEL_POWERPC_604e 7 +#define CPU_MODEL_POWERPC_620 8 +#define CPU_MODEL_POWERPC_750 9 +#define CPU_MODEL_POWERPC_7400 10 +#define CPU_MODEL_POWERPC_7450 11 + +AL_ARRAY(char, cpu_vendor); +AL_VAR(int, cpu_family); +AL_VAR(int, cpu_model); +AL_VAR(int, cpu_capabilities); + + +typedef struct SYSTEM_DRIVER +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); + AL_METHOD(void, get_executable_name, (char *output, int size)); + AL_METHOD(int, find_resource, (char *dest, AL_CONST char *resource, int size)); + AL_METHOD(void, set_window_title, (AL_CONST char *name)); + AL_METHOD(int, set_close_button_callback, (AL_METHOD(void, proc, (void)))); + AL_METHOD(void, message, (AL_CONST char *msg)); + AL_METHOD(void, assert, (AL_CONST char *msg)); + AL_METHOD(void, save_console_state, (void)); + AL_METHOD(void, restore_console_state, (void)); + AL_METHOD(struct BITMAP *, create_bitmap, (int color_depth, int width, int height)); + AL_METHOD(void, created_bitmap, (struct BITMAP *bmp)); + AL_METHOD(struct BITMAP *, create_sub_bitmap, (struct BITMAP *parent, int x, int y, int width, int height)); + AL_METHOD(void, created_sub_bitmap, (struct BITMAP *bmp, struct BITMAP *parent)); + AL_METHOD(int, destroy_bitmap, (struct BITMAP *bitmap)); + AL_METHOD(void, read_hardware_palette, (void)); + AL_METHOD(void, set_palette_range, (AL_CONST struct RGB *p, int from, int to, int retracesync)); + AL_METHOD(struct GFX_VTABLE *, get_vtable, (int color_depth)); + AL_METHOD(int, set_display_switch_mode, (int mode)); + AL_METHOD(void, display_switch_lock, (int lock, int foreground)); + AL_METHOD(int, desktop_color_depth, (void)); + AL_METHOD(int, get_desktop_resolution, (int *width, int *height)); + AL_METHOD(void, get_gfx_safe_mode, (int *driver, struct GFX_MODE *mode)); + AL_METHOD(void, yield_timeslice, (void)); + AL_METHOD(void *, create_mutex, (void)); + AL_METHOD(void, destroy_mutex, (void *handle)); + AL_METHOD(void, lock_mutex, (void *handle)); + AL_METHOD(void, unlock_mutex, (void *handle)); + AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, joystick_drivers, (void)); + AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); +} SYSTEM_DRIVER; + + +AL_VAR(SYSTEM_DRIVER, system_none); +AL_VAR(SYSTEM_DRIVER *, system_driver); +AL_ARRAY(_DRIVER_INFO, _system_driver_list); + +#ifdef __cplusplus + } +#endif + +#include "inline/system.inl" + +#endif /* ifndef ALLEGRO_SYSTEM_H */ + + diff --git a/allegro/allegro/text.h b/allegro/allegro/text.h new file mode 100644 index 0000000000..feafc1ddf4 --- /dev/null +++ b/allegro/allegro/text.h @@ -0,0 +1,54 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Text output routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_TEXT_H +#define ALLEGRO_TEXT_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +struct BITMAP; + +struct FONT_VTABLE; + +struct FONT; + +AL_VAR(struct FONT *, font); +AL_VAR(int, allegro_404_char); +AL_FUNC(void, textout_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); +AL_FUNC(void, textout_centre_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); +AL_FUNC(void, textout_right_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x, int y, int color, int bg)); +AL_FUNC(void, textout_justify_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, AL_CONST char *str, int x1, int x2, int y, int diff, int color, int bg)); +AL_PRINTFUNC(void, textprintf_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); +AL_PRINTFUNC(void, textprintf_centre_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); +AL_PRINTFUNC(void, textprintf_right_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x, int y, int color, int bg, AL_CONST char *format, ...), 7, 8); +AL_PRINTFUNC(void, textprintf_justify_ex, (struct BITMAP *bmp, AL_CONST struct FONT *f, int x1, int x2, int y, int diff, int color, int bg, AL_CONST char *format, ...), 9, 10); +AL_FUNC(int, text_length, (AL_CONST struct FONT *f, AL_CONST char *str)); +AL_FUNC(int, text_height, (AL_CONST struct FONT *f)); +AL_FUNC(void, destroy_font, (struct FONT *f)); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_TEXT_H */ + + diff --git a/allegro/allegro/timer.h b/allegro/allegro/timer.h new file mode 100644 index 0000000000..1332919543 --- /dev/null +++ b/allegro/allegro/timer.h @@ -0,0 +1,76 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Timer routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_TIMER_H +#define ALLEGRO_TIMER_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define TIMERS_PER_SECOND 1193181L +#define SECS_TO_TIMER(x) ((long)(x) * TIMERS_PER_SECOND) +#define MSEC_TO_TIMER(x) ((long)(x) * (TIMERS_PER_SECOND / 1000)) +#define BPS_TO_TIMER(x) (TIMERS_PER_SECOND / (long)(x)) +#define BPM_TO_TIMER(x) ((60 * TIMERS_PER_SECOND) / (long)(x)) + +typedef struct TIMER_DRIVER +{ + int id; + AL_CONST char *name; + AL_CONST char *desc; + AL_CONST char *ascii_name; + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); + AL_METHOD(int, install_int, (AL_METHOD(void, proc, (void)), long speed)); + AL_METHOD(void, remove_int, (AL_METHOD(void, proc, (void)))); + AL_METHOD(int, install_param_int, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); + AL_METHOD(void, remove_param_int, (AL_METHOD(void, proc, (void *param)), void *param)); + AL_METHOD(int, can_simulate_retrace, (void)); + AL_METHOD(void, simulate_retrace, (int enable)); + AL_METHOD(void, rest, (unsigned int tyme, AL_METHOD(void, callback, (void)))); +} TIMER_DRIVER; + + +AL_VAR(TIMER_DRIVER *, timer_driver); +AL_ARRAY(_DRIVER_INFO, _timer_driver_list); + +AL_FUNC(int, install_timer, (void)); +AL_FUNC(void, remove_timer, (void)); + +AL_FUNC(int, install_int_ex, (AL_METHOD(void, proc, (void)), long speed)); +AL_FUNC(int, install_int, (AL_METHOD(void, proc, (void)), long speed)); +AL_FUNC(void, remove_int, (AL_METHOD(void, proc, (void)))); + +AL_FUNC(int, install_param_int_ex, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); +AL_FUNC(int, install_param_int, (AL_METHOD(void, proc, (void *param)), void *param, long speed)); +AL_FUNC(void, remove_param_int, (AL_METHOD(void, proc, (void *param)), void *param)); + +AL_VAR(volatile int, retrace_count); + +AL_FUNC(void, rest, (unsigned int tyme)); +AL_FUNC(void, rest_callback, (unsigned int tyme, AL_METHOD(void, callback, (void)))); + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_TIMER_H */ + diff --git a/allegro/allegro/unicode.h b/allegro/allegro/unicode.h new file mode 100644 index 0000000000..f4d8b30a7f --- /dev/null +++ b/allegro/allegro/unicode.h @@ -0,0 +1,116 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Unicode support routines. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_UNICODE__H +#define ALLEGRO_UNICODE__H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define U_ASCII AL_ID('A','S','C','8') +#define U_ASCII_CP AL_ID('A','S','C','P') +#define U_UNICODE AL_ID('U','N','I','C') +#define U_UTF8 AL_ID('U','T','F','8') +#define U_CURRENT AL_ID('c','u','r','.') + +AL_FUNC(void, set_uformat, (int type)); +AL_FUNC(int, get_uformat, (void)); +AL_FUNC(void, register_uformat, (int type, AL_METHOD(int, u_getc, (AL_CONST char *s)), AL_METHOD(int, u_getx, (char **s)), AL_METHOD(int, u_setc, (char *s, int c)), AL_METHOD(int, u_width, (AL_CONST char *s)), AL_METHOD(int, u_cwidth, (int c)), AL_METHOD(int, u_isok, (int c)), int u_width_max)); +AL_FUNC(void, set_ucodepage, (AL_CONST unsigned short *table, AL_CONST unsigned short *extras)); + +AL_FUNC(int, need_uconvert, (AL_CONST char *s, int type, int newtype)); +AL_FUNC(int, uconvert_size, (AL_CONST char *s, int type, int newtype)); +AL_FUNC(void, do_uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); +AL_FUNC(char *, uconvert, (AL_CONST char *s, int type, char *buf, int newtype, int size)); +AL_FUNC(int, uwidth_max, (int type)); + +#define uconvert_ascii(s, buf) uconvert(s, U_ASCII, buf, U_CURRENT, sizeof(buf)) +#define uconvert_toascii(s, buf) uconvert(s, U_CURRENT, buf, U_ASCII, sizeof(buf)) + +#define EMPTY_STRING "\0\0\0" + +AL_ARRAY(char, empty_string); + +AL_FUNCPTR(int, ugetc, (AL_CONST char *s)); +AL_FUNCPTR(int, ugetx, (char **s)); +AL_FUNCPTR(int, ugetxc, (AL_CONST char **s)); +AL_FUNCPTR(int, usetc, (char *s, int c)); +AL_FUNCPTR(int, uwidth, (AL_CONST char *s)); +AL_FUNCPTR(int, ucwidth, (int c)); +AL_FUNCPTR(int, uisok, (int c)); +AL_FUNC(int, uoffset, (AL_CONST char *s, int idx)); +AL_FUNC(int, ugetat, (AL_CONST char *s, int idx)); +AL_FUNC(int, usetat, (char *s, int idx, int c)); +AL_FUNC(int, uinsert, (char *s, int idx, int c)); +AL_FUNC(int, uremove, (char *s, int idx)); +AL_FUNC(int, utolower, (int c)); +AL_FUNC(int, utoupper, (int c)); +AL_FUNC(int, uisspace, (int c)); +AL_FUNC(int, uisdigit, (int c)); +AL_FUNC(int, ustrsize, (AL_CONST char *s)); +AL_FUNC(int, ustrsizez, (AL_CONST char *s)); +AL_FUNC(char *, _ustrdup, (AL_CONST char *src, AL_METHOD(void *, malloc_func, (size_t)))); +AL_FUNC(char *, ustrzcpy, (char *dest, int size, AL_CONST char *src)); +AL_FUNC(char *, ustrzcat, (char *dest, int size, AL_CONST char *src)); +AL_FUNC(int, ustrlen, (AL_CONST char *s)); +AL_FUNC(int, ustrcmp, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(char *, ustrzncpy, (char *dest, int size, AL_CONST char *src, int n)); +AL_FUNC(char *, ustrzncat, (char *dest, int size, AL_CONST char *src, int n)); +AL_FUNC(int, ustrncmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); +AL_FUNC(int, ustricmp, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(int, ustrnicmp, (AL_CONST char *s1, AL_CONST char *s2, int n)); +AL_FUNC(char *, ustrlwr, (char *s)); +AL_FUNC(char *, ustrupr, (char *s)); +AL_FUNC(char *, ustrchr, (AL_CONST char *s, int c)); +AL_FUNC(char *, ustrrchr, (AL_CONST char *s, int c)); +AL_FUNC(char *, ustrstr, (AL_CONST char *s1, AL_CONST char *s2)); +AL_FUNC(char *, ustrpbrk, (AL_CONST char *s, AL_CONST char *set)); +AL_FUNC(char *, ustrtok, (char *s, AL_CONST char *set)); +AL_FUNC(char *, ustrtok_r, (char *s, AL_CONST char *set, char **last)); +AL_FUNC(double, uatof, (AL_CONST char *s)); +AL_FUNC(long, ustrtol, (AL_CONST char *s, char **endp, int base)); +AL_FUNC(double, ustrtod, (AL_CONST char *s, char **endp)); +AL_FUNC(AL_CONST char *, ustrerror, (int err)); +AL_PRINTFUNC(int, uszprintf, (char *buf, int size, AL_CONST char *format, ...), 3, 4); +AL_FUNC(int, uvszprintf, (char *buf, int size, AL_CONST char *format, va_list args)); +AL_PRINTFUNC(int, usprintf, (char *buf, AL_CONST char *format, ...), 2, 3); + +#ifndef ustrdup + #ifdef FORTIFY + #define ustrdup(src) _ustrdup(src, Fortify_malloc) + #else + #define ustrdup(src) _ustrdup(src, malloc) + #endif +#endif + +#define ustrcpy(dest, src) ustrzcpy(dest, INT_MAX, src) +#define ustrcat(dest, src) ustrzcat(dest, INT_MAX, src) +#define ustrncpy(dest, src, n) ustrzncpy(dest, INT_MAX, src, n) +#define ustrncat(dest, src, n) ustrzncat(dest, INT_MAX, src, n) +#define uvsprintf(buf, format, args) uvszprintf(buf, INT_MAX, format, args) + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_UNICODE__H */ + + diff --git a/allegro/fixed/aintern.h b/allegro/fixed/aintern.h new file mode 100644 index 0000000000..f8ef9f2141 --- /dev/null +++ b/allegro/fixed/aintern.h @@ -0,0 +1,1260 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Some definitions for internal use by the library code. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef AINTERN_H +#define AINTERN_H + +#ifndef ALLEGRO_H + #error must include allegro.h first +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* length in bytes of the cpu_vendor string */ +#define _AL_CPU_VENDOR_SIZE 32 + + +/* flag for how many times we have been initialised */ +AL_VAR(int, _allegro_count); + + +/* flag to know whether we are being called by the exit mechanism */ +AL_VAR(int, _allegro_in_exit); + + +/* These functions are referenced by 4.2.0 binaries, but should no longer be + * used by newer versions directly. + * _get_allegro_version would be marked deprecated except that misc/fixdll.* + * would complain about it being missing. + */ +AL_FUNC(int, _get_allegro_version, (void)); +AL_FUNC(int, _install_allegro, (int system_id, int *errno_ptr, AL_METHOD(int, atexit_ptr, (AL_METHOD(void, func, (void)))))); + + +/* flag to decide whether to disable the screensaver */ +enum { + NEVER_DISABLED, + FULLSCREEN_DISABLED, + ALWAYS_DISABLED +}; + +AL_VAR(int, _screensaver_policy); + + +AL_FUNCPTR(int, _al_trace_handler, (AL_CONST char *msg)); + + +/* malloc wrappers */ +/* The 4.3 branch uses the following macro names to allow the user to customise + * the memory management routines. We don't have that feature in 4.2, but we + * use the same macros names in order to reduce divergence of the codebases. + */ +#define _AL_MALLOC(SIZE) (_al_malloc(SIZE)) +#define _AL_MALLOC_ATOMIC(SIZE) (_al_malloc(SIZE)) +#define _AL_FREE(PTR) (_al_free(PTR)) +#define _AL_REALLOC(PTR, SIZE) (_al_realloc(PTR, SIZE)) + +AL_FUNC(void *, _al_malloc, (size_t size)); +AL_FUNC(void, _al_free, (void *mem)); +AL_FUNC(void *, _al_realloc, (void *mem, size_t size)); + + + +/* some Allegro functions need a block of scratch memory */ +AL_VAR(void *, _scratch_mem); +AL_VAR(int, _scratch_mem_size); + + +AL_INLINE(void, _grow_scratch_mem, (int size), +{ + if (size > _scratch_mem_size) { + size = (size+1023) & 0xFFFFFC00; + _scratch_mem = _AL_REALLOC(_scratch_mem, size); + _scratch_mem_size = size; + } +}) + + +/* list of functions to call at program cleanup */ +AL_FUNC(void, _add_exit_func, (AL_METHOD(void, func, (void)), AL_CONST char *desc)); +AL_FUNC(void, _remove_exit_func, (AL_METHOD(void, func, (void)))); + + +/* helper structure for talking to Unicode strings */ +typedef struct UTYPE_INFO +{ + int id; + AL_METHOD(int, u_getc, (AL_CONST char *s)); + AL_METHOD(int, u_getx, (char **s)); + AL_METHOD(int, u_setc, (char *s, int c)); + AL_METHOD(int, u_width, (AL_CONST char *s)); + AL_METHOD(int, u_cwidth, (int c)); + AL_METHOD(int, u_isok, (int c)); + int u_width_max; +} UTYPE_INFO; + +AL_FUNC(UTYPE_INFO *, _find_utype, (int type)); + + +/* message stuff */ +#define ALLEGRO_MESSAGE_SIZE 4096 + + +/* wrappers for implementing disk I/O on different platforms */ +AL_FUNC(int, _al_file_isok, (AL_CONST char *filename)); +AL_FUNC(uint64_t, _al_file_size_ex, (AL_CONST char *filename)); +AL_FUNC(time_t, _al_file_time, (AL_CONST char *filename)); +AL_FUNC(int, _al_drive_exists, (int drive)); +AL_FUNC(int, _al_getdrive, (void)); +AL_FUNC(void, _al_getdcwd, (int drive, char *buf, int size)); + +/* obsolete; only exists for binary compatibility with 4.2.0 */ +AL_FUNC(long, _al_file_size, (AL_CONST char *filename)); + + +/* packfile stuff */ +AL_VAR(int, _packfile_filesize); +AL_VAR(int, _packfile_datasize); +AL_VAR(int, _packfile_type); +AL_FUNC(PACKFILE *, _pack_fdopen, (int fd, AL_CONST char *mode, AL_CONST char *password)); + +AL_FUNC(int, _al_lzss_incomplete_state, (AL_CONST LZSS_UNPACK_DATA *dat)); + + +/* config stuff */ +void _reload_config(void); + + +/* various bits of mouse stuff */ +AL_FUNC(void, _handle_mouse_input, (void)); + +AL_VAR(int, _mouse_x); +AL_VAR(int, _mouse_y); +AL_VAR(int, _mouse_z); +AL_VAR(int, _mouse_w); +AL_VAR(int, _mouse_b); +AL_VAR(int, _mouse_on); + +AL_VAR(int, _mouse_installed); + +AL_VAR(int, _mouse_type); +AL_VAR(BITMAP *, _mouse_screen); +AL_VAR(BITMAP *, _mouse_pointer); + + +/* various bits of timer stuff */ +AL_FUNC(long, _handle_timer_tick, (int interval)); + +#define MAX_TIMERS 16 + +/* list of active timer handlers */ +typedef struct TIMER_QUEUE +{ + AL_METHOD(void, proc, (void)); /* timer handler functions */ + AL_METHOD(void, param_proc, (void *param)); + void *param; /* param for param_proc if used */ + long speed; /* timer speed */ + long counter; /* counts down to zero=blastoff */ +} TIMER_QUEUE; + +AL_ARRAY(TIMER_QUEUE, _timer_queue); + +AL_VAR(int, _timer_installed); + +AL_VAR(int, _timer_use_retrace); +AL_VAR(volatile int, _retrace_hpp_value); + +AL_VAR(long, _vsync_speed); + + +/* various bits of keyboard stuff */ +AL_FUNC(void, _handle_key_press, (int keycode, int scancode)); +AL_FUNC(void, _handle_key_release, (int scancode)); + +AL_VAR(int, _keyboard_installed); +AL_ARRAY(AL_CONST char *, _keyboard_common_names); +AL_ARRAY(volatile char, _key); +AL_VAR(volatile int, _key_shifts); + + +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_DJGPP) || (defined ALLEGRO_WATCOM) || \ + (defined ALLEGRO_QNX) || (defined ALLEGRO_BEOS) + +AL_ARRAY(char *, _pckeys_names); + +AL_FUNC(void, _pckeys_init, (void)); +AL_FUNC(void, _handle_pckey, (int code)); +AL_FUNC(int, _pckey_scancode_to_ascii, (int scancode)); +AL_FUNC(AL_CONST char *, _pckey_scancode_to_name, (int scancode)); + +AL_VAR(unsigned short *, _key_ascii_table); +AL_VAR(unsigned short *, _key_capslock_table); +AL_VAR(unsigned short *, _key_shift_table); +AL_VAR(unsigned short *, _key_control_table); +AL_VAR(unsigned short *, _key_altgr_lower_table); +AL_VAR(unsigned short *, _key_altgr_upper_table); +AL_VAR(unsigned short *, _key_accent1_lower_table); +AL_VAR(unsigned short *, _key_accent1_upper_table); +AL_VAR(unsigned short *, _key_accent2_lower_table); +AL_VAR(unsigned short *, _key_accent2_upper_table); +AL_VAR(unsigned short *, _key_accent3_lower_table); +AL_VAR(unsigned short *, _key_accent3_upper_table); +AL_VAR(unsigned short *, _key_accent4_lower_table); +AL_VAR(unsigned short *, _key_accent4_upper_table); + +AL_VAR(int, _key_accent1); +AL_VAR(int, _key_accent2); +AL_VAR(int, _key_accent3); +AL_VAR(int, _key_accent4); +AL_VAR(int, _key_accent1_flag); +AL_VAR(int, _key_accent2_flag); +AL_VAR(int, _key_accent3_flag); +AL_VAR(int, _key_accent4_flag); + +AL_VAR(int, _key_standard_kb); + +AL_VAR(char *, _keyboard_layout); + +#endif + +#if (defined ALLEGRO_WINDOWS) + + AL_FUNC(int, _al_win_open, (const char *filename, int mode, int perm)); + AL_FUNC(int, _al_win_unlink, (const char *filename)); + + + #define _al_open(filename, mode, perm) _al_win_open(filename, mode, perm) + #define _al_unlink(filename) _al_win_unlink(filename) + +#else + + #define _al_open(filename, mode, perm) open(filename, mode, perm) + #define _al_unlink(filename) unlink(filename) + +#endif + + +/* various bits of joystick stuff */ +AL_VAR(int, _joy_type); + +AL_VAR(int, _joystick_installed); + + +/* some GUI innards that other people need to use */ +AL_FUNC(int, _gui_shadow_box_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_ctext_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_button_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_edit_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_list_proc, (int msg, DIALOG *d, int c)); +AL_FUNC(int, _gui_text_list_proc, (int msg, DIALOG *d, int c)); + +AL_FUNC(void, _handle_scrollable_scroll_click, (DIALOG *d, int listsize, int *offset, int height)); +AL_FUNC(void, _handle_scrollable_scroll, (DIALOG *d, int listsize, int *idx, int *offset)); +AL_FUNC(void, _handle_listbox_click, (DIALOG *d)); +AL_FUNC(void, _draw_scrollable_frame, (DIALOG *d, int listsize, int offset, int height, int fg_color, int bg)); +AL_FUNC(void, _draw_listbox, (DIALOG *d)); +AL_FUNC(void, _draw_textbox, (char *thetext, int *listsize, int draw, int offset, int wword, int tabsize, int x, int y, int w, int h, int disabled, int fore, int deselect, int disable)); + + +/* text- and font-related stuff */ +typedef struct FONT_VTABLE +{ + AL_METHOD(int, font_height, (AL_CONST FONT *f)); + AL_METHOD(int, char_length, (AL_CONST FONT *f, int ch)); + AL_METHOD(int, text_length, (AL_CONST FONT *f, AL_CONST char *text)); + AL_METHOD(int, render_char, (AL_CONST FONT *f, int ch, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, render, (AL_CONST FONT *f, AL_CONST char *text, int fg, int bg, BITMAP *bmp, int x, int y)); + AL_METHOD(void, destroy, (FONT *f)); + + AL_METHOD(int, get_font_ranges, (FONT *f)); + AL_METHOD(int, get_font_range_begin, (FONT *f, int range)); + AL_METHOD(int, get_font_range_end, (FONT *f, int range)); + AL_METHOD(FONT *, extract_font_range, (FONT *f, int begin, int end)); + AL_METHOD(FONT *, merge_fonts, (FONT *f1, FONT *f2)); + AL_METHOD(int, transpose_font, (FONT *f, int drange)); +} FONT_VTABLE; + +AL_VAR(FONT_VTABLE, _font_vtable_mono); +AL_VAR(FONT_VTABLE *, font_vtable_mono); +AL_VAR(FONT_VTABLE, _font_vtable_color); +AL_VAR(FONT_VTABLE *, font_vtable_color); +AL_VAR(FONT_VTABLE, _font_vtable_trans); +AL_VAR(FONT_VTABLE *, font_vtable_trans); + +AL_FUNC(FONT_GLYPH *, _mono_find_glyph, (AL_CONST FONT *f, int ch)); +AL_FUNC(BITMAP *, _color_find_glyph, (AL_CONST FONT *f, int ch)); + +typedef struct FONT_MONO_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + FONT_GLYPH **glyphs; /* our glyphs */ + struct FONT_MONO_DATA *next; /* linked list structure */ +} FONT_MONO_DATA; + +typedef struct FONT_COLOR_DATA +{ + int begin, end; /* first char and one-past-the-end char */ + BITMAP **bitmaps; /* our glyphs */ + struct FONT_COLOR_DATA *next; /* linked list structure */ +} FONT_COLOR_DATA; + + +/* caches and tables for svga bank switching */ +AL_VAR(int, _last_bank_1); +AL_VAR(int, _last_bank_2); + +AL_VAR(int *, _gfx_bank); + +/* bank switching routines (these use a non-C calling convention on i386!) */ +AL_FUNC(uintptr_t, _stub_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _stub_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _stub_bank_switch_end, (void)); + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(uintptr_t, _x_bank_switch, (BITMAP *bmp, int lyne)); +AL_FUNC(void, _x_unbank_switch, (BITMAP *bmp)); +AL_FUNC(void, _x_bank_switch_end, (void)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VBEAF + +AL_FUNC(void, _accel_bank_stub, (void)); +AL_FUNC(void, _accel_bank_stub_end, (void)); +AL_FUNC(void, _accel_bank_switch, (void)); +AL_FUNC(void, _accel_bank_switch_end, (void)); + +AL_VAR(void *, _accel_driver); + +AL_VAR(int, _accel_active); + +AL_VAR(void *, _accel_set_bank); +AL_VAR(void *, _accel_idle); + +AL_FUNC(void, _fill_vbeaf_libc_exports, (void *ptr)); +AL_FUNC(void, _fill_vbeaf_pmode_exports, (void *ptr)); + +#endif + + +/* stuff for setting up bitmaps */ +AL_FUNC(BITMAP *, _make_bitmap, (int w, int h, uintptr_t addr, GFX_DRIVER *driver, int color_depth, int bpl)); +AL_FUNC(void, _sort_out_virtual_width, (int *width, GFX_DRIVER *driver)); + +AL_FUNC(GFX_VTABLE *, _get_vtable, (int color_depth)); + +AL_VAR(GFX_VTABLE, _screen_vtable); + +AL_VAR(int, _gfx_mode_set_count); + +AL_VAR(int, _refresh_rate_request); +AL_FUNC(void, _set_current_refresh_rate, (int rate)); + +AL_VAR(int, _wait_for_vsync); + +AL_VAR(int, _sub_bitmap_id_count); + +AL_VAR(int, _screen_split_position); + +AL_VAR(int, _safe_gfx_mode_change); + +#ifdef ALLEGRO_I386 + #define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) +#else + #ifdef ALLEGRO_MPW + /* in Mac 24 bit is a unsigned long */ + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : 4)) + #else + #define BYTES_PER_PIXEL(bpp) (((bpp) <= 8) ? 1 \ + : (((bpp) <= 16) ? 2 \ + : (((bpp) <= 24) ? 3 : 4))) + #endif +#endif + +AL_FUNC(int, _color_load_depth, (int depth, int hasalpha)); + +AL_VAR(int, _color_conv); + +AL_FUNC(BITMAP *, _fixup_loaded_bitmap, (BITMAP *bmp, PALETTE pal, int bpp)); + +AL_FUNC(int, _bitmap_has_alpha, (BITMAP *bmp)); + +/* default truecolor pixel format */ +#define DEFAULT_RGB_R_SHIFT_15 0 +#define DEFAULT_RGB_G_SHIFT_15 5 +#define DEFAULT_RGB_B_SHIFT_15 10 +#define DEFAULT_RGB_R_SHIFT_16 0 +#define DEFAULT_RGB_G_SHIFT_16 5 +#define DEFAULT_RGB_B_SHIFT_16 11 +#define DEFAULT_RGB_R_SHIFT_24 0 +#define DEFAULT_RGB_G_SHIFT_24 8 +#define DEFAULT_RGB_B_SHIFT_24 16 +#define DEFAULT_RGB_R_SHIFT_32 0 +#define DEFAULT_RGB_G_SHIFT_32 8 +#define DEFAULT_RGB_B_SHIFT_32 16 +#define DEFAULT_RGB_A_SHIFT_32 24 + + +/* display switching support */ +AL_FUNC(void, _switch_in, (void)); +AL_FUNC(void, _switch_out, (void)); + +AL_FUNC(void, _register_switch_bitmap, (BITMAP *bmp, BITMAP *parent)); +AL_FUNC(void, _unregister_switch_bitmap, (BITMAP *bmp)); +AL_FUNC(void, _save_switch_state, (int switch_mode)); +AL_FUNC(void, _restore_switch_state, (void)); + +AL_VAR(int, _dispsw_status); + + +/* current drawing mode */ +AL_VAR(int, _drawing_mode); +AL_VAR(BITMAP *, _drawing_pattern); +AL_VAR(int, _drawing_x_anchor); +AL_VAR(int, _drawing_y_anchor); +AL_VAR(unsigned int, _drawing_x_mask); +AL_VAR(unsigned int, _drawing_y_mask); + +AL_FUNCPTR(int *, _palette_expansion_table, (int bpp)); + +AL_VAR(int, _color_depth); + +AL_VAR(int, _current_palette_changed); +AL_VAR(PALETTE, _prev_current_palette); +AL_VAR(int, _got_prev_current_palette); + +AL_ARRAY(int, _palette_color8); +AL_ARRAY(int, _palette_color15); +AL_ARRAY(int, _palette_color16); +AL_ARRAY(int, _palette_color24); +AL_ARRAY(int, _palette_color32); + +/* truecolor blending functions */ +AL_VAR(BLENDER_FUNC, _blender_func15); +AL_VAR(BLENDER_FUNC, _blender_func16); +AL_VAR(BLENDER_FUNC, _blender_func24); +AL_VAR(BLENDER_FUNC, _blender_func32); + +AL_VAR(BLENDER_FUNC, _blender_func15x); +AL_VAR(BLENDER_FUNC, _blender_func16x); +AL_VAR(BLENDER_FUNC, _blender_func24x); + +AL_VAR(int, _blender_col_15); +AL_VAR(int, _blender_col_16); +AL_VAR(int, _blender_col_24); +AL_VAR(int, _blender_col_32); + +AL_VAR(int, _blender_alpha); + +AL_FUNC(unsigned long, _blender_black, (unsigned long x, unsigned long y, unsigned long n)); + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(unsigned long, _blender_trans15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen15, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_trans16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen16, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32) + +AL_FUNC(unsigned long, _blender_trans24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_add24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_burn24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_color24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_difference24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dissolve24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_dodge24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_hue24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_invert24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_luminance24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_multiply24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_saturation24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_screen24, (unsigned long x, unsigned long y, unsigned long n)); + +#endif + +AL_FUNC(unsigned long, _blender_alpha15, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha16, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha24, (unsigned long x, unsigned long y, unsigned long n)); +AL_FUNC(unsigned long, _blender_alpha32, (unsigned long x, unsigned long y, unsigned long n)); + +AL_FUNC(unsigned long, _blender_write_alpha, (unsigned long x, unsigned long y, unsigned long n)); + + +/* graphics drawing routines */ +AL_FUNC(void, _normal_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _fast_line, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); +AL_FUNC(void, _normal_rectfill, (BITMAP *bmp, int x1, int y_1, int x2, int y2, int color)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(int, _linear_getpixel8, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel8, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline8, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline8, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite8, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character8, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph8, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward8, (BITMAP *source,BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit8, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color8, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _linear_putpixel15, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline15, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline15, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_trans_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite15, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite15, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); + +AL_FUNC(int, _linear_getpixel16, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel16, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline16, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline16, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite16, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character16, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph16, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit16, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color16, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(int, _linear_getpixel24, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel24, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline24, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline24, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rgba_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite24, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character24, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph24, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit24, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color24, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(int, _linear_getpixel32, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _linear_putpixel32, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _linear_vline32, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _linear_hline32, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _linear_draw_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_256_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_v_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_h_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_sprite_vh_flip32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_sprite32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_trans_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _linear_draw_lit_rle_sprite32, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _linear_draw_character32, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_draw_glyph32, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _linear_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_blit_backward32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_masked_blit32, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _linear_clear_to_color32, (BITMAP *bitmap, int color)); + +#endif + +#ifdef ALLEGRO_GFX_HAS_VGA + +AL_FUNC(int, _x_getpixel, (BITMAP *bmp, int x, int y)); +AL_FUNC(void, _x_putpixel, (BITMAP *bmp, int x, int y, int color)); +AL_FUNC(void, _x_vline, (BITMAP *bmp, int x, int y_1, int y2, int color)); +AL_FUNC(void, _x_hline, (BITMAP *bmp, int x1, int y, int x2, int color)); +AL_FUNC(void, _x_draw_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_v_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_h_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_sprite_vh_flip, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_sprite, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_trans_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y)); +AL_FUNC(void, _x_draw_lit_rle_sprite, (BITMAP *bmp, AL_CONST struct RLE_SPRITE *sprite, int x, int y, int color)); +AL_FUNC(void, _x_draw_character, (BITMAP *bmp, BITMAP *sprite, int x, int y, int color, int bg)); +AL_FUNC(void, _x_draw_glyph, (BITMAP *bmp, AL_CONST FONT_GLYPH *glyph, int x, int y, int color, int bg)); +AL_FUNC(void, _x_blit_from_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_to_memory, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_forward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_blit_backward, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_masked_blit, (BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height)); +AL_FUNC(void, _x_clear_to_color, (BITMAP *bitmap, int color)); + +#endif + + +/* color conversion routines */ +typedef struct GRAPHICS_RECT { + int width; + int height; + int pitch; + void *data; +} GRAPHICS_RECT; + +typedef void (COLORCONV_BLITTER_FUNC)(GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect); + +AL_FUNC(COLORCONV_BLITTER_FUNC *, _get_colorconv_blitter, (int from_depth, int to_depth)); +AL_FUNC(void, _release_colorconv_blitter, (COLORCONV_BLITTER_FUNC *blitter)); +AL_FUNC(void, _set_colorconv_palette, (AL_CONST struct RGB *p, int from, int to)); +AL_FUNC(unsigned char *, _get_colorconv_map, (void)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _colorconv_blit_8_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_8_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _colorconv_blit_15_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_15_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +AL_FUNC(void, _colorconv_blit_16_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_16_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _colorconv_blit_24_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_24_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _colorconv_blit_32_to_8, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorconv_blit_32_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); + +#endif + + +/* color copy routines */ +#ifndef ALLEGRO_NO_COLORCOPY + +#ifdef ALLEGRO_COLOR16 +AL_FUNC(void, _colorcopy_blit_15_to_15, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +AL_FUNC(void, _colorcopy_blit_16_to_16, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR24 +AL_FUNC(void, _colorcopy_blit_24_to_24, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#ifdef ALLEGRO_COLOR32 +AL_FUNC(void, _colorcopy_blit_32_to_32, (GRAPHICS_RECT *src_rect, GRAPHICS_RECT *dest_rect)); +#endif + +#endif + + +/* generic color conversion blitter */ +AL_FUNC(void, _blit_between_formats, (BITMAP *src, BITMAP *dest, int s_x, int s_y, int d_x, int d_y, int w, int h)); + + +/* asm helper for stretch_blit() */ +#ifndef SCAN_EXPORT +AL_FUNC(void, _do_stretch, (BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth)); +#endif + + +/* lower level functions for rotation */ +AL_FUNC(void, _parallelogram_map, (BITMAP *bmp, BITMAP *spr, fixed xs[4], fixed ys[4], void (*draw_scanline)(BITMAP *bmp, BITMAP *spr, fixed l_bmp_x, int bmp_y, fixed r_bmp_x, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy), int sub_pixel_accuracy)); +AL_FUNC(void, _parallelogram_map_standard, (BITMAP *bmp, BITMAP *sprite, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _rotate_scale_flip_coordinates, (fixed w, fixed h, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale_x, fixed scale_y, int h_flip, int v_flip, fixed xs[4], fixed ys[4])); +AL_FUNC(void, _pivot_scaled_sprite_flip, (struct BITMAP *bmp, struct BITMAP *sprite, fixed x, fixed y, fixed cx, fixed cy, fixed angle, fixed scale, int v_flip)); + + +/* number of fractional bits used by the polygon rasteriser */ +#define POLYGON_FIX_SHIFT 18 + + +/* bitfield specifying which polygon attributes need interpolating */ +#define INTERP_FLAT 1 /* no interpolation */ +#define INTERP_1COL 2 /* gcol or alpha */ +#define INTERP_3COL 4 /* grgb */ +#define INTERP_FIX_UV 8 /* atex */ +#define INTERP_Z 16 /* always in scene3d */ +#define INTERP_FLOAT_UV 32 /* ptex */ +#define OPT_FLOAT_UV_TO_FIX 64 /* translate ptex to atex */ +#define COLOR_TO_RGB 128 /* grgb to gcol for truecolor */ +#define INTERP_ZBUF 256 /* z-buffered */ +#define INTERP_THRU 512 /* any kind of transparent */ +#define INTERP_NOSOLID 1024 /* non-solid modes for 8-bit flat */ +#define INTERP_BLEND 2048 /* lit for truecolor */ +#define INTERP_TRANS 4096 /* trans for truecolor */ + + +/* information for polygon scanline fillers */ +typedef struct POLYGON_SEGMENT +{ + fixed u, v, du, dv; /* fixed point u/v coordinates */ + fixed c, dc; /* single color gouraud shade values */ + fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ + float z, dz; /* polygon depth (1/z) */ + float fu, fv, dfu, dfv; /* floating point u/v coordinates */ + unsigned char *texture; /* the texture map */ + int umask, vmask, vshift; /* texture map size information */ + int seg; /* destination bitmap selector */ + uintptr_t zbuf_addr; /* Z-buffer address */ + uintptr_t read_addr; /* reading address for transparency modes */ +} POLYGON_SEGMENT; + + +/* prototype for the scanline filler functions */ +typedef AL_METHOD(void, SCANLINE_FILLER, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + + +/* an active polygon edge */ +typedef struct POLYGON_EDGE +{ + int top; /* top y position */ + int bottom; /* bottom y position */ + fixed x, dx; /* fixed point x position and gradient */ + fixed w; /* width of line segment */ + POLYGON_SEGMENT dat; /* texture/gouraud information */ + struct POLYGON_EDGE *prev; /* doubly linked list */ + struct POLYGON_EDGE *next; + struct POLYGON_INFO *poly; /* father polygon */ +} POLYGON_EDGE; + + +typedef struct POLYGON_INFO /* a polygon waiting rendering */ +{ + struct POLYGON_INFO *next, *prev;/* double linked list */ + int inside; /* flag for "scanlining" */ + int flags; /* INTERP_* flags */ + int color; /* vtx[0]->c */ + float a, b, c; /* plane's coefficients -a/d, -b/d, -c/d */ + int dmode; /* drawing mode */ + BITMAP *dpat; /* drawing pattern */ + int xanchor, yanchor; /* for dpat */ + int alpha; /* blender alpha */ + int b15, b16, b24, b32; /* blender colors */ + COLOR_MAP *cmap; /* trans color map */ + SCANLINE_FILLER drawer; /* scanline drawing functions */ + SCANLINE_FILLER alt_drawer; + POLYGON_EDGE *left_edge; /* true edges used in interpolation */ + POLYGON_EDGE *right_edge; + POLYGON_SEGMENT info; /* base information for scanline functions */ +} POLYGON_INFO; + + +/* global variable for z-buffer */ +AL_VAR(BITMAP *, _zbuffer); + + +/* polygon helper functions */ +AL_VAR(SCANLINE_FILLER, _optim_alternative_drawer); +AL_FUNC(POLYGON_EDGE *, _add_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x)); +AL_FUNC(POLYGON_EDGE *, _remove_edge, (POLYGON_EDGE *list, POLYGON_EDGE *edge)); +AL_FUNC(int, _fill_3d_edge_structure, (POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp)); +AL_FUNC(int, _fill_3d_edge_structure_f, (POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp)); +AL_FUNC(SCANLINE_FILLER, _get_scanline_filler, (int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp)); +AL_FUNC(void, _clip_polygon_segment, (POLYGON_SEGMENT *info, fixed gap, int flags)); +AL_FUNC(void, _clip_polygon_segment_f, (POLYGON_SEGMENT *info, int gap, int flags)); + + +/* polygon scanline filler functions */ +AL_FUNC(void, _poly_scanline_dummy, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifdef ALLEGRO_COLOR8 + +AL_FUNC(void, _poly_scanline_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb8x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_gcol8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans8, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR16 + +AL_FUNC(void, _poly_scanline_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit15d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_grgb15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans15, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit16d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans16, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR24 + +AL_FUNC(void, _poly_scanline_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit24d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans24, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + +#ifdef ALLEGRO_COLOR32 + +AL_FUNC(void, _poly_scanline_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#ifndef SCAN_EXPORT +AL_FUNC(void, _poly_scanline_grgb32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_atex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32x, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +AL_FUNC(void, _poly_scanline_ptex_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_scanline_ptex_mask_lit32d, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +#endif + +AL_FUNC(void, _poly_zbuf_flat32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_grgb32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_lit32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_atex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); +AL_FUNC(void, _poly_zbuf_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGMENT *info)); + +#endif + + +/* sound lib stuff */ +AL_VAR(MIDI_DRIVER, _midi_none); +AL_VAR(int, _digi_volume); +AL_VAR(int, _midi_volume); +AL_VAR(int, _sound_flip_pan); +AL_VAR(int, _sound_hq); +AL_VAR(int, _sound_stereo); +AL_VAR(int, _sound_bits); +AL_VAR(int, _sound_freq); +AL_VAR(int, _sound_port); +AL_VAR(int, _sound_dma); +AL_VAR(int, _sound_irq); + +AL_VAR(int, _sound_installed); +AL_VAR(int, _sound_input_installed); + +AL_FUNC(int, _midi_allocate_voice, (int min, int max)); + +AL_VAR(volatile long, _midi_tick); + +AL_FUNC(int, _digmid_find_patches, (char *dir, int dir_size, char *file, int size_of_file)); + +#define VIRTUAL_VOICES 256 + + +typedef struct /* a virtual (as seen by the user) soundcard voice */ +{ + AL_CONST SAMPLE *sample; /* which sample are we playing? (NULL = free) */ + int num; /* physical voice number (-1 = been killed off) */ + int autokill; /* set to free the voice when the sample finishes */ + long time; /* when we were started (for voice allocation) */ + int priority; /* how important are we? */ +} VOICE; + + +typedef struct /* a physical (as used by hardware) soundcard voice */ +{ + int num; /* the virtual voice currently using me (-1 = free) */ + int playmode; /* are we looping? */ + int vol; /* current volume (fixed point .12) */ + int dvol; /* volume delta, for ramping */ + int target_vol; /* target volume, for ramping */ + int pan; /* current pan (fixed point .12) */ + int dpan; /* pan delta, for sweeps */ + int target_pan; /* target pan, for sweeps */ + int freq; /* current frequency (fixed point .12) */ + int dfreq; /* frequency delta, for sweeps */ + int target_freq; /* target frequency, for sweeps */ +} PHYS_VOICE; + +AL_ARRAY(PHYS_VOICE, _phys_voice); + + +#define MIXER_DEF_SFX 8 +#define MIXER_MAX_SFX 64 + +AL_FUNC(int, _mixer_init, (int bufsize, int freq, int stereo, int is16bit, int *voices)); +AL_FUNC(void, _mixer_exit, (void)); +AL_FUNC(void, _mix_some_samples, (uintptr_t buf, unsigned short seg, int issigned)); +AL_FUNC(void, _mixer_init_voice, (int voice, AL_CONST SAMPLE *sample)); +AL_FUNC(void, _mixer_release_voice, (int voice)); +AL_FUNC(void, _mixer_start_voice, (int voice)); +AL_FUNC(void, _mixer_stop_voice, (int voice)); +AL_FUNC(void, _mixer_loop_voice, (int voice, int loopmode)); +AL_FUNC(int, _mixer_get_position, (int voice)); +AL_FUNC(void, _mixer_set_position, (int voice, int position)); +AL_FUNC(int, _mixer_get_volume, (int voice)); +AL_FUNC(void, _mixer_set_volume, (int voice, int volume)); +AL_FUNC(void, _mixer_ramp_volume, (int voice, int tyme, int endvol)); +AL_FUNC(void, _mixer_stop_volume_ramp, (int voice)); +AL_FUNC(int, _mixer_get_frequency, (int voice)); +AL_FUNC(void, _mixer_set_frequency, (int voice, int frequency)); +AL_FUNC(void, _mixer_sweep_frequency, (int voice, int tyme, int endfreq)); +AL_FUNC(void, _mixer_stop_frequency_sweep, (int voice)); +AL_FUNC(int, _mixer_get_pan, (int voice)); +AL_FUNC(void, _mixer_set_pan, (int voice, int pan)); +AL_FUNC(void, _mixer_sweep_pan, (int voice, int tyme, int endpan)); +AL_FUNC(void, _mixer_stop_pan_sweep, (int voice)); +AL_FUNC(void, _mixer_set_echo, (int voice, int strength, int delay)); +AL_FUNC(void, _mixer_set_tremolo, (int voice, int rate, int depth)); +AL_FUNC(void, _mixer_set_vibrato, (int voice, int rate, int depth)); + +AL_FUNC(void, _dummy_noop1, (int p)); +AL_FUNC(void, _dummy_noop2, (int p1, int p2)); +AL_FUNC(void, _dummy_noop3, (int p1, int p2, int p3)); +AL_FUNC(int, _dummy_load_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); +AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan)); + + +/* datafile ID's for compatibility with the old datafile format */ +#define V1_DAT_MAGIC 0x616C6C2EL + +#define V1_DAT_DATA 0 +#define V1_DAT_FONT 1 +#define V1_DAT_BITMAP_16 2 +#define V1_DAT_BITMAP_256 3 +#define V1_DAT_SPRITE_16 4 +#define V1_DAT_SPRITE_256 5 +#define V1_DAT_PALETTE_16 6 +#define V1_DAT_PALETTE_256 7 +#define V1_DAT_FONT_8x8 8 +#define V1_DAT_FONT_PROP 9 +#define V1_DAT_BITMAP 10 +#define V1_DAT_PALETTE 11 +#define V1_DAT_SAMPLE 12 +#define V1_DAT_MIDI 13 +#define V1_DAT_RLE_SPRITE 14 +#define V1_DAT_FLI 15 +#define V1_DAT_C_SPRITE 16 +#define V1_DAT_XC_SPRITE 17 + +#define OLD_FONT_SIZE 95 +#define LESS_OLD_FONT_SIZE 224 + + +/* datafile object loading functions */ +AL_FUNC(void, _unload_datafile_object, (DATAFILE *dat)); + + +/* information about a datafile object */ +typedef struct DATAFILE_TYPE +{ + int type; + AL_METHOD(void *, load, (PACKFILE *f, long size)); + AL_METHOD(void, destroy, (void *)); +} DATAFILE_TYPE; + + +#define MAX_DATAFILE_TYPES 32 + +AL_ARRAY(DATAFILE_TYPE, _datafile_type); + +AL_VAR(int, _compile_sprites); + +AL_FUNC(void, _construct_datafile, (DATAFILE *data)); + + +/* for readbmp.c */ +AL_FUNC(void, _register_bitmap_file_type_init, (void)); + +/* for readsmp.c */ +AL_FUNC(void, _register_sample_file_type_init, (void)); + +/* for readfont.c */ +AL_FUNC(void, _register_font_file_type_init, (void)); + + +/* for module linking system; see comment in allegro.c */ +struct _AL_LINKER_MIDI +{ + AL_METHOD(int, init, (void)); + AL_METHOD(void, exit, (void)); +}; + +AL_VAR(struct _AL_LINKER_MIDI *, _al_linker_midi); + +struct _AL_LINKER_MOUSE +{ + AL_METHOD(void, set_mouse_etc, (void)); + AL_METHOD(void, show_mouse, (BITMAP *)); + BITMAP **mouse_screen_ptr; +}; + +AL_VAR(struct _AL_LINKER_MOUSE *, _al_linker_mouse); + + +/* dynamic driver lists */ +AL_FUNC(_DRIVER_INFO *, _create_driver_list, (void)); +AL_FUNC(void, _destroy_driver_list, (_DRIVER_INFO *drvlist)); +AL_FUNC(void, _driver_list_append_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_prepend_driver, (_DRIVER_INFO **drvlist, int id, void *driver, int autodetect)); +AL_FUNC(void, _driver_list_append_list, (_DRIVER_INFO **drvlist, _DRIVER_INFO *srclist)); + + +/* various libc stuff */ +AL_FUNC(void *, _al_sane_realloc, (void *ptr, size_t size)); +AL_FUNC(char *, _al_sane_strncpy, (char *dest, const char *src, size_t n)); + + +#define _AL_RAND_MAX 0xFFFF +AL_FUNC(void, _al_srand, (int seed)); +AL_FUNC(int, _al_rand, (void)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef AINTERN_H */ diff --git a/allegro/fixed/all422-fixed.zip b/allegro/fixed/all422-fixed.zip new file mode 100644 index 0000000000..e058d0ea40 Binary files /dev/null and b/allegro/fixed/all422-fixed.zip differ diff --git a/allegro/fixed/alsa9.c b/allegro/fixed/alsa9.c new file mode 100644 index 0000000000..a0637ee516 --- /dev/null +++ b/allegro/fixed/alsa9.c @@ -0,0 +1,567 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * ALSA 0.9 sound driver. + * + * By Thomas Fjellstrom. + * + * Extensively modified by Elias Pschernig. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" + +#if (ALLEGRO_ALSA_VERSION == 9) && (defined ALLEGRO_WITH_ALSADIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) + +#include "allegro/internal/aintern.h" +#ifdef ALLEGRO_QNX +#include "allegro/platform/aintqnx.h" +#else +#include "allegro/platform/aintunix.h" +#endif + +#ifndef SCAN_DEPEND + #include + #define ALSA_PCM_NEW_HW_PARAMS_API 1 + #include + #include +#endif + + +#ifndef SND_PCM_FORMAT_S16_NE + #ifdef ALLEGRO_BIG_ENDIAN + #define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_BE + #else + #define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_LE + #endif +#endif +#ifndef SND_PCM_FORMAT_U16_NE + #ifdef ALLEGRO_BIG_ENDIAN + #define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_BE + #else + #define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_LE + #endif +#endif + +#define ALSA9_CHECK(a) do { \ + int err = (a); \ + if (err<0) { \ + uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "ALSA: %s : %s", #a, get_config_text(snd_strerror(err))); \ + goto Error; \ + } \ +} while(0) + + +#define PREFIX_I "al-alsa9 INFO: " +#define PREFIX_W "al-alsa9 WARNING: " +#define PREFIX_E "al-alsa9 ERROR: " + +static char const *alsa_device = "default"; +static char const *alsa_mixer_device = "default"; +static snd_pcm_hw_params_t *hwparams = NULL; +static snd_pcm_sw_params_t *swparams = NULL; +static snd_output_t *snd_output = NULL; +static snd_pcm_uframes_t alsa_bufsize; +static snd_mixer_t *alsa_mixer = NULL; +static snd_mixer_elem_t *alsa_mixer_elem = NULL; +static long alsa_mixer_elem_min, alsa_mixer_elem_max; +static double alsa_mixer_allegro_ratio = 0.0; + +#define ALSA_DEFAULT_BUFFER_MS 100 +#define ALSA_DEFAULT_NUMFRAGS 5 + +static snd_pcm_t *pcm_handle; +static unsigned char *alsa_bufdata; +static int alsa_bits, alsa_signed, alsa_stereo; +static unsigned int alsa_rate; +static unsigned int alsa_fragments; +static int alsa_sample_size; + +static struct pollfd *ufds = NULL; +static int pdc = 0; +static int poll_next; + +static char alsa_desc[256] = EMPTY_STRING; + +static int alsa_detect(int input); +static int alsa_init(int input, int voices); +static void alsa_exit(int input); +static int alsa_set_mixer_volume(int volume); +static int alsa_get_mixer_volume(void); +static int alsa_buffer_size(void); + + + +DIGI_DRIVER digi_alsa = +{ + DIGI_ALSA, + empty_string, + empty_string, + "ALSA", + 0, + 0, + MIXER_MAX_SFX, + MIXER_DEF_SFX, + + alsa_detect, + alsa_init, + alsa_exit, + alsa_set_mixer_volume, + alsa_get_mixer_volume, + + NULL, + NULL, + alsa_buffer_size, + _mixer_init_voice, + _mixer_release_voice, + _mixer_start_voice, + _mixer_stop_voice, + _mixer_loop_voice, + + _mixer_get_position, + _mixer_set_position, + + _mixer_get_volume, + _mixer_set_volume, + _mixer_ramp_volume, + _mixer_stop_volume_ramp, + + _mixer_get_frequency, + _mixer_set_frequency, + _mixer_sweep_frequency, + _mixer_stop_frequency_sweep, + + _mixer_get_pan, + _mixer_set_pan, + _mixer_sweep_pan, + _mixer_stop_pan_sweep, + + _mixer_set_echo, + _mixer_set_tremolo, + _mixer_set_vibrato, + 0, 0, + 0, + 0, + 0, + 0, + 0, + 0 +}; + + + +/* alsa_buffer_size: + * Returns the current DMA buffer size, for use by the audiostream code. + */ +static int alsa_buffer_size(void) +{ + return alsa_bufsize; +} + +/* xrun_recovery: + * Underrun and suspend recovery + */ +static int xrun_recovery(snd_pcm_t *handle, int err) +{ + if (err == -EPIPE) { /* under-run */ + err = snd_pcm_prepare(pcm_handle); + if (err < 0) + fprintf(stderr, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); + return 0; + } + /* TODO: Can't wait here like that - we are inside an 'interrupt' after all. */ +#if 0 + else if (err == -ESTRPIPE) { + while ((err = snd_pcm_resume(pcm_handle)) == -EAGAIN) + sleep(1); /* wait until the suspend flag is released */ + + if (err < 0) { + err = snd_pcm_prepare(pcm_handle); + if (err < 0) + fprintf(stderr, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); + } + return 0; + } +#endif + + return err; +} + + + +/* alsa_mix + * Mix and send some samples to ALSA. + */ +static void alsa_mix(void) +{ + int ret, samples = alsa_bufsize; + unsigned char *ptr = alsa_bufdata; + + while (samples > 0) { + ret = snd_pcm_writei(pcm_handle, ptr, samples); + if (ret == -EAGAIN) + continue; + + if (ret < 0) { + if (xrun_recovery(pcm_handle, ret) < 0) + fprintf(stderr, "Write error: %s\n", snd_strerror(ret)); + poll_next = 0; + break; /* skip one period */ + } + if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_RUNNING) + poll_next = 1; + samples -= ret; + ptr += ret * alsa_sample_size; + } + + _mix_some_samples((uintptr_t)alsa_bufdata, 0, alsa_signed); +} + + + +/* alsa_update: + * Updates main buffer in case ALSA is ready. + */ +static void alsa_update(int threaded) +{ + unsigned short revents; + + if (poll_next) { + poll(ufds, pdc, 0); + snd_pcm_poll_descriptors_revents(pcm_handle, ufds, pdc, &revents); + if (revents & POLLERR) { + if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN || + snd_pcm_state(pcm_handle) == SND_PCM_STATE_SUSPENDED) { + int err = snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE; + if (xrun_recovery(pcm_handle, err) < 0) { + fprintf(stderr, "Write error: %s\n", snd_strerror(err)); + } + poll_next = 0; + } + else { + fprintf(stderr, "Wait for poll failed\n"); + } + return; + } + if (!(revents & POLLOUT)) + return; + } + alsa_mix(); +} + + + +/* alsa_detect: + * Detects driver presence. + */ +static int alsa_detect(int input) +{ + int ret = FALSE; + char tmp1[128], tmp2[128]; + + alsa_device = get_config_string(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_device", tmp2), + alsa_device); + + ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + if (ret < 0) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device")); + return FALSE; + } + + snd_pcm_close(pcm_handle); + pcm_handle = NULL; + return TRUE; +} + + + +/* alsa_init: + * ALSA init routine. + */ +static int alsa_init(int input, int voices) +{ + int ret = 0; + char tmp1[128], tmp2[128]; + int format = 0; + unsigned int numfrags = 0; + snd_pcm_uframes_t fragsize; + + if (input) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); + return -1; + } + + ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0)); + + alsa_device = get_config_string(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_device", tmp2), + alsa_device); + + alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_mixer_device", tmp2), + alsa_mixer_device); + + fragsize = get_config_int(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_fragsize", tmp2), 0); + + numfrags = get_config_int(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_numfrags", tmp2), + ALSA_DEFAULT_NUMFRAGS); + + ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + if (ret < 0) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device")); + return -1; + } + + snd_mixer_open(&alsa_mixer, 0); + + if (alsa_mixer + && snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0 + && snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0 + && snd_mixer_load(alsa_mixer) >= 0) { + const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1), + uconvert_ascii("alsa_mixer_elem", tmp2), + "PCM"); + + alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer); + + while (alsa_mixer_elem) { + const char *name = snd_mixer_selem_get_name(alsa_mixer_elem); + + if (strcasecmp(name, alsa_mixer_elem_name) == 0) { + snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max); + alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255; + break; + } + + alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem); + } + } + + /* Set format variables. */ + alsa_bits = (_sound_bits == 8) ? 8 : 16; + alsa_stereo = (_sound_stereo) ? 1 : 0; + alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100; + + snd_pcm_hw_params_malloc(&hwparams); + ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams)); + + if (alsa_bits == 8) { + if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U8) == 0) { + format = SND_PCM_FORMAT_U8; + alsa_signed = 0; + } + else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8) == 0) { + format = SND_PCM_FORMAT_S8; + alsa_signed = 1; + } + else { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); + goto Error; + } + } + else if (alsa_bits == 16) + { + if (sizeof(short) != 2) + { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); + goto Error; + } + + if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U16_NE) == 0) + { + format = SND_PCM_FORMAT_U16_NE; + alsa_signed = 0; + } + else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_NE) == 0) + { + format = SND_PCM_FORMAT_S16_NE; + alsa_signed = 1; + } + else + { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format")); + goto Error; + } + } + + alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1); + + if (fragsize == 0) { + unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags; + fragsize = 1; + while (fragsize < size) + fragsize <<= 1; + } + + ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)); + ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format)); + ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1)); + + ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL)); + ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL)); + ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL)); + + ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams)); + + ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL)); + ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL)); + + TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments); + + snd_pcm_sw_params_malloc(&swparams); + ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams)); + ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize)); + ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize)); + ALSA9_CHECK(snd_pcm_sw_params_set_xfer_align(pcm_handle, swparams, 1)); + ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams)); + + /* Allocate mixing buffer. */ + alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size); + if (!alsa_bufdata) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); + goto Error; + } + + /* Initialise mixer. */ + digi_alsa.voices = voices; + + if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate, + alsa_stereo, ((alsa_bits == 16) ? 1 : 0), + &digi_alsa.voices) != 0) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); + goto Error; + } + + snd_pcm_prepare(pcm_handle); + pdc = snd_pcm_poll_descriptors_count (pcm_handle); + if (pdc <= 0) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count")); + goto Error; + } + + ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc); + if (ufds == NULL) { + ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors")); + goto Error; + } + ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc)); + + poll_next = 0; + + _mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed); + + /* Add audio interrupt. */ + _unix_bg_man->register_func(alsa_update); + + uszprintf(alsa_desc, sizeof(alsa_desc), + get_config_text + ("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"), + alsa_device, alsa_bits, + uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1), + alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2)); + + digi_driver->desc = alsa_desc; + return 0; + + Error: + if (pcm_handle) { + snd_pcm_close(pcm_handle); + pcm_handle = NULL; + } + + return -1; +} + + + +/* alsa_exit: + * Shuts down ALSA driver. + */ +static void alsa_exit(int input) +{ + if (input) + return; + + _unix_bg_man->unregister_func(alsa_update); + + _AL_FREE(alsa_bufdata); + alsa_bufdata = NULL; + + _mixer_exit(); + + if (alsa_mixer) + snd_mixer_close(alsa_mixer); + + snd_pcm_close(pcm_handle); + + snd_pcm_hw_params_free(hwparams); + snd_pcm_sw_params_free(swparams); +} + + + +/* alsa_set_mixer_volume: + * Set mixer volume (0-255) + */ +static int alsa_set_mixer_volume(int volume) +{ + if (alsa_mixer && alsa_mixer_elem) { + snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 0, volume * alsa_mixer_allegro_ratio); + snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 1, volume * alsa_mixer_allegro_ratio); + } + return 0; +} + + + +/* alsa_get_mixer_volume: + * Return mixer volume (0-255) + */ +static int alsa_get_mixer_volume(void) +{ + if (alsa_mixer && alsa_mixer_elem) { + long vol1, vol2; + + snd_mixer_handle_events(alsa_mixer); + + if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 0, &vol1) < 0) + return -1; + if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 1, &vol2) < 0) + return -1; + + vol1 /= alsa_mixer_allegro_ratio; + vol2 /= alsa_mixer_allegro_ratio; + + return (vol1 + vol2) / 2; + } + + return -1; +} + + + +#ifdef ALLEGRO_MODULE + +/* _module_init: + * Called when loaded as a dynamically linked module. + */ +void _module_init(int system_driver) +{ + _unix_register_digi_driver(DIGI_ALSA, &digi_alsa, TRUE, TRUE); +} + +#endif + +#endif diff --git a/allegro/fixed/file.c b/allegro/fixed/file.c new file mode 100644 index 0000000000..5d6eb1c82f --- /dev/null +++ b/allegro/fixed/file.c @@ -0,0 +1,3034 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * _pack_fdopen() and related modifications by Annie Testes. + * + * Evert Glebbeek added the support for relative filenames: + * make_absolute_filename(), make_relative_filename() and + * is_relative_filename(). + * + * Peter Wang added support for packfile vtables. + * + * See readme.txt for copyright information. + */ + + +#include +#include +#include + +#include "allegro.h" +#include "allegro/internal/aintern.h" + +#ifndef ALLEGRO_MPW + #include +#endif + +#ifdef ALLEGRO_UNIX + #include /* for tilde expansion */ +#endif + +#ifdef ALLEGRO_WINDOWS + #include "winalleg.h" /* for GetTempPath */ +#endif + + +/* permissions to use when opening files */ +#ifndef ALLEGRO_MPW + +/* some OSes have no concept of "group" and "other" */ +#ifndef S_IRGRP + #define S_IRGRP 0 + #define S_IWGRP 0 +#endif +#ifndef S_IROTH + #define S_IROTH 0 + #define S_IWOTH 0 +#endif + +#define OPEN_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) + +#endif /* !ALLEGRO_MPW */ + + + +static char the_password[256] = EMPTY_STRING; + +int _packfile_filesize = 0; +int _packfile_datasize = 0; + +int _packfile_type = 0; + +static PACKFILE_VTABLE normal_vtable; + +static PACKFILE *pack_fopen_special_file(AL_CONST char *filename, AL_CONST char *mode, AL_CONST char *password); + +static int file_encoding = U_ASCII; + + +#define FA_DAT_FLAGS (FA_RDONLY | FA_ARCH) + + +typedef struct RESOURCE_PATH +{ + int priority; + char path[1024]; + struct RESOURCE_PATH *next; +} RESOURCE_PATH; + +static RESOURCE_PATH *resource_path_list = NULL; + + +static void destroy_resource_path_list(void); + + + +/*************************************************** + ****************** Path handling ****************** + ***************************************************/ + + +/* fix_filename_case: + * Converts filename to upper case. + */ +char *fix_filename_case(char *filename) +{ + ASSERT(filename); + + if (!ALLEGRO_LFN) + ustrupr(filename); + + return filename; +} + + + +/* fix_filename_slashes: + * Converts '/' or '\' to system specific path separator. + */ +char *fix_filename_slashes(char *filename) +{ + int pos, c; + ASSERT(filename); + + for (pos=0; ugetc(filename+pos); pos+=uwidth(filename+pos)) { + c = ugetc(filename+pos); + if ((c == '/') || (c == '\\')) + usetat(filename+pos, 0, OTHER_PATH_SEPARATOR); + } + + return filename; +} + + + +/* Canonicalize_filename: + * Returns the canonical form of the specified filename, i.e. the + * minimal absolute filename describing the same file. + */ +char *canonicalize_filename(char *dest, AL_CONST char *filename, int size) +{ + int saved_errno = errno; + char buf[1024], buf2[1024]; + char *p; + int pos = 0; + int drive = -1; + int c1, i; + ASSERT(dest); + ASSERT(filename); + ASSERT(size >= 0); + + #if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') + + /* check whether we have a drive letter */ + c1 = utolower(ugetc(filename)); + if ((c1 >= 'a') && (c1 <= 'z')) { + int c2 = ugetat(filename, 1); + if (c2 == DEVICE_SEPARATOR) { + drive = c1 - 'a'; + filename += uwidth(filename); + filename += uwidth(filename); + } + } + + /* if not, use the current drive */ + if (drive < 0) + drive = _al_getdrive(); + + pos += usetc(buf+pos, drive+'a'); + pos += usetc(buf+pos, DEVICE_SEPARATOR); + + #endif + + #ifdef ALLEGRO_UNIX + + /* if the filename starts with ~ then it's relative to a home directory */ + if ((ugetc(filename) == '~')) { + AL_CONST char *tail = filename + uwidth(filename); /* could be the username */ + char *home = NULL; /* their home directory */ + + if (ugetc(tail) == '/' || !ugetc(tail)) { + /* easy */ + home = getenv("HOME"); + if (home) + home = strdup(home); + } + else { + /* harder */ + char *username = (char *)tail, *ascii_username, *ch; + int userlen; + struct passwd *pwd; + + /* find the end of the username */ + tail = ustrchr(username, '/'); + if (!tail) + tail = ustrchr(username, '\0'); + + /* this ought to be the ASCII length, but I can't see a Unicode + * function to return the difference in characters between two + * pointers. This code is safe on the assumption that ASCII is + * the most efficient encoding, but wasteful of memory */ + userlen = tail - username + ucwidth('\0'); + ascii_username = _AL_MALLOC_ATOMIC(userlen); + + if (ascii_username) { + /* convert the username to ASCII, find the password entry, + * and copy their home directory. */ + do_uconvert(username, U_CURRENT, ascii_username, U_ASCII, userlen); + + if ((ch = strchr(ascii_username, '/'))) + *ch = '\0'; + + setpwent(); + + while (((pwd = getpwent()) != NULL) && + (strcmp(pwd->pw_name, ascii_username) != 0)) + ; + + _AL_FREE(ascii_username); + + if (pwd) + home = strdup(pwd->pw_dir); + + endpwent(); + } + } + + /* If we got a home directory, prepend it to the filename. Otherwise + * we leave the filename alone, like bash but not tcsh; bash is better + * anyway. :) + */ + if (home) { + do_uconvert(home, U_ASCII, buf+pos, U_CURRENT, sizeof(buf)-pos); + _AL_FREE(home); + pos = ustrsize(buf); + filename = tail; + goto no_relativisation; + } + } + + #endif /* Unix */ + + /* if the filename is relative, make it absolute */ + if ((ugetc(filename) != '/') && (ugetc(filename) != OTHER_PATH_SEPARATOR) && (ugetc(filename) != '#')) { + _al_getdcwd(drive, buf2, sizeof(buf2) - ucwidth(OTHER_PATH_SEPARATOR)); + put_backslash(buf2); + + p = buf2; + if ((utolower(p[0]) >= 'a') && (utolower(p[0]) <= 'z') && (p[1] == DEVICE_SEPARATOR)) + p += 2; + + ustrzcpy(buf+pos, sizeof(buf)-pos, p); + pos = ustrsize(buf); + } + + #ifdef ALLEGRO_UNIX + no_relativisation: + #endif + + /* add our filename, and clean it up a bit */ + ustrzcpy(buf+pos, sizeof(buf)-pos, filename); + + fix_filename_case(buf); + fix_filename_slashes(buf); + + /* remove duplicate slashes */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) + uremove(p, 0); + + /* remove /./ patterns */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) { + uremove(p, 0); + uremove(p, 0); + } + + /* collapse /../ patterns */ + pos = usetc(buf2, OTHER_PATH_SEPARATOR); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, '.'); + pos += usetc(buf2+pos, OTHER_PATH_SEPARATOR); + usetc(buf2+pos, 0); + + while ((p = ustrstr(buf, buf2)) != NULL) { + for (i=0; buf+uoffset(buf, i) < p; i++) + ; + + while (--i > 0) { + c1 = ugetat(buf, i); + + if (c1 == OTHER_PATH_SEPARATOR) + break; + + if (c1 == DEVICE_SEPARATOR) { + i++; + break; + } + } + + if (i < 0) + i = 0; + + p += ustrsize(buf2); + memmove(buf+uoffset(buf, i+1), p, ustrsizez(p)); + } + + /* all done! */ + ustrzcpy(dest, size, buf); + + errno = saved_errno; + + return dest; +} + + + +/* make_absolute_filename: + * Makes the absolute filename corresponding to the specified relative + * filename using the specified base (PATH is absolute and represents + * the base, FILENAME is the relative filename), stores it in DEST + * whose size in bytes is SIZE and returns a pointer to it. + * It does not append '/' to the path. + */ +char *make_absolute_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char tmp[1024]; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + replace_filename(tmp, path, filename, sizeof(tmp)); + + canonicalize_filename(dest, tmp, size); + + return dest; +} + + + +/* make_relative_filename: + * Makes the relative filename corresponding to the specified absolute + * filename using the specified base (PATH is absolute and represents + * the base, FILENAME is the absolute filename), stores it in DEST + * whose size in bytes is SIZE and returns a pointer to it, or returns + * NULL if it cannot do so. + * It does not append '/' to the path. + */ +char *make_relative_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char *my_path, *my_filename; + char *reduced_path = NULL, *reduced_filename = NULL; + char *p1, *p2; + int c, c1, c2, pos; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + /* The first check under DOS/Windows would be for the drive: since the + * paths are absolute, they will always contain a drive letter. Do this + * check under Unix too where the first character should always be '/' + * in order not to screw up existing DOS/Windows paths. + */ + if (ugetc(path) != ugetc(filename)) + return NULL; + + my_path = ustrdup(path); + if (!my_path) + return NULL; + + my_filename = ustrdup(filename); + if (!my_filename) { + _AL_FREE(my_path); + return NULL; + } + + /* Strip the filenames to keep only the directories. */ + usetc(get_filename(my_path), 0); + usetc(get_filename(my_filename), 0); + + /* Both paths are on the same device. There are three cases: + * - the filename is a "child" of the path in the directory tree, + * - the filename is a "brother" of the path, + * - the filename is only a "cousin" of the path. + * In the two former cases, we will only need to keep a suffix of the + * filename. In the latter case, we will need to back-paddle through + * the directory tree. + */ + p1 = my_path; + p2 = my_filename; + while (((c1=ugetx(&p1)) == (c2=ugetx(&p2))) && c1 && c2) { + if ((c1 == '/') || (c1 == OTHER_PATH_SEPARATOR)) { + reduced_path = p1; + reduced_filename = p2; + } + } + + if (!c1) { + /* If the path is exhausted, we are in one of the two former cases. */ + + if (!c2) { + /* If the filename is also exhausted, we are in the second case. + * Prepend './' to the reduced filename. + */ + pos = usetc(dest, '.'); + pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); + usetc(dest+pos, 0); + } + else { + /* Otherwise we are in the first case. Nothing to do. */ + usetc(dest, 0); + } + } + else { + /* Bail out if previously something went wrong (eg. user supplied + * paths are not canonical and we can't understand them). */ + if (!reduced_path) { + _AL_FREE(my_path); + _AL_FREE(my_filename); + return NULL; + } + /* Otherwise, we are in the latter case and need to count the number + * of remaining directories in the reduced path and prepend the same + * number of '../' to the reduced filename. + */ + pos = 0; + while ((c=ugetx(&reduced_path))) { + if ((c == '/') || (c == OTHER_PATH_SEPARATOR)) { + pos += usetc(dest+pos, '.'); + pos += usetc(dest+pos, '.'); + pos += usetc(dest+pos, OTHER_PATH_SEPARATOR); + } + } + + usetc(dest+pos, 0); + } + + /* Bail out if previously something went wrong (eg. user supplied + * paths are not canonical and we can't understand them). */ + if (!reduced_filename) { + _AL_FREE(my_path); + _AL_FREE(my_filename); + return NULL; + } + + ustrzcat(dest, size, reduced_filename); + ustrzcat(dest, size, get_filename(filename)); + + _AL_FREE(my_path); + _AL_FREE(my_filename); + + /* Harmonize path separators. */ + return fix_filename_slashes(dest); +} + + + +/* is_relative_filename: + * Checks whether the specified filename is relative. + */ +int is_relative_filename(AL_CONST char *filename) +{ + ASSERT(filename); + + /* All filenames that start with a '.' are relative. */ + if (ugetc(filename) == '.') + return TRUE; + + /* Filenames that contain a device separator (DOS/Windows) + * or start with a '/' (Unix) are considered absolute. + */ +#if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + if (ustrchr(filename, DEVICE_SEPARATOR)) + return FALSE; +#endif + + if ((ugetc(filename) == '/') || (ugetc(filename) == OTHER_PATH_SEPARATOR)) + return FALSE; + + return TRUE; +} + + + +/* replace_filename: + * Replaces filename in path with different one. + * It does not append '/' to the path. + */ +char *replace_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char tmp[1024]; + int pos, c; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + pos = ustrlen(path); + + while (pos>0) { + c = ugetat(path, pos-1); + if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + break; + pos--; + } + + ustrzncpy(tmp, sizeof(tmp), path, pos); + ustrzcat(tmp, sizeof(tmp), filename); + + ustrzcpy(dest, size, tmp); + + return dest; +} + + + +/* replace_extension: + * Replaces extension in filename with different one. + * It appends '.' if it is not present in the filename. + */ +char *replace_extension(char *dest, AL_CONST char *filename, AL_CONST char *ext, int size) +{ + char tmp[1024], tmp2[16]; + int pos, end, c; + ASSERT(dest); + ASSERT(filename); + ASSERT(ext); + ASSERT(size >= 0); + + pos = end = ustrlen(filename); + + while (pos>0) { + c = ugetat(filename, pos-1); + if ((c == '.') || (c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + break; + pos--; + } + + if (ugetat(filename, pos-1) == '.') + end = pos-1; + + ustrzncpy(tmp, sizeof(tmp), filename, end); + ustrzcat(tmp, sizeof(tmp), uconvert_ascii(".", tmp2)); + ustrzcat(tmp, sizeof(tmp), ext); + + ustrzcpy(dest, size, tmp); + + return dest; +} + + + +/* append_filename: + * Append filename to path, adding separator if necessary. + */ +char *append_filename(char *dest, AL_CONST char *path, AL_CONST char *filename, int size) +{ + char tmp[1024]; + int pos, c; + ASSERT(dest); + ASSERT(path); + ASSERT(filename); + ASSERT(size >= 0); + + ustrzcpy(tmp, sizeof(tmp), path); + pos = ustrlen(tmp); + + if ((pos > 0) && (uoffset(tmp, pos) < ((int)sizeof(tmp) - ucwidth(OTHER_PATH_SEPARATOR) - ucwidth(0)))) { + c = ugetat(tmp, pos-1); + + if ((c != '/') && (c != OTHER_PATH_SEPARATOR) && (c != DEVICE_SEPARATOR)) { + pos = uoffset(tmp, pos); + pos += usetc(tmp+pos, OTHER_PATH_SEPARATOR); + usetc(tmp+pos, 0); + } + } + + ustrzcat(tmp, sizeof(tmp), filename); + + ustrzcpy(dest, size, tmp); + + return dest; +} + + + +/* get_filename: + * When passed a completely specified file path, this returns a pointer + * to the filename portion. Both '\' and '/' are recognized as directory + * separators. + */ +char *get_filename(AL_CONST char *path) +{ + int c; + const char *ptr, *ret; + ASSERT(path); + + ptr = path; + ret = ptr; + for (;;) { + c = ugetxc(&ptr); + if (!c) break; + if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + ret = (char*)ptr; + } + return (char*)ret; +} + + + +/* get_extension: + * When passed a complete filename (with or without path information) + * this returns a pointer to the file extension. + */ +char *get_extension(AL_CONST char *filename) +{ + int pos, c; + ASSERT(filename); + + pos = ustrlen(filename); + + while (pos>0) { + c = ugetat(filename, pos-1); + if ((c == '.') || (c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR)) + break; + pos--; + } + + if ((pos>0) && (ugetat(filename, pos-1) == '.')) + return (char *)filename + uoffset(filename, pos); + + return (char *)filename + ustrsize(filename); +} + + + +/* put_backslash: + * If the last character of the filename is not a \, /, or #, or a device + * separator (eg. : under DOS), this routine will concatenate a \ or / on + * to it (depending on platform). + */ +void put_backslash(char *filename) +{ + int c; + ASSERT(filename); + + if (ugetc(filename)) { + c = ugetat(filename, -1); + + if ((c == '/') || (c == OTHER_PATH_SEPARATOR) || (c == DEVICE_SEPARATOR) || (c == '#')) + return; + } + + filename += ustrsize(filename); + filename += usetc(filename, OTHER_PATH_SEPARATOR); + usetc(filename, 0); +} + + + +/*************************************************** + ******************* Filesystem ******************** + ***************************************************/ + + +/* set_file_encoding: + * Sets the encoding to use for filenames. By default, UTF8 is assumed. + */ +void set_file_encoding(int encoding) +{ + file_encoding = encoding; +} + + + +/* get_file_encoding: + * Returns the encoding currently assumed for filenames. + */ +int get_file_encoding(void) +{ + return file_encoding ; +} + + + +/* file_exists: + * Checks whether a file matching the given name and attributes exists, + * returning non zero if it does. The file attribute may contain any of + * the FA_* constants from dir.h. If aret is not null, it will be set + * to the attributes of the matching file. If an error occurs the system + * error code will be stored in errno. + */ +int file_exists(AL_CONST char *filename, int attrib, int *aret) +{ + struct al_ffblk info; + ASSERT(filename); + + if (ustrchr(filename, '#')) { + PACKFILE *f = pack_fopen_special_file(filename, F_READ, NULL); + if (f) { + pack_fclose(f); + if (aret) + *aret = FA_DAT_FLAGS; + return ((attrib & FA_DAT_FLAGS) == FA_DAT_FLAGS) ? TRUE : FALSE; + } + } + + if (!_al_file_isok(filename)) + return FALSE; + + if (al_findfirst(filename, &info, attrib) != 0) { + /* no entry is not an error for file_exists() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return FALSE; + } + + al_findclose(&info); + + if (aret) + *aret = info.attrib; + + return TRUE; +} + + + +/* exists: + * Shortcut version of file_exists(). + */ +int exists(AL_CONST char *filename) +{ + ASSERT(filename); + return file_exists(filename, FA_ARCH | FA_RDONLY, NULL); +} + + + +/* file_size_ex: + * Returns the size of a file, in bytes. + * If the file does not exist or an error occurs, it will return zero + * and store the system error code in errno. + */ +uint64_t file_size_ex_password(AL_CONST char *filename, AL_CONST char *password) +{ + ASSERT(filename); + if (ustrchr(filename, '#')) { + PACKFILE *f = pack_fopen_special_file(filename, F_READ,password); + if (f) { + long ret; + ASSERT(f->is_normal_packfile); + ret = f->normal.todo; + pack_fclose(f); + return ret; + } + } + + if (!_al_file_isok(filename)) + return 0; + + return _al_file_size_ex(filename); +} + +uint64_t file_size_ex(AL_CONST char *filename) +{ + return file_size_ex_password(filename, NULL); +} + + + +/* For binary compatibility with 4.2.0. */ +long file_size(AL_CONST char *filename) +{ + return file_size_ex(filename); +} + + + +/* For binary compatibility with 4.2.0. + * This is an internal symbol and only required because _al_file_size was + * exposed in the Windows DLL. + */ +long _al_file_size(AL_CONST char *filename) +{ + return _al_file_size_ex(filename); +} + + + +/* file_time: + * Returns a file time-stamp. + * If the file does not exist or an error occurs, it will return zero + * and store the system error code in errno. + */ +time_t file_time(AL_CONST char *filename) +{ + ASSERT(filename); + + if (!_al_file_isok(filename)) + return 0; + + return _al_file_time(filename); +} + + + +/* delete_file: + * Removes a file from the disk. + */ +int delete_file(AL_CONST char *filename) +{ + char tmp[1024]; + ASSERT(filename); + + if (!_al_file_isok(filename)) + return -1; + + if (_al_unlink(uconvert_tofilename(filename, tmp)) != 0) { + *allegro_errno = errno; + return -1; + } + + return 0; +} + + + +/* for_each_file: + * Finds all the files on the disk which match the given wildcard + * specification and file attributes, and executes callback() once for + * each. callback() will be passed three arguments, the first a string + * which contains the completed filename, the second being the attributes + * of the file, and the third an int which is simply a copy of param (you + * can use this for whatever you like). If an error occurs an error code + * will be stored in errno, and callback() can cause for_each_file() to + * abort by setting errno itself. Returns the number of successful calls + * made to callback(). The file attribute may contain any of the FA_* + * flags from dir.h. + */ +int for_each_file(AL_CONST char *name, int attrib, void (*callback)(AL_CONST char *filename, int attrib, int param), int param) +{ + char buf[1024]; + struct al_ffblk info; + int c = 0; + ASSERT(name); + + if (!_al_file_isok(name)) + return 0; + + if (al_findfirst(name, &info, attrib) != 0) { + /* no entry is not an error for for_each_file() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return 0; + } + + *allegro_errno = 0; + + do { + replace_filename(buf, name, info.name, sizeof(buf)); + (*callback)(buf, info.attrib, param); + + if (*allegro_errno) /* evil, evil, evil! */ + break; + + c++; + } while (al_findnext(&info) == 0); + + al_findclose(&info); + + /* no entry is not an error for for_each_file() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return c; +} + + + +/* for_each_file_ex: + * Finds all the files on disk which match the given wildcard specification + * and file attributes, and executes callback() once for each. callback() + * will be passed three arguments: the first is a string which contains the + * completed filename, the second is the actual attributes of the file, and + * the third is a void pointer which is simply a copy of param (you can use + * this for whatever you like). It must return 0 to let the enumeration + * proceed, or any non-zero value to stop it. If an error occurs, the error + * code will be stored in errno but the enumeration won't stop. Returns the + * number of successful calls made to callback(), that is the number of + * times callback() was called and returned 0. The file attribute masks may + * contain any of the FA_* flags from dir.h. + */ +int for_each_file_ex(AL_CONST char *name, int in_attrib, int out_attrib, int (*callback)(AL_CONST char *filename, int attrib, void *param), void *param) +{ + char buf[1024]; + struct al_ffblk info; + int ret, c = 0; + ASSERT(name); + + if (!_al_file_isok(name)) + return 0; + + if (al_findfirst(name, &info, ~out_attrib) != 0) { + /* no entry is not an error for for_each_file_ex() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return 0; + } + + do { + if ((~info.attrib & in_attrib) == 0) { + replace_filename(buf, name, info.name, sizeof(buf)); + ret = (*callback)(buf, info.attrib, param); + + if (ret != 0) + break; + + c++; + } + } while (al_findnext(&info) == 0); + + al_findclose(&info); + + /* no entry is not an error for for_each_file_ex() */ + if (*allegro_errno == ENOENT) + *allegro_errno = 0; + + return c; +} + + + +/* find_resource: + * Tries lots of different places that a resource file might live. + */ +static int find_resource(char *dest, AL_CONST char *path, AL_CONST char *name, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *subdir, int size) +{ + char _name[128], _objectname[128], hash[8]; + char tmp[16]; + int i; + + /* convert from name.ext to name_ext (datafile object name format) */ + ustrzcpy(_name, sizeof(_name), name); + + for (i=0; ipriority > priority) { + prior_node = node; + node = node->next; + } + + if (path) { + if (node && priority == node->priority) + new_node = node; + else { + new_node = _AL_MALLOC(sizeof(RESOURCE_PATH)); + if (!new_node) + return 0; + + new_node->priority = priority; + + if (prior_node) { + prior_node->next = new_node; + new_node->next = node; + } + else { + new_node->next = resource_path_list; + resource_path_list = new_node; + } + + if (!resource_path_list->next) + _add_exit_func(destroy_resource_path_list, + "destroy_resource_path_list"); + } + + ustrzcpy(new_node->path, + sizeof(new_node->path) - ucwidth(OTHER_PATH_SEPARATOR), + path); + fix_filename_slashes(new_node->path); + put_backslash(new_node->path); + } + else { + if (node && node->priority == priority) { + if (prior_node) + prior_node->next = node->next; + else + resource_path_list = node->next; + + _AL_FREE(node); + + if (!resource_path_list) + _remove_exit_func(destroy_resource_path_list); + } + else + return 0; + } + + return 1; +} + + + +static void destroy_resource_path_list(void) +{ + RESOURCE_PATH *node = resource_path_list; + + if (node) + _remove_exit_func(destroy_resource_path_list); + + while (node) { + resource_path_list = node->next; + _AL_FREE(node); + node = resource_path_list; + } +} + + + +/* find_allegro_resource: + * Searches for a support file, eg. allegro.cfg or language.dat. Passed + * a resource string describing what you are looking for, along with + * extra optional information such as the default extension, what datafile + * to look inside, what the datafile object name is likely to be, any + * special environment variable to check, and any subdirectory that you + * would like to check as well as the default location, this function + * looks in a hell of a lot of different places :-) Returns zero on + * success, and stores a full path to the file (at most size bytes) in + * the dest parameter. + */ +int find_allegro_resource(char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size) +{ + int (*sys_find_resource)(char *, AL_CONST char *, int); + char rname[128], path[1024], tmp[128]; + char *s; + int i, c; + RESOURCE_PATH *rp_list_node = resource_path_list; + + ASSERT(dest); + + /* if the resource is a path with no filename, look in that location */ + if ((resource) && (ugetc(resource)) && (!ugetc(get_filename(resource)))) + return find_resource(dest, resource, empty_string, datafile, objectname, subdir, size); + + /* if we have a path+filename, just use it directly */ + if ((resource) && (ustrpbrk(resource, uconvert_ascii("\\/#", tmp)))) { + if (file_exists(resource, FA_RDONLY | FA_ARCH, NULL)) { + ustrzcpy(dest, size, resource); + + /* if the resource is a datafile, try looking inside it */ + if ((ustricmp(get_extension(dest), uconvert_ascii("dat", tmp)) == 0) && (objectname)) { + ustrzcat(dest, size, uconvert_ascii("#", tmp)); + + for (i=0; ipath, rname, datafile, objectname, + subdir, size) == 0) + return 0; + rp_list_node = rp_list_node->next; + } + + /* try looking in the same directory as the program */ + get_executable_name(path, sizeof(path)); + usetc(get_filename(path), 0); + + if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) + return 0; + + /* try the ALLEGRO environment variable */ + s = getenv("ALLEGRO"); + + if (s) { + do_uconvert(s, U_ASCII, path, U_CURRENT, sizeof(path)-ucwidth(OTHER_PATH_SEPARATOR)); + put_backslash(path); + + if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) + return 0; + } + + /* try any extra environment variable that the parameters say to use */ + if (envvar) { + s = getenv(uconvert_tofilename(envvar, tmp)); + + if (s) { + do_uconvert(s, U_ASCII, path, U_CURRENT, sizeof(path)-ucwidth(OTHER_PATH_SEPARATOR)); + put_backslash(path); + + if (find_resource(dest, path, rname, datafile, objectname, subdir, size) == 0) + return 0; + } + } + + /* ask the system driver */ + if (system_driver) + sys_find_resource = system_driver->find_resource; + else + sys_find_resource = NULL; + + if (sys_find_resource) { + if ((ugetc(rname)) && (sys_find_resource(dest, (char *)rname, size) == 0)) + return 0; + + if ((datafile) && ((ugetc(rname)) || (objectname)) && (sys_find_resource(path, (char *)datafile, sizeof(path)) == 0)) { + if (!ugetc(rname)) + ustrzcpy(rname, sizeof(rname), objectname); + + for (i=0; iis_normal_packfile); + + /* seek to the end and check for the magic number */ + pack_fseek(f, f->normal.todo-8); + + if (pack_mgetl(f) != F_EXE_MAGIC) { + pack_fclose(f); + *allegro_errno = ENOTDIR; + return NULL; + } + + size = pack_mgetl(f); + + /* rewind */ + pack_fclose(f); + f = pack_fopen_password(exe_name, F_READ, password); + if (!f) + return NULL; + + /* seek to the start of the appended data */ + pack_fseek(f, f->normal.todo-size); + + f = pack_fopen_chunk(f, FALSE); + + if (f) + f->normal.flags |= PACKFILE_FLAG_EXEDAT; + + return f; +} + + + +/* pack_fopen_datafile_object: + * Recursive helper to handle opening member objects from datafiles, + * given a fake filename in the form 'object_name[/nestedobject]'. + */ +static PACKFILE *pack_fopen_datafile_object(PACKFILE *f, AL_CONST char *objname) +{ + char buf[512]; /* text is read into buf as UTF-8 */ + char tmp[512*4]; /* this should be enough even when expanding to UCS-4 */ + char name[512]; + int use_next = FALSE; + int recurse = FALSE; + int type, size, pos, c; + + /* split up the object name */ + pos = 0; + + while ((c = ugetxc(&objname)) != 0) { + if ((c == '#') || (c == '/') || (c == OTHER_PATH_SEPARATOR)) { + recurse = TRUE; + break; + } + pos += usetc(name+pos, c); + } + + usetc(name+pos, 0); + + pack_mgetl(f); + + /* search for the requested object */ + while (!pack_feof(f)) { + type = pack_mgetl(f); + + if (type == DAT_PROPERTY) { + type = pack_mgetl(f); + size = pack_mgetl(f); + if (type == DAT_NAME) { + /* examine name property */ + pack_fread(buf, size, f); + buf[size] = 0; + if (ustricmp(uconvert(buf, U_UTF8, tmp, U_CURRENT, sizeof tmp), name) == 0) + use_next = TRUE; + } + else { + /* skip property */ + pack_fseek(f, size); + } + } + else { + if (use_next) { + /* found it! */ + if (recurse) { + if (type == DAT_FILE) + return pack_fopen_datafile_object(pack_fopen_chunk(f, FALSE), objname); + else + break; + } + else { + _packfile_type = type; + return pack_fopen_chunk(f, FALSE); + } + } + else { + /* skip unwanted object */ + size = pack_mgetl(f); + pack_fseek(f, size+4); + } + } + } + + /* oh dear, the object isn't there... */ + pack_fclose(f); + *allegro_errno = ENOENT; + return NULL; +} + + + +/* pack_fopen_special_file: + * Helper to handle opening psuedo-files, ie. datafile objects and data + * that has been appended to the end of the executable. + */ +static PACKFILE *pack_fopen_special_file(AL_CONST char *filename, AL_CONST char *mode, AL_CONST char *password) +{ + char fname[1024], objname[512], tmp[16]; + PACKFILE *f; + char *p; + int c; + + /* special files are read-only */ + while ((c = *(mode++)) != 0) { + if ((c == 'w') || (c == 'W')) { + *allegro_errno = EROFS; + return NULL; + } + } + + if (ustrcmp(filename, uconvert_ascii("#", tmp)) == 0) { + /* read appended executable data */ + return pack_fopen_exe_file(password); + } + else { + if (ugetc(filename) == '#') { + /* read object from an appended datafile */ + ustrzcpy(fname, sizeof(fname), uconvert_ascii("#", tmp)); + ustrzcpy(objname, sizeof(objname), filename+uwidth(filename)); + } + else { + /* read object from a regular datafile */ + ustrzcpy(fname, sizeof(fname), filename); + p = ustrrchr(fname, '#'); + usetat(p, 0, 0); + ustrzcpy(objname, sizeof(objname), p+uwidth(p)); + } + + /* open the file */ + f = pack_fopen_password(fname, F_READ_PACKED, password); + if (!f) + return NULL; + + if (pack_mgetl(f) != DAT_MAGIC) { + pack_fclose(f); + *allegro_errno = ENOTDIR; + return NULL; + } + + /* find the required object */ + return pack_fopen_datafile_object(f, objname); + } +} + + + +/* packfile_password: + * Sets the password to be used by all future read/write operations. + * This only affects "normal" PACKFILEs, i.e. ones not using user-supplied + * packfile vtables. + */ +void packfile_password(AL_CONST char *password) +{ + int i = 0; + int c; + + if (password) { + while ((c = ugetxc(&password)) != 0) { + the_password[i++] = c; + if (i >= (int)sizeof(the_password)-1) + break; + } + } + + the_password[i] = 0; +} + + + +/* encrypt_id: + * Helper for encrypting magic numbers, using the current password. + */ +static int32_t encrypt_id(long x, int new_format, const char* password) +{ + int32_t mask = 0; + int i, pos; + + if (password && password[0]) { + for (i=0; password[i]; i++) + mask ^= ((int32_t)password[i] << ((i&3) * 8)); + + for (i=0, pos=0; i<4; i++) { + mask ^= (int32_t)password[pos++] << (24-i*8); + if (!password[pos]) + pos = 0; + } + + if (new_format) + mask ^= 42; + } + + return x ^ mask; +} + + + +/* clone_password: + * Sets up a local password string for use by this packfile. + */ +static int clone_password(PACKFILE *f, const char *password) +{ + ASSERT(f); + ASSERT(f->is_normal_packfile); + + if(password == NULL) + password = the_password; + + if (password[0]) { + if ((f->normal.passdata = _AL_MALLOC_ATOMIC(strlen(password)+1)) == NULL) { + *allegro_errno = ENOMEM; + return FALSE; + } + _al_sane_strncpy(f->normal.passdata, password, strlen(password)+1); + f->normal.passpos = f->normal.passdata; + } + else { + f->normal.passpos = NULL; + f->normal.passdata = NULL; + } + + return TRUE; +} + + + +/* create_packfile: + * Helper function for creating a PACKFILE structure. + */ +static PACKFILE *create_packfile(int is_normal_packfile, AL_CONST char *password) +{ + PACKFILE *f; + + if (is_normal_packfile) + f = _AL_MALLOC(sizeof(PACKFILE)); + else + f = _AL_MALLOC(sizeof(PACKFILE) - sizeof(struct _al_normal_packfile_details)); + + if (f == NULL) { + *allegro_errno = ENOMEM; + return NULL; + } + + if (!is_normal_packfile) { + f->vtable = NULL; + f->userdata = NULL; + f->is_normal_packfile = FALSE; + } + else { + f->vtable = &normal_vtable; + f->userdata = f; + f->is_normal_packfile = TRUE; + + f->normal.buf_pos = f->normal.buf; + f->normal.flags = 0; + f->normal.buf_size = 0; + f->normal.filename = NULL; + f->normal.passdata = NULL; + f->normal.passpos = NULL; + f->normal.parent = NULL; + f->normal.pack_data = NULL; + f->normal.unpack_data = NULL; + f->normal.todo = 0; + if (!clone_password(f, password)) { + _AL_FREE(f); + return NULL; + } + } + + return f; +} + + + +/* free_packfile: + * Helper function for freeing the PACKFILE struct. + */ +static void free_packfile(PACKFILE *f) +{ + if (f) { + /* These are no longer the responsibility of this function, but + * these assertions help catch instances of old code which still + * rely on the old behaviour. + */ + if (f->is_normal_packfile) { + ASSERT(!f->normal.pack_data); + ASSERT(!f->normal.unpack_data); + //ASSERT(!f->normal.passdata); + //ASSERT(!f->normal.passpos); + if(f->normal.passdata) + { + _AL_FREE(f->normal.passdata); + f->normal.passdata = NULL; + f->normal.passpos = NULL; + } + + } + + _AL_FREE(f); + } +} + + + +/* _pack_fdopen: + * Converts the given file descriptor into a PACKFILE. The mode can have + * the same values as for pack_fopen() and must be compatible with the + * mode of the file descriptor. Unlike the libc fdopen(), pack_fdopen() + * is unable to convert an already partially read or written file (i.e. + * the file offset must be 0). + * On success, it returns a pointer to a file structure, and on error it + * returns NULL and stores an error code in errno. An attempt to read + * a normal file in packed mode will cause errno to be set to EDOM. + */ +PACKFILE *_pack_fdopen(int fd, AL_CONST char *mode, AL_CONST char *password) +{ + PACKFILE *f, *f2; + long header = FALSE; + int c; + + if ((f = create_packfile(TRUE, password)) == NULL) + return NULL; + + ASSERT(f->is_normal_packfile); + + while ((c = *(mode++)) != 0) { + switch (c) { + case 'r': case 'R': f->normal.flags &= ~PACKFILE_FLAG_WRITE; break; + case 'w': case 'W': f->normal.flags |= PACKFILE_FLAG_WRITE; break; + case 'p': case 'P': f->normal.flags |= PACKFILE_FLAG_PACK; break; + case '!': f->normal.flags &= ~PACKFILE_FLAG_PACK; header = TRUE; break; + } + } + + if (f->normal.flags & PACKFILE_FLAG_WRITE) { + if (f->normal.flags & PACKFILE_FLAG_PACK) { + /* write a packed file */ + f->normal.pack_data = create_lzss_pack_data(); + ASSERT(!f->normal.unpack_data); + + if (!f->normal.pack_data) { + free_packfile(f); + return NULL; + } + + if ((f->normal.parent = _pack_fdopen(fd, F_WRITE, password)) == NULL) { + free_lzss_pack_data(f->normal.pack_data); + f->normal.pack_data = NULL; + free_packfile(f); + return NULL; + } + + pack_mputl(encrypt_id(F_PACK_MAGIC, TRUE, f->normal.passdata), f->normal.parent); + + f->normal.todo = 4; + } + else { + /* write a 'real' file */ + + /*if (!clone_password(f)) { + free_packfile(f); + return NULL; + }*/ + + f->normal.hndl = fd; + f->normal.todo = 0; + + errno = 0; + + if (header) + pack_mputl(encrypt_id(F_NOPACK_MAGIC, TRUE, f->normal.passdata), f); + } + } + else { + if (f->normal.flags & PACKFILE_FLAG_PACK) { + /* read a packed file */ + f->normal.unpack_data = create_lzss_unpack_data(); + ASSERT(!f->normal.pack_data); + + if (!f->normal.unpack_data) { + free_packfile(f); + return NULL; + } + + if ((f->normal.parent = _pack_fdopen(fd, F_READ, password)) == NULL) { + free_lzss_unpack_data(f->normal.unpack_data); + f->normal.unpack_data = NULL; + free_packfile(f); + return NULL; + } + + header = pack_mgetl(f->normal.parent); + + if ((f->normal.parent->normal.passpos) && + ((header == encrypt_id(F_PACK_MAGIC, FALSE, f->normal.passdata)) || + (header == encrypt_id(F_NOPACK_MAGIC, FALSE, f->normal.passdata)))) + { + /* duplicate the file descriptor */ + int fd2 = dup(fd); + + if (fd2<0) { + pack_fclose(f->normal.parent); + free_packfile(f); + *allegro_errno = errno; + return NULL; + } + + /* close the parent file (logically, not physically) */ + pack_fclose(f->normal.parent); + + /* + // backward compatibility mode + if (!clone_password(f)) { + free_packfile(f); + return NULL; + }*/ + + f->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; + + /* re-open the parent file */ + lseek(fd2, 0, SEEK_SET); + + if ((f->normal.parent = _pack_fdopen(fd2, F_READ, password)) == NULL) { + free_packfile(f); + return NULL; + } + + f->normal.parent->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; + + pack_mgetl(f->normal.parent); + + if (header == encrypt_id(F_PACK_MAGIC, FALSE, f->normal.passdata)) + header = encrypt_id(F_PACK_MAGIC, TRUE, f->normal.passdata); + else + header = encrypt_id(F_NOPACK_MAGIC, TRUE, f->normal.passdata); + } + + if (header == encrypt_id(F_PACK_MAGIC, TRUE, f->normal.passdata)) { + f->normal.todo = LONG_MAX; + } + else if (header == encrypt_id(F_NOPACK_MAGIC, TRUE, f->normal.passdata)) { + f2 = f->normal.parent; + free_lzss_unpack_data(f->normal.unpack_data); + f->normal.unpack_data = NULL; + free_packfile(f); + return f2; + } + else { + pack_fclose(f->normal.parent); + free_lzss_unpack_data(f->normal.unpack_data); + f->normal.unpack_data = NULL; + free_packfile(f); + *allegro_errno = EDOM; + return NULL; + } + } + else { + /* read a 'real' file */ + f->normal.todo = lseek(fd, 0, SEEK_END); /* size of the file */ + if (f->normal.todo < 0) { + *allegro_errno = errno; + free_packfile(f); + return NULL; + } + + lseek(fd, 0, SEEK_SET); + + /*if (!clone_password(f)) { + free_packfile(f); + return NULL; + }*/ + + f->normal.hndl = fd; + } + } + + return f; +} + + + +/* pack_fopen: + * Opens a file according to mode, which may contain any of the flags: + * 'r': open file for reading. + * 'w': open file for writing, overwriting any existing data. + * 'p': open file in 'packed' mode. Data will be compressed as it is + * written to the file, and automatically uncompressed during read + * operations. Files created in this mode will produce garbage if + * they are read without this flag being set. + * '!': open file for writing in normal, unpacked mode, but add the value + * F_NOPACK_MAGIC to the start of the file, so that it can be opened + * in packed mode and Allegro will automatically detect that the + * data does not need to be decompressed. + * + * Instead of these flags, one of the constants F_READ, F_WRITE, + * F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the second + * argument to fopen(). + * + * On success, fopen() returns a pointer to a file structure, and on error + * it returns NULL and stores an error code in errno. An attempt to read a + * normal file in packed mode will cause errno to be set to EDOM. + */ +PACKFILE *pack_fopen_password(AL_CONST char *filename, AL_CONST char *mode, AL_CONST char *password) +{ + char tmp[1024]; + int fd; + ASSERT(filename); + + _packfile_type = 0; + + if (ustrchr(filename, '#')) { + PACKFILE *special = pack_fopen_special_file(filename, mode, password); + if (special) + return special; + } + + if (!_al_file_isok(filename)) + return NULL; + +#ifndef ALLEGRO_MPW + if (strpbrk(mode, "wW")) /* write mode? */ + fd = _al_open(uconvert_tofilename(filename, tmp), O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, OPEN_PERMS); + else + fd = _al_open(uconvert_tofilename(filename, tmp), O_RDONLY | O_BINARY, OPEN_PERMS); +#else + if (strpbrk(mode, "wW")) /* write mode? */ + fd = _al_open(uconvert_tofilename(filename, tmp), O_WRONLY | O_BINARY | O_CREAT | O_TRUNC); + else + fd = _al_open(uconvert_tofilename(filename, tmp), O_RDONLY | O_BINARY); +#endif + + if (fd < 0) { + *allegro_errno = errno; + return NULL; + } + + return _pack_fdopen(fd, mode, password); +} + +PACKFILE *pack_fopen(AL_CONST char *filename, AL_CONST char *mode) +{ + return pack_fopen_password(filename, mode, NULL); +} + + + +/* pack_fopen_vtable: + * Creates a new packfile structure that uses the functions specified in + * the vtable instead of the standard functions. On success, it returns a + * pointer to a file structure, and on error it returns NULL and + * stores an error code in errno. + * + * The vtable and userdata must remain available for the lifetime of the + * created packfile. + * + * Opening chunks using pack_fopen_chunk() on top of the returned packfile + * is not possible at this time. + * + * packfile_password() does not have any effect on packfiles opened + * with pack_fopen_vtable(). + */ +PACKFILE *pack_fopen_vtable(AL_CONST PACKFILE_VTABLE *vtable, void *userdata) +{ + PACKFILE *f; + ASSERT(vtable); + ASSERT(vtable->pf_fclose); + ASSERT(vtable->pf_getc); + ASSERT(vtable->pf_ungetc); + ASSERT(vtable->pf_fread); + ASSERT(vtable->pf_putc); + ASSERT(vtable->pf_fwrite); + ASSERT(vtable->pf_fseek); + ASSERT(vtable->pf_feof); + ASSERT(vtable->pf_ferror); + + if ((f = create_packfile(FALSE, NULL)) == NULL) + return NULL; + + f->vtable = vtable; + f->userdata = userdata; + ASSERT(!f->is_normal_packfile); + + return f; +} + + + +/* pack_fclose: + * Closes a file after it has been read or written. + * Returns zero on success. On error it returns an error code which is + * also stored in errno. This function can fail only when writing to + * files: if the file was opened in read mode it will always succeed. + */ +int pack_fclose(PACKFILE *f) +{ + int ret; + + if (!f) + return 0; + + ASSERT(f->vtable); + ASSERT(f->vtable->pf_fclose); + + ret = f->vtable->pf_fclose(f->userdata); + if (ret != 0) + *allegro_errno = errno; + + free_packfile(f); + + return ret; +} + + + +/* pack_fopen_chunk: + * Opens a sub-chunk of the specified file, for reading or writing depending + * on the type of the file. The returned file pointer describes the sub + * chunk, and replaces the original file, which will no longer be valid. + * When writing to a chunk file, data is sent to the original file, but + * is prefixed with two length counts (32 bit, big-endian). For uncompressed + * chunks these will both be set to the length of the data in the chunk. + * For compressed chunks, created by setting the pack flag, the first will + * contain the raw size of the chunk, and the second will be the negative + * size of the uncompressed data. When reading chunks, the pack flag is + * ignored, and the compression type is detected from the sign of the + * second size value. The file structure used to read chunks checks the + * chunk size, and will return EOF if you try to read past the end of + * the chunk. If you don't read all of the chunk data, when you call + * pack_fclose_chunk(), the parent file will advance past the unused data. + * When you have finished reading or writing a chunk, you should call + * pack_fclose_chunk() to return to your original file. + */ +PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack) +{ + PACKFILE *chunk; + char tmp[1024]; + char *name; + ASSERT(f); + + /* unsupported */ + if (!f->is_normal_packfile) { + *allegro_errno = EINVAL; + return NULL; + } + + if (f->normal.flags & PACKFILE_FLAG_WRITE) { + + /* write a sub-chunk */ + int tmp_fd = -1; + char *tmp_dir = NULL; + char *tmp_name = NULL; + #ifndef ALLEGRO_HAVE_MKSTEMP + char* tmpnam_string; + #endif + + #ifdef ALLEGRO_WINDOWS + int size; + int new_size = 64; + + /* Get the path of the temporary directory */ + do { + size = new_size; + tmp_dir = _AL_REALLOC(tmp_dir, size); + new_size = GetTempPath(size, tmp_dir); + } while ( (size < new_size) && (new_size > 0) ); + + /* Check if we retrieved the path OK */ + if (new_size == 0) + sprintf(tmp_dir, "%s", ""); + #else + /* Get the path of the temporary directory */ + + /* Try various possible locations to store the temporary file */ + if (getenv("TEMP")) { + tmp_dir = strdup(getenv("TEMP")); + } + else if (getenv("TMP")) { + tmp_dir = strdup(getenv("TMP")); + } + else if (file_exists("/tmp", FA_DIREC, NULL)) { + tmp_dir = strdup("/tmp"); + } + else if (getenv("HOME")) { + tmp_dir = strdup(getenv("HOME")); + } + else { + /* Give up - try current directory */ + tmp_dir = strdup("."); + } + + #endif + + /* the file is open in read/write mode, even if the pack file + * seems to be in write only mode + */ + #ifdef ALLEGRO_HAVE_MKSTEMP + + tmp_name = _AL_MALLOC_ATOMIC(strlen(tmp_dir) + 16); + sprintf(tmp_name, "%s/XXXXXX", tmp_dir); + tmp_fd = mkstemp(tmp_name); + + #else + + /* note: since the filename creation and the opening are not + * an atomic operation, this is not secure + */ + tmpnam_string = tmpnam(NULL); + tmp_name = _AL_MALLOC_ATOMIC(strlen(tmp_dir) + strlen(tmpnam_string) + 2); + sprintf(tmp_name, "%s/%s", tmp_dir, tmpnam_string); + + if (tmp_name) { +#ifndef ALLEGRO_MPW + tmp_fd = open(tmp_name, O_RDWR | O_BINARY | O_CREAT | O_EXCL, OPEN_PERMS); +#else + tmp_fd = _al_open(tmp_name, O_RDWR | O_BINARY | O_CREAT | O_EXCL); +#endif + } + + #endif + + if (tmp_fd < 0) { + _AL_FREE(tmp_dir); + _AL_FREE(tmp_name); + + return NULL; + } + + name = uconvert_ascii(tmp_name, tmp); + chunk = _pack_fdopen(tmp_fd, (pack ? F_WRITE_PACKED : F_WRITE_NOPACK), f->normal.passdata); + + if (chunk) { + chunk->normal.filename = ustrdup(name); + + if (pack) + chunk->normal.parent->normal.parent = f; + else + chunk->normal.parent = f; + + chunk->normal.flags |= PACKFILE_FLAG_CHUNK; + } + + _AL_FREE(tmp_dir); + _AL_FREE(tmp_name); + } + else { + /* read a sub-chunk */ + _packfile_filesize = pack_mgetl(f); + _packfile_datasize = pack_mgetl(f); + + if ((chunk = create_packfile(TRUE, f->normal.passdata)) == NULL) + return NULL; + + chunk->normal.flags = PACKFILE_FLAG_CHUNK; + chunk->normal.parent = f; + + if (f->normal.flags & PACKFILE_FLAG_OLD_CRYPT) { + /* backward compatibility mode */ + + /* + if (f->normal.passdata) { + + if ((chunk->normal.passdata = _AL_MALLOC_ATOMIC(strlen(f->normal.passdata)+1)) == NULL) { + *allegro_errno = ENOMEM; + _AL_FREE(chunk); + return NULL; + } + _al_sane_strncpy(chunk->normal.passdata, f->normal.passdata, strlen(f->normal.passdata)+1); + chunk->normal.passpos = chunk->normal.passdata + (long)f->normal.passpos - (long)f->normal.passdata; + f->normal.passpos = f->normal.passdata; + } + */ + chunk->normal.flags |= PACKFILE_FLAG_OLD_CRYPT; + } + + if (_packfile_datasize < 0) { + /* read a packed chunk */ + chunk->normal.unpack_data = create_lzss_unpack_data(); + ASSERT(!chunk->normal.pack_data); + + if (!chunk->normal.unpack_data) { + free_packfile(chunk); + return NULL; + } + + _packfile_datasize = -_packfile_datasize; + chunk->normal.todo = _packfile_datasize; + chunk->normal.flags |= PACKFILE_FLAG_PACK; + } + else { + /* read an uncompressed chunk */ + chunk->normal.todo = _packfile_datasize; + } + } + + return chunk; +} + + + +/* pack_fclose_chunk: + * Call after reading or writing a sub-chunk. This closes the chunk file, + * and returns a pointer to the original file structure (the one you + * passed to pack_fopen_chunk()), to allow you to read or write data + * after the chunk. If an error occurs, returns NULL and sets errno. + */ +PACKFILE *pack_fclose_chunk(PACKFILE *f) +{ + PACKFILE *parent; + PACKFILE *tmp; + char *name; + int header, c; + ASSERT(f); + + /* unsupported */ + if (!f->is_normal_packfile) { + *allegro_errno = EINVAL; + return NULL; + } + + parent = f->normal.parent; + name = f->normal.filename; + + if (f->normal.flags & PACKFILE_FLAG_WRITE) { + /* finish writing a chunk */ + int hndl; + char *password; + + /* duplicate the file descriptor to create a readable pack file, + * the file descriptor must have been opened in read/write mode + */ + if (f->normal.flags & PACKFILE_FLAG_PACK) + hndl = dup(f->normal.parent->normal.hndl); + else + hndl = dup(f->normal.hndl); + + if (hndl<0) { + *allegro_errno = errno; + return NULL; + } + + _packfile_datasize = f->normal.todo + f->normal.buf_size - 4; + + if (f->normal.flags & PACKFILE_FLAG_PACK) { + parent = parent->normal.parent; + f->normal.parent->normal.parent = NULL; + } + else + f->normal.parent = NULL; + + /* close the writeable temp file, it isn't physically closed + * because the descriptor has been duplicated + */ + f->normal.flags &= ~PACKFILE_FLAG_CHUNK; + password = f->normal.passdata; + f->normal.passdata = NULL; + f->normal.passpos = NULL; + pack_fclose(f); + + lseek(hndl, 0, SEEK_SET); + + /* create a readable pack file */ + tmp = _pack_fdopen(hndl, F_READ, password); + if (!tmp) + return NULL; + + _packfile_filesize = tmp->normal.todo - 4; + + header = pack_mgetl(tmp); + + pack_mputl(_packfile_filesize, parent); + + if (header == encrypt_id(F_PACK_MAGIC, TRUE, password)) + pack_mputl(-_packfile_datasize, parent); + else + pack_mputl(_packfile_datasize, parent); + + while ((c = pack_getc(tmp)) != EOF) + pack_putc(c, parent); + + pack_fclose(tmp); + + delete_file(name); + _AL_FREE(name); + if(password) + _AL_FREE(password); + } + else { + /* finish reading a chunk */ + while (f->normal.todo > 0) + pack_getc(f); + + if (f->normal.unpack_data) { + free_lzss_unpack_data(f->normal.unpack_data); + f->normal.unpack_data = NULL; + } + + if ((f->normal.passpos) && (f->normal.flags & PACKFILE_FLAG_OLD_CRYPT)) + parent->normal.passpos = parent->normal.passdata + (long)f->normal.passpos - (long)f->normal.passdata; + + free_packfile(f); + } + + return parent; +} + + + +/* pack_fseek: + * Like the stdio fseek() function, but only supports forward seeks + * relative to the current file position. + */ +int pack_fseek(PACKFILE *f, int offset) +{ + ASSERT(f); + ASSERT(offset >= 0); + + return f->vtable->pf_fseek(f->userdata, offset); +} + + + +/* pack_getc: + * Returns the next character from the stream f, or EOF if the end of the + * file has been reached. + */ +int pack_getc(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_getc); + + return f->vtable->pf_getc(f->userdata); +} + + + +/* pack_putc: + * Puts a character in the stream f. + */ +int pack_putc(int c, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_putc); + + return f->vtable->pf_putc(c, f->userdata); +} + + + +/* pack_feof: + * pack_feof() returns nonzero as soon as you reach the end of the file. It + * does not wait for you to attempt to read beyond the end of the file, + * contrary to the ISO C feof() function. + */ +int pack_feof(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_feof); + + return f->vtable->pf_feof(f->userdata); +} + + + +/* pack_ferror: + * Returns nonzero if the error indicator for the stream is set, indicating + * that an error has occurred during a previous operation on the stream. + */ +int pack_ferror(PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_ferror); + + return f->vtable->pf_ferror(f->userdata); +} + + + +/* pack_igetw: + * Reads a 16 bit word from a file, using intel byte ordering. + */ +int pack_igetw(PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + return ((b2 << 8) | b1); + + return EOF; +} + + + +/* pack_igetl: + * Reads a 32 bit long from a file, using intel byte ordering. + */ +long pack_igetl(PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + if ((b3 = pack_getc(f)) != EOF) + if ((b4 = pack_getc(f)) != EOF) + return (((long)b4 << 24) | ((long)b3 << 16) | + ((long)b2 << 8) | (long)b1); + + return EOF; +} + + + +/* pack_iputw: + * Writes a 16 bit int to a file, using intel byte ordering. + */ +int pack_iputw(int w, PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + b1 = (w & 0xFF00) >> 8; + b2 = w & 0x00FF; + + if (pack_putc(b2,f)==b2) + if (pack_putc(b1,f)==b1) + return w; + + return EOF; +} + + + +/* pack_iputl: + * Writes a 32 bit long to a file, using intel byte ordering. + */ +long pack_iputl(long l, PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + b1 = (int)((l & 0xFF000000L) >> 24); + b2 = (int)((l & 0x00FF0000L) >> 16); + b3 = (int)((l & 0x0000FF00L) >> 8); + b4 = (int)l & 0x00FF; + + if (pack_putc(b4,f)==b4) + if (pack_putc(b3,f)==b3) + if (pack_putc(b2,f)==b2) + if (pack_putc(b1,f)==b1) + return l; + + return EOF; +} + + + +/* pack_mgetw: + * Reads a 16 bit int from a file, using motorola byte-ordering. + */ +int pack_mgetw(PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + return ((b1 << 8) | b2); + + return EOF; +} + + + +/* pack_mgetl: + * Reads a 32 bit long from a file, using motorola byte-ordering. + */ +long pack_mgetl(PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + if ((b1 = pack_getc(f)) != EOF) + if ((b2 = pack_getc(f)) != EOF) + if ((b3 = pack_getc(f)) != EOF) + if ((b4 = pack_getc(f)) != EOF) + return (((long)b1 << 24) | ((long)b2 << 16) | + ((long)b3 << 8) | (long)b4); + + return EOF; +} + + + +/* pack_mputw: + * Writes a 16 bit int to a file, using motorola byte-ordering. + */ +int pack_mputw(int w, PACKFILE *f) +{ + int b1, b2; + ASSERT(f); + + b1 = (w & 0xFF00) >> 8; + b2 = w & 0x00FF; + + if (pack_putc(b1,f)==b1) + if (pack_putc(b2,f)==b2) + return w; + + return EOF; +} + + + +/* pack_mputl: + * Writes a 32 bit long to a file, using motorola byte-ordering. + */ +long pack_mputl(long l, PACKFILE *f) +{ + int b1, b2, b3, b4; + ASSERT(f); + + b1 = (int)((l & 0xFF000000L) >> 24); + b2 = (int)((l & 0x00FF0000L) >> 16); + b3 = (int)((l & 0x0000FF00L) >> 8); + b4 = (int)l & 0x00FF; + + if (pack_putc(b1,f)==b1) + if (pack_putc(b2,f)==b2) + if (pack_putc(b3,f)==b3) + if (pack_putc(b4,f)==b4) + return l; + + return EOF; +} + + + +/* pack_fread: + * Reads n bytes from f and stores them at memory location p. Returns the + * number of items read, which will be less than n if EOF is reached or an + * error occurs. Error codes are stored in errno. + */ +long pack_fread(void *p, long n, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_fread); + ASSERT(p); + ASSERT(n >= 0); + + return f->vtable->pf_fread(p, n, f->userdata); +} + + + +/* pack_fwrite: + * Writes n bytes to the file f from memory location p. Returns the number + * of items written, which will be less than n if an error occurs. Error + * codes are stored in errno. + */ +long pack_fwrite(AL_CONST void *p, long n, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_fwrite); + ASSERT(p); + ASSERT(n >= 0); + + return f->vtable->pf_fwrite(p, n, f->userdata); +} + + + +/* pack_ungetc: + * Puts a character back in the file's input buffer. It only works + * for characters just fetched by pack_getc and, like ungetc, only a + * single push back is guaranteed. + */ +int pack_ungetc(int c, PACKFILE *f) +{ + ASSERT(f); + ASSERT(f->vtable); + ASSERT(f->vtable->pf_ungetc); + + return f->vtable->pf_ungetc(c, f->userdata); +} + + + +/* pack_fgets: + * Reads a line from a text file, storing it at location p. Stops when a + * linefeed is encountered, or max bytes have been read. Returns a pointer + * to where it stored the text, or NULL on error. The end of line is + * handled by detecting optional '\r' characters optionally followed + * by '\n' characters. This supports CR-LF (DOS/Windows), LF (Unix), and + * CR (Mac) formats. + */ +char *pack_fgets(char *p, int max, PACKFILE *f) +{ + char *pmax, *orig_p = p; + int c; + ASSERT(f); + + *allegro_errno = 0; + + pmax = p+max - ucwidth(0); + + if ((c = pack_getc(f)) == EOF) { + if (ucwidth(0) <= max) + usetc(p,0); + return NULL; + } + + do { + + if (c == '\r' || c == '\n') { + /* Technically we should check there's space in the buffer, and if so, + * add a \n. But pack_fgets has never done this. */ + if (c == '\r') { + /* eat the following \n, if any */ + c = pack_getc(f); + if ((c != '\n') && (c != EOF)) + pack_ungetc(c, f); + } + break; + } + + /* is there room in the buffer? */ + if (ucwidth(c) > pmax - p) { + pack_ungetc(c, f); + c = '\0'; + break; + } + + /* write the character */ + p += usetc(p, c); + } + while ((c = pack_getc(f)) != EOF); + + /* terminate the string */ + usetc(p, 0); + + if (c == '\0' || *allegro_errno) + return NULL; + + return orig_p; /* p has changed */ +} + + + +/* pack_fputs: + * Writes a string to a text file, returning zero on success, -1 on error. + * The input string is converted from the current text encoding format + * to UTF-8 before writing. Newline characters (\n) are written as \r\n + * on DOS and Windows platforms. + */ +int pack_fputs(AL_CONST char *p, PACKFILE *f) +{ + char *buf, *s; + int bufsize; + ASSERT(f); + ASSERT(p); + + *allegro_errno = 0; + + bufsize = uconvert_size(p, U_CURRENT, U_UTF8); + buf = _AL_MALLOC_ATOMIC(bufsize); + if (!buf) + return -1; + + s = uconvert(p, U_CURRENT, buf, U_UTF8, bufsize); + + while (*s) { + #if (defined ALLEGRO_DOS) || (defined ALLEGRO_WINDOWS) + if (*s == '\n') + pack_putc('\r', f); + #endif + + pack_putc(*s, f); + s++; + } + + _AL_FREE(buf); + + if (*allegro_errno) + return -1; + else + return 0; +} + + + +/* pack_get_userdata: + * Returns the userdata field of packfiles using user-defined vtables. + */ +void *pack_get_userdata(PACKFILE *f) +{ + ASSERT(f); + + return f->userdata; +} + + + +/*************************************************** + ************ "Normal" packfile vtable ************* + *************************************************** + + Ideally this would be the only section which knows about the details + of "normal" packfiles. However, this ideal is still being violated in + many places (partly due to the API, and partly because it would be + quite a lot of work to move the _al_normal_packfile_details field + into the userdata field of the PACKFILE structure. +*/ + + +static int normal_fclose(void *_f); +static int normal_getc(void *_f); +static int normal_ungetc(int ch, void *_f); +static int normal_putc(int c, void *_f); +static long normal_fread(void *p, long n, void *_f); +static long normal_fwrite(AL_CONST void *p, long n, void *_f); +static int normal_fseek(void *_f, int offset); +static int normal_feof(void *_f); +static int normal_ferror(void *_f); + +static int normal_refill_buffer(PACKFILE *f); +static int normal_flush_buffer(PACKFILE *f, int last); + + + +static PACKFILE_VTABLE normal_vtable = +{ + normal_fclose, + normal_getc, + normal_ungetc, + normal_fread, + normal_putc, + normal_fwrite, + normal_fseek, + normal_feof, + normal_ferror +}; + + + +static int normal_fclose(void *_f) +{ + PACKFILE *f = _f; + int ret; + + if (f->normal.flags & PACKFILE_FLAG_WRITE) { + if (f->normal.flags & PACKFILE_FLAG_CHUNK) { + f = pack_fclose_chunk(_f); + if (!f) + return -1; + + return pack_fclose(f); + } + + normal_flush_buffer(f, TRUE); + } + + if (f->normal.parent) { + ret = pack_fclose(f->normal.parent); + } + else { + ret = close(f->normal.hndl); + if (ret != 0) + *allegro_errno = errno; + } + + if (f->normal.pack_data) { + free_lzss_pack_data(f->normal.pack_data); + f->normal.pack_data = NULL; + } + + if (f->normal.unpack_data) { + free_lzss_unpack_data(f->normal.unpack_data); + f->normal.unpack_data = NULL; + } + + if (f->normal.passdata) { + _AL_FREE(f->normal.passdata); + f->normal.passdata = NULL; + f->normal.passpos = NULL; + } + + return ret; +} + + + +/* normal_no_more_input: + * Return non-zero if the number of bytes remaining in the file (todo) is + * less than or equal to zero. + * + * However, there is a special case. If we are reading from a LZSS + * compressed file, the latest call to lzss_read() may have suspended while + * writing out a sequence of bytes due to the output buffer being too small. + * In that case the `todo' count would be decremented (possibly to zero), + * but the output isn't yet completely written out. + */ +static INLINE int normal_no_more_input(PACKFILE *f) +{ + /* see normal_refill_buffer() to see when lzss_read() is called */ + if (f->normal.parent && (f->normal.flags & PACKFILE_FLAG_PACK) && + _al_lzss_incomplete_state(f->normal.unpack_data)) + return 0; + + return (f->normal.todo <= 0); +} + + + +static int normal_getc(void *_f) +{ + PACKFILE *f = _f; + + f->normal.buf_size--; + if (f->normal.buf_size > 0) + return *(f->normal.buf_pos++); + + if (f->normal.buf_size == 0) { + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + return *(f->normal.buf_pos++); + } + + return normal_refill_buffer(f); +} + + + +static int normal_ungetc(int c, void *_f) +{ + PACKFILE *f = _f; + + if (f->normal.buf_pos == f->normal.buf) { + return EOF; + } + else { + *(--f->normal.buf_pos) = (unsigned char)c; + f->normal.buf_size++; + f->normal.flags &= ~PACKFILE_FLAG_EOF; + return (unsigned char)c; + } +} + + + +static long normal_fread(void *p, long n, void *_f) +{ + PACKFILE *f = _f; + unsigned char *cp = (unsigned char *)p; + long i; + int c; + + for (i=0; inormal.buf_size + 1 >= F_BUF_SIZE) { + if (normal_flush_buffer(f, FALSE)) + return EOF; + } + + f->normal.buf_size++; + return (*(f->normal.buf_pos++) = c); +} + + + +static long normal_fwrite(AL_CONST void *p, long n, void *_f) +{ + PACKFILE *f = _f; + AL_CONST unsigned char *cp = (AL_CONST unsigned char *)p; + long i; + + for (i=0; inormal.flags & PACKFILE_FLAG_WRITE) + return -1; + + *allegro_errno = 0; + + /* skip forward through the buffer */ + if (f->normal.buf_size > 0) { + i = MIN(offset, f->normal.buf_size); + f->normal.buf_size -= i; + f->normal.buf_pos += i; + offset -= i; + if ((f->normal.buf_size <= 0) && normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + } + + /* need to seek some more? */ + if (offset > 0) { + i = MIN(offset, f->normal.todo); + + if ((f->normal.flags & PACKFILE_FLAG_PACK) || (f->normal.passpos)) { + /* for compressed or encrypted files, we just have to read through the data */ + while (i > 0) { + pack_getc(f); + i--; + } + } + else { + if (f->normal.parent) { + /* pass the seek request on to the parent file */ + pack_fseek(f->normal.parent, i); + } + else { + /* do a real seek */ + lseek(f->normal.hndl, i, SEEK_CUR); + } + f->normal.todo -= i; + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + } + } + + if (*allegro_errno) + return -1; + else + return 0; +} + + + +static int normal_feof(void *_f) +{ + PACKFILE *f = _f; + + return (f->normal.flags & PACKFILE_FLAG_EOF); +} + + + +static int normal_ferror(void *_f) +{ + PACKFILE *f = _f; + + return (f->normal.flags & PACKFILE_FLAG_ERROR); +} + + + +/* normal_refill_buffer: + * Refills the read buffer. The file must have been opened in read mode, + * and the buffer must be empty. + */ +static int normal_refill_buffer(PACKFILE *f) +{ + int i, sz, done, offset; + + if (f->normal.flags & PACKFILE_FLAG_EOF) + return EOF; + + if (normal_no_more_input(f)) { + f->normal.flags |= PACKFILE_FLAG_EOF; + return EOF; + } + + if (f->normal.parent) { + if (f->normal.flags & PACKFILE_FLAG_PACK) { + f->normal.buf_size = lzss_read(f->normal.parent, f->normal.unpack_data, MIN(F_BUF_SIZE, f->normal.todo), f->normal.buf); + } + else { + f->normal.buf_size = pack_fread(f->normal.buf, MIN(F_BUF_SIZE, f->normal.todo), f->normal.parent); + } + if (f->normal.parent->normal.flags & PACKFILE_FLAG_EOF) + f->normal.todo = 0; + if (f->normal.parent->normal.flags & PACKFILE_FLAG_ERROR) + goto Error; + } + else { + f->normal.buf_size = MIN(F_BUF_SIZE, f->normal.todo); + + offset = lseek(f->normal.hndl, 0, SEEK_CUR); + done = 0; + + errno = 0; + sz = read(f->normal.hndl, f->normal.buf, f->normal.buf_size); + + while (sz+done < f->normal.buf_size) { + if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) + goto Error; + + if (sz > 0) + done += sz; + + lseek(f->normal.hndl, offset+done, SEEK_SET); + errno = 0; + sz = read(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); + } + + if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { + for (i=0; inormal.buf_size; i++) { + f->normal.buf[i] ^= *(f->normal.passpos++); + if (!*f->normal.passpos) + f->normal.passpos = f->normal.passdata; + } + } + } + + f->normal.todo -= f->normal.buf_size; + f->normal.buf_pos = f->normal.buf; + f->normal.buf_size--; + if (f->normal.buf_size <= 0) + if (normal_no_more_input(f)) + f->normal.flags |= PACKFILE_FLAG_EOF; + + if (f->normal.buf_size < 0) + return EOF; + else + return *(f->normal.buf_pos++); + + Error: + *allegro_errno = EFAULT; + f->normal.flags |= PACKFILE_FLAG_ERROR; + return EOF; +} + + + +/* normal_flush_buffer: + * Flushes a file buffer to the disk. The file must be open in write mode. + */ +static int normal_flush_buffer(PACKFILE *f, int last) +{ + int i, sz, done, offset; + + if (f->normal.buf_size > 0) { + if (f->normal.flags & PACKFILE_FLAG_PACK) { + if (lzss_write(f->normal.parent, f->normal.pack_data, f->normal.buf_size, f->normal.buf, last)) + goto Error; + } + else { + if ((f->normal.passpos) && (!(f->normal.flags & PACKFILE_FLAG_OLD_CRYPT))) { + for (i=0; inormal.buf_size; i++) { + f->normal.buf[i] ^= *(f->normal.passpos++); + if (!*f->normal.passpos) + f->normal.passpos = f->normal.passdata; + } + } + + offset = lseek(f->normal.hndl, 0, SEEK_CUR); + done = 0; + + errno = 0; + sz = write(f->normal.hndl, f->normal.buf, f->normal.buf_size); + + while (sz+done < f->normal.buf_size) { + if ((sz < 0) && ((errno != EINTR) && (errno != EAGAIN))) + goto Error; + + if (sz > 0) + done += sz; + + lseek(f->normal.hndl, offset+done, SEEK_SET); + errno = 0; + sz = write(f->normal.hndl, f->normal.buf+done, f->normal.buf_size-done); + } + } + f->normal.todo += f->normal.buf_size; + } + + f->normal.buf_pos = f->normal.buf; + f->normal.buf_size = 0; + return 0; + + Error: + *allegro_errno = EFAULT; + f->normal.flags |= PACKFILE_FLAG_ERROR; + return EOF; +} diff --git a/allegro/fixed/file.h b/allegro/fixed/file.h new file mode 100644 index 0000000000..c8b2e97c5e --- /dev/null +++ b/allegro/fixed/file.h @@ -0,0 +1,182 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * File I/O. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef ALLEGRO_FILE_H +#define ALLEGRO_FILE_H + +#include "base.h" + +#ifdef __cplusplus + extern "C" { +#endif + +AL_FUNC(char *, fix_filename_case, (char *path)); +AL_FUNC(char *, fix_filename_slashes, (char *path)); +AL_FUNC(char *, canonicalize_filename, (char *dest, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_absolute_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, make_relative_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(int, is_relative_filename, (AL_CONST char *filename)); +AL_FUNC(char *, replace_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, replace_extension, (char *dest, AL_CONST char *filename, AL_CONST char *ext, int size)); +AL_FUNC(char *, append_filename, (char *dest, AL_CONST char *path, AL_CONST char *filename, int size)); +AL_FUNC(char *, get_filename, (AL_CONST char *path)); +AL_FUNC(char *, get_extension, (AL_CONST char *filename)); +AL_FUNC(void, put_backslash, (char *filename)); +AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret)); +AL_FUNC(int, exists, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename)); +AL_FUNC(uint64_t, file_size_ex_password, (AL_CONST char *filename, AL_CONST char *password)); +AL_FUNC(time_t, file_time, (AL_CONST char *filename)); +AL_FUNC(int, delete_file, (AL_CONST char *filename)); +AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param)); +AL_FUNC(int, set_allegro_resource_path, (int priority, AL_CONST char *path)); +AL_FUNC(int, find_allegro_resource, (char *dest, AL_CONST char *resource, AL_CONST char *ext, AL_CONST char *datafile, AL_CONST char *objectname, AL_CONST char *envvar, AL_CONST char *subdir, int size)); + +struct al_ffblk /* file info block for the al_find*() routines */ +{ + int attrib; /* actual attributes of the file found */ + time_t time; /* modification time of file */ + long size; /* size of file */ + char name[512]; /* name of file */ + void *ff_data; /* private hook */ +}; + +AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info)); + +AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib)); +AL_FUNC(int, al_findnext, (struct al_ffblk *info)); +AL_FUNC(void, al_findclose, (struct al_ffblk *info)); + +#ifndef EOF + #define EOF (-1) +#endif + +#define F_READ "r" +#define F_WRITE "w" +#define F_READ_PACKED "rp" +#define F_WRITE_PACKED "wp" +#define F_WRITE_NOPACK "w!" + +#define F_BUF_SIZE 4096 /* 4K buffer for caching data */ +#define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ +#define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ +#define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ + +#define PACKFILE_FLAG_WRITE 1 /* the file is being written */ +#define PACKFILE_FLAG_PACK 2 /* data is compressed */ +#define PACKFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ +#define PACKFILE_FLAG_EOF 8 /* reached the end-of-file */ +#define PACKFILE_FLAG_ERROR 16 /* an error has occurred */ +#define PACKFILE_FLAG_OLD_CRYPT 32 /* backward compatibility mode */ +#define PACKFILE_FLAG_EXEDAT 64 /* reading from our executable */ + + +typedef struct PACKFILE_VTABLE PACKFILE_VTABLE; +typedef struct PACKFILE PACKFILE; + +struct LZSS_PACK_DATA; +struct LZSS_UNPACK_DATA; + + +struct _al_normal_packfile_details +{ + int hndl; /* DOS file handle */ + int flags; /* PACKFILE_FLAG_* constants */ + unsigned char *buf_pos; /* position in buffer */ + int buf_size; /* number of bytes in the buffer */ + long todo; /* number of bytes still on the disk */ + struct PACKFILE *parent; /* nested, parent file */ + struct LZSS_PACK_DATA *pack_data; /* for LZSS compression */ + struct LZSS_UNPACK_DATA *unpack_data; /* for LZSS decompression */ + char *filename; /* name of the file */ + char *passdata; /* encryption key data */ + char *passpos; /* current key position */ + unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ +}; + + +struct PACKFILE /* our very own FILE structure... */ +{ + AL_CONST PACKFILE_VTABLE *vtable; + void *userdata; + int is_normal_packfile; + + /* The following is only to be used for the "normal" PACKFILE vtable, + * i.e. what is implemented by Allegro itself. If is_normal_packfile is + * false then the following is not even allocated. This must be the last + * member in the structure. + */ + struct _al_normal_packfile_details normal; +}; + + +struct PACKFILE_VTABLE +{ + AL_METHOD(int, pf_fclose, (void *userdata)); + AL_METHOD(int, pf_getc, (void *userdata)); + AL_METHOD(int, pf_ungetc, (int c, void *userdata)); + AL_METHOD(long, pf_fread, (void *p, long n, void *userdata)); + AL_METHOD(int, pf_putc, (int c, void *userdata)); + AL_METHOD(long, pf_fwrite, (AL_CONST void *p, long n, void *userdata)); + AL_METHOD(int, pf_fseek, (void *userdata, int offset)); + AL_METHOD(int, pf_feof, (void *userdata)); + AL_METHOD(int, pf_ferror, (void *userdata)); +}; + + +#define uconvert_tofilename(s, buf) uconvert(s, U_CURRENT, buf, get_file_encoding(), sizeof(buf)) + +AL_FUNC(void, set_file_encoding, (int encoding)); +AL_FUNC(int, get_file_encoding, (void)); + +AL_FUNC(void, packfile_password, (AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen, (AL_CONST char *filename, AL_CONST char *mode)); +AL_FUNC(PACKFILE *, pack_fopen_password, (AL_CONST char *filename, AL_CONST char *mode, AL_CONST char *password)); +AL_FUNC(PACKFILE *, pack_fopen_vtable, (AL_CONST PACKFILE_VTABLE *vtable, void *userdata)); +AL_FUNC(int, pack_fclose, (PACKFILE *f)); +AL_FUNC(int, pack_fseek, (PACKFILE *f, int offset)); +AL_FUNC(PACKFILE *, pack_fopen_chunk, (PACKFILE *f, int pack)); +AL_FUNC(PACKFILE *, pack_fclose_chunk, (PACKFILE *f)); +AL_FUNC(int, pack_getc, (PACKFILE *f)); +AL_FUNC(int, pack_putc, (int c, PACKFILE *f)); +AL_FUNC(int, pack_feof, (PACKFILE *f)); +AL_FUNC(int, pack_ferror, (PACKFILE *f)); +AL_FUNC(int, pack_igetw, (PACKFILE *f)); +AL_FUNC(long, pack_igetl, (PACKFILE *f)); +AL_FUNC(int, pack_iputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_iputl, (long l, PACKFILE *f)); +AL_FUNC(int, pack_mgetw, (PACKFILE *f)); +AL_FUNC(long, pack_mgetl, (PACKFILE *f)); +AL_FUNC(int, pack_mputw, (int w, PACKFILE *f)); +AL_FUNC(long, pack_mputl, (long l, PACKFILE *f)); +AL_FUNC(long, pack_fread, (void *p, long n, PACKFILE *f)); +AL_FUNC(long, pack_fwrite, (AL_CONST void *p, long n, PACKFILE *f)); +AL_FUNC(int, pack_ungetc, (int c, PACKFILE *f)); +AL_FUNC(char *, pack_fgets, (char *p, int max, PACKFILE *f)); +AL_FUNC(int, pack_fputs, (AL_CONST char *p, PACKFILE *f)); +AL_FUNC(void *, pack_get_userdata, (PACKFILE *f)); + + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef ALLEGRO_FILE_H */ + + diff --git a/allegro/fixed/wwnd.c b/allegro/fixed/wwnd.c new file mode 100644 index 0000000000..b8d31a85ff --- /dev/null +++ b/allegro/fixed/wwnd.c @@ -0,0 +1,784 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Main window creation and management. + * + * By Stefan Schimanski. + * + * See readme.txt for copyright information. + */ + + +#include "allegro.h" +#include "allegro/internal/aintern.h" +#include "allegro/platform/aintwin.h" +#include "wddraw.h" + +#ifndef SCAN_DEPEND + #include + #include + #include +#endif + +#ifndef ALLEGRO_WINDOWS + #error something is wrong with the makefile +#endif + +#define PREFIX_I "al-wwnd INFO: " +#define PREFIX_W "al-wwnd WARNING: " +#define PREFIX_E "al-wwnd ERROR: " + + +/* general */ +static HWND allegro_wnd = NULL; +char wnd_title[WND_TITLE_SIZE]; /* ASCII string */ +int wnd_x = 0; +int wnd_y = 0; +int wnd_width = 0; +int wnd_height = 0; +int wnd_sysmenu = FALSE; + +static int last_wnd_x = -1; +static int last_wnd_y = -1; + +static int window_is_initialized = FALSE; + +/* graphics */ +WIN_GFX_DRIVER *win_gfx_driver; +CRITICAL_SECTION gfx_crit_sect; +int gfx_crit_sect_nesting = 0; + +/* close button user hook */ +void (*user_close_proc)(void) = NULL; + +/* window thread internals */ +#define ALLEGRO_WND_CLASS "AllegroWindow" +static HWND user_wnd = NULL; +static WNDPROC user_wnd_proc = NULL; +static HANDLE wnd_thread = NULL; +static HWND (*wnd_create_proc)(WNDPROC) = NULL; +static int old_style = 0; + +/* custom window msgs */ +#define SWITCH_TIMER 1 +static UINT msg_call_proc = 0; +static UINT msg_suicide = 0; + +/* window modules management */ +struct WINDOW_MODULES { + int keyboard; + int mouse; + int joystick; + int joy_type; + int sound; + int digi_card; + int midi_card; + int sound_input; + int digi_input_card; + int midi_input_card; +}; + +/* Used in adjust_window(). */ +#ifndef CCHILDREN_TITLEBAR + #define CCHILDREN_TITLEBAR 5 +typedef struct { + DWORD cbSize; + RECT rcTitleBar; + DWORD rgstate[CCHILDREN_TITLEBAR + 1]; +} TITLEBARINFO, *PTITLEBARINFO, *LPTITLEBARINFO; +#endif /* ifndef CCHILDREN_TITLEBAR */ + + + +/* init_window_modules: + * Initialises the modules that are specified by the WM argument. + */ +static int init_window_modules(struct WINDOW_MODULES *wm) +{ + if (wm->keyboard) + install_keyboard(); + + if (wm->mouse) + install_mouse(); + + if (wm->joystick) + install_joystick(wm->joy_type); + + if (wm->sound) + install_sound(wm->digi_card, wm->midi_card, NULL); + + if (wm->sound_input) + install_sound_input(wm->digi_input_card, wm->midi_input_card); + + return 0; +} + + + +/* exit_window_modules: + * Removes the modules that depend upon the main window: + * - keyboard (DirectInput), + * - mouse (DirectInput), + * - joystick (DirectInput), + * - sound (DirectSound), + * - sound input (DirectSoundCapture). + * If WM is not NULL, record which modules are really removed. + */ +static void exit_window_modules(struct WINDOW_MODULES *wm) +{ + if (wm) + memset(wm, 0, sizeof(*wm)); + + if (_keyboard_installed) { + if (wm) + wm->keyboard = TRUE; + + remove_keyboard(); + } + + if (_mouse_installed) { + if (wm) + wm->mouse = TRUE; + + remove_mouse(); + } + + if (_joystick_installed) { + if (wm) { + wm->joystick = TRUE; + wm->joy_type = _joy_type; + } + + remove_joystick(); + } + + if (_sound_installed) { + if (wm) { + wm->sound = TRUE; + wm->digi_card = digi_card; + wm->midi_card = midi_card; + } + + remove_sound(); + } + + if (_sound_input_installed) { + if (wm) { + wm->sound_input = TRUE; + wm->digi_input_card = digi_input_card; + wm->midi_input_card = midi_input_card; + } + + remove_sound_input(); + } +} + + + +/* wnd_call_proc: + * Instructs the window thread to call the specified procedure and + * waits until the procedure has returned. + */ +int wnd_call_proc(int (*proc) (void)) +{ + return SendMessage(allegro_wnd, msg_call_proc, (DWORD) proc, 0); +} + + + +/* wnd_schedule_proc: + * Instructs the window thread to call the specified procedure but + * doesn't wait until the procedure has returned. + */ +void wnd_schedule_proc(int (*proc) (void)) +{ + PostMessage(allegro_wnd, msg_call_proc, (DWORD) proc, 0); +} + + + +/* directx_wnd_proc: + * Window procedure for the Allegro window class. + */ +static LRESULT CALLBACK directx_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) +{ + PAINTSTRUCT ps; + + if (message == msg_call_proc) + return ((int (*)(void))wparam) (); + + if (message == msg_suicide) { + DestroyWindow(wnd); + return 0; + } + + /* See get_reverse_mapping() in wkeybd.c to see what this is for. */ + if (FALSE && (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)) { + static char name[256]; + TCHAR str[256]; + WCHAR wstr[256]; + + GetKeyNameText(lparam, str, sizeof str); + MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, sizeof wstr); + uconvert((char *)wstr, U_UNICODE, name, U_CURRENT, sizeof name); + _TRACE(PREFIX_I" key[%s] = 0x%08lx;\n", name, lparam & 0x1ff0000); + } + + switch (message) { + + case WM_CREATE: + if (!user_wnd_proc) + allegro_wnd = wnd; + break; + + case WM_DESTROY: + if (user_wnd_proc) { + exit_window_modules(NULL); + _win_reset_switch_mode(); + } + else { + PostQuitMessage(0); + } + + allegro_wnd = NULL; + break; + + case WM_SETCURSOR: + if (!user_wnd_proc || _mouse_installed) { + mouse_set_syscursor(); + return 1; /* not TRUE */ + } + break; + + case WM_ACTIVATE: + if (LOWORD(wparam) == WA_INACTIVE) { + _win_switch_out(); + } + else { + /* Ignore the WM_ACTIVATE event if the window is minimized. */ + if (HIWORD(wparam)) + break; + + if (gfx_driver && !gfx_driver->windowed) { + /* 1.2s delay to let Windows complete the switch in fullscreen mode */ + SetTimer(allegro_wnd, SWITCH_TIMER, 1200, NULL); + } + else { + /* no delay in windowed mode */ + _win_switch_in(); + } + } + break; + + case WM_TIMER: + if (wparam == SWITCH_TIMER) { + KillTimer(allegro_wnd, SWITCH_TIMER); + _win_switch_in(); + return 0; + } + break; + + case WM_ENTERSIZEMOVE: + if (win_gfx_driver && win_gfx_driver->enter_sysmode) + win_gfx_driver->enter_sysmode(); + break; + + case WM_EXITSIZEMOVE: + if (win_gfx_driver && win_gfx_driver->exit_sysmode) + win_gfx_driver->exit_sysmode(); + break; + + case WM_MOVE: + if (GetActiveWindow() == allegro_wnd) { + if (!IsIconic(allegro_wnd)) { + wnd_x = (short) LOWORD(lparam); + wnd_y = (short) HIWORD(lparam); + + if (win_gfx_driver && win_gfx_driver->move) + win_gfx_driver->move(wnd_x, wnd_y, wnd_width, wnd_height); + } + else if (win_gfx_driver && win_gfx_driver->iconify) { + win_gfx_driver->iconify(); + } + } + break; + + case WM_SIZE: + wnd_width = LOWORD(lparam); + wnd_height = HIWORD(lparam); + break; + + case WM_PAINT: + if (!user_wnd_proc || win_gfx_driver) { + BeginPaint(wnd, &ps); + if (win_gfx_driver && win_gfx_driver->paint) + win_gfx_driver->paint(&ps.rcPaint); + EndPaint(wnd, &ps); + return 0; + } + break; + + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + /* Disable the default message-based key handler + * in order to prevent conflicts on NT kernels. + */ + if (!user_wnd_proc || _keyboard_installed) + return 0; + break; + + case WM_SYSCOMMAND: + if (wparam == SC_MONITORPOWER || wparam == SC_SCREENSAVE) { + if (_screensaver_policy == ALWAYS_DISABLED + || (_screensaver_policy == FULLSCREEN_DISABLED + && gfx_driver && !gfx_driver->windowed)) + return 0; + } + break; + + case WM_INITMENUPOPUP: + wnd_sysmenu = TRUE; + mouse_set_sysmenu(TRUE); + + if (win_gfx_driver && win_gfx_driver->enter_sysmode) + win_gfx_driver->enter_sysmode(); + break; + + case WM_MENUSELECT: + if ((HIWORD(wparam) == 0xFFFF) && (!lparam)) { + wnd_sysmenu = FALSE; + mouse_set_sysmenu(FALSE); + + if (win_gfx_driver && win_gfx_driver->exit_sysmode) + win_gfx_driver->exit_sysmode(); + } + break; + + case WM_MENUCHAR : + return (MNC_CLOSE<<16)|(wparam&0xffff); + + case WM_CLOSE: + if (!user_wnd_proc) { + if (user_close_proc) + (*user_close_proc)(); + return 0; + } + break; + + case WM_QUERYNEWPALETTE: + case WM_PALETTECHANGED: + if ((HWND)wparam != wnd && gfx_directx_primary_surface) { + IDirectDrawSurface2_SetPalette(gfx_directx_primary_surface->id, ddpalette); + InvalidateRect(wnd, NULL, 1); + } + return 1; + } + + /* pass message to default window proc */ + if (user_wnd_proc) + return CallWindowProc(user_wnd_proc, wnd, message, wparam, lparam); + else + return DefWindowProc(wnd, message, wparam, lparam); +} + + + +/* create_directx_window: + * Creates the Allegro window. + */ +static HWND create_directx_window(void) +{ + static int first = 1; + WNDCLASS wnd_class; + char fname[1024]; + HWND wnd; + + if (first) { + /* setup the window class */ + wnd_class.style = CS_HREDRAW | CS_VREDRAW; + wnd_class.lpfnWndProc = directx_wnd_proc; + wnd_class.cbClsExtra = 0; + wnd_class.cbWndExtra = 0; + wnd_class.hInstance = allegro_inst; + wnd_class.hIcon = LoadIcon(allegro_inst, "allegro_icon"); + if (!wnd_class.hIcon) + wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW); + wnd_class.hbrBackground = NULL; + wnd_class.lpszMenuName = NULL; + wnd_class.lpszClassName = ALLEGRO_WND_CLASS; + + RegisterClass(&wnd_class); + + /* what are we called? */ + get_executable_name(fname, sizeof(fname)); + ustrlwr(fname); + + usetc(get_extension(fname), 0); + if (ugetat(fname, -1) == '.') + usetat(fname, -1, 0); + + do_uconvert(get_filename(fname), U_CURRENT, wnd_title, U_ASCII, WND_TITLE_SIZE); + + first = 0; + } + + /* create the window now */ + wnd = CreateWindowEx(WS_EX_APPWINDOW, ALLEGRO_WND_CLASS, wnd_title, + WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX, + -100, -100, 0, 0, + NULL, NULL, allegro_inst, NULL); + if (!wnd) { + _TRACE(PREFIX_E "CreateWindowEx() failed (%s)\n", win_err_str(GetLastError())); + return NULL; + } + + SetSystemPaletteUse(GetDC(wnd), SYSPAL_NOSTATIC256); + ShowWindow(wnd, SW_SHOWNORMAL); + SetForegroundWindow(wnd); + UpdateWindow(wnd); + + return wnd; +} + + + +/* wnd_thread_proc: + * Thread function that handles the messages of the directx window. + */ +static void wnd_thread_proc(HANDLE setup_event) +{ + int result; + MSG msg; + + _win_thread_init(); + _TRACE(PREFIX_I "window thread starts\n"); + + /* setup window */ + if (wnd_create_proc) + allegro_wnd = wnd_create_proc(directx_wnd_proc); + else + allegro_wnd = create_directx_window(); + + if (!allegro_wnd) + goto End; + + /* now the thread it running successfully, let's acknowledge */ + SetEvent(setup_event); + + /* message loop */ + while (TRUE) { + result = MsgWaitForMultipleObjects(_win_input_events, _win_input_event_id, FALSE, INFINITE, QS_ALLINPUT); + if ((result >= WAIT_OBJECT_0) && (result < WAIT_OBJECT_0 + _win_input_events)) { + /* one of the registered events is in signaled state */ + (*_win_input_event_handler[result - WAIT_OBJECT_0])(); + } + else if (result == WAIT_OBJECT_0 + _win_input_events) { + /* messages are waiting in the queue */ + while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if (GetMessage(&msg, NULL, 0, 0)) { + DispatchMessage(&msg); + } + else { + goto End; + } + } + } + } + + End: + _TRACE(PREFIX_I "window thread exits\n"); + _win_thread_exit(); +} + + + +/* init_directx_window: + * If the user called win_set_window, the user window will be hooked to receive + * messages from Allegro. Otherwise a thread is created to own the new window. + */ +int init_directx_window(void) +{ + union { + POINT p; + RECT r; + } win_rect; + HANDLE events[2]; + long result; + + /* setup globals */ + msg_call_proc = RegisterWindowMessage("Allegro call proc"); + msg_suicide = RegisterWindowMessage("Allegro window suicide"); + + if (user_wnd) { + /* initializes input module and requests dedicated thread */ + _win_input_init(TRUE); + + /* hook the user window */ + user_wnd_proc = (WNDPROC) SetWindowLong(user_wnd, GWL_WNDPROC, (long)directx_wnd_proc); + if (!user_wnd_proc) + return -1; + + allegro_wnd = user_wnd; + + /* retrieve the window dimensions */ + GetWindowRect(allegro_wnd, &win_rect.r); + ClientToScreen(allegro_wnd, &win_rect.p); + ClientToScreen(allegro_wnd, &win_rect.p + 1); + wnd_x = win_rect.r.left; + wnd_y = win_rect.r.top; + wnd_width = win_rect.r.right - win_rect.r.left; + wnd_height = win_rect.r.bottom - win_rect.r.top; + } + else { + /* initializes input module without dedicated thread */ + _win_input_init(FALSE); + + /* create window thread */ + events[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* acknowledges that thread is up */ + events[1] = (HANDLE) _beginthread(wnd_thread_proc, 0, events[0]); + result = WaitForMultipleObjects(2, events, FALSE, INFINITE); + + CloseHandle(events[0]); + + switch (result) { + case WAIT_OBJECT_0: /* window was created successfully */ + wnd_thread = events[1]; + SetThreadPriority(wnd_thread, THREAD_PRIORITY_ABOVE_NORMAL); + break; + + default: /* thread failed to create window */ + return -1; + } + } + + /* initialize gfx critical section */ + InitializeCriticalSection(&gfx_crit_sect); + + /* save window style */ + old_style = GetWindowLong(allegro_wnd, GWL_STYLE); + + return 0; +} + + + +/* exit_directx_window: + * If a user window was hooked, the old window proc is set. Otherwise + * the window thread is destroyed. + */ +void exit_directx_window(void) +{ + if (user_wnd) { + /* restore old window proc */ + SetWindowLong(user_wnd, GWL_WNDPROC, (long)user_wnd_proc); + user_wnd_proc = NULL; + user_wnd = NULL; + allegro_wnd = NULL; + } + else { + /* Destroy the window: we cannot directly use DestroyWindow() because + * we are not running in the same thread as that of the window. + */ + PostMessage(allegro_wnd, msg_suicide, 0, 0); + + /* wait until the window thread ends */ + WaitForSingleObject(wnd_thread, INFINITE); + wnd_thread = NULL; + } + + DeleteCriticalSection(&gfx_crit_sect); + + _win_input_exit(); + + window_is_initialized = FALSE; +} + + + +/* restore_window_style: + * Restores the previous style of the window. + */ +void restore_window_style(void) +{ + SetWindowLong(allegro_wnd, GWL_STYLE, old_style); + SetWindowPos(allegro_wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); +} + + + +/* adjust_window: + * Moves and resizes the window if we have full control over it. + */ +int adjust_window(int w, int h) +{ + RECT working_area, win_size; + TITLEBARINFO tb_info; + HMODULE user32_handle; + typedef BOOL (WINAPI *func)(HWND, PTITLEBARINFO); + func get_title_bar_info = NULL; + int tb_height = 0; + static int last_w=-1, last_h=-1; + + if (!user_wnd) { + SystemParametersInfo(SPI_GETWORKAREA, 0, &working_area, 0); + + if ((last_w == -1) && (last_h == -1)) { + /* first window placement: try to center it */ + last_wnd_x = (working_area.left + working_area.right - w)/2; + last_wnd_y = (working_area.top + working_area.bottom - h)/2; + } + else { + /* try to get the height of the window's title bar */ + user32_handle = GetModuleHandle("user32"); + if (user32_handle) { + get_title_bar_info + = (func)GetProcAddress(user32_handle, "GetTitleBarInfo"); + if (get_title_bar_info) { + tb_info.cbSize = sizeof(TITLEBARINFO); + if (get_title_bar_info(allegro_wnd, &tb_info)) + tb_height + = tb_info.rcTitleBar.bottom - tb_info.rcTitleBar.top; + } + } + if (!user32_handle || !get_title_bar_info) + tb_height = GetSystemMetrics(SM_CYSIZE); + + /* try to center the window relative to its last position */ + last_wnd_x += (last_w - w)/2; + last_wnd_y += (last_h - h)/2; + + if (last_wnd_x + w >= working_area.right) + last_wnd_x = working_area.right - w; + if (last_wnd_y + h >= working_area.bottom) + last_wnd_y = working_area.bottom - h; + if (last_wnd_x < working_area.left) + last_wnd_x = working_area.left; + if (last_wnd_y - tb_height < working_area.top) + last_wnd_y = working_area.top + tb_height; + } + +#ifdef ALLEGRO_COLORCONV_ALIGNED_WIDTH + last_wnd_x &= 0xfffffffc; +#endif + + win_size.left = last_wnd_x; + win_size.top = last_wnd_y; + win_size.right = last_wnd_x+w; + win_size.bottom = last_wnd_y+h; + + last_w = w; + last_h = h; + + /* retrieve the size of the decorated window */ + AdjustWindowRect(&win_size, GetWindowLong(allegro_wnd, GWL_STYLE), FALSE); + + /* display the window */ + MoveWindow(allegro_wnd, win_size.left, win_size.top, + win_size.right - win_size.left, win_size.bottom - win_size.top, TRUE); + + /* check that the actual window size is the one requested */ + GetClientRect(allegro_wnd, &win_size); + if (((win_size.right - win_size.left) != w) || ((win_size.bottom - win_size.top) != h)) + return -1; + + wnd_x = last_wnd_x; + wnd_y = last_wnd_y; + wnd_width = w; + wnd_height = h; + } + + return 0; +} + + + +/* save_window_pos: + * Stores the position of the current window before closing it so that + * it can be used as the initial position for the next window. + */ +void save_window_pos(void) +{ + last_wnd_x = wnd_x; + last_wnd_y = wnd_y; +} + + + +/* win_set_window: + * Selects an user-defined window for Allegro or + * the built-in window if NULL is passed. + */ +void win_set_window(HWND wnd) +{ + static int (*saved_scbc)(void (*proc)(void)) = NULL; + struct WINDOW_MODULES wm; + + if (window_is_initialized || !wnd) { + exit_window_modules(&wm); + exit_directx_window(); + } + + user_wnd = wnd; + + /* The user retains full control over the close button if he registers + a user-defined window. */ + if (user_wnd) { + if (!saved_scbc) + saved_scbc = system_directx.set_close_button_callback; + + system_directx.set_close_button_callback = NULL; + } + else { + if (saved_scbc) + system_directx.set_close_button_callback = saved_scbc; + } + + if (window_is_initialized || !wnd) { + init_directx_window(); + init_window_modules(&wm); + } + + window_is_initialized = TRUE; +} + + + +/* win_get_window: + * Returns the Allegro window handle. + */ +HWND win_get_window(void) +{ + return allegro_wnd; +} + + + +/* win_set_wnd_create_proc: + * Sets a custom window creation proc. + */ +void win_set_wnd_create_proc(HWND (*proc)(WNDPROC)) +{ + wnd_create_proc = proc; +} + + + +/* win_grab_input: + * Grabs the input devices. + */ +void win_grab_input(void) +{ + wnd_schedule_proc(key_dinput_acquire); + wnd_schedule_proc(mouse_dinput_grab); + wnd_schedule_proc(joystick_dinput_acquire); +} diff --git a/allegro/winalleg.h b/allegro/winalleg.h new file mode 100644 index 0000000000..b422a84258 --- /dev/null +++ b/allegro/winalleg.h @@ -0,0 +1,117 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Windows header file for the Allegro library. + * + * It must be included by Allegro programs that need to use + * direct Win32 API calls and by Win32 programs that need to + * interface with Allegro. + * + * By Shawn Hargreaves. + * + * See readme.txt for copyright information. + */ + + +#ifndef WIN_ALLEGRO_H +#define WIN_ALLEGRO_H + +#ifndef ALLEGRO_H + #error Please include allegro.h before winalleg.h! +#endif + +#ifdef ALLEGRO_SRC + #define WIN32_LEAN_AND_MEAN /* to save compilation time */ +#endif + + + +/* bodges to avoid conflicts between Allegro and Windows */ +#define BITMAP WINDOWS_BITMAP + +#if (!defined SCAN_EXPORT) && (!defined SCAN_DEPEND) + #ifdef ALLEGRO_AND_MFC + #ifdef DEBUGMODE + #define AL_ASSERT(condition) { if (!(condition)) al_assert(__FILE__, __LINE__); } + #define AL_TRACE al_trace + #else + #define AL_ASSERT(condition) + #define AL_TRACE 1 ? (void) 0 : al_trace + #endif + + #undef TRACE + #undef ASSERT + + #include + #else + #include + #endif +#endif + +#define WINDOWS_RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16))) + +#undef BITMAP +#undef RGB + + + +/* Allegro's Win32 specific interface */ +#ifdef __cplusplus + extern "C" { +#endif + + +/* external graphics driver support */ +typedef struct WIN_GFX_DRIVER { + int has_backing_store; + AL_METHOD(void, switch_in, (void)); + AL_METHOD(void, switch_out, (void)); + AL_METHOD(void, enter_sysmode, (void)); + AL_METHOD(void, exit_sysmode, (void)); + AL_METHOD(void, move, (int x, int y, int w, int h)); + AL_METHOD(void, iconify, (void)); + AL_METHOD(void, paint, (RECT *rect)); +} WIN_GFX_DRIVER; + +AL_VAR(WIN_GFX_DRIVER *, win_gfx_driver); + +AL_FUNC(void, win_grab_input, (void)); + + +/* external window support */ +AL_FUNC(HWND, win_get_window, (void)); +AL_FUNC(void, win_set_window, (HWND wnd)); +AL_FUNC(void, win_set_wnd_create_proc, (AL_METHOD(HWND, proc, (WNDPROC)))); + + +/* GDI to DirectDraw routines */ +AL_FUNC(HDC, win_get_dc, (BITMAP *bmp)); +AL_FUNC(void, win_release_dc, (BITMAP *bmp, HDC dc)); + + +/* GDI routines */ +AL_FUNC(void, set_gdi_color_format, (void)); +AL_FUNC(void, set_palette_to_hdc, (HDC dc, PALETTE pal)); +AL_FUNC(HPALETTE, convert_palette_to_hpalette, (PALETTE pal)); +AL_FUNC(void, convert_hpalette_to_palette, (HPALETTE hpal, PALETTE pal)); +AL_FUNC(HBITMAP, convert_bitmap_to_hbitmap, (BITMAP *bitmap)); +AL_FUNC(BITMAP *, convert_hbitmap_to_bitmap, (HBITMAP bitmap)); +AL_FUNC(void, draw_to_hdc, (HDC dc, BITMAP *bitmap, int x, int y)); +AL_FUNC(void, blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); +AL_FUNC(void, stretch_blit_to_hdc, (BITMAP *bitmap, HDC dc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); +AL_FUNC(void, blit_from_hdc, (HDC dc, BITMAP *bitmap, int src_x, int src_y, int dest_x, int dest_y, int w, int h)); +AL_FUNC(void, stretch_blit_from_hdc, (HDC hdc, BITMAP *bitmap, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h)); + + +#ifdef __cplusplus + } +#endif + +#endif /* ifndef WIN_ALLEGRO_H */ diff --git a/bin/win32/alleg42.dll b/bin/win32/alleg42.dll new file mode 100644 index 0000000000..d6cddeaf20 Binary files /dev/null and b/bin/win32/alleg42.dll differ diff --git a/bin/win32/zcsound.dll b/bin/win32/zcsound.dll new file mode 100644 index 0000000000..0761a41e75 Binary files /dev/null and b/bin/win32/zcsound.dll differ diff --git a/build-final b/build-final new file mode 100644 index 0000000000..ffbf0f0728 --- /dev/null +++ b/build-final @@ -0,0 +1,44 @@ +#!/bin/bash +# +# Let's get this bad boy.. +# Welcome to the Mac OS X installer script for Zelda Classic +#do some basic stuff +#echo "Input password for gcc_select 4.0" +#sudo gcc_select 4.0 + +# start with the normal build. +make clean +make macosx +cp -R ZQuest\ Editor.app ZQuest\ Editor.app.bak +cp -R Zelda\ Classic.app Zelda\ Classic.app.bak +hdiutil create -type SPARSE -size 25m -fs HFS -volname ZC_N -attach ZC.dmg +sleep 3 +echo "Please Wait while your files are being copied" +mv -v ZQuest\ Editor.app /Volumes/ZC_N/ZQuest\ Editor.app +mv -v Zelda\ Classic.app /Volumes/ZC_N/Zelda\ Classic.app +hdiutil detach /Volumes/ZC_N/ +hdiutil convert ZC.dmg.sparseimage -format UDRO -o ZC-N.dmg +rm -Rf ZC.dmg.sparseimage +rm -Rf *.bak +tar -cjvf ZC-N.tar.bz2 ZC-N.dmg +rm -Rf ZC-N.dmg +#now for the older one, >_<; + +sudo gcc_select 3.3 +make clean +make macosx +cp -R ZQuest\ Editor.app ZQuest\ Editor.app.bak +cp -R Zelda\ Classic.app Zelda\ Classic.app.bak +hdiutil create -type SPARSE -size 45m -fs HFS -volname ZC_O -attach ZC.dmg +sleep 3 +echo "Please Wait while your files are being copied" +mv -v ZQuest\ Editor.app /Volumes/ZC_O/ZQuest\ Editor.app +mv -v Zelda\ Classic.app /Volumes/ZC_O/Zelda\ Classic.app +hdiutil detach /Volumes/ZC_O/ +hdiutil convert ZC.dmg.sparseimage -format UDRO -o ZC-O.dmg +rm -Rf ZC.dmg.sparseimage +rm -Rf *.bak +tar -cjvf ZC-O.tar.bz2 ZC-O.dmg +rm -Rf ZC-O.dmg +sudo gcc_select 4.0 +make clean diff --git a/include/almp3/almp3.h b/include/almp3/almp3.h new file mode 100644 index 0000000000..a45a574b83 --- /dev/null +++ b/include/almp3/almp3.h @@ -0,0 +1,155 @@ +/* Allegro MP3 - a wrapper for mpglib from mpg123 */ +/* to play MP3 files with Allegro */ + +/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ +/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ + +/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ + + +#ifndef ALMP3_H +#define ALMP3_H + + +#include + +#include "almp3dll.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* common define */ + +#define ALMP3_MAJOR_VERSION 2 +#define ALMP3_MINOR_VERSION 0 +#define ALMP3_SUB_VERSION 4 +#define ALMP3_VERSION_STR "2.0.4" +#define ALMP3_DATE_STR "08/04/2003" +#define ALMP3_DATE 20030408 /* yyyymmdd */ + +/* error codes */ + +#define ALMP3_OK 0 + +#define ALMP3_PLAY_BUFFERTOOSMALL -1 + +#define ALMP3_POLL_PLAYJUSTFINISHED 1 +#define ALMP3_POLL_NOTPLAYING -1 +#define ALMP3_POLL_FRAMECORRUPT -2 +#define ALMP3_POLL_BUFFERUNDERRUN -3 +#define ALMP3_POLL_INTERNALERROR -4 + + +/* API - MP3 */ + +typedef struct ALMP3_MP3 ALMP3_MP3; + + +ALMP3_DLL_DECLSPEC ALMP3_MP3 *almp3_create_mp3(void *data, int data_len); +ALMP3_DLL_DECLSPEC void almp3_destroy_mp3(ALMP3_MP3 *mp3); + +ALMP3_DLL_DECLSPEC int almp3_play_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan); +ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3(ALMP3_MP3 *mp3, int buffer_len, int vol, int pan, int speed, int loop); +ALMP3_DLL_DECLSPEC void almp3_stop_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC void almp3_rewind_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC void almp3_seek_abs_frames_mp3(ALMP3_MP3 *mp3, int frame); +ALMP3_DLL_DECLSPEC void almp3_seek_abs_msecs_mp3(ALMP3_MP3 *mp3, int msecs); +ALMP3_DLL_DECLSPEC void almp3_seek_abs_secs_mp3(ALMP3_MP3 *mp3, int secs); +ALMP3_DLL_DECLSPEC void almp3_seek_abs_bytes_mp3(ALMP3_MP3 *mp3, int bytes); +ALMP3_DLL_DECLSPEC void almp3_seek_rel_frames_mp3(ALMP3_MP3 *mp3, int frame); +ALMP3_DLL_DECLSPEC void almp3_seek_rel_msecs_mp3(ALMP3_MP3 *mp3, int msec); +ALMP3_DLL_DECLSPEC void almp3_seek_rel_secs_mp3(ALMP3_MP3 *mp3, int sec); +ALMP3_DLL_DECLSPEC void almp3_seek_rel_bytes_mp3(ALMP3_MP3 *mp3, int bytes); +ALMP3_DLL_DECLSPEC void almp3_adjust_mp3(ALMP3_MP3 *mp3, int vol, int pan, int speed, int loop); + +ALMP3_DLL_DECLSPEC int almp3_poll_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3(ALMP3_MP3 *mp3, int speed); +ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3(ALMP3_MP3 *mp3); + +ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3(ALMP3_MP3 *mp3); + +ALMP3_DLL_DECLSPEC SAMPLE *almp3_create_sample_from_mp3(ALMP3_MP3 *mp3); + +ALMP3_DLL_DECLSPEC void *almp3get_output_wave_mp3(ALMP3_MP3 *mp3, int *buffer_size); + +ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3(ALMP3_MP3 *mp3); +ALMP3_DLL_DECLSPEC int almp3_is_looping_mp3(ALMP3_MP3 *mp3); + +ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3(ALMP3_MP3 *mp3); + + + +/* API - MP3STREAM */ + +typedef struct ALMP3_MP3STREAM ALMP3_MP3STREAM; + + +ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream(void *first_data_buffer, int data_buffer_len, int last_block); +ALMP3_DLL_DECLSPEC ALMP3_MP3STREAM *almp3_create_mp3stream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); +ALMP3_DLL_DECLSPEC void almp3_destroy_mp3stream(ALMP3_MP3STREAM *mp3); + +ALMP3_DLL_DECLSPEC int almp3_play_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan); +ALMP3_DLL_DECLSPEC int almp3_play_ex_mp3stream(ALMP3_MP3STREAM *mp3, int buffer_len, int vol, int pan, int speed); +ALMP3_DLL_DECLSPEC void almp3_stop_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC void almp3_adjust_mp3stream(ALMP3_MP3STREAM *mp3, int vol, int pan, int speed); + +ALMP3_DLL_DECLSPEC int almp3_poll_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC void almp3_start_autopoll_mp3stream(ALMP3_MP3STREAM *mp3, int speed); +ALMP3_DLL_DECLSPEC void almp3_stop_autopoll_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC void *almp3_get_mp3stream_buffer(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC void almp3_free_mp3stream_buffer(ALMP3_MP3STREAM *mp3, int bytes_used); + +ALMP3_DLL_DECLSPEC int almp3_get_length_frames_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); +ALMP3_DLL_DECLSPEC int almp3_get_length_secs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); +ALMP3_DLL_DECLSPEC int almp3_get_length_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); +ALMP3_DLL_DECLSPEC int almp3_get_length_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int total_size); +ALMP3_DLL_DECLSPEC int almp3_get_pos_frames_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_msecs_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_secs_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_pos_bytes_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_msecs_per_frame_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_bitrate_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_layer_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_bits_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_is_stereo_mp3stream(ALMP3_MP3STREAM *mp3); +ALMP3_DLL_DECLSPEC int almp3_get_wave_freq_mp3stream(ALMP3_MP3STREAM *mp3); + +ALMP3_DLL_DECLSPEC void *almp3_get_output_wave_mp3stream(ALMP3_MP3STREAM *mp3, int *buffer_size); + +ALMP3_DLL_DECLSPEC int almp3_is_playing_mp3stream(ALMP3_MP3STREAM *mp3); + +ALMP3_DLL_DECLSPEC AUDIOSTREAM *almp3_get_audiostream_mp3stream(ALMP3_MP3STREAM *mp3); + +ALMP3_DLL_DECLSPEC int almp3_seek_abs_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_abs_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msecs, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_abs_secs_mp3stream(ALMP3_MP3STREAM *mp3, int secs, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_abs_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_rel_frames_mp3stream(ALMP3_MP3STREAM *mp3, int frame, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_rel_msecs_mp3stream(ALMP3_MP3STREAM *mp3, int msec, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_rel_secs_mp3stream(ALMP3_MP3STREAM *mp3, int sec, int total_size); +ALMP3_DLL_DECLSPEC int almp3_seek_rel_bytes_mp3stream(ALMP3_MP3STREAM *mp3, int bytes, int total_size); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/almp3/almp3dll.h b/include/almp3/almp3dll.h new file mode 100644 index 0000000000..a69c03f66a --- /dev/null +++ b/include/almp3/almp3dll.h @@ -0,0 +1,20 @@ +/* Allegro MP3 - a wrapper for mpglib from mpg123 */ +/* to play MP3 files with Allegro */ + +/* MP3 decoder part of mpglib from mpg123 (www.mpg123.com) */ +/* Allegro MP3 is copyright (c) 2001, 2002 Javier Gonz lez */ + +/* See COPYING.txt (GNU Lesser General Public License 2.1) for license */ + + +#ifndef ALMP3_DLL_DECLSPEC +# ifdef ALMP3_DLL +# ifdef ALMP3_DLL_EXPORTS +# define ALMP3_DLL_DECLSPEC __declspec(dllexport) +# else +# define ALMP3_DLL_DECLSPEC __declspec(dllimport) +# endif +# else +# define ALMP3_DLL_DECLSPEC +# endif +#endif diff --git a/include/alogg/alogg.h b/include/alogg/alogg.h new file mode 100644 index 0000000000..33aea48263 --- /dev/null +++ b/include/alogg/alogg.h @@ -0,0 +1,141 @@ +/* Allegro OGG */ +/* to play OGG files with Allegro */ + +/* OGG decoder part ofOgg Vorbis (Xiph.org Foundation) */ +/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ + +/* See COPYING.txt for license */ + + +#ifndef ALOGG_H +#define ALOGG_H + + +#include +#include + +#include "aloggdll.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* common define */ + +#define ALOGG_MAJOR_VERSION 1 +#define ALOGG_MINOR_VERSION 0 +#define ALOGG_SUB_VERSION 3 +#define ALOGG_VERSION_STR "1.0.3" +#define ALOGG_DATE_STR "15/10/2002" +#define ALOGG_DATE 20021015 /* yyyymmdd */ + +/* error codes */ + +#define ALOGG_OK 0 + +#define ALOGG_PLAY_BUFFERTOOSMALL -1 + +#define ALOGG_POLL_PLAYJUSTFINISHED 1 +#define ALOGG_POLL_NOTPLAYING -1 +#define ALOGG_POLL_FRAMECORRUPT -2 +#define ALOGG_POLL_BUFFERUNDERRUN -3 +#define ALOGG_POLL_INTERNALERROR -4 + + +/* API - OGG */ + +typedef struct ALOGG_OGG ALOGG_OGG; + + +ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_buffer(void *data, int data_len); +ALOGG_DLL_DECLSPEC ALOGG_OGG *alogg_create_ogg_from_file(FILE *f); +ALOGG_DLL_DECLSPEC void alogg_destroy_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC int alogg_play_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan); +ALOGG_DLL_DECLSPEC int alogg_play_ex_ogg(ALOGG_OGG *ogg, int buffer_len, int vol, int pan, int speed, int loop); +ALOGG_DLL_DECLSPEC void alogg_stop_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC void alogg_adjust_ogg(ALOGG_OGG *ogg, int vol, int pan, int speed, int loop); + +ALOGG_DLL_DECLSPEC void alogg_rewind_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC void alogg_seek_abs_msecs_ogg(ALOGG_OGG *ogg, int msecs); +ALOGG_DLL_DECLSPEC void alogg_seek_abs_secs_ogg(ALOGG_OGG *ogg, int secs); +ALOGG_DLL_DECLSPEC void alogg_seek_abs_bytes_ogg(ALOGG_OGG *ogg, int bytes); +ALOGG_DLL_DECLSPEC void alogg_seek_rel_msecs_ogg(ALOGG_OGG *ogg, int msec); +ALOGG_DLL_DECLSPEC void alogg_seek_rel_secs_ogg(ALOGG_OGG *ogg, int sec); +ALOGG_DLL_DECLSPEC void alogg_seek_rel_bytes_ogg(ALOGG_OGG *ogg, int bytes); + +ALOGG_DLL_DECLSPEC int alogg_poll_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC void alogg_start_autopoll_ogg(ALOGG_OGG *ogg, int speed); +ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC int alogg_get_length_secs_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_length_msecs_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_length_bytes_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC int alogg_get_bitrate_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC SAMPLE *alogg_create_sample_from_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC void *aloggget_output_wave_ogg(ALOGG_OGG *ogg, int *buffer_size); + +ALOGG_DLL_DECLSPEC int alogg_is_playing_ogg(ALOGG_OGG *ogg); +ALOGG_DLL_DECLSPEC int alogg_is_looping_ogg(ALOGG_OGG *ogg); + +ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_ogg(ALOGG_OGG *ogg); + + + +/* API - OGGSTREAM */ + +typedef struct ALOGG_OGGSTREAM ALOGG_OGGSTREAM; + + +ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream(void *first_data_buffer, int data_buffer_len, int last_block); +ALOGG_DLL_DECLSPEC ALOGG_OGGSTREAM *alogg_create_oggstream_ex(void *first_data_buffer, int data_buffer_len, int last_block, int downsample, int downmix); +ALOGG_DLL_DECLSPEC void alogg_destroy_oggstream(ALOGG_OGGSTREAM *ogg); + +ALOGG_DLL_DECLSPEC int alogg_play_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan); +ALOGG_DLL_DECLSPEC int alogg_play_ex_oggstream(ALOGG_OGGSTREAM *ogg, int buffer_len, int vol, int pan, int speed); +ALOGG_DLL_DECLSPEC void alogg_stop_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC void alogg_adjust_oggstream(ALOGG_OGGSTREAM *ogg, int vol, int pan, int speed); + +ALOGG_DLL_DECLSPEC int alogg_poll_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC void alogg_start_autopoll_oggstream(ALOGG_OGGSTREAM *ogg, int speed); +ALOGG_DLL_DECLSPEC void alogg_stop_autopoll_oggstream(ALOGG_OGGSTREAM *ogg); + +ALOGG_DLL_DECLSPEC void *alogg_get_oggstream_buffer(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC void alogg_free_oggstream_buffer(ALOGG_OGGSTREAM *ogg, int bytes_used); + +ALOGG_DLL_DECLSPEC int alogg_get_pos_msecs_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_pos_secs_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_pos_bytes_oggstream(ALOGG_OGGSTREAM *ogg); + +ALOGG_DLL_DECLSPEC int alogg_get_bitrate_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_bits_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_is_stereo_oggstream(ALOGG_OGGSTREAM *ogg); +ALOGG_DLL_DECLSPEC int alogg_get_wave_freq_oggstream(ALOGG_OGGSTREAM *ogg); + +ALOGG_DLL_DECLSPEC void *alogg_get_output_wave_oggstream(ALOGG_OGGSTREAM *ogg, int *buffer_size); + +ALOGG_DLL_DECLSPEC int alogg_is_playing_oggstream(ALOGG_OGGSTREAM *ogg); + +ALOGG_DLL_DECLSPEC AUDIOSTREAM *alogg_get_audiostream_oggstream(ALOGG_OGGSTREAM *ogg); + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/alogg/aloggdll.h b/include/alogg/aloggdll.h new file mode 100644 index 0000000000..2a417de229 --- /dev/null +++ b/include/alogg/aloggdll.h @@ -0,0 +1,20 @@ +/* Allegro OGG */ +/* to play OGG files with Allegro */ + +/* OGG decoder part of Ogg Vorbis (Xiph.org Foundation) */ +/* Allegro OGG is copyright (c) 2002 Javier Gonz lez */ + +/* See COPYING.txt for license */ + + +#ifndef ALOGG_DLL_DECLSPEC +# ifdef ALOGG_DLL +# ifdef ALOGG_DLL_EXPORTS +# define ALOGG_DLL_DECLSPEC __declspec(dllexport) +# else +# define ALOGG_DLL_DECLSPEC __declspec(dllimport) +# endif +# else +# define ALOGG_DLL_DECLSPEC +# endif +#endif diff --git a/include/dumb/aldumb.h b/include/dumb/aldumb.h new file mode 100644 index 0000000000..265c385df5 --- /dev/null +++ b/include/dumb/aldumb.h @@ -0,0 +1,98 @@ +/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * aldumb.h - The user header file for DUMB with / / \ \ + * Allegro. | < / \_ + * | \/ /\ / + * Include this file if you wish to use DUMB \_ / > / + * with Allegro. It will include dumb.h for you, | \ / / + * and provide extra functionality such as audio | ' / + * stream and datafile integration. \__/ + */ + +#ifndef ALDUMB_H +#define ALDUMB_H + + +#include + +#include "dumb.h" + + +#ifdef __cplusplus + extern "C" { +#endif + + +/* Packfile Support */ + +void dumb_register_packfiles(void); + +DUMBFILE *dumbfile_open_packfile(PACKFILE *p); +DUMBFILE *dumbfile_from_packfile(PACKFILE *p); + + +/* Datafile Registration Functions */ + +#define DUMB_DAT_DUH DAT_ID('D','U','H',' ') +#define DUMB_DAT_IT DAT_ID('I','T',' ',' ') +#define DUMB_DAT_XM DAT_ID('X','M',' ',' ') +#define DUMB_DAT_S3M DAT_ID('S','3','M',' ') +#define DUMB_DAT_MOD DAT_ID('M','O','D',' ') + +void dumb_register_dat_duh(long type); +void dumb_register_dat_it(long type); +void dumb_register_dat_xm(long type); +void dumb_register_dat_s3m(long type); +void dumb_register_dat_mod(long type); +void dumb_register_dat_it_quick(long type); +void dumb_register_dat_xm_quick(long type); +void dumb_register_dat_s3m_quick(long type); +void dumb_register_dat_mod_quick(long type); + + +/* DUH Playing Functions */ + +typedef struct AL_DUH_PLAYER AL_DUH_PLAYER; + +AL_DUH_PLAYER *al_start_duh(DUH *duh, int n_channels, long pos, float volume, long bufsize, int freq); +void al_stop_duh(AL_DUH_PLAYER *dp); +void al_pause_duh(AL_DUH_PLAYER *dp); +void al_resume_duh(AL_DUH_PLAYER *dp); +void al_duh_set_priority(AL_DUH_PLAYER *dp, int priority); +void al_duh_set_volume(AL_DUH_PLAYER *dp, float volume); +float al_duh_get_volume(AL_DUH_PLAYER *dp); +int al_poll_duh(AL_DUH_PLAYER *dp); +long al_duh_get_position(AL_DUH_PLAYER *dp); + +AL_DUH_PLAYER *al_duh_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer, float volume, long bufsize, int freq); +DUH_SIGRENDERER *al_duh_get_sigrenderer(AL_DUH_PLAYER *dp); + +/* IMPORTANT: This function will return NULL if the music has ended. */ +DUH_SIGRENDERER *al_duh_decompose_to_sigrenderer(AL_DUH_PLAYER *dp); + +#ifdef DUMB_DECLARE_DEPRECATED + +AL_DUH_PLAYER *al_duh_encapsulate_renderer(DUH_SIGRENDERER *dr, float volume, long bufsize, int freq) DUMB_DEPRECATED; +DUH_SIGRENDERER *al_duh_get_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; +DUH_SIGRENDERER *al_duh_decompose_to_renderer(AL_DUH_PLAYER *dp) DUMB_DEPRECATED; +/* Replace 'renderer' with 'sigrenderer' in each case where you called one of + * these functions. + */ + +#endif + + +#ifdef __cplusplus + } +#endif + + +#endif /* ALDUMB_H */ diff --git a/include/dumb/dumb.h b/include/dumb/dumb.h new file mode 100644 index 0000000000..06dd3bd8e5 --- /dev/null +++ b/include/dumb/dumb.h @@ -0,0 +1,687 @@ +/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * dumb.h - The user header file for DUMB. / / \ \ + * | < / \_ + * Include this file in any of your files in | \/ /\ / + * which you wish to use the DUMB functions \_ / > / + * and variables. | \ / / + * | ' / + * Allegro users, you will probably want aldumb.h. \__/ + */ + +#ifndef DUMB_H +#define DUMB_H + + +#include +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + +#define DUMB_MAJOR_VERSION 0 +#define DUMB_MINOR_VERSION 9 +#define DUMB_REVISION_VERSION 3 + +#define DUMB_VERSION (DUMB_MAJOR_VERSION*10000 + DUMB_MINOR_VERSION*100 + DUMB_REVISION_VERSION) + +#define DUMB_VERSION_STR "0.9.3" + +#define DUMB_NAME "DUMB v"DUMB_VERSION_STR + +#define DUMB_YEAR 2005 +#define DUMB_MONTH 8 +#define DUMB_DAY 7 + +#define DUMB_YEAR_STR2 "05" +#define DUMB_YEAR_STR4 "2005" +#define DUMB_MONTH_STR1 "8" +#define DUMB_DAY_STR1 "7" + +#if DUMB_MONTH < 10 +#define DUMB_MONTH_STR2 "0"DUMB_MONTH_STR1 +#else +#define DUMB_MONTH_STR2 DUMB_MONTH_STR1 +#endif + +#if DUMB_DAY < 10 +#define DUMB_DAY_STR2 "0"DUMB_DAY_STR1 +#else +#define DUMB_DAY_STR2 DUMB_DAY_STR1 +#endif + + +/* WARNING: The month and day were inadvertently swapped in the v0.8 release. + * Please do not compare this constant against any date in 2002. In + * any case, DUMB_VERSION is probably more useful for this purpose. + */ +#define DUMB_DATE (DUMB_YEAR*10000 + DUMB_MONTH*100 + DUMB_DAY) + +#define DUMB_DATE_STR DUMB_DAY_STR1"."DUMB_MONTH_STR1"."DUMB_YEAR_STR4 + + +#undef MIN +#undef MAX +#undef MID + +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#define MID(x,y,z) MAX((x), MIN((y), (z))) + +#undef ABS +#define ABS(x) (((x) >= 0) ? (x) : (-(x))) + + +#ifdef DEBUGMODE + +#ifndef ASSERT +#include +#define ASSERT(n) assert(n) +#endif +#ifndef TRACE +// it would be nice if this did actually trace ... +#define TRACE 1 ? (void)0 : (void)printf +#endif + +#else + +#ifndef ASSERT +#define ASSERT(n) +#endif +#ifndef TRACE +#define TRACE 1 ? (void)0 : (void)printf +#endif + +#endif + + +#define DUMB_ID(a,b,c,d) (((unsigned int)(a) << 24) | \ + ((unsigned int)(b) << 16) | \ + ((unsigned int)(c) << 8) | \ + ((unsigned int)(d) )) + + + +#ifndef LONG_LONG +#if defined __GNUC__ || defined __INTEL_COMPILER || defined __MWERKS__ +#define LONG_LONG long long +#elif defined _MSC_VER || defined __WATCOMC__ +#define LONG_LONG __int64 +#elif defined __sgi +#define LONG_LONG long long +#else +#error 64-bit integer type unknown +#endif +#endif + +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 301 /* GCC 3.1+ */ +#ifndef DUMB_DECLARE_DEPRECATED +#define DUMB_DECLARE_DEPRECATED +#endif +#define DUMB_DEPRECATED __attribute__((__deprecated__)) +#else +#define DUMB_DEPRECATED +#endif + + +/* Basic Sample Type. Normal range is -0x800000 to 0x7FFFFF. */ + +typedef int sample_t; + + +/* Library Clean-up Management */ + +int dumb_atexit(void (*proc)(void)); + +void dumb_exit(void); + + +/* File Input Functions */ + +typedef struct DUMBFILE_SYSTEM +{ + void *(*open)(const char *filename); + int (*skip)(void *f, long n); + int (*getc)(void *f); + long (*getnc)(char *ptr, long n, void *f); + void (*close)(void *f); +} +DUMBFILE_SYSTEM; + +typedef struct DUMBFILE DUMBFILE; + +void register_dumbfile_system(DUMBFILE_SYSTEM *dfs); + +DUMBFILE *dumbfile_open(const char *filename); +DUMBFILE *dumbfile_open_ex(void *file, DUMBFILE_SYSTEM *dfs); + +long dumbfile_pos(DUMBFILE *f); +int dumbfile_skip(DUMBFILE *f, long n); + +int dumbfile_getc(DUMBFILE *f); + +int dumbfile_igetw(DUMBFILE *f); +int dumbfile_mgetw(DUMBFILE *f); + +long dumbfile_igetl(DUMBFILE *f); +long dumbfile_mgetl(DUMBFILE *f); + +unsigned long dumbfile_cgetul(DUMBFILE *f); +signed long dumbfile_cgetsl(DUMBFILE *f); + +long dumbfile_getnc(char *ptr, long n, DUMBFILE *f); + +int dumbfile_error(DUMBFILE *f); +int dumbfile_close(DUMBFILE *f); + + +/* stdio File Input Module */ + +void dumb_register_stdfiles(void); + +DUMBFILE *dumbfile_open_stdfile(FILE *p); + + +/* Memory File Input Module */ + +DUMBFILE *dumbfile_open_memory(const char *data, long size); + + +/* DUH Management */ + +typedef struct DUH DUH; + +#define DUH_SIGNATURE DUMB_ID('D','U','H','!') + +void unload_duh(DUH *duh); + +DUH *load_duh(const char *filename); +DUH *read_duh(DUMBFILE *f); + +long duh_get_length(DUH *duh); + +const char *duh_get_tag(DUH *duh, const char *key); + + +/* Signal Rendering Functions */ + +typedef struct DUH_SIGRENDERER DUH_SIGRENDERER; + +DUH_SIGRENDERER *duh_start_sigrenderer(DUH *duh, int sig, int n_channels, long pos); + +#ifdef DUMB_DECLARE_DEPRECATED +typedef void (*DUH_SIGRENDERER_CALLBACK)(void *data, sample_t **samples, int n_channels, long length); +/* This is deprecated, but is not marked as such because GCC tends to + * complain spuriously when the typedef is used later. See comments below. + */ + +void duh_sigrenderer_set_callback( + DUH_SIGRENDERER *sigrenderer, + DUH_SIGRENDERER_CALLBACK callback, void *data +) DUMB_DEPRECATED; +/* The 'callback' argument's type has changed for const-correctness. See the + * DUH_SIGRENDERER_CALLBACK definition just above. Also note that the samples + * in the buffer are now 256 times as large; the normal range is -0x800000 to + * 0x7FFFFF. The function has been renamed partly because its functionality + * has changed slightly and partly so that its name is more meaningful. The + * new one is duh_sigrenderer_set_analyser_callback(), and the typedef for + * the function pointer has also changed, from DUH_SIGRENDERER_CALLBACK to + * DUH_SIGRENDERER_ANALYSER_CALLBACK. (If you wanted to use this callback to + * apply a DSP effect, don't worry; there is a better way of doing this. It + * is undocumented, so contact me and I shall try to help. Contact details + * are in readme.txt.) + */ + +typedef void (*DUH_SIGRENDERER_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length); +/* This is deprecated, but is not marked as such because GCC tends to + * complain spuriously when the typedef is used later. See comments below. + */ + +void duh_sigrenderer_set_analyser_callback( + DUH_SIGRENDERER *sigrenderer, + DUH_SIGRENDERER_ANALYSER_CALLBACK callback, void *data +) DUMB_DEPRECATED; +/* This is deprecated because the meaning of the 'samples' parameter in the + * callback needed to change. For stereo applications, the array used to be + * indexed with samples[channel][pos]. It is now indexed with + * samples[0][pos*2+channel]. Mono sample data are still indexed with + * samples[0][pos]. The array is still 2D because samples will probably only + * ever be interleaved in twos. In order to fix your code, adapt it to the + * new sample layout and then call + * duh_sigrenderer_set_sample_analyser_callback below instead of this + * function. + */ +#endif + +typedef void (*DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK)(void *data, const sample_t *const *samples, int n_channels, long length); + +void duh_sigrenderer_set_sample_analyser_callback( + DUH_SIGRENDERER *sigrenderer, + DUH_SIGRENDERER_SAMPLE_ANALYSER_CALLBACK callback, void *data +); + +int duh_sigrenderer_get_n_channels(DUH_SIGRENDERER *sigrenderer); +long duh_sigrenderer_get_position(DUH_SIGRENDERER *sigrenderer); + +void duh_sigrenderer_set_sigparam(DUH_SIGRENDERER *sigrenderer, unsigned char id, long value); + +#ifdef DUMB_DECLARE_DEPRECATED +long duh_sigrenderer_get_samples( + DUH_SIGRENDERER *sigrenderer, + float volume, float delta, + long size, sample_t **samples +) DUMB_DEPRECATED; +/* The sample format has changed, so if you were using this function, + * you should switch to duh_sigrenderer_generate_samples() and change + * how you interpret the samples array. See the comments for + * duh_sigrenderer_set_analyser_callback(). + */ +#endif + +long duh_sigrenderer_generate_samples( + DUH_SIGRENDERER *sigrenderer, + float volume, float delta, + long size, sample_t **samples +); + +void duh_sigrenderer_get_current_sample(DUH_SIGRENDERER *sigrenderer, float volume, sample_t *samples); + +void duh_end_sigrenderer(DUH_SIGRENDERER *sigrenderer); + + +/* DUH Rendering Functions */ + +long duh_render( + DUH_SIGRENDERER *sigrenderer, + int bits, int unsign, + float volume, float delta, + long size, void *sptr +); + +#ifdef DUMB_DECLARE_DEPRECATED + +long duh_render_signal( + DUH_SIGRENDERER *sigrenderer, + float volume, float delta, + long size, sample_t **samples +) DUMB_DEPRECATED; +/* Please use duh_sigrenderer_generate_samples(), and see the + * comments for the deprecated duh_sigrenderer_get_samples() too. + */ + +typedef DUH_SIGRENDERER DUH_RENDERER DUMB_DEPRECATED; +/* Please use DUH_SIGRENDERER instead of DUH_RENDERER. */ + +DUH_SIGRENDERER *duh_start_renderer(DUH *duh, int n_channels, long pos) DUMB_DEPRECATED; +/* Please use duh_start_sigrenderer() instead. Pass 0 for 'sig'. */ + +int duh_renderer_get_n_channels(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; +long duh_renderer_get_position(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; +/* Please use the duh_sigrenderer_*() equivalents of these two functions. */ + +void duh_end_renderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; +/* Please use duh_end_sigrenderer() instead. */ + +DUH_SIGRENDERER *duh_renderer_encapsulate_sigrenderer(DUH_SIGRENDERER *sigrenderer) DUMB_DEPRECATED; +DUH_SIGRENDERER *duh_renderer_get_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; +DUH_SIGRENDERER *duh_renderer_decompose_to_sigrenderer(DUH_SIGRENDERER *dr) DUMB_DEPRECATED; +/* These functions have become no-ops that just return the parameter. + * So, for instance, replace + * duh_renderer_encapsulate_sigrenderer(my_sigrenderer) + * with + * my_sigrenderer + */ + +#endif + + +/* Impulse Tracker Support */ + +extern int dumb_it_max_to_mix; + +typedef struct DUMB_IT_SIGDATA DUMB_IT_SIGDATA; +typedef struct DUMB_IT_SIGRENDERER DUMB_IT_SIGRENDERER; + +DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh); +DUH_SIGRENDERER *duh_encapsulate_it_sigrenderer(DUMB_IT_SIGRENDERER *it_sigrenderer, int n_channels, long pos); +DUMB_IT_SIGRENDERER *duh_get_it_sigrenderer(DUH_SIGRENDERER *sigrenderer); + +DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder); + +void dumb_it_set_loop_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); +void dumb_it_set_xm_speed_zero_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data), void *data); +void dumb_it_set_midi_callback(DUMB_IT_SIGRENDERER *sigrenderer, int (*callback)(void *data, int channel, unsigned char midi_byte), void *data); + +int dumb_it_callback_terminate(void *data); +int dumb_it_callback_midi_block(void *data, int channel, unsigned char midi_byte); + +DUH *dumb_load_it(const char *filename); +DUH *dumb_load_xm(const char *filename); +DUH *dumb_load_s3m(const char *filename); +DUH *dumb_load_mod(const char *filename); + +DUH *dumb_read_it(DUMBFILE *f); +DUH *dumb_read_xm(DUMBFILE *f); +DUH *dumb_read_s3m(DUMBFILE *f); +DUH *dumb_read_mod(DUMBFILE *f); + +DUH *dumb_load_it_quick(const char *filename); +DUH *dumb_load_xm_quick(const char *filename); +DUH *dumb_load_s3m_quick(const char *filename); +DUH *dumb_load_mod_quick(const char *filename); + +DUH *dumb_read_it_quick(DUMBFILE *f); +DUH *dumb_read_xm_quick(DUMBFILE *f); +DUH *dumb_read_s3m_quick(DUMBFILE *f); +DUH *dumb_read_mod_quick(DUMBFILE *f); + +long dumb_it_build_checkpoints(DUMB_IT_SIGDATA *sigdata); +void dumb_it_do_initial_runthrough(DUH *duh); + +const unsigned char *dumb_it_sd_get_song_message(DUMB_IT_SIGDATA *sd); + +int dumb_it_sd_get_n_orders(DUMB_IT_SIGDATA *sd); +int dumb_it_sd_get_n_samples(DUMB_IT_SIGDATA *sd); +int dumb_it_sd_get_n_instruments(DUMB_IT_SIGDATA *sd); + +const unsigned char *dumb_it_sd_get_sample_name(DUMB_IT_SIGDATA *sd, int i); +const unsigned char *dumb_it_sd_get_sample_filename(DUMB_IT_SIGDATA *sd, int i); +const unsigned char *dumb_it_sd_get_instrument_name(DUMB_IT_SIGDATA *sd, int i); +const unsigned char *dumb_it_sd_get_instrument_filename(DUMB_IT_SIGDATA *sd, int i); + +int dumb_it_sd_get_initial_global_volume(DUMB_IT_SIGDATA *sd); +void dumb_it_sd_set_initial_global_volume(DUMB_IT_SIGDATA *sd, int gv); + +int dumb_it_sd_get_mixing_volume(DUMB_IT_SIGDATA *sd); +void dumb_it_sd_set_mixing_volume(DUMB_IT_SIGDATA *sd, int mv); + +int dumb_it_sd_get_initial_speed(DUMB_IT_SIGDATA *sd); +void dumb_it_sd_set_initial_speed(DUMB_IT_SIGDATA *sd, int speed); + +int dumb_it_sd_get_initial_tempo(DUMB_IT_SIGDATA *sd); +void dumb_it_sd_set_initial_tempo(DUMB_IT_SIGDATA *sd, int tempo); + +int dumb_it_sd_get_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel); +void dumb_it_sd_set_initial_channel_volume(DUMB_IT_SIGDATA *sd, int channel, int volume); + +int dumb_it_sr_get_current_order(DUMB_IT_SIGRENDERER *sr); +int dumb_it_sr_get_current_row(DUMB_IT_SIGRENDERER *sr); + +int dumb_it_sr_get_global_volume(DUMB_IT_SIGRENDERER *sr); +void dumb_it_sr_set_global_volume(DUMB_IT_SIGRENDERER *sr, int gv); + +int dumb_it_sr_get_tempo(DUMB_IT_SIGRENDERER *sr); +void dumb_it_sr_set_tempo(DUMB_IT_SIGRENDERER *sr, int tempo); + +int dumb_it_sr_get_speed(DUMB_IT_SIGRENDERER *sr); +void dumb_it_sr_set_speed(DUMB_IT_SIGRENDERER *sr, int speed); + +#define DUMB_IT_N_CHANNELS 64 +#define DUMB_IT_N_NNA_CHANNELS 192 +#define DUMB_IT_TOTAL_CHANNELS (DUMB_IT_N_CHANNELS + DUMB_IT_N_NNA_CHANNELS) + +/* Channels passed to any of these functions are 0-based */ +int dumb_it_sr_get_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel); +void dumb_it_sr_set_channel_volume(DUMB_IT_SIGRENDERER *sr, int channel, int volume); + +int dumb_it_sr_get_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel); +void dumb_it_sr_set_channel_muted(DUMB_IT_SIGRENDERER *sr, int channel, int muted); + +typedef struct DUMB_IT_CHANNEL_STATE DUMB_IT_CHANNEL_STATE; + +struct DUMB_IT_CHANNEL_STATE +{ + int channel; /* 0-based; meaningful for NNA channels */ + int sample; /* 1-based; 0 if nothing playing, then other fields undef */ + int freq; /* in Hz */ + float volume; /* 1.0 maximum; affected by ALL factors, inc. mixing vol */ + unsigned char pan; /* 0-64, 100 for surround */ + signed char subpan; /* use (pan + subpan/256.0f) or ((pan<<8)+subpan) */ + unsigned char filter_cutoff; /* 0-127 cutoff=127 AND resonance=0 */ + unsigned char filter_subcutoff; /* 0-255 -> no filters (subcutoff */ + unsigned char filter_resonance; /* 0-127 always 0 in this case) */ + /* subcutoff only changes from zero if filter envelopes are in use. The + * calculation (filter_cutoff + filter_subcutoff/256.0f) gives a more + * accurate filter cutoff measurement as a float. It would often be more + * useful to use a scaled int such as ((cutoff<<8) + subcutoff). + */ +}; + +/* Values of 64 or more will access NNA channels here. */ +void dumb_it_sr_get_channel_state(DUMB_IT_SIGRENDERER *sr, int channel, DUMB_IT_CHANNEL_STATE *state); + + +/* Signal Design Helper Values */ + +/* Use pow(DUMB_SEMITONE_BASE, n) to get the 'delta' value to transpose up by + * n semitones. To transpose down, use negative n. + */ +#define DUMB_SEMITONE_BASE 1.059463094359295309843105314939748495817 + +/* Use pow(DUMB_QUARTERTONE_BASE, n) to get the 'delta' value to transpose up + * by n quartertones. To transpose down, use negative n. + */ +#define DUMB_QUARTERTONE_BASE 1.029302236643492074463779317738953977823 + +/* Use pow(DUMB_PITCH_BASE, n) to get the 'delta' value to transpose up by n + * units. In this case, 256 units represent one semitone; 3072 units + * represent one octave. These units are used by the sequence signal (SEQU). + */ +#define DUMB_PITCH_BASE 1.000225659305069791926712241547647863626 + + +/* Signal Design Function Types */ + +typedef void sigdata_t; +typedef void sigrenderer_t; + +typedef sigdata_t *(*DUH_LOAD_SIGDATA)(DUH *duh, DUMBFILE *file); + +typedef sigrenderer_t *(*DUH_START_SIGRENDERER)( + DUH *duh, + sigdata_t *sigdata, + int n_channels, + long pos +); + +typedef void (*DUH_SIGRENDERER_SET_SIGPARAM)( + sigrenderer_t *sigrenderer, + unsigned char id, long value +); + +typedef long (*DUH_SIGRENDERER_GENERATE_SAMPLES)( + sigrenderer_t *sigrenderer, + float volume, float delta, + long size, sample_t **samples +); + +typedef void (*DUH_SIGRENDERER_GET_CURRENT_SAMPLE)( + sigrenderer_t *sigrenderer, + float volume, + sample_t *samples +); + +typedef void (*DUH_END_SIGRENDERER)(sigrenderer_t *sigrenderer); + +typedef void (*DUH_UNLOAD_SIGDATA)(sigdata_t *sigdata); + + +/* Signal Design Function Registration */ + +typedef struct DUH_SIGTYPE_DESC +{ + long type; + DUH_LOAD_SIGDATA load_sigdata; + DUH_START_SIGRENDERER start_sigrenderer; + DUH_SIGRENDERER_SET_SIGPARAM sigrenderer_set_sigparam; + DUH_SIGRENDERER_GENERATE_SAMPLES sigrenderer_generate_samples; + DUH_SIGRENDERER_GET_CURRENT_SAMPLE sigrenderer_get_current_sample; + DUH_END_SIGRENDERER end_sigrenderer; + DUH_UNLOAD_SIGDATA unload_sigdata; +} +DUH_SIGTYPE_DESC; + +void dumb_register_sigtype(DUH_SIGTYPE_DESC *desc); + + +// Decide where to put these functions; new heading? + +sigdata_t *duh_get_raw_sigdata(DUH *duh, int sig, long type); + +DUH_SIGRENDERER *duh_encapsulate_raw_sigrenderer(sigrenderer_t *vsigrenderer, DUH_SIGTYPE_DESC *desc, int n_channels, long pos); +sigrenderer_t *duh_get_raw_sigrenderer(DUH_SIGRENDERER *sigrenderer, long type); + + +/* Standard Signal Types */ + +//void dumb_register_sigtype_sample(void); + + +/* Sample Buffer Allocation Helpers */ + +#ifdef DUMB_DECLARE_DEPRECATED +sample_t **create_sample_buffer(int n_channels, long length) DUMB_DEPRECATED; +/* DUMB has been changed to interleave stereo samples. Use + * allocate_sample_buffer() instead, and see the comments for + * duh_sigrenderer_set_analyser_callback(). + */ +#endif +sample_t **allocate_sample_buffer(int n_channels, long length); +void destroy_sample_buffer(sample_t **samples); + + +/* Silencing Helper */ + +void dumb_silence(sample_t *samples, long length); + + +/* Click Removal Helpers */ + +typedef struct DUMB_CLICK_REMOVER DUMB_CLICK_REMOVER; + +DUMB_CLICK_REMOVER *dumb_create_click_remover(void); +void dumb_record_click(DUMB_CLICK_REMOVER *cr, long pos, sample_t step); +void dumb_remove_clicks(DUMB_CLICK_REMOVER *cr, sample_t *samples, long length, int step, float halflife); +sample_t dumb_click_remover_get_offset(DUMB_CLICK_REMOVER *cr); +void dumb_destroy_click_remover(DUMB_CLICK_REMOVER *cr); + +DUMB_CLICK_REMOVER **dumb_create_click_remover_array(int n); +void dumb_record_click_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); +void dumb_record_click_negative_array(int n, DUMB_CLICK_REMOVER **cr, long pos, sample_t *step); +void dumb_remove_clicks_array(int n, DUMB_CLICK_REMOVER **cr, sample_t **samples, long length, float halflife); +void dumb_click_remover_get_offset_array(int n, DUMB_CLICK_REMOVER **cr, sample_t *offset); +void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr); + + +/* Resampling Helpers */ + +#define DUMB_RQ_ALIASING 0 +#define DUMB_RQ_LINEAR 1 +#define DUMB_RQ_CUBIC 2 +#define DUMB_RQ_N_LEVELS 3 +extern int dumb_resampling_quality; + +typedef struct DUMB_RESAMPLER DUMB_RESAMPLER; + +typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data); + +struct DUMB_RESAMPLER +{ + void *src; + long pos; + int subpos; + long start, end; + int dir; + DUMB_RESAMPLE_PICKUP pickup; + void *pickup_data; + int min_quality; + int max_quality; + /* Everything below this point is internal: do not use. */ + union { + sample_t x24[3*2]; + short x16[3*2]; + signed char x8[3*2]; + } x; + int overshot; +}; + +void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, int src_channels, long pos, long start, long end); +DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, int src_channels, long pos, long start, long end); +long dumb_resample_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); +long dumb_resample_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +void dumb_resample_get_current_sample_1_1(DUMB_RESAMPLER *resampler, float volume, sample_t *dst); +void dumb_resample_get_current_sample_1_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_2_1(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_2_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_end_resampler(DUMB_RESAMPLER *resampler); + +void dumb_reset_resampler_16(DUMB_RESAMPLER *resampler, short *src, int src_channels, long pos, long start, long end); +DUMB_RESAMPLER *dumb_start_resampler_16(short *src, int src_channels, long pos, long start, long end); +long dumb_resample_16_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); +long dumb_resample_16_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_16_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_16_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +void dumb_resample_get_current_sample_16_1_1(DUMB_RESAMPLER *resampler, float volume, sample_t *dst); +void dumb_resample_get_current_sample_16_1_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_16_2_1(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_16_2_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_end_resampler_16(DUMB_RESAMPLER *resampler); + +void dumb_reset_resampler_8(DUMB_RESAMPLER *resampler, signed char *src, int src_channels, long pos, long start, long end); +DUMB_RESAMPLER *dumb_start_resampler_8(signed char *src, int src_channels, long pos, long start, long end); +long dumb_resample_8_1_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); +long dumb_resample_8_1_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_8_2_1(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_8_2_2(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +void dumb_resample_get_current_sample_8_1_1(DUMB_RESAMPLER *resampler, float volume, sample_t *dst); +void dumb_resample_get_current_sample_8_1_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_8_2_1(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_8_2_2(DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_end_resampler_8(DUMB_RESAMPLER *resampler); + +void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, long pos, long start, long end); +DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, long pos, long start, long end); +long dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta); +long dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +long dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume_left, float volume_right, float delta); +void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, float volume, sample_t *dst); +void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, float volume_left, float volume_right, sample_t *dst); +void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler); + + +/* DUH Construction */ + +DUH *make_duh( + long length, + int n_tags, + const char *const tag[][2], + int n_signals, + DUH_SIGTYPE_DESC *desc[], + sigdata_t *sigdata[] +); + +void duh_set_length(DUH *duh, long length); + + +#ifdef __cplusplus + } +#endif + + +#endif /* DUMB_H */ diff --git a/include/dumb/internal/aldumb.h b/include/dumb/internal/aldumb.h new file mode 100644 index 0000000000..0a7395bae8 --- /dev/null +++ b/include/dumb/internal/aldumb.h @@ -0,0 +1,34 @@ +/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * internal/aldumb.h - The internal header file / / \ \ + * for DUMB with Allegro. | < / \_ + * | \/ /\ / + * This header file provides access to the \_ / > / + * internal structure of DUMB, and is liable | \ / / + * to change, mutate or cease to exist at any | ' / + * moment. Include it at your own peril. \__/ + * + * ... + * + * Seriously. You don't need access to anything in this file. All right, you + * probably do actually. But if you use it, you will be relying on a specific + * version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please + * contact the authors so that we can provide a public API for what you need. + */ + +#ifndef INTERNAL_ALDUMB_H +#define INTERNAL_ALDUMB_H + + +void _dat_unload_duh(void *duh); + + +#endif /* INTERNAL_DUMB_H */ diff --git a/include/dumb/internal/dumb.h b/include/dumb/internal/dumb.h new file mode 100644 index 0000000000..bed5956664 --- /dev/null +++ b/include/dumb/internal/dumb.h @@ -0,0 +1,61 @@ +/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * internal/dumb.h - DUMB's internal declarations. / / \ \ + * | < / \_ + * This header file provides access to the | \/ /\ / + * internal structure of DUMB, and is liable \_ / > / + * to change, mutate or cease to exist at any | \ / / + * moment. Include it at your own peril. | ' / + * \__/ + * ... + * + * Seriously. You don't need access to anything in this file. All right, you + * probably do actually. But if you use it, you will be relying on a specific + * version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please + * contact the authors so that we can provide a public API for what you need. + */ + +#ifndef INTERNAL_DUMB_H +#define INTERNAL_DUMB_H + + +typedef struct DUH_SIGTYPE_DESC_LINK +{ + struct DUH_SIGTYPE_DESC_LINK *next; + DUH_SIGTYPE_DESC *desc; +} +DUH_SIGTYPE_DESC_LINK; + + +typedef struct DUH_SIGNAL +{ + sigdata_t *sigdata; + DUH_SIGTYPE_DESC *desc; +} +DUH_SIGNAL; + + +struct DUH +{ + long length; + + int n_tags; + char *(*tag)[2]; + + int n_signals; + DUH_SIGNAL **signal; +}; + + +DUH_SIGTYPE_DESC *_dumb_get_sigtype_desc(long type); + + +#endif /* INTERNAL_DUMB_H */ diff --git a/include/dumb/internal/it.h b/include/dumb/internal/it.h new file mode 100644 index 0000000000..bb27659214 --- /dev/null +++ b/include/dumb/internal/it.h @@ -0,0 +1,733 @@ +/* _______ ____ __ ___ ___ + * \ _ \ \ / \ / \ \ / / ' ' ' + * | | \ \ | | || | \/ | . . + * | | | | | | || ||\ /| | + * | | | | | | || || \/ | | ' ' ' + * | | | | | | || || | | . . + * | |_/ / \ \__// || | | + * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque + * / \ + * / . \ + * internal/it.h - Internal stuff for IT playback / / \ \ + * and MOD/XM/S3M conversion. | < / \_ + * | \/ /\ / + * This header file provides access to the \_ / > / + * internal structure of DUMB, and is liable | \ / / + * to change, mutate or cease to exist at any | ' / + * moment. Include it at your own peril. \__/ + * + * ... + * + * Seriously. You don't need access to anything in this file. All right, you + * probably do actually. But if you use it, you will be relying on a specific + * version of DUMB, so please check DUMB_VERSION defined in dumb.h. Please + * contact the authors so that we can provide a public API for what you need. + */ + +#ifndef INTERNAL_IT_H +#define INTERNAL_IT_H + + + +#include + + + +/** TO DO: THINK ABOUT THE FOLLOWING: + +sigdata->flags & IT_COMPATIBLE_GXX + + Bit 5: On = Link Effect G's memory with Effect E/F. Also + Gxx with an instrument present will cause the + envelopes to be retriggered. If you change a + sample on a row with Gxx, it'll adjust the + frequency of the current note according to: + + NewFrequency = OldFrequency * NewC5 / OldC5; +*/ + + + +/* These #defines are TEMPORARY. They are used to write alternative code to + * handle ambiguities in the format specification. The correct code in each + * case will be determined most likely by experimentation. + */ +#define STEREO_SAMPLES_COUNT_AS_TWO +#define INVALID_ORDERS_END_SONG +#define INVALID_NOTES_CAUSE_NOTE_CUT +#define SUSTAIN_LOOP_OVERRIDES_NORMAL_LOOP +#define VOLUME_OUT_OF_RANGE_SETS_MAXIMUM + + + +#define SIGTYPE_IT DUMB_ID('I', 'T', ' ', ' ') + +#define IT_SIGNATURE DUMB_ID('I', 'M', 'P', 'M') +#define IT_INSTRUMENT_SIGNATURE DUMB_ID('I', 'M', 'P', 'I') +#define IT_SAMPLE_SIGNATURE DUMB_ID('I', 'M', 'P', 'S') + + + +/* 1 minute per 4 rows, each row 6 ticks; this is divided by the tempo to get + * the interval between ticks. + */ +#define TICK_TIME_DIVIDEND ((65536 * 60) / (4 * 6)) + + + +/* I'm not going to try to explain this, because I didn't derive it very + * formally ;) + */ +/* #define AMIGA_DIVISOR ((float)(4.0 * 14317056.0)) */ +/* I believe the following one to be more accurate. */ +#define AMIGA_DIVISOR ((float)(8.0 * 7159090.5)) + + + +typedef struct IT_MIDI IT_MIDI; +typedef struct IT_FILTER_STATE IT_FILTER_STATE; +typedef struct IT_ENVELOPE IT_ENVELOPE; +typedef struct IT_INSTRUMENT IT_INSTRUMENT; +typedef struct IT_SAMPLE IT_SAMPLE; +typedef struct IT_ENTRY IT_ENTRY; +typedef struct IT_PATTERN IT_PATTERN; +typedef struct IT_PLAYING_ENVELOPE IT_PLAYING_ENVELOPE; +typedef struct IT_PLAYING IT_PLAYING; +typedef struct IT_CHANNEL IT_CHANNEL; +typedef struct IT_CHECKPOINT IT_CHECKPOINT; +typedef struct IT_CALLBACKS IT_CALLBACKS; + + + +struct IT_MIDI +{ + unsigned char SFmacro[16][16]; // read these from 0x120 + unsigned char SFmacrolen[16]; + unsigned short SFmacroz[16]; /* Bitfield; bit 0 set = z in first position */ + unsigned char Zmacro[128][16]; // read these from 0x320 + unsigned char Zmacrolen[128]; +}; + + + +struct IT_FILTER_STATE +{ + sample_t currsample, prevsample; +}; + + + +#define IT_ENVELOPE_ON 1 +#define IT_ENVELOPE_LOOP_ON 2 +#define IT_ENVELOPE_SUSTAIN_LOOP 4 +#define IT_ENVELOPE_PITCH_IS_FILTER 128 + +struct IT_ENVELOPE +{ + unsigned char flags; + unsigned char n_nodes; + unsigned char loop_start; + unsigned char loop_end; + unsigned char sus_loop_start; + unsigned char sus_loop_end; + signed char node_y[25]; + unsigned short node_t[25]; +}; + + + +#define NNA_NOTE_CUT 0 +#define NNA_NOTE_CONTINUE 1 +#define NNA_NOTE_OFF 2 +#define NNA_NOTE_FADE 3 + +#define DCT_OFF 0 +#define DCT_NOTE 1 +#define DCT_SAMPLE 2 +#define DCT_INSTRUMENT 3 + +#define DCA_NOTE_CUT 0 +#define DCA_NOTE_OFF 1 +#define DCA_NOTE_FADE 2 + +struct IT_INSTRUMENT +{ + unsigned char name[27]; + unsigned char filename[14]; + + int fadeout; + + IT_ENVELOPE volume_envelope; + IT_ENVELOPE pan_envelope; + IT_ENVELOPE pitch_envelope; + + unsigned char new_note_action; + unsigned char dup_check_type; + unsigned char dup_check_action; + unsigned char pp_separation; + unsigned char pp_centre; + unsigned char global_volume; + unsigned char default_pan; + unsigned char random_volume; + unsigned char random_pan; + + unsigned char filter_cutoff; + unsigned char filter_resonance; + + unsigned char map_note[120]; + unsigned short map_sample[120]; +}; + + + +#define IT_SAMPLE_EXISTS 1 +#define IT_SAMPLE_16BIT 2 +#define IT_SAMPLE_STEREO 4 +#define IT_SAMPLE_LOOP 16 +#define IT_SAMPLE_SUS_LOOP 32 +#define IT_SAMPLE_PINGPONG_LOOP 64 +#define IT_SAMPLE_PINGPONG_SUS_LOOP 128 + +#define IT_VIBRATO_SINE 0 +#define IT_VIBRATO_SAWTOOTH 1 /* Ramp down */ +#define IT_VIBRATO_SQUARE 2 +#define IT_VIBRATO_RANDOM 3 + +struct IT_SAMPLE +{ + unsigned char name[29]; + unsigned char filename[14]; + unsigned char flags; + unsigned char global_volume; + unsigned char default_volume; + unsigned char default_pan; + /* default_pan: + * 0-255 for XM + * ignored for MOD + * otherwise, 0-64, and add 128 to enable + */ + + long length; + long loop_start; + long loop_end; + long C5_speed; + long sus_loop_start; + long sus_loop_end; + + unsigned char vibrato_speed; + unsigned char vibrato_depth; + unsigned char vibrato_rate; + unsigned char vibrato_waveform; + + void *data; +}; + + + +#define IT_ENTRY_NOTE 1 +#define IT_ENTRY_INSTRUMENT 2 +#define IT_ENTRY_VOLPAN 4 +#define IT_ENTRY_EFFECT 8 + +#define IT_SET_END_ROW(entry) ((entry)->channel = 255) +#define IT_IS_END_ROW(entry) ((entry)->channel >= DUMB_IT_N_CHANNELS) + +#define IT_NOTE_OFF 255 +#define IT_NOTE_CUT 254 + +#define IT_ENVELOPE_SHIFT 8 + +#define IT_SURROUND 100 +#define IT_IS_SURROUND(pan) ((pan) > 64) +#define IT_IS_SURROUND_SHIFTED(pan) ((pan) > 64 << IT_ENVELOPE_SHIFT) + +#define IT_SET_SPEED 1 +#define IT_JUMP_TO_ORDER 2 +#define IT_BREAK_TO_ROW 3 +#define IT_VOLUME_SLIDE 4 +#define IT_PORTAMENTO_DOWN 5 +#define IT_PORTAMENTO_UP 6 +#define IT_TONE_PORTAMENTO 7 +#define IT_VIBRATO 8 +#define IT_TREMOR 9 +#define IT_ARPEGGIO 10 +#define IT_VOLSLIDE_VIBRATO 11 +#define IT_VOLSLIDE_TONEPORTA 12 +#define IT_SET_CHANNEL_VOLUME 13 +#define IT_CHANNEL_VOLUME_SLIDE 14 +#define IT_SET_SAMPLE_OFFSET 15 +#define IT_PANNING_SLIDE 16 +#define IT_RETRIGGER_NOTE 17 +#define IT_TREMOLO 18 +#define IT_S 19 +#define IT_SET_SONG_TEMPO 20 +#define IT_FINE_VIBRATO 21 +#define IT_SET_GLOBAL_VOLUME 22 +#define IT_GLOBAL_VOLUME_SLIDE 23 +#define IT_SET_PANNING 24 +#define IT_PANBRELLO 25 +#define IT_MIDI_MACRO 26 //see MIDI.TXT + +/* Some effects needed for XM compatibility */ +#define IT_XM_PORTAMENTO_DOWN 27 +#define IT_XM_PORTAMENTO_UP 28 +#define IT_XM_FINE_VOLSLIDE_DOWN 29 +#define IT_XM_FINE_VOLSLIDE_UP 30 +#define IT_XM_RETRIGGER_NOTE 31 +#define IT_XM_KEY_OFF 32 +#define IT_XM_SET_ENVELOPE_POSITION 33 + +#define IT_N_EFFECTS 34 + +/* These represent the top nibble of the command value. */ +#define IT_S_SET_FILTER 0 /* Greyed out in IT... */ +#define IT_S_SET_GLISSANDO_CONTROL 1 /* Greyed out in IT... */ +#define IT_S_FINETUNE 2 /* Greyed out in IT... */ +#define IT_S_SET_VIBRATO_WAVEFORM 3 +#define IT_S_SET_TREMOLO_WAVEFORM 4 +#define IT_S_SET_PANBRELLO_WAVEFORM 5 +#define IT_S_FINE_PATTERN_DELAY 6 +#define IT_S7 7 +#define IT_S_SET_PAN 8 +#define IT_S_SET_SURROUND_SOUND 9 +#define IT_S_SET_HIGH_OFFSET 10 +#define IT_S_PATTERN_LOOP 11 +#define IT_S_DELAYED_NOTE_CUT 12 +#define IT_S_NOTE_DELAY 13 +#define IT_S_PATTERN_DELAY 14 +#define IT_S_SET_MIDI_MACRO 15 + +/* +S0x Set filter +S1x Set glissando control +S2x Set finetune + + +S3x Set vibrato waveform to type x +S4x Set tremelo waveform to type x +S5x Set panbrello waveform to type x + Waveforms for commands S3x, S4x and S5x: + 0: Sine wave + 1: Ramp down + 2: Square wave + 3: Random wave +S6x Pattern delay for x ticks +S70 Past note cut +S71 Past note off +S72 Past note fade +S73 Set NNA to note cut +S74 Set NNA to continue +S75 Set NNA to note off +S76 Set NNA to note fade +S77 Turn off volume envelope +S78 Turn on volume envelope +S79 Turn off panning envelope +S7A Turn on panning envelope +S7B Turn off pitch envelope +S7C Turn on pitch envelope +S8x Set panning position +S91 Set surround sound +SAy Set high value of sample offset yxx00h +SB0 Set loopback point +SBx Loop x times to loopback point +SCx Note cut after x ticks +SDx Note delay for x ticks +SEx Pattern delay for x rows +SFx Set parameterised MIDI Macro +*/ + +struct IT_ENTRY +{ + unsigned char channel; /* End of row if channel >= DUMB_IT_N_CHANNELS */ + unsigned char mask; + unsigned char note; + unsigned char instrument; + unsigned char volpan; + unsigned char effect; + unsigned char effectvalue; +}; + + + +struct IT_PATTERN +{ + int n_rows; + int n_entries; + IT_ENTRY *entry; +}; + + + +#define IT_STEREO 1 +#define IT_USE_INSTRUMENTS 4 +#define IT_LINEAR_SLIDES 8 /* If not set, use Amiga slides */ +#define IT_OLD_EFFECTS 16 +#define IT_COMPATIBLE_GXX 32 + +/* Make sure IT_WAS_AN_XM and IT_WAS_A_MOD aren't set accidentally */ +#define IT_REAL_FLAGS 63 + +#define IT_WAS_AN_XM 64 /* Set for both XMs and MODs */ +#define IT_WAS_A_MOD 128 + +#define IT_ORDER_END 255 +#define IT_ORDER_SKIP 254 + +struct DUMB_IT_SIGDATA +{ + unsigned char name[29]; + + unsigned char *song_message; + + int n_orders; + int n_instruments; + int n_samples; + int n_patterns; + + int flags; + + int global_volume; + int mixing_volume; + int speed; + int tempo; + int pan_separation; + + unsigned char channel_pan[DUMB_IT_N_CHANNELS]; + unsigned char channel_volume[DUMB_IT_N_CHANNELS]; + + unsigned char *order; + unsigned char restart_position; /* for XM compatiblity */ + + IT_INSTRUMENT *instrument; + IT_SAMPLE *sample; + IT_PATTERN *pattern; + + IT_MIDI *midi; + + IT_CHECKPOINT *checkpoint; +}; + + + +struct IT_PLAYING_ENVELOPE +{ + int next_node; + int tick; + int value; +}; + + + +#define IT_PLAYING_BACKGROUND 1 +#define IT_PLAYING_SUSTAINOFF 2 +#define IT_PLAYING_FADING 4 +#define IT_PLAYING_DEAD 8 + +struct IT_PLAYING +{ + int flags; + + IT_CHANNEL *channel; + IT_SAMPLE *sample; + IT_INSTRUMENT *instrument; + IT_INSTRUMENT *env_instrument; + + unsigned short sampnum; + unsigned char instnum; + + unsigned char channel_volume; + + unsigned char volume; + unsigned short pan; + + unsigned char note; + + unsigned char filter_cutoff; + unsigned char filter_resonance; + + unsigned short true_filter_cutoff; /* These incorporate the filter envelope, and will not */ + unsigned char true_filter_resonance; /* be changed if they would be set to 127<<8 and 0. */ + + unsigned char vibrato_speed; + unsigned char vibrato_depth; + unsigned char vibrato_n; /* May be specified twice: volpan & effect. */ + unsigned char vibrato_time; + + unsigned char tremolo_speed; + unsigned char tremolo_depth; + unsigned char tremolo_time; + + unsigned char sample_vibrato_time; + int sample_vibrato_depth; /* Starts at rate?0:depth, increases by rate */ + + int slide; + float delta; + + IT_PLAYING_ENVELOPE volume_envelope; + IT_PLAYING_ENVELOPE pan_envelope; + IT_PLAYING_ENVELOPE pitch_envelope; + + int fadeoutcount; + + IT_FILTER_STATE filter_state[2]; /* Left and right */ + + DUMB_RESAMPLER resampler; + + /* time_lost is used to emulate Impulse Tracker's sample looping + * characteristics. When time_lost is added to pos, the result represents + * the position in the theoretical version of the sample where all loops + * have been expanded. If this is stored, the resampling helpers will + * safely convert it for use with new loop boundaries. The situation is + * slightly more complicated if dir == -1 when the change takes place; we + * must reflect pos off the loop end point and set dir to 1 before + * proceeding. + */ + long time_lost; +}; + + + +#define IT_CHANNEL_MUTED 1 + +struct IT_CHANNEL +{ + int flags; + + unsigned char volume; + signed char volslide; + signed char xm_volslide; + signed char panslide; + + /* xm_volslide is used for volume slides done in the volume column in an + * XM file, since it seems the volume column slide is applied first, + * followed by clamping, followed by the effects column slide. IT does + * not exhibit this behaviour, so xm_volslide is maintained at zero. + */ + + unsigned char pan; + unsigned short truepan; + + unsigned char channelvolume; + signed char channelvolslide; + + unsigned char instrument; + unsigned char note; + + unsigned char SFmacro; + + unsigned char filter_cutoff; + unsigned char filter_resonance; + + unsigned char key_off_count; + unsigned char note_cut_count; + unsigned char note_delay_count; + IT_ENTRY *note_delay_entry; + + int arpeggio; + unsigned char retrig; + unsigned char xm_retrig; + int retrig_tick; + + unsigned char tremor; + unsigned char tremor_time; /* Bit 6 set if note on; bit 7 set if tremor active. */ + + int portamento; + int toneporta; + unsigned char destnote; + + /** WARNING - for neatness, should one or both of these be in the IT_PLAYING struct? */ + unsigned short sample; + unsigned char truenote; + + unsigned char midi_state; + + signed char lastvolslide; + unsigned char lastDKL; + unsigned char lastEF; /* Doubles as last portamento up for XM files */ + unsigned char lastG; + unsigned char lastHspeed; + unsigned char lastHdepth; + unsigned char lastRspeed; + unsigned char lastRdepth; + unsigned char lastI; + unsigned char lastJ; /* Doubles as last portamento down for XM files */ + unsigned char lastN; + unsigned char lastO; + unsigned char high_offset; + unsigned char lastP; + unsigned char lastQ; + unsigned char lastS; + unsigned char pat_loop_row; + unsigned char pat_loop_count; + unsigned char pat_loop_end_row; /* Used to catch infinite pattern loops */ + unsigned char lastW; + + unsigned char xm_lastE1; + unsigned char xm_lastE2; + unsigned char xm_lastEA; + unsigned char xm_lastEB; + unsigned char xm_lastX1; + unsigned char xm_lastX2; + + IT_PLAYING *playing; +}; + + + +struct DUMB_IT_SIGRENDERER +{ + DUMB_IT_SIGDATA *sigdata; + + int n_channels; + + unsigned char globalvolume; + signed char globalvolslide; + + unsigned char tempo; + signed char temposlide; + + IT_CHANNEL channel[DUMB_IT_N_CHANNELS]; + + IT_PLAYING *playing[DUMB_IT_N_NNA_CHANNELS]; + + int tick; + int speed; + int rowcount; + + int order; /* Set to -1 if the song is terminated by a callback. */ + int row; + int processorder; + int processrow; + int breakrow; + int pat_loop_row; + + int n_rows; + + IT_ENTRY *entry_start; + IT_ENTRY *entry; + IT_ENTRY *entry_end; + + long time_left; /* Time before the next tick is processed */ + int sub_time_left; + + DUMB_CLICK_REMOVER **click_remover; + + IT_CALLBACKS *callbacks; +}; + + + +struct IT_CHECKPOINT +{ + IT_CHECKPOINT *next; + long time; + DUMB_IT_SIGRENDERER *sigrenderer; +}; + + + +struct IT_CALLBACKS +{ + int (*loop)(void *data); + void *loop_data; + /* Return 1 to prevent looping; the music will terminate abruptly. If you + * want to make the music stop but allow samples to fade (beware, as they + * might not fade at all!), use dumb_it_sr_set_speed() and set the speed + * to 0. Note that xm_speed_zero() will not be called if you set the + * speed manually, and also that this will work for IT and S3M files even + * though the music can't stop in this way by itself. + */ + + int (*xm_speed_zero)(void *data); + void *xm_speed_zero_data; + /* Return 1 to terminate the mod, without letting samples fade. */ + + int (*midi)(void *data, int channel, unsigned char byte); + void *midi_data; + /* Return 1 to prevent DUMB from subsequently interpreting the MIDI bytes + * itself. In other words, return 1 if the Zxx macros in an IT file are + * controlling filters and shouldn't be. + */ +}; + + + +void _dumb_it_end_sigrenderer(sigrenderer_t *sigrenderer); +void _dumb_it_unload_sigdata(sigdata_t *vsigdata); + +extern DUH_SIGTYPE_DESC _dumb_sigtype_it; + + + +#define XM_APPREGIO 0 +#define XM_PORTAMENTO_UP 1 +#define XM_PORTAMENTO_DOWN 2 +#define XM_TONE_PORTAMENTO 3 +#define XM_VIBRATO 4 +#define XM_VOLSLIDE_TONEPORTA 5 +#define XM_VOLSLIDE_VIBRATO 6 +#define XM_TREMOLO 7 +#define XM_SET_PANNING 8 +#define XM_SAMPLE_OFFSET 9 +#define XM_VOLUME_SLIDE 10 /* A */ +#define XM_POSITION_JUMP 11 /* B */ +#define XM_SET_CHANNEL_VOLUME 12 /* C */ +#define XM_PATTERN_BREAK 13 /* D */ +#define XM_E 14 /* E */ +#define XM_SET_TEMPO_BPM 15 /* F */ +#define XM_SET_GLOBAL_VOLUME 16 /* G */ +#define XM_GLOBAL_VOLUME_SLIDE 17 /* H */ +#define XM_KEY_OFF 20 /* K (undocumented) */ +#define XM_SET_ENVELOPE_POSITION 21 /* L */ +#define XM_PANNING_SLIDE 25 /* P */ +#define XM_MULTI_RETRIG 27 /* R */ +#define XM_TREMOR 29 /* T */ +#define XM_X 33 /* X */ +#define XM_N_EFFECTS (10+26) + +#define XM_E_SET_FILTER 0x0 +#define XM_E_FINE_PORTA_UP 0x1 +#define XM_E_FINE_PORTA_DOWN 0x2 +#define XM_E_SET_GLISSANDO_CONTROL 0x3 +#define XM_E_SET_VIBRATO_CONTROL 0x4 +#define XM_E_SET_FINETUNE 0x5 +#define XM_E_SET_LOOP 0x6 +#define XM_E_SET_TREMOLO_CONTROL 0x7 +#define XM_E_RETRIG_NOTE 0x9 +#define XM_E_FINE_VOLSLIDE_UP 0xA +#define XM_E_FINE_VOLSLIDE_DOWN 0xB +#define XM_E_NOTE_CUT 0xC +#define XM_E_NOTE_DELAY 0xD +#define XM_E_PATTERN_DELAY 0xE + +#define XM_X_EXTRAFINE_PORTA_UP 1 +#define XM_X_EXTRAFINE_PORTA_DOWN 2 + +/* To make my life a bit simpler during conversion, effect E:xy is converted + * to effect number EBASE+x:y. The same applies to effect X, and IT's S. That + * way, these effects can be manipulated like regular effects. + */ +#define EBASE (XM_N_EFFECTS) +#define XBASE (EBASE+16) +#define SBASE (IT_N_EFFECTS) + +#define EFFECT_VALUE(x, y) (((x)<<4)|(y)) +#define HIGH(v) ((v)>>4) +#define LOW(v) ((v)&0x0F) +#define SET_HIGH(v, x) v = (((x)<<4)|((v)&0x0F)) +#define SET_LOW(v, y) v = (((v)&0xF0)|(y)) +#define BCD_TO_NORMAL(v) (HIGH(v)*10+LOW(v)) + + + +#if 0 +unsigned char **_dumb_malloc2(int w, int h); +void _dumb_free2(unsigned char **line); +#endif + +void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry); +int _dumb_it_fix_invalid_orders(DUMB_IT_SIGDATA *sigdata); + + + +#endif /* INTERNAL_IT_H */ diff --git a/include/gme/Blip_Buffer.h b/include/gme/Blip_Buffer.h new file mode 100644 index 0000000000..8e29d9feaf --- /dev/null +++ b/include/gme/Blip_Buffer.h @@ -0,0 +1,354 @@ + +// Band-limited sound synthesis and buffering + +// Blip_Buffer 0.4.0 + +#ifndef BLIP_BUFFER_H +#define BLIP_BUFFER_H + +// Time unit at source clock rate +typedef long blip_time_t; + +// Output samples are 16-bit signed, with a range of -32768 to 32767 +typedef short blip_sample_t; +enum { blip_sample_max = 32767 }; + +class Blip_Buffer { +public: + typedef const char* blargg_err_t; + + // Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults + // to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there + // isn't enough memory, returns error without affecting current buffer setup. + blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 ); + + // Set number of source time units per second + void clock_rate( long ); + + // End current time frame of specified duration and make its samples available + // (along with any still-unread samples) for reading with read_samples(). Begins + // a new time frame at the end of the current frame. + void end_frame( blip_time_t time ); + + // Read at most 'max_samples' out of buffer into 'dest', removing them from from + // the buffer. Returns number of samples actually read and removed. If stereo is + // true, increments 'dest' one extra time after writing each sample, to allow + // easy interleving of two channels into a stereo output buffer. + long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 ); + +// Additional optional features + + // Current output sample rate + long sample_rate() const; + + // Length of buffer, in milliseconds + int length() const; + + // Number of source time units per second + long clock_rate() const; + + // Set frequency high-pass filter frequency, where higher values reduce bass more + void bass_freq( int frequency ); + + // Number of samples delay from synthesis to samples read out + int output_latency() const; + + // Remove all available samples and clear buffer to silence. If 'entire_buffer' is + // false, just clears out any samples waiting rather than the entire buffer. + void clear( int entire_buffer = 1 ); + + // Number of samples available for reading with read_samples() + long samples_avail() const; + + // Remove 'count' samples from those waiting to be read + void remove_samples( long count ); + +// Experimental features + + // Number of raw samples that can be mixed within frame of specified duration. + long count_samples( blip_time_t duration ) const; + + // Mix 'count' samples from 'buf' into buffer. + void mix_samples( blip_sample_t const* buf, long count ); + + // Count number of clocks needed until 'count' samples will be available. + // If buffer can't even hold 'count' samples, returns number of clocks until + // buffer becomes full. + blip_time_t count_clocks( long count ) const; + + // not documented yet + typedef unsigned long blip_resampled_time_t; + void remove_silence( long count ); + blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; } + blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; } + blip_resampled_time_t clock_rate_factor( long clock_rate ) const; +public: + Blip_Buffer(); + ~Blip_Buffer(); + + // Deprecated + typedef blip_resampled_time_t resampled_time_t; + blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); } + blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); } +private: + // noncopyable + Blip_Buffer( const Blip_Buffer& ); + Blip_Buffer& operator = ( const Blip_Buffer& ); +public: + typedef long buf_t_; + unsigned long factor_; + blip_resampled_time_t offset_; + buf_t_* buffer_; + long buffer_size_; +private: + long reader_accum; + int bass_shift; + long sample_rate_; + long clock_rate_; + int bass_freq_; + int length_; + friend class Blip_Reader; +}; + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +// Number of bits in resample ratio fraction. Higher values give a more accurate ratio +// but reduce maximum buffer size. +#ifndef BLIP_BUFFER_ACCURACY + #define BLIP_BUFFER_ACCURACY 16 +#endif + +// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in +// noticeable broadband noise when synthesizing high frequency square waves. +// Affects size of Blip_Synth objects since they store the waveform directly. +#ifndef BLIP_PHASE_BITS + #define BLIP_PHASE_BITS 6 +#endif + + // Internal + typedef unsigned long blip_resampled_time_t; + int const blip_widest_impulse_ = 16; + int const blip_res = 1 << BLIP_PHASE_BITS; + class blip_eq_t; + + class Blip_Synth_ { + double volume_unit_; + short* const impulses; + int const width; + long kernel_unit; + int impulses_size() const { return blip_res / 2 * width + 1; } + void adjust_impulse(); + public: + Blip_Buffer* buf; + int last_amp; + int delta_factor; + + Blip_Synth_( short* impulses, int width ); + void treble_eq( blip_eq_t const& ); + void volume_unit( double ); + }; + +// Quality level. Start with blip_good_quality. +const int blip_med_quality = 8; +const int blip_good_quality = 12; +const int blip_high_quality = 16; + +// Range specifies the greatest expected change in amplitude. Calculate it +// by finding the difference between the maximum and minimum expected +// amplitudes (max - min). +template +class Blip_Synth { +public: + // Set overall volume of waveform + void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); } + + // Configure low-pass filter (see notes.txt) + void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); } + + // Get/set Blip_Buffer used for output + Blip_Buffer* output() const { return impl.buf; } + void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; } + + // Update amplitude of waveform at given time. Using this requires a separate + // Blip_Synth for each waveform. + void update( blip_time_t time, int amplitude ); + +// Low-level interface + + // Add an amplitude transition of specified delta, optionally into specified buffer + // rather than the one set with output(). Delta can be positive or negative. + // The actual change in amplitude is delta * (volume / range) + void offset( blip_time_t, int delta, Blip_Buffer* ) const; + void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); } + + // Works directly in terms of fractional output samples. Contact author for more. + void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const; + + // Same as offset(), except code is inlined for higher performance + void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { + offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); + } + void offset_inline( blip_time_t t, int delta ) const { + offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); + } + +public: + Blip_Synth() : impl( impulses, quality ) { } +private: + typedef short imp_t; + imp_t impulses [blip_res * (quality / 2) + 1]; + Blip_Synth_ impl; +}; + +// Low-pass equalization parameters +class blip_eq_t { +public: + // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce + // treble, small positive values (0 to 5.0) increase treble. + blip_eq_t( double treble_db = 0 ); + + // See notes.txt + blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 ); + +private: + double treble; + long rolloff_freq; + long sample_rate; + long cutoff_freq; + void generate( float* out, int count ) const; + friend class Blip_Synth_; +}; + +int const blip_sample_bits = 30; + +// Optimized inline sample reader for custom sample formats and mixing of Blip_Buffer samples +class Blip_Reader { +public: + // Begin reading samples from buffer. Returns value to pass to next() (can + // be ignored if default bass_freq is acceptable). + int begin( Blip_Buffer& ); + + // Current sample + long read() const { return accum >> (blip_sample_bits - 16); } + + // Current raw sample in full internal resolution + long read_raw() const { return accum; } + + // Advance to next sample + void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); } + + // End reading samples from buffer. The number of samples read must now be removed + // using Blip_Buffer::remove_samples(). + void end( Blip_Buffer& b ) { b.reader_accum = accum; } + +private: + const Blip_Buffer::buf_t_* buf; + long accum; +}; + + +// End of public interface + + +#include + +// Compatibility with older version +const long blip_unscaled = 65535; +const int blip_low_quality = blip_med_quality; +const int blip_best_quality = blip_high_quality; + +#define BLIP_FWD( i ) { \ + long t0 = i0 * delta + buf [fwd + i]; \ + long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i]; \ + i0 = imp [blip_res * (i + 2)]; \ + buf [fwd + i] = t0; \ + buf [fwd + 1 + i] = t1; } + +#define BLIP_REV( r ) { \ + long t0 = i0 * delta + buf [rev - r]; \ + long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r]; \ + i0 = imp [blip_res * (r - 1)]; \ + buf [rev - r] = t0; \ + buf [rev + 1 - r] = t1; } + +template +inline void Blip_Synth::offset_resampled( blip_resampled_time_t time, + int delta, Blip_Buffer* blip_buf ) const +{ + // Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the + // need for a longer buffer as set by set_sample_rate(). + assert( (long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); + delta *= impl.delta_factor; + int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1)); + imp_t const* imp = impulses + blip_res - phase; + long* buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); + long i0 = *imp; + + int const fwd = (blip_widest_impulse_ - quality) / 2; + int const rev = fwd + quality - 2; + + BLIP_FWD( 0 ) + if ( quality > 8 ) BLIP_FWD( 2 ) + if ( quality > 12 ) BLIP_FWD( 4 ) + { + int const mid = quality / 2 - 1; + long t0 = i0 * delta + buf [fwd + mid - 1]; + long t1 = imp [blip_res * mid] * delta + buf [fwd + mid]; + imp = impulses + phase; + i0 = imp [blip_res * mid]; + buf [fwd + mid - 1] = t0; + buf [fwd + mid] = t1; + } + if ( quality > 12 ) BLIP_REV( 6 ) + if ( quality > 8 ) BLIP_REV( 4 ) + BLIP_REV( 2 ) + + long t0 = i0 * delta + buf [rev]; + long t1 = *imp * delta + buf [rev + 1]; + buf [rev] = t0; + buf [rev + 1] = t1; +} + +#undef BLIP_FWD +#undef BLIP_REV + +template +void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const +{ + offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); +} + +template +void Blip_Synth::update( blip_time_t t, int amp ) +{ + int delta = amp - impl.last_amp; + impl.last_amp = amp; + offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); +} + +inline blip_eq_t::blip_eq_t( double t ) : + treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { } +inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) : + treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { } + +inline int Blip_Buffer::length() const { return length_; } +inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); } +inline long Blip_Buffer::sample_rate() const { return sample_rate_; } +inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } +inline long Blip_Buffer::clock_rate() const { return clock_rate_; } +inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); } + +inline int Blip_Reader::begin( Blip_Buffer& blip_buf ) +{ + buf = blip_buf.buffer_; + accum = blip_buf.reader_accum; + return blip_buf.bass_shift; +} + +int const blip_max_length = 0; +int const blip_default_length = 250; + +#endif + diff --git a/include/gme/Classic_Emu.h b/include/gme/Classic_Emu.h new file mode 100644 index 0000000000..16ed3c76bf --- /dev/null +++ b/include/gme/Classic_Emu.h @@ -0,0 +1,48 @@ + +// Classic game music emulator interface base class for emulators which use Blip_Buffer +// for sound output. + +// Game_Music_Emu 0.3.0 + +#ifndef CLASSIC_EMU_H +#define CLASSIC_EMU_H + +#include "Music_Emu.h" +class Blip_Buffer; +class blip_eq_t; +typedef long blip_time_t; + +class Classic_Emu : public Music_Emu { +public: + Classic_Emu(); + ~Classic_Emu(); + blargg_err_t set_sample_rate( long sample_rate ); + void set_buffer( Multi_Buffer* ); + void mute_voices( int ); + void play( long, sample_t* ); + void start_track( int track ); + void set_equalizer( equalizer_t const& ); +public: + // deprecated + blargg_err_t init( long rate ) { return set_sample_rate( rate ); } +protected: + virtual blargg_err_t setup_buffer( long clock_rate ); + virtual void set_voice( int index, Blip_Buffer* center, + Blip_Buffer* left, Blip_Buffer* right ) = 0; + virtual blip_time_t run( int msec, bool* added_stereo ); + virtual blip_time_t run_clocks( blip_time_t, bool* added_stereo ); + virtual void update_eq( blip_eq_t const& ) = 0; +private: + Multi_Buffer* buf; + Multi_Buffer* stereo_buffer; + long clock_rate; +}; + +inline void Classic_Emu::set_buffer( Multi_Buffer* new_buf ) +{ + assert( !buf && new_buf ); + buf = new_buf; +} + +#endif + diff --git a/include/gme/Dual_Resampler.h b/include/gme/Dual_Resampler.h new file mode 100644 index 0000000000..0bd1e1711a --- /dev/null +++ b/include/gme/Dual_Resampler.h @@ -0,0 +1,49 @@ + +// Combination of Fir_Resampler and Blip_Buffer mixing. Used by Sega FM emulators. + +// Game_Music_Emu 0.3.0 + +#ifndef DUAL_RESAMPLER_H +#define DUAL_RESAMPLER_H + +#include "Fir_Resampler.h" +#include "Blip_Buffer.h" + +class Dual_Resampler { +public: + Dual_Resampler(); + virtual ~Dual_Resampler(); + + typedef short sample_t; + + double setup( double oversample, double rolloff, double gain ); + blargg_err_t resize( int pairs ); + void clear(); + + void play( long count, sample_t* out, Blip_Buffer& ); + +protected: + virtual int play_frame( blip_time_t, int pcm_count, sample_t* pcm_out ) = 0; +private: + + blargg_vector sample_buf; + int oversamples_per_frame; + int buf_pos; + Fir_Resampler<12> resampler; + void mix_samples( Blip_Buffer&, sample_t* ); + void play_frame_( Blip_Buffer&, sample_t* ); +}; + +inline double Dual_Resampler::setup( double oversample, double rolloff, double gain ) +{ + return resampler.time_ratio( oversample, rolloff, gain * 0.5 ); +} + +inline void Dual_Resampler::clear() +{ + buf_pos = sample_buf.size(); + resampler.clear(); +} + +#endif + diff --git a/include/gme/Effects_Buffer.h b/include/gme/Effects_Buffer.h new file mode 100644 index 0000000000..597bb7e852 --- /dev/null +++ b/include/gme/Effects_Buffer.h @@ -0,0 +1,92 @@ + +// Multi-channel effects buffer with panning, echo and reverb + +// Game_Music_Emu 0.3.0 + +#ifndef EFFECTS_BUFFER_H +#define EFFECTS_BUFFER_H + +#include "Multi_Buffer.h" + +// Effects_Buffer uses several buffers and outputs stereo sample pairs. +class Effects_Buffer : public Multi_Buffer { +public: + // If center_only is true, only center buffers are created and + // less memory is used. + Effects_Buffer( bool center_only = false ); + + // Channel Effect Center Pan + // --------------------------------- + // 0,5 reverb pan_1 + // 1,6 reverb pan_2 + // 2,7 echo - + // 3 echo - + // 4 echo - + + // Channel configuration + struct config_t { + double pan_1; // -1.0 = left, 0.0 = center, 1.0 = right + double pan_2; + double echo_delay; // msec + double echo_level; // 0.0 to 1.0 + double reverb_delay; // msec + double delay_variance; // difference between left/right delays (msec) + double reverb_level; // 0.0 to 1.0 + bool effects_enabled; // if false, use optimized simple mixer + config_t(); + }; + + // Set configuration of buffer + void config( const config_t& ); + +public: + ~Effects_Buffer(); + blargg_err_t set_sample_rate( long samples_per_sec, int msec = blip_default_length ); + void clock_rate( long ); + void bass_freq( int ); + void clear(); + channel_t channel( int ); + void end_frame( blip_time_t, bool was_stereo = true ); + long read_samples( blip_sample_t*, long ); + long samples_avail() const; +private: + typedef long fixed_t; + + enum { max_buf_count = 7 }; + Blip_Buffer bufs [max_buf_count]; + enum { chan_count = 5 }; + channel_t channels [chan_count]; + config_t config_; + long stereo_remain; + long effect_remain; + int buf_count; + bool effects_enabled; + + blip_sample_t* reverb_buf; + blip_sample_t* echo_buf; + int reverb_pos; + int echo_pos; + + struct { + fixed_t pan_1_levels [2]; + fixed_t pan_2_levels [2]; + int echo_delay_l; + int echo_delay_r; + fixed_t echo_level; + int reverb_delay_l; + int reverb_delay_r; + fixed_t reverb_level; + } chans; + + void mix_mono( blip_sample_t*, long ); + void mix_stereo( blip_sample_t*, long ); + void mix_enhanced( blip_sample_t*, long ); + void mix_mono_enhanced( blip_sample_t*, long ); +}; + + inline Effects_Buffer::channel_t Effects_Buffer::channel( int i ) { + return channels [i % chan_count]; + } + +#endif + diff --git a/include/gme/Fir_Resampler.h b/include/gme/Fir_Resampler.h new file mode 100644 index 0000000000..67731a202d --- /dev/null +++ b/include/gme/Fir_Resampler.h @@ -0,0 +1,174 @@ + +// Finite impulse response (FIR) resampler with adjustable FIR size + +// Game_Music_Emu 0.3.0 + +#ifndef FIR_RESAMPLER_H +#define FIR_RESAMPLER_H + +#include "blargg_common.h" +#include + +class Fir_Resampler_ { +public: + + // Use Fir_Resampler (below) + + // Set input/output resampling ratio and optionally low-pass rolloff and gain. + // Returns actual ratio used (rounded to internal precision). + double time_ratio( double factor, double rolloff = 0.999, double gain = 1.0 ); + + // Current input/output ratio + double ratio() const { return ratio_; } + +// Input + + typedef short sample_t; + + // Resize and clear input buffer + blargg_err_t buffer_size( int ); + + // Clear input buffer. At least two output samples will be available after + // two input samples are written. + void clear(); + + // Number of input samples that can be written + int max_write() const { return buf.end() - write_pos; } + + // Pointer to place to write input samples + sample_t* buffer() { return write_pos; } + + // Notify resampler that 'count' input samples have been written + void write( long count ); + + // Number of input samples in buffer + int written() const { return write_pos - &buf [write_offset]; } + + // Skip 'count' input samples. Returns number of samples actually skipped. + int skip_input( long count ); + +// Output + + // Number of extra input samples needed until 'count' output samples are available + int input_needed( long count ) const; + + // Number of output samples available + int avail() const { return avail_( write_pos - &buf [width_ * stereo] ); } + +public: + ~Fir_Resampler_(); +protected: + enum { stereo = 2 }; + enum { max_res = 32 }; + blargg_vector buf; + sample_t* write_pos; + int res; + int imp; + int const width_; + int const write_offset; + unsigned long skip_bits; + int step; + int input_per_cycle; + double ratio_; + sample_t* impulses; + + Fir_Resampler_( int width, sample_t* ); + int avail_( long input_count ) const; +}; + +// Width is number of points in FIR. Must be even and 4 or more. More points give +// better quality and rolloff effectiveness, and take longer to calculate. +template +class Fir_Resampler : public Fir_Resampler_ { + BOOST_STATIC_ASSERT( width >= 4 && width % 2 == 0 ); + short impulses [max_res] [width]; +public: + Fir_Resampler() : Fir_Resampler_( width, impulses [0] ) { } + + // Read at most 'count' samples. Returns number of samples actually read. + typedef short sample_t; + int read( sample_t* out, long count ); +}; + +// End of public interface + +inline void Fir_Resampler_::write( long count ) +{ + write_pos += count; + assert( write_pos <= buf.end() ); +} + +template +int Fir_Resampler::read( sample_t* out_begin, long count ) +{ + sample_t* out = out_begin; + const sample_t* in = buf.begin(); + sample_t* end_pos = write_pos; + unsigned long skip = skip_bits >> this->imp; + sample_t const* imp = impulses [this->imp]; + int remain = res - this->imp; + int const step = this->step; + + count >>= 1; + + if ( end_pos - in >= width * stereo ) + { + end_pos -= width * stereo; + do + { + count--; + + // accumulate in extended precision + long l = 0; + long r = 0; + + const sample_t* i = in; + if ( count < 0 ) + break; + + for ( int n = width / 2; n; --n ) + { + int pt0 = imp [0]; + l += pt0 * i [0]; + r += pt0 * i [1]; + int pt1 = imp [1]; + imp += 2; + l += pt1 * i [2]; + r += pt1 * i [3]; + i += 4; + } + + remain--; + + l >>= 15; + r >>= 15; + + in += (skip * stereo) & stereo; + skip >>= 1; + in += step; + + if ( !remain ) + { + imp = impulses [0]; + skip = skip_bits; + remain = res; + } + + out [0] = l; + out [1] = r; + out += 2; + } + while ( in <= end_pos ); + } + + this->imp = res - remain; + + int left = write_pos - in; + write_pos = &buf [left]; + memmove( buf.begin(), in, left * sizeof *in ); + + return out - out_begin; +} + +#endif + diff --git a/include/gme/Gb_Apu.h b/include/gme/Gb_Apu.h new file mode 100644 index 0000000000..05b72cf307 --- /dev/null +++ b/include/gme/Gb_Apu.h @@ -0,0 +1,97 @@ + +// Nintendo Game Boy PAPU sound chip emulator + +// Gb_Snd_Emu 0.1.4 + +#ifndef GB_APU_H +#define GB_APU_H + +typedef long gb_time_t; // clock cycle count +typedef unsigned gb_addr_t; // 16-bit address + +#include "Gb_Oscs.h" + +class Gb_Apu { +public: + + // Set overall volume of all oscillators, where 1.0 is full volume + void volume( double ); + + // Set treble equalization + void treble_eq( const blip_eq_t& ); + + // Outputs can be assigned to a single buffer for mono output, or to three + // buffers for stereo output (using Stereo_Buffer to do the mixing). + + // Assign all oscillator outputs to specified buffer(s). If buffer + // is NULL, silences all oscillators. + void output( Blip_Buffer* mono ); + void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); + + // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3, + // which refer to Square 1, Square 2, Wave, and Noise. If buffer is NULL, + // silences oscillator. + enum { osc_count = 4 }; + void osc_output( int index, Blip_Buffer* mono ); + void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); + + // Reset oscillators and internal state + void reset(); + + // Reads and writes at addr must satisfy start_addr <= addr <= end_addr + enum { start_addr = 0xFF10 }; + enum { end_addr = 0xFF3f }; + enum { register_count = end_addr - start_addr + 1 }; + + // Write 'data' to address at specified time + void write_register( gb_time_t, gb_addr_t, int data ); + + // Read from address at specified time + int read_register( gb_time_t, gb_addr_t ); + + // Run all oscillators up to specified time, end current time frame, then + // start a new frame at time 0. Returns true if any oscillators added + // sound to one of the left/right buffers, false if they only added + // to the center buffer. + bool end_frame( gb_time_t ); + +public: + Gb_Apu(); + ~Gb_Apu(); +private: + // noncopyable + Gb_Apu( const Gb_Apu& ); + Gb_Apu& operator = ( const Gb_Apu& ); + + Gb_Osc* oscs [osc_count]; + gb_time_t next_frame_time; + gb_time_t last_time; + double volume_unit; + int frame_count; + bool stereo_found; + + Gb_Square square1; + Gb_Square square2; + Gb_Wave wave; + Gb_Noise noise; + BOOST::uint8_t regs [register_count]; + Gb_Square::Synth square_synth; // used by squares + Gb_Wave::Synth other_synth; // used by wave and noise + + void update_volume(); + void run_until( gb_time_t ); + void write_osc( int index, int reg, int data ); +}; + +inline void Gb_Apu::output( Blip_Buffer* b ) { output( b, b, b ); } + +inline void Gb_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); } + +inline void Gb_Apu::volume( double vol ) +{ + volume_unit = 0.60 / osc_count / 15 /*steps*/ / 2 /*?*/ / 8 /*master vol range*/ * vol; + update_volume(); +} + +#endif + diff --git a/include/gme/Gb_Cpu.h b/include/gme/Gb_Cpu.h new file mode 100644 index 0000000000..e143ec6a71 --- /dev/null +++ b/include/gme/Gb_Cpu.h @@ -0,0 +1,103 @@ + +// Nintendo Game Boy CPU emulator + +// Game_Music_Emu 0.3.0 + +#ifndef GB_CPU_H +#define GB_CPU_H + +#include "blargg_common.h" + +typedef unsigned gb_addr_t; // 16-bit CPU address + +class Gbs_Emu; + +// Game Boy CPU emulator. Currently treats every instruction as taking 4 cycles. +class Gb_Cpu { + typedef BOOST::uint8_t uint8_t; + enum { page_bits = 8 }; + enum { page_count = 0x10000 >> page_bits }; + uint8_t const* code_map [page_count + 1]; + long remain_; + Gbs_Emu* callback_data; +public: + + Gb_Cpu( Gbs_Emu* ); + + // Memory read/write function types. Reader must return value from 0 to 255. + typedef int (*reader_t)( Gbs_Emu*, gb_addr_t ); + typedef void (*writer_t)( Gbs_Emu*, gb_addr_t, int data ); + + // Clear registers, unmap memory, and map code pages to unmapped_page. + void reset( const void* unmapped_page = NULL, reader_t read = NULL, writer_t write = NULL ); + + // Memory mapping functions take a block of memory of specified 'start' address + // and 'size' in bytes. Both start address and size must be a multiple of page_size. + enum { page_size = 1L << page_bits }; + + // Map code memory to 'code' (memory accessed via the program counter) + void map_code( gb_addr_t start, unsigned long size, const void* code ); + + // Map data memory to read and write functions + void map_memory( gb_addr_t start, unsigned long size, reader_t, writer_t ); + + // Access memory as the emulated CPU does. + int read( gb_addr_t ); + void write( gb_addr_t, int data ); + uint8_t* get_code( gb_addr_t ); // non-const to allow debugger to modify code + + // Push a byte on the stack + void push_byte( int ); + + // Game Boy Z80 registers. *Not* kept updated during a call to run(). + struct registers_t { + long pc; // more than 16 bits to allow overflow detection + BOOST::uint16_t sp; + uint8_t flags; + uint8_t a; + uint8_t b; + uint8_t c; + uint8_t d; + uint8_t e; + uint8_t h; + uint8_t l; + }; + registers_t r; + + // Interrupt enable flag set by EI and cleared by DI + bool interrupts_enabled; + + // Base address for RST vectors (normally 0) + gb_addr_t rst_base; + + // Reasons that run() returns + enum result_t { + result_cycles, // Requested number of cycles (or more) were executed + result_halt, // PC is at HALT instruction + result_badop // PC is at bad (unimplemented) instruction + }; + + // Run CPU for at least 'count' cycles, or until one of the above conditions + // arises. Returns reason for stopping. + result_t run( long count ); + + // Number of clock cycles remaining for most recent run() call + long remain() const; + +private: + // noncopyable + Gb_Cpu( const Gb_Cpu& ); + Gb_Cpu& operator = ( const Gb_Cpu& ); + + reader_t data_reader [page_count + 1]; // extra entry catches address overflow + writer_t data_writer [page_count + 1]; + void set_code_page( int, uint8_t const* ); +}; + +inline long Gb_Cpu::remain() const +{ + return remain_; +} + +#endif + diff --git a/include/gme/Gb_Oscs.h b/include/gme/Gb_Oscs.h new file mode 100644 index 0000000000..544cd4709e --- /dev/null +++ b/include/gme/Gb_Oscs.h @@ -0,0 +1,86 @@ + +// Private oscillators used by Gb_Apu + +// Gb_Snd_Emu 0.1.4 + +#ifndef GB_OSCS_H +#define GB_OSCS_H + +#include "blargg_common.h" +#include "Blip_Buffer.h" + +struct Gb_Osc +{ + enum { trigger = 0x80 }; + enum { len_enabled_mask = 0x40 }; + + Blip_Buffer* outputs [4]; // NULL, right, left, center + Blip_Buffer* output; + int output_select; + BOOST::uint8_t* regs; // osc's 5 registers + + int delay; + int last_amp; + int volume; + int length; + bool enabled; + + void reset(); + void clock_length(); + int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; } +}; + +struct Gb_Env : Gb_Osc +{ + int env_delay; + + void reset(); + void clock_envelope(); + bool write_register( int, int ); +}; + +struct Gb_Square : Gb_Env +{ + enum { period_mask = 0x70 }; + enum { shift_mask = 0x07 }; + + typedef Blip_Synth Synth; + Synth const* synth; + int sweep_delay; + int sweep_freq; + int phase; + + void reset(); + void clock_sweep(); + void run( gb_time_t, gb_time_t, int playing ); +}; + +struct Gb_Noise : Gb_Env +{ + typedef Blip_Synth Synth; + Synth const* synth; + unsigned bits; + + void run( gb_time_t, gb_time_t, int playing ); +}; + +struct Gb_Wave : Gb_Osc +{ + typedef Blip_Synth Synth; + Synth const* synth; + int wave_pos; + enum { wave_size = 32 }; + BOOST::uint8_t wave [wave_size]; + + void write_register( int, int ); + void run( gb_time_t, gb_time_t, int playing ); +}; + +inline void Gb_Env::reset() +{ + env_delay = 0; + Gb_Osc::reset(); +} + +#endif + diff --git a/include/gme/Gbs_Emu.h b/include/gme/Gbs_Emu.h new file mode 100644 index 0000000000..8f1822bcbc --- /dev/null +++ b/include/gme/Gbs_Emu.h @@ -0,0 +1,108 @@ + +// Nintendo Game Boy GBS music file emulator + +// Game_Music_Emu 0.3.0 + +#ifndef GBS_EMU_H +#define GBS_EMU_H + +#include "Classic_Emu.h" +#include "Gb_Apu.h" +#include "Gb_Cpu.h" + +class Gbs_Emu : public Classic_Emu { +public: + + // Sets internal gain, where 1.0 results in almost no clamping. Default gain + // roughly matches volume of other emulators. + Gbs_Emu( double gain = 1.2 ); + + // GBS file header + struct header_t + { + char tag [3]; + byte vers; + byte track_count; + byte first_track; + byte load_addr [2]; + byte init_addr [2]; + byte play_addr [2]; + byte stack_ptr [2]; + byte timer_modulo; + byte timer_mode; + char game [32]; + char author [32]; + char copyright [32]; + + enum { song = 0 }; // no song titles + }; + BOOST_STATIC_ASSERT( sizeof (header_t) == 112 ); + + // Load GBS data + blargg_err_t load( Data_Reader& ); + + // Load GBS using already-loaded header and remaining data + blargg_err_t load( header_t const&, Data_Reader& ); + + // Header for currently loaded GBS + header_t const& header() const { return header_; } + + // Equalizer profiles for Game Boy Color speaker and headphones + static equalizer_t const handheld_eq; + static equalizer_t const headphones_eq; + +public: + ~Gbs_Emu(); + const char** voice_names() const; + void start_track( int ); +protected: + void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); + void update_eq( blip_eq_t const& ); + blip_time_t run_clocks( blip_time_t, bool* ); +private: + // rom + const byte* rom_bank; + blargg_vector rom; + void unload(); + int bank_count; + void set_bank( int ); + static void write_rom( Gbs_Emu*, gb_addr_t, int ); + static int read_rom( Gbs_Emu*, gb_addr_t ); + static int read_bank( Gbs_Emu*, gb_addr_t ); + + // state + gb_addr_t load_addr; + gb_addr_t init_addr; + gb_addr_t play_addr; + gb_addr_t stack_ptr; + int timer_modulo_init; + int timer_mode; + + // timer + gb_time_t cpu_time; + gb_time_t play_period; + gb_time_t next_play; + int double_speed; + + // hardware + Gb_Apu apu; + void set_timer( int tma, int tmc ); + static int read_io( Gbs_Emu*, gb_addr_t ); + static void write_io( Gbs_Emu*, gb_addr_t, int ); + static int read_unmapped( Gbs_Emu*, gb_addr_t ); + static void write_unmapped( Gbs_Emu*, gb_addr_t, int ); + + // large objects + + header_t header_; + byte hi_page [0x100]; + Gb_Cpu cpu; + void cpu_jsr( gb_addr_t ); + gb_time_t clock() const; + byte ram [0x4000]; + static int read_ram( Gbs_Emu*, gb_addr_t ); + static void write_ram( Gbs_Emu*, gb_addr_t, int ); +}; + +#endif + diff --git a/include/gme/Gym_Emu.h b/include/gme/Gym_Emu.h new file mode 100644 index 0000000000..a2684c791c --- /dev/null +++ b/include/gme/Gym_Emu.h @@ -0,0 +1,96 @@ + +// Sega Genesis GYM music file emulator + +// Game_Music_Emu 0.3.0 + +#ifndef GYM_EMU_H +#define GYM_EMU_H + +#include "Dual_Resampler.h" +#include "Ym2612_Emu.h" +#include "Music_Emu.h" +#include "Sms_Apu.h" + +class Gym_Emu : public Music_Emu, private Dual_Resampler { +public: + + // GYM file header + struct header_t + { + char tag [4]; + char song [32]; + char game [32]; + char copyright [32]; + char emulator [32]; + char dumper [32]; + char comment [256]; + byte loop_start [4]; // in 1/60 seconds, 0 if not looped + byte packed [4]; + + enum { track_count = 1 }; // one track per file + enum { author = 0 }; // no author field + }; + BOOST_STATIC_ASSERT( sizeof (header_t) == 428 ); + + // Load GYM data + blargg_err_t load( Data_Reader& ); + + // Load GYM file using already-loaded header and remaining data + blargg_err_t load( header_t const&, Data_Reader& ); + blargg_err_t load( void const* data, long size ); // keeps pointer to data + + // Header for currently loaded GYM (cleared to zero if GYM lacks header) + header_t const& header() const { return header_; } + + // Length of track in 1/60 seconds + enum { gym_rate = 60 }; // GYM time units (frames) per second + long track_length() const; + +public: + typedef Music_Emu::sample_t sample_t; + Gym_Emu(); + ~Gym_Emu(); + blargg_err_t set_sample_rate( long sample_rate ); + void mute_voices( int ); + void start_track( int ); + void play( long count, sample_t* ); + const char** voice_names() const; + void skip( long count ); +public: + // deprecated + blargg_err_t init( long r, double gain = 1.5, double oversample = 5 / 3.0 ) + { + return set_sample_rate( r ); + } +protected: + int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf ); +private: + // sequence data begin, loop begin, current position, end + const byte* data; + const byte* loop_begin; + const byte* pos; + const byte* data_end; + long loop_remain; // frames remaining until loop beginning has been located + blargg_vector mem; + header_t header_; + blargg_err_t load_( const void* file, long data_offset, long file_size ); + void unload(); + void parse_frame(); + + // dac (pcm) + int dac_amp; + int prev_dac_count; + bool dac_enabled; + bool dac_muted; + void run_dac( int ); + + // sound + Blip_Buffer blip_buf; + Ym2612_Emu fm; + Blip_Synth dac_synth; + Sms_Apu apu; + byte dac_buf [1024]; +}; + +#endif + diff --git a/include/gme/Gzip_File.h b/include/gme/Gzip_File.h new file mode 100644 index 0000000000..dd692a9881 --- /dev/null +++ b/include/gme/Gzip_File.h @@ -0,0 +1,43 @@ + +// Gzip file access + +#ifndef GZIP_FILE_H +#define GZIP_FILE_H + +#include "abstract_file.h" + +// Get size of gzipped file data (or size of file if not gzipped). NULL +// on success, otherwise error string. +const char* get_gzip_eof( const char* path, long* eof_out ); + +class Gzip_File_Reader : public File_Reader { + void* file_; + long size_; +public: + Gzip_File_Reader(); + ~Gzip_File_Reader(); + + error_t open( const char* ); + + long size() const; + long read_avail( void*, long ); + + long tell() const; + error_t seek( long ); + + void close(); +}; + +class Gzip_File_Writer : public Data_Writer { + void* file_; +public: + Gzip_File_Writer(); + ~Gzip_File_Writer(); + + error_t open( const char* ); + error_t write( const void*, long ); + void close(); +}; + +#endif + diff --git a/include/gme/Multi_Buffer.h b/include/gme/Multi_Buffer.h new file mode 100644 index 0000000000..734224531e --- /dev/null +++ b/include/gme/Multi_Buffer.h @@ -0,0 +1,175 @@ + +// Multi-channel sound buffer interface, and basic mono and stereo buffers + +// Blip_Buffer 0.4.0 + +#ifndef MULTI_BUFFER_H +#define MULTI_BUFFER_H + +#include "blargg_common.h" +#include "Blip_Buffer.h" + +// Interface to one or more Blip_Buffers mapped to one or more channels +// consisting of left, center, and right buffers. +class Multi_Buffer { +public: + Multi_Buffer( int samples_per_frame ); + virtual ~Multi_Buffer() { } + + // Set the number of channels available + virtual blargg_err_t set_channel_count( int ); + + // Get indexed channel, from 0 to channel count - 1 + struct channel_t { + Blip_Buffer* center; + Blip_Buffer* left; + Blip_Buffer* right; + }; + virtual channel_t channel( int index ) = 0; + + // See Blip_Buffer.h + virtual blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ) = 0; + virtual void clock_rate( long ) = 0; + virtual void bass_freq( int ) = 0; + virtual void clear() = 0; + long sample_rate() const; + + // Length of buffer, in milliseconds + int length() const; + + // See Blip_Buffer.h. For optimal operation, pass false for 'added_stereo' + // if nothing was added to the left and right buffers of any channel for + // this time frame. + virtual void end_frame( blip_time_t, bool added_stereo = true ) = 0; + + // Number of samples per output frame (1 = mono, 2 = stereo) + int samples_per_frame() const; + + // Count of changes to channel configuration. Incremented whenever + // a change is made to any of the Blip_Buffers for any channel. + unsigned channels_changed_count() { return channels_changed_count_; } + + // See Blip_Buffer.h + virtual long read_samples( blip_sample_t*, long ) = 0; + virtual long samples_avail() const = 0; + +protected: + void channels_changed() { channels_changed_count_++; } +private: + // noncopyable + Multi_Buffer( const Multi_Buffer& ); + Multi_Buffer& operator = ( const Multi_Buffer& ); + + unsigned channels_changed_count_; + long sample_rate_; + int length_; + int const samples_per_frame_; +}; + +// Uses a single buffer and outputs mono samples. +class Mono_Buffer : public Multi_Buffer { + Blip_Buffer buf; +public: + Mono_Buffer(); + ~Mono_Buffer(); + + // Buffer used for all channels + Blip_Buffer* center() { return &buf; } + + // See Multi_Buffer + blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ); + void clock_rate( long ); + void bass_freq( int ); + void clear(); + channel_t channel( int ); + void end_frame( blip_time_t, bool unused = true ); + long samples_avail() const; + long read_samples( blip_sample_t*, long ); +}; + +// Uses three buffers (one for center) and outputs stereo sample pairs. +class Stereo_Buffer : public Multi_Buffer { +public: + Stereo_Buffer(); + ~Stereo_Buffer(); + + // Buffers used for all channels + Blip_Buffer* center() { return &bufs [0]; } + Blip_Buffer* left() { return &bufs [1]; } + Blip_Buffer* right() { return &bufs [2]; } + + // See Multi_Buffer + blargg_err_t set_sample_rate( long, int msec = blip_default_length ); + void clock_rate( long ); + void bass_freq( int ); + void clear(); + channel_t channel( int index ); + void end_frame( blip_time_t, bool added_stereo = true ); + + long samples_avail() const; + long read_samples( blip_sample_t*, long ); + +private: + enum { buf_count = 3 }; + Blip_Buffer bufs [buf_count]; + channel_t chan; + bool stereo_added; + bool was_stereo; + + void mix_stereo( blip_sample_t*, long ); + void mix_mono( blip_sample_t*, long ); +}; + +// Silent_Buffer generates no samples, useful where no sound is wanted +class Silent_Buffer : public Multi_Buffer { + channel_t chan; +public: + Silent_Buffer(); + + blargg_err_t set_sample_rate( long rate, int msec = blip_default_length ); + void clock_rate( long ) { } + void bass_freq( int ) { } + void clear() { } + channel_t channel( int ) { return chan; } + void end_frame( blip_time_t, bool unused = true ) { } + long samples_avail() const { return 0; } + long read_samples( blip_sample_t*, long ) { return 0; } +}; + + +// End of public interface + +inline blargg_err_t Multi_Buffer::set_sample_rate( long rate, int msec ) +{ + sample_rate_ = rate; + length_ = msec; + return blargg_success; +} + +inline blargg_err_t Silent_Buffer::set_sample_rate( long rate, int msec ) +{ + return Multi_Buffer::set_sample_rate( rate, msec ); +} + +inline int Multi_Buffer::samples_per_frame() const { return samples_per_frame_; } + +inline long Stereo_Buffer::samples_avail() const { return bufs [0].samples_avail() * 2; } + +inline Stereo_Buffer::channel_t Stereo_Buffer::channel( int ) { return chan; } + +inline long Multi_Buffer::sample_rate() const { return sample_rate_; } + +inline int Multi_Buffer::length() const { return length_; } + +inline void Mono_Buffer::clock_rate( long rate ) { buf.clock_rate( rate ); } + +inline void Mono_Buffer::clear() { buf.clear(); } + +inline void Mono_Buffer::bass_freq( int freq ) { buf.bass_freq( freq ); } + +inline long Mono_Buffer::read_samples( blip_sample_t* p, long s ) { return buf.read_samples( p, s ); } + +inline long Mono_Buffer::samples_avail() const { return buf.samples_avail(); } + +#endif + diff --git a/include/gme/Music_Emu.h b/include/gme/Music_Emu.h new file mode 100644 index 0000000000..a67cf38fc7 --- /dev/null +++ b/include/gme/Music_Emu.h @@ -0,0 +1,137 @@ + +// Game music emulator interface base class + +// Game_Music_Emu 0.3.0 + +#ifndef MUSIC_EMU_H +#define MUSIC_EMU_H + +#include "blargg_common.h" +#include "abstract_file.h" +class Multi_Buffer; + +class Music_Emu { +public: + + // Initialize emulator with specified sample rate. Currently should only be + // called once. + virtual blargg_err_t set_sample_rate( long sample_rate ) = 0; + + // Load music file + blargg_err_t load_file( const char* path ); + + // Start a track, where 0 is the first track. Might un-mute any muted voices. + virtual void start_track( int ) = 0; + + // Generate 'count' samples info 'buf'. Output is in stereo unless using custom + // buffer that generates mono output. + typedef short sample_t; + virtual void play( long count, sample_t* buf ) = 0; + +// Additional optional features + + // Request use of custom multichannel buffer. Only supported by "classic" emulators; + // on others this has no effect. Should be called only once *before* set_sample_rate(). + virtual void set_buffer( Multi_Buffer* ) { } + + // Load music file data from custom source + virtual blargg_err_t load( Data_Reader& ) = 0; + + // Sample rate sound is generated at + long sample_rate() const; + + // Number of voices used by currently loaded file + int voice_count() const; + + // Names of voices + virtual const char** voice_names() const; + + // Mute voice n if bit n (1 << n) of mask is set + virtual void mute_voices( int mask ); + + // Frequency equalizer parameters (see notes.txt) + struct equalizer_t { + double treble; // -50.0 = muffled, 0 = flat, +5.0 = extra-crisp + long bass; // 1 = full bass, 90 = average, 16000 = almost no bass + }; + + // Current frequency equalizater parameters + const equalizer_t& equalizer() const; + + // Set frequency equalizer parameters + virtual void set_equalizer( equalizer_t const& ); + + // Equalizer settings for TV speaker + static equalizer_t const tv_eq; + + // Number of tracks. Zero if file hasn't been loaded yet. + int track_count() const; + + // Skip 'count' samples + virtual void skip( long count ); + + // True if a track was started and has since ended. Currently only logged + // format tracks (VGM, GYM) without loop points have an ending. + bool track_ended() const; + + // Number of errors encountered while playing track due to undefined CPU + // instructions in emulated formats and undefined stream events in + // logged formats. + int error_count() const; + + Music_Emu(); + virtual ~Music_Emu(); + +protected: + typedef BOOST::uint8_t byte; + void set_voice_count( int n ) { voice_count_ = n; } + void set_track_count( int n ) { track_count_ = n; } + void set_track_ended( bool b = true ) { track_ended_ = b; } + void log_error() { error_count_++; } + void remute_voices(); +private: + // noncopyable + Music_Emu( const Music_Emu& ); + Music_Emu& operator = ( const Music_Emu& ); + + equalizer_t equalizer_; + long sample_rate_; + int voice_count_; + int mute_mask_; + int track_count_; + int error_count_; + bool track_ended_; +}; + +// Deprecated +typedef Data_Reader Emu_Reader; +typedef Std_File_Reader Emu_Std_Reader; +typedef Mem_File_Reader Emu_Mem_Reader; + +inline int Music_Emu::error_count() const { return error_count_; } +inline int Music_Emu::voice_count() const { return voice_count_; } +inline int Music_Emu::track_count() const { return track_count_; } +inline bool Music_Emu::track_ended() const { return track_ended_; } +inline void Music_Emu::mute_voices( int mask ) { mute_mask_ = mask; } +inline void Music_Emu::remute_voices() { mute_voices( mute_mask_ ); } +inline const Music_Emu::equalizer_t& Music_Emu::equalizer() const { return equalizer_; } +inline void Music_Emu::set_equalizer( const equalizer_t& eq ) { equalizer_ = eq; } +inline long Music_Emu::sample_rate() const { return sample_rate_; } + +inline blargg_err_t Music_Emu::set_sample_rate( long r ) +{ + assert( !sample_rate_ ); // sample rate can't be changed once set + sample_rate_ = r; + return blargg_success; +} + +inline void Music_Emu::start_track( int track ) +{ + assert( (unsigned) track <= (unsigned) track_count() ); + assert( sample_rate_ ); // set_sample_rate() must have been called first + track_ended_ = false; + error_count_ = 0; +} + +#endif + diff --git a/include/gme/Nes_Apu.h b/include/gme/Nes_Apu.h new file mode 100644 index 0000000000..dab2502460 --- /dev/null +++ b/include/gme/Nes_Apu.h @@ -0,0 +1,174 @@ + +// NES 2A03 APU sound chip emulator + +// Nes_Snd_Emu 0.1.7 + +#ifndef NES_APU_H +#define NES_APU_H + +typedef long nes_time_t; // CPU clock cycle count +typedef unsigned nes_addr_t; // 16-bit memory address + +#include "Nes_Oscs.h" + +struct apu_snapshot_t; +class Nonlinear_Buffer; + +class Nes_Apu { +public: + Nes_Apu(); + ~Nes_Apu(); + + // Set buffer to generate all sound into, or disable sound if NULL + void output( Blip_Buffer* ); + + // Set memory reader callback used by DMC oscillator to fetch samples. + // When callback is invoked, 'user_data' is passed unchanged as the + // first parameter. + void dmc_reader( int (*callback)( void* user_data, nes_addr_t ), void* user_data = NULL ); + + // All time values are the number of CPU clock cycles relative to the + // beginning of the current time frame. Before resetting the CPU clock + // count, call end_frame( last_cpu_time ). + + // Write to register (0x4000-0x4017, except 0x4014 and 0x4016) + enum { start_addr = 0x4000 }; + enum { end_addr = 0x4017 }; + void write_register( nes_time_t, nes_addr_t, int data ); + + // Read from status register at 0x4015 + enum { status_addr = 0x4015 }; + int read_status( nes_time_t ); + + // Run all oscillators up to specified time, end current time frame, then + // start a new time frame at time 0. Time frames have no effect on emulation + // and each can be whatever length is convenient. + void end_frame( nes_time_t ); + +// Additional optional features (can be ignored without any problem) + + // Reset internal frame counter, registers, and all oscillators. + // Use PAL timing if pal_timing is true, otherwise use NTSC timing. + // Set the DMC oscillator's initial DAC value to initial_dmc_dac without + // any audible click. + void reset( bool pal_timing = false, int initial_dmc_dac = 0 ); + + // Save/load snapshot of exact emulation state + void save_snapshot( apu_snapshot_t* out ) const; + void load_snapshot( apu_snapshot_t const& ); + + // Set overall volume (default is 1.0) + void volume( double ); + + // Set treble equalization (see notes.txt) + void treble_eq( const blip_eq_t& ); + + // Set sound output of specific oscillator to buffer. If buffer is NULL, + // the specified oscillator is muted and emulation accuracy is reduced. + // The oscillators are indexed as follows: 0) Square 1, 1) Square 2, + // 2) Triangle, 3) Noise, 4) DMC. + enum { osc_count = 5 }; + void osc_output( int index, Blip_Buffer* buffer ); + + // Set IRQ time callback that is invoked when the time of earliest IRQ + // may have changed, or NULL to disable. When callback is invoked, + // 'user_data' is passed unchanged as the first parameter. + void irq_notifier( void (*callback)( void* user_data ), void* user_data = NULL ); + + // Get time that APU-generated IRQ will occur if no further register reads + // or writes occur. If IRQ is already pending, returns irq_waiting. If no + // IRQ will occur, returns no_irq. + enum { no_irq = LONG_MAX / 2 + 1 }; + enum { irq_waiting = 0 }; + nes_time_t earliest_irq( nes_time_t ) const; + + // Count number of DMC reads that would occur if 'run_until( t )' were executed. + // If last_read is not NULL, set *last_read to the earliest time that + // 'count_dmc_reads( time )' would result in the same result. + int count_dmc_reads( nes_time_t t, nes_time_t* last_read = NULL ) const; + + // Time when next DMC memory read will occur + nes_time_t next_dmc_read_time() const; + + // Run DMC until specified time, so that any DMC memory reads can be + // accounted for (i.e. inserting CPU wait states). + void run_until( nes_time_t ); + +// End of public interface. +private: + friend class Nes_Nonlinearizer; + void enable_nonlinear( double volume ); + static double nonlinear_tnd_gain() { return 0.75; } +private: + friend struct Nes_Dmc; + + // noncopyable + Nes_Apu( const Nes_Apu& ); + Nes_Apu& operator = ( const Nes_Apu& ); + + Nes_Osc* oscs [osc_count]; + Nes_Square square1; + Nes_Square square2; + Nes_Noise noise; + Nes_Triangle triangle; + Nes_Dmc dmc; + + nes_time_t last_time; // has been run until this time in current frame + nes_time_t last_dmc_time; + nes_time_t earliest_irq_; + nes_time_t next_irq; + int frame_period; + int frame_delay; // cycles until frame counter runs next + int frame; // current frame (0-3) + int osc_enables; + int frame_mode; + bool irq_flag; + void (*irq_notifier_)( void* user_data ); + void* irq_data; + Nes_Square::Synth square_synth; // shared by squares + + void irq_changed(); + void state_restored(); + void run_until_( nes_time_t ); +}; + +inline void Nes_Apu::osc_output( int osc, Blip_Buffer* buf ) +{ + assert( (unsigned) osc < osc_count ); + oscs [osc]->output = buf; +} + +inline nes_time_t Nes_Apu::earliest_irq( nes_time_t ) const +{ + return earliest_irq_; +} + +inline void Nes_Apu::dmc_reader( int (*func)( void*, nes_addr_t ), void* user_data ) +{ + dmc.rom_reader_data = user_data; + dmc.rom_reader = func; +} + +inline void Nes_Apu::irq_notifier( void (*func)( void* user_data ), void* user_data ) +{ + irq_notifier_ = func; + irq_data = user_data; +} + +inline int Nes_Apu::count_dmc_reads( nes_time_t time, nes_time_t* last_read ) const +{ + return dmc.count_reads( time, last_read ); +} + +inline nes_time_t Nes_Dmc::next_read_time() const +{ + if ( length_counter == 0 ) + return Nes_Apu::no_irq; // not reading + + return apu->last_dmc_time + delay + long (bits_remain - 1) * period; +} + +inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); } + +#endif + diff --git a/include/gme/Nes_Cpu.h b/include/gme/Nes_Cpu.h new file mode 100644 index 0000000000..52c07a8cf2 --- /dev/null +++ b/include/gme/Nes_Cpu.h @@ -0,0 +1,174 @@ + +// Nintendo Entertainment System (NES) 6502 CPU emulator + +// Game_Music_Emu 0.3.0 + +#ifndef NES_CPU_H +#define NES_CPU_H + +#include "blargg_common.h" + +typedef long nes_time_t; // clock cycle count +typedef unsigned nes_addr_t; // 16-bit address + +class Nes_Emu; + +class Nes_Cpu { + typedef BOOST::uint8_t uint8_t; + enum { page_bits = 11 }; + enum { page_count = 0x10000 >> page_bits }; + uint8_t const* code_map [page_count + 1]; +public: + Nes_Cpu(); + + // Memory read/write function types. Reader must return value from 0 to 255. + typedef int (*reader_t)( Nes_Emu*, nes_addr_t ); + typedef void (*writer_t)( Nes_Emu*, nes_addr_t, int data ); + void set_emu( Nes_Emu* emu ) { callback_data = emu; } + + // Clear registers, unmap memory, and map code pages to unmapped_page. + void reset( const void* unmapped_page = NULL, reader_t read = NULL, writer_t write = NULL ); + + // Memory mapping functions take a block of memory of specified 'start' address + // and 'size' in bytes. Both start address and size must be a multiple of page_size. + enum { page_size = 1L << page_bits }; + + // Map code memory (memory accessed via the program counter) + void map_code( nes_addr_t start, unsigned long size, const void* code ); + + // Set read function for address range + void set_reader( nes_addr_t start, unsigned long size, reader_t ); + + // Set write function for address range + void set_writer( nes_addr_t start, unsigned long size, writer_t ); + + // Set read and write functions for address range + void map_memory( nes_addr_t start, unsigned long size, reader_t, writer_t ); + + // Access memory as the emulated CPU does. + int read( nes_addr_t ); + void write( nes_addr_t, int data ); + uint8_t* get_code( nes_addr_t ); // non-const to allow debugger to modify code + + // Push a byte on the stack + void push_byte( int ); + + // NES 6502 registers. *Not* kept updated during a call to run(). + struct registers_t { + long pc; // more than 16 bits to allow overflow detection + BOOST::uint8_t a; + BOOST::uint8_t x; + BOOST::uint8_t y; + BOOST::uint8_t status; + BOOST::uint8_t sp; + }; + registers_t r; + + // Reasons that run() returns + enum result_t { + result_cycles, // Requested number of cycles (or more) were executed + result_sei, // I flag just set and IRQ time would generate IRQ now + result_cli, // I flag just cleared but IRQ should occur *after* next instr + result_badop // unimplemented/illegal instruction + }; + + result_t run( nes_time_t end_time_ ); + + nes_time_t time() const { return base_time + clock_count; } + void set_time( nes_time_t t ); + void end_frame( nes_time_t ); + nes_time_t end_time() const { return base_time + end_time_; } + nes_time_t irq_time() const { return base_time + irq_time_; } + void set_end_time( nes_time_t t ); + void set_irq_time( nes_time_t t ); + + // If PC exceeds 0xFFFF and encounters page_wrap_opcode, it will be silently wrapped. + enum { page_wrap_opcode = 0xF2 }; + + // One of the many opcodes that are undefined and stop CPU emulation. + enum { bad_opcode = 0xD2 }; + + // End of public interface +private: + // noncopyable + Nes_Cpu( const Nes_Cpu& ); + Nes_Cpu& operator = ( const Nes_Cpu& ); + + nes_time_t clock_limit; + nes_time_t base_time; + nes_time_t clock_count; + nes_time_t irq_time_; + nes_time_t end_time_; + + Nes_Emu* callback_data; + + enum { irq_inhibit = 0x04 }; + reader_t data_reader [page_count + 1]; // extra entry catches address overflow + writer_t data_writer [page_count + 1]; + void set_code_page( int, uint8_t const* ); + void update_clock_limit(); + +public: + // low_mem is a full page size so it can be mapped with code_map + uint8_t low_mem [page_size > 0x800 ? page_size : 0x800]; +}; + +inline BOOST::uint8_t* Nes_Cpu::get_code( nes_addr_t addr ) +{ + #if BLARGG_NONPORTABLE + return (uint8_t*) code_map [addr >> page_bits] + addr; + #else + return (uint8_t*) code_map [addr >> page_bits] + (addr & (page_size - 1)); + #endif +} + +inline void Nes_Cpu::update_clock_limit() +{ + nes_time_t t = end_time_; + if ( t > irq_time_ && !(r.status & irq_inhibit) ) + t = irq_time_; + clock_limit = t; +} + +inline void Nes_Cpu::set_end_time( nes_time_t t ) +{ + end_time_ = t - base_time; + update_clock_limit(); +} + +inline void Nes_Cpu::set_irq_time( nes_time_t t ) +{ + irq_time_ = t - base_time; + update_clock_limit(); +} + +inline void Nes_Cpu::end_frame( nes_time_t end_time_ ) +{ + base_time -= end_time_; + assert( time() >= 0 ); +} + +inline void Nes_Cpu::set_time( nes_time_t t ) +{ + t -= time(); + clock_limit -= t; + end_time_ -= t; + irq_time_ -= t; + base_time += t; +} + +inline void Nes_Cpu::push_byte( int data ) +{ + int sp = r.sp; + r.sp = (sp - 1) & 0xff; + low_mem [0x100 + sp] = data; +} + +inline void Nes_Cpu::map_memory( nes_addr_t addr, unsigned long s, reader_t r, writer_t w ) +{ + set_reader( addr, s, r ); + set_writer( addr, s, w ); +} + +#endif + diff --git a/include/gme/Nes_Fme7_Apu.h b/include/gme/Nes_Fme7_Apu.h new file mode 100644 index 0000000000..81848d65e8 --- /dev/null +++ b/include/gme/Nes_Fme7_Apu.h @@ -0,0 +1,135 @@ + +// Sunsoft FME-7 sound emulator + +// Game_Music_Emu 0.3.0 + +#ifndef NES_FME7_APU_H +#define NES_FME7_APU_H + +#include "blargg_common.h" +#include "Blip_Buffer.h" + +struct fme7_snapshot_t +{ + enum { reg_count = 14 }; + BOOST::uint8_t regs [reg_count]; + BOOST::uint8_t phases [3]; // 0 or 1 + BOOST::uint8_t latch; + BOOST::uint16_t delays [3]; // a, b, c +}; +BOOST_STATIC_ASSERT( sizeof (fme7_snapshot_t) == 24 ); + +class Nes_Fme7_Apu : private fme7_snapshot_t { +public: + Nes_Fme7_Apu(); + + // See Nes_Apu.h for reference + void reset(); + void volume( double ); + void treble_eq( blip_eq_t const& ); + void output( Blip_Buffer* ); + enum { osc_count = 3 }; + void osc_output( int index, Blip_Buffer* ); + void end_frame( blip_time_t ); + void save_snapshot( fme7_snapshot_t* ) const; + void load_snapshot( fme7_snapshot_t const& ); + + // Mask and addresses of registers + enum { addr_mask = 0xe000 }; + enum { data_addr = 0xe000 }; + enum { latch_addr = 0xc000 }; + + // (addr & addr_mask) == latch_addr + void write_latch( int ); + + // (addr & addr_mask) == data_addr + void write_data( blip_time_t, int data ); + + // End of public interface +private: + // noncopyable + Nes_Fme7_Apu( const Nes_Fme7_Apu& ); + Nes_Fme7_Apu& operator = ( const Nes_Fme7_Apu& ); + + static unsigned char amp_table [16]; + + struct { + Blip_Buffer* output; + int last_amp; + } oscs [osc_count]; + blip_time_t last_time; + + enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff + Blip_Synth synth; + + void run_until( blip_time_t ); +}; + +inline void Nes_Fme7_Apu::volume( double v ) +{ + synth.volume( 0.38 / amp_range * v ); // to do: fine-tune +} + +inline void Nes_Fme7_Apu::treble_eq( blip_eq_t const& eq ) +{ + synth.treble_eq( eq ); +} + +inline void Nes_Fme7_Apu::osc_output( int i, Blip_Buffer* buf ) +{ + assert( (unsigned) i < osc_count ); + oscs [i].output = buf; +} + +inline void Nes_Fme7_Apu::output( Blip_Buffer* buf ) +{ + for ( int i = 0; i < osc_count; i++ ) + osc_output( i, buf ); +} + +inline Nes_Fme7_Apu::Nes_Fme7_Apu() +{ + output( NULL ); + volume( 1.0 ); + reset(); +} + +inline void Nes_Fme7_Apu::write_latch( int data ) { latch = data; } + +inline void Nes_Fme7_Apu::write_data( blip_time_t time, int data ) +{ + if ( (unsigned) latch >= reg_count ) + { + #ifdef dprintf + dprintf( "FME7 write to %02X (past end of sound registers)\n", (int) latch ); + #endif + return; + } + + run_until( time ); + regs [latch] = data; +} + +inline void Nes_Fme7_Apu::end_frame( blip_time_t time ) +{ + if ( time > last_time ) + run_until( time ); + + assert( last_time >= time ); + last_time -= time; +} + +inline void Nes_Fme7_Apu::save_snapshot( fme7_snapshot_t* out ) const +{ + *out = *this; +} + +inline void Nes_Fme7_Apu::load_snapshot( fme7_snapshot_t const& in ) +{ + reset(); + fme7_snapshot_t* state = this; + *state = in; +} + +#endif + diff --git a/include/gme/Nes_Namco_Apu.h b/include/gme/Nes_Namco_Apu.h new file mode 100644 index 0000000000..82c841972d --- /dev/null +++ b/include/gme/Nes_Namco_Apu.h @@ -0,0 +1,104 @@ + +// Namco 106 sound chip emulator + +// Nes_Snd_Emu 0.1.7 + +#ifndef NES_NAMCO_APU_H +#define NES_NAMCO_APU_H + +#include "Nes_Apu.h" + +struct namco_snapshot_t; + +class Nes_Namco_Apu { +public: + Nes_Namco_Apu(); + ~Nes_Namco_Apu(); + + // See Nes_Apu.h for reference. + void volume( double ); + void treble_eq( const blip_eq_t& ); + void output( Blip_Buffer* ); + enum { osc_count = 8 }; + void osc_output( int index, Blip_Buffer* ); + void reset(); + void end_frame( nes_time_t ); + + // Read/write data register is at 0x4800 + enum { data_reg_addr = 0x4800 }; + void write_data( nes_time_t, int ); + int read_data(); + + // Write-only address register is at 0xF800 + enum { addr_reg_addr = 0xF800 }; + void write_addr( int ); + + // to do: implement save/restore + void save_snapshot( namco_snapshot_t* out ) const; + void load_snapshot( namco_snapshot_t const& ); + +private: + // noncopyable + Nes_Namco_Apu( const Nes_Namco_Apu& ); + Nes_Namco_Apu& operator = ( const Nes_Namco_Apu& ); + + struct Namco_Osc { + long delay; + Blip_Buffer* output; + short last_amp; + short wave_pos; + }; + + Namco_Osc oscs [osc_count]; + + nes_time_t last_time; + int addr_reg; + + enum { reg_count = 0x80 }; + BOOST::uint8_t reg [reg_count]; + Blip_Synth synth; + + BOOST::uint8_t& access(); + void run_until( nes_time_t ); +}; +/* +struct namco_snapshot_t +{ + BOOST::uint8_t regs [0x80]; + BOOST::uint8_t addr; + BOOST::uint8_t unused; + BOOST::uint8_t positions [8]; + BOOST::uint32_t delays [8]; +}; +*/ + +inline BOOST::uint8_t& Nes_Namco_Apu::access() +{ + int addr = addr_reg & 0x7f; + if ( addr_reg & 0x80 ) + addr_reg = (addr + 1) | 0x80; + return reg [addr]; +} + +inline void Nes_Namco_Apu::volume( double v ) { synth.volume( 0.10 / osc_count * v ); } + +inline void Nes_Namco_Apu::treble_eq( const blip_eq_t& eq ) { synth.treble_eq( eq ); } + +inline void Nes_Namco_Apu::write_addr( int v ) { addr_reg = v; } + +inline int Nes_Namco_Apu::read_data() { return access(); } + +inline void Nes_Namco_Apu::osc_output( int i, Blip_Buffer* buf ) +{ + assert( (unsigned) i < osc_count ); + oscs [i].output = buf; +} + +inline void Nes_Namco_Apu::write_data( nes_time_t time, int data ) +{ + run_until( time ); + access() = data; +} + +#endif + diff --git a/include/gme/Nes_Oscs.h b/include/gme/Nes_Oscs.h new file mode 100644 index 0000000000..88257762e2 --- /dev/null +++ b/include/gme/Nes_Oscs.h @@ -0,0 +1,146 @@ + +// Private oscillators used by Nes_Apu + +// Nes_Snd_Emu 0.1.7 + +#ifndef NES_OSCS_H +#define NES_OSCS_H + +#include "blargg_common.h" +#include "Blip_Buffer.h" + +class Nes_Apu; + +struct Nes_Osc +{ + unsigned char regs [4]; + bool reg_written [4]; + Blip_Buffer* output; + int length_counter;// length counter (0 if unused by oscillator) + int delay; // delay until next (potential) transition + int last_amp; // last amplitude oscillator was outputting + + void clock_length( int halt_mask ); + int period() const { + return (regs [3] & 7) * 0x100 + (regs [2] & 0xff); + } + void reset() { + delay = 0; + last_amp = 0; + } + int update_amp( int amp ) { + int delta = amp - last_amp; + last_amp = amp; + return delta; + } +}; + +struct Nes_Envelope : Nes_Osc +{ + int envelope; + int env_delay; + + void clock_envelope(); + int volume() const; + void reset() { + envelope = 0; + env_delay = 0; + Nes_Osc::reset(); + } +}; + +// Nes_Square +struct Nes_Square : Nes_Envelope +{ + enum { negate_flag = 0x08 }; + enum { shift_mask = 0x07 }; + enum { phase_range = 8 }; + int phase; + int sweep_delay; + + typedef Blip_Synth Synth; + Synth const& synth; // shared between squares + + Nes_Square( Synth const* s ) : synth( *s ) { } + + void clock_sweep( int adjust ); + void run( nes_time_t, nes_time_t ); + void reset() { + sweep_delay = 0; + Nes_Envelope::reset(); + } +}; + +// Nes_Triangle +struct Nes_Triangle : Nes_Osc +{ + enum { phase_range = 16 }; + int phase; + int linear_counter; + Blip_Synth synth; + + int calc_amp() const; + void run( nes_time_t, nes_time_t ); + void clock_linear_counter(); + void reset() { + linear_counter = 0; + phase = phase_range; + Nes_Osc::reset(); + } +}; + +// Nes_Noise +struct Nes_Noise : Nes_Envelope +{ + int noise; + Blip_Synth synth; + + void run( nes_time_t, nes_time_t ); + void reset() { + noise = 1 << 14; + Nes_Envelope::reset(); + } +}; + +// Nes_Dmc +struct Nes_Dmc : Nes_Osc +{ + int address; // address of next byte to read + int period; + //int length_counter; // bytes remaining to play (already defined in Nes_Osc) + int buf; + int bits_remain; + int bits; + bool buf_full; + bool silence; + + enum { loop_flag = 0x40 }; + + int dac; + + nes_time_t next_irq; + bool irq_enabled; + bool irq_flag; + bool pal_mode; + bool nonlinear; + + int (*rom_reader)( void*, nes_addr_t ); // needs to be initialized to rom read function + void* rom_reader_data; + + Nes_Apu* apu; + + Blip_Synth synth; + + void start(); + void write_register( int, int ); + void run( nes_time_t, nes_time_t ); + void recalc_irq(); + void fill_buffer(); + void reload_sample(); + void reset(); + int count_reads( nes_time_t, nes_time_t* ) const; + nes_time_t next_read_time() const; +}; + +#endif + diff --git a/include/gme/Nes_Vrc6_Apu.h b/include/gme/Nes_Vrc6_Apu.h new file mode 100644 index 0000000000..9312840f04 --- /dev/null +++ b/include/gme/Nes_Vrc6_Apu.h @@ -0,0 +1,99 @@ + +// Konami VRC6 sound chip emulator + +// Nes_Snd_Emu 0.1.7 + +#ifndef NES_VRC6_APU_H +#define NES_VRC6_APU_H + +#include "Nes_Apu.h" +#include "Blip_Buffer.h" + +struct vrc6_snapshot_t; + +class Nes_Vrc6_Apu { +public: + Nes_Vrc6_Apu(); + ~Nes_Vrc6_Apu(); + + // See Nes_Apu.h for reference + void reset(); + void volume( double ); + void treble_eq( blip_eq_t const& ); + void output( Blip_Buffer* ); + enum { osc_count = 3 }; + void osc_output( int index, Blip_Buffer* ); + void end_frame( nes_time_t ); + void save_snapshot( vrc6_snapshot_t* ) const; + void load_snapshot( vrc6_snapshot_t const& ); + + // Oscillator 0 write-only registers are at $9000-$9002 + // Oscillator 1 write-only registers are at $A000-$A002 + // Oscillator 2 write-only registers are at $B000-$B002 + enum { reg_count = 3 }; + enum { base_addr = 0x9000 }; + enum { addr_step = 0x1000 }; + void write_osc( nes_time_t, int osc, int reg, int data ); + +private: + // noncopyable + Nes_Vrc6_Apu( const Nes_Vrc6_Apu& ); + Nes_Vrc6_Apu& operator = ( const Nes_Vrc6_Apu& ); + + struct Vrc6_Osc + { + BOOST::uint8_t regs [3]; + Blip_Buffer* output; + int delay; + int last_amp; + int phase; + int amp; // only used by saw + + int period() const + { + return (regs [2] & 0x0f) * 0x100L + regs [1] + 1; + } + }; + + Vrc6_Osc oscs [osc_count]; + nes_time_t last_time; + + Blip_Synth saw_synth; + Blip_Synth square_synth; + + void run_until( nes_time_t ); + void run_square( Vrc6_Osc& osc, nes_time_t ); + void run_saw( nes_time_t ); +}; + +struct vrc6_snapshot_t +{ + BOOST::uint8_t regs [3] [3]; + BOOST::uint8_t saw_amp; + BOOST::uint16_t delays [3]; + BOOST::uint8_t phases [3]; + BOOST::uint8_t unused; +}; +BOOST_STATIC_ASSERT( sizeof (vrc6_snapshot_t) == 20 ); + +inline void Nes_Vrc6_Apu::osc_output( int i, Blip_Buffer* buf ) +{ + assert( (unsigned) i < osc_count ); + oscs [i].output = buf; +} + +inline void Nes_Vrc6_Apu::volume( double v ) +{ + double const factor = 0.0967 * 2; + saw_synth.volume( factor / 31 * v ); + square_synth.volume( factor * 0.5 / 15 * v ); +} + +inline void Nes_Vrc6_Apu::treble_eq( blip_eq_t const& eq ) +{ + saw_synth.treble_eq( eq ); + square_synth.treble_eq( eq ); +} + +#endif + diff --git a/include/gme/Nsf_Emu.h b/include/gme/Nsf_Emu.h new file mode 100644 index 0000000000..cf7bcb21bd --- /dev/null +++ b/include/gme/Nsf_Emu.h @@ -0,0 +1,137 @@ + +// Nintendo Entertainment System (NES) NSF music file emulator + +// Game_Music_Emu 0.3.0 + +#ifndef NSF_EMU_H +#define NSF_EMU_H + +#include "Classic_Emu.h" +#include "Nes_Apu.h" +#include "Nes_Cpu.h" + +typedef Nes_Emu Nsf_Emu; + +class Nes_Emu : public Classic_Emu { +public: + + // Set internal gain, where 1.0 results in almost no clamping. Default gain + // roughly matches volume of other emulators. + Nes_Emu( double gain = 1.4 ); + + // NSF file header + struct header_t + { + char tag [5]; + byte vers; + byte track_count; + byte first_track; + byte load_addr [2]; + byte init_addr [2]; + byte play_addr [2]; + char game [32]; + char author [32]; + char copyright [32]; + byte ntsc_speed [2]; + byte banks [8]; + byte pal_speed [2]; + byte speed_flags; + byte chip_flags; + byte unused [4]; + + enum { song = 0 }; // no song titles + }; + BOOST_STATIC_ASSERT( sizeof (header_t) == 0x80 ); + + // Load NSF data + blargg_err_t load( Data_Reader& ); + + // Load NSF using already-loaded header and remaining data + blargg_err_t load( header_t const&, Data_Reader& ); + + // Header for currently loaded NSF + header_t const& header() const { return header_; } + + // Equalizer profiles for US NES and Japanese Famicom + static equalizer_t const nes_eq; + static equalizer_t const famicom_eq; + +public: + ~Nes_Emu(); + void start_track( int ); + Nes_Apu* apu_() { return &apu; } + const char** voice_names() const; +protected: + void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); + void update_eq( blip_eq_t const& ); + blip_time_t run_clocks( blip_time_t, bool* ); + virtual void call_play(); +protected: + // initial state + enum { bank_count = 8 }; + byte initial_banks [bank_count]; + int initial_pcm_dac; + double gain; + bool needs_long_frames; + bool pal_only; + unsigned init_addr; + unsigned play_addr; + int exp_flags; + + // timing + nes_time_t next_play; + long play_period; + int play_extra; + nes_time_t clock() const; + nes_time_t next_irq( nes_time_t end_time ); + static void irq_changed( void* ); + + // rom + int total_banks; + blargg_vector rom; + static int read_code( Nsf_Emu*, nes_addr_t ); + void unload(); + + blargg_err_t init_sound(); + + // expansion sound + + class Nes_Namco_Apu* namco; + static int read_namco( Nsf_Emu*, nes_addr_t ); + static void write_namco( Nsf_Emu*, nes_addr_t, int ); + static void write_namco_addr( Nsf_Emu*, nes_addr_t, int ); + + class Nes_Vrc6_Apu* vrc6; + static void write_vrc6( Nsf_Emu*, nes_addr_t, int ); + + class Nes_Fme7_Apu* fme7; + static void write_fme7( Nsf_Emu*, nes_addr_t, int ); + + // large objects + + header_t header_; + + // cpu + Nes_Cpu cpu; + void cpu_jsr( unsigned pc, int adj ); + static int read_low_mem( Nsf_Emu*, nes_addr_t ); + static void write_low_mem( Nsf_Emu*, nes_addr_t, int ); + static int read_unmapped( Nsf_Emu*, nes_addr_t ); + static void write_unmapped( Nsf_Emu*, nes_addr_t, int ); + static void write_exram( Nsf_Emu*, nes_addr_t, int ); + + // apu + Nes_Apu apu; + static int read_snd( Nsf_Emu*, nes_addr_t ); + static void write_snd( Nsf_Emu*, nes_addr_t, int ); + static int pcm_read( void*, nes_addr_t ); + + // sram + enum { sram_size = 0x2000 }; + byte sram [sram_size]; + static int read_sram( Nsf_Emu*, nes_addr_t ); + static void write_sram( Nsf_Emu*, nes_addr_t, int ); +}; + +#endif + diff --git a/include/gme/Sms_Apu.h b/include/gme/Sms_Apu.h new file mode 100644 index 0000000000..e16e281ab9 --- /dev/null +++ b/include/gme/Sms_Apu.h @@ -0,0 +1,81 @@ + +// Sega Master System SN76489 PSG sound chip emulator + +// Sms_Snd_Emu 0.1.3 + +#ifndef SMS_APU_H +#define SMS_APU_H + +typedef long sms_time_t; // clock cycle count + +#include "Sms_Oscs.h" + +class Sms_Apu { +public: + // Set overall volume of all oscillators, where 1.0 is full volume + void volume( double ); + + // Set treble equalization + void treble_eq( const blip_eq_t& ); + + // Outputs can be assigned to a single buffer for mono output, or to three + // buffers for stereo output (using Stereo_Buffer to do the mixing). + + // Assign all oscillator outputs to specified buffer(s). If buffer + // is NULL, silences all oscillators. + void output( Blip_Buffer* mono ); + void output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); + + // Assign single oscillator output to buffer(s). Valid indicies are 0 to 3, + // which refer to Square 1, Square 2, Square 3, and Noise. If buffer is NULL, + // silences oscillator. + enum { osc_count = 4 }; + void osc_output( int index, Blip_Buffer* mono ); + void osc_output( int index, Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right ); + + // Reset oscillators and internal state + void reset(); + + // Write GameGear left/right assignment byte + void write_ggstereo( sms_time_t, int ); + + // Write to data port + void write_data( sms_time_t, int ); + + // Run all oscillators up to specified time, end current frame, then + // start a new frame at time 0. Returns true if any oscillators added + // sound to one of the left/right buffers, false if they only added + // to the center buffer. + bool end_frame( sms_time_t ); + +public: + Sms_Apu(); + ~Sms_Apu(); +private: + // noncopyable + Sms_Apu( const Sms_Apu& ); + Sms_Apu& operator = ( const Sms_Apu& ); + + Sms_Osc* oscs [osc_count]; + Sms_Square squares [3]; + Sms_Square::Synth square_synth; // used by squares + sms_time_t last_time; + int latch; + bool stereo_found; + Sms_Noise noise; + + void run_until( sms_time_t ); +}; + +struct sms_apu_state_t +{ + unsigned char regs [8] [2]; + unsigned char latch; +}; + +inline void Sms_Apu::output( Blip_Buffer* b ) { output( b, b, b ); } + +inline void Sms_Apu::osc_output( int i, Blip_Buffer* b ) { osc_output( i, b, b, b ); } + +#endif + diff --git a/include/gme/Sms_Oscs.h b/include/gme/Sms_Oscs.h new file mode 100644 index 0000000000..aa5f74ea5c --- /dev/null +++ b/include/gme/Sms_Oscs.h @@ -0,0 +1,52 @@ + +// Private oscillators used by Sms_Apu + +// Sms_Snd_Emu 0.1.3 + +#ifndef SMS_OSCS_H +#define SMS_OSCS_H + +#include "blargg_common.h" +#include "Blip_Buffer.h" + +struct Sms_Osc +{ + Blip_Buffer* outputs [4]; // NULL, right, left, center + Blip_Buffer* output; + int output_select; + + int delay; + int last_amp; + int volume; + + Sms_Osc(); + void reset(); +}; + +struct Sms_Square : Sms_Osc +{ + int period; + int phase; + + typedef Blip_Synth Synth; + const Synth* synth; + + void reset(); + void run( sms_time_t, sms_time_t ); +}; + +struct Sms_Noise : Sms_Osc +{ + const int* period; + unsigned shifter; + unsigned tap; + + typedef Blip_Synth Synth; + Synth synth; + + void reset(); + void run( sms_time_t, sms_time_t ); +}; + +#endif + diff --git a/include/gme/Snes_Spc.h b/include/gme/Snes_Spc.h new file mode 100644 index 0000000000..ba4ab0b48c --- /dev/null +++ b/include/gme/Snes_Spc.h @@ -0,0 +1,113 @@ + +// Super Nintendo (SNES) SPC-700 APU Emulator + +// Game_Music_Emu 0.3.0 + +#ifndef SNES_SPC_H +#define SNES_SPC_H + +#include "blargg_common.h" +#include "Spc_Cpu.h" +#include "Spc_Dsp.h" + +class Snes_Spc { +public: + typedef BOOST::uint8_t uint8_t; + + Snes_Spc(); + + // Load copy of SPC data into emulator. Clear echo buffer if 'clear_echo' is true. + enum { spc_file_size = 0x10180 }; + blargg_err_t load_spc( const void* spc, long spc_size, bool clear_echo = 1 ); + + // Load copy of state into emulator. + typedef Spc_Cpu::registers_t registers_t; + blargg_err_t load_state( const registers_t& cpu_state, const void* ram_64k, + const void* dsp_regs_128 ); + + // Clear echo buffer + void clear_echo(); + + // Mute voice n if bit n (1 << n) of mask is set + enum { voice_count = Spc_Dsp::voice_count }; + void mute_voices( int mask ); + + // Generate 'count' samples and optionally write to 'buf'. Count must be even. + // Sample output is 16-bit 32kHz, signed stereo pairs with the left channel first. + typedef short sample_t; + blargg_err_t play( long count, sample_t* buf = NULL ); + + // Skip forward by the specified number of samples (64000 samples = 1 second) + blargg_err_t skip( long count ); + + // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped the + // 16-bit sample range. + void set_gain( double ); + + // If true, prevent channels and global volumes from being phase-negated + void disable_surround( bool disable ); + +// End of public interface +private: + // timers + struct Timer + { + spc_time_t next_tick; + int period; + int count; + int shift; + int counter; + int enabled; + + void run_until_( spc_time_t ); + void run_until( spc_time_t time ) + { + if ( time >= next_tick ) + run_until_( time ); + } + }; + enum { timer_count = 3 }; + Timer timer [timer_count]; + + // hardware + int extra_cycles; + spc_time_t time() const; + int read( spc_addr_t ); + void write( spc_addr_t, int ); + friend class Spc_Cpu; + + // dsp + sample_t* sample_buf; + sample_t* buf_end; // to do: remove this once possible bug resolved + spc_time_t next_dsp; + Spc_Dsp dsp; + int keys_pressed; + int keys_released; + sample_t skip_sentinel [1]; // special value for play() passed by skip() + void run_dsp( spc_time_t ); + void run_dsp_( spc_time_t ); + bool echo_accessed; + void check_for_echo_access( spc_addr_t ); + + // boot rom + enum { rom_size = 64 }; + enum { rom_addr = 0xffc0 }; + bool rom_enabled; + uint8_t extra_ram [rom_size]; + static const uint8_t boot_rom [rom_size]; + void enable_rom( bool ); + + // CPU and RAM (at end because it's large) + Spc_Cpu cpu; + enum { ram_size = 0x10000 }; + uint8_t ram [ram_size + 0x100]; // padding for catching jumps past end +}; + +inline void Snes_Spc::disable_surround( bool disable ) { dsp.disable_surround( disable ); } + +inline void Snes_Spc::mute_voices( int mask ) { dsp.mute_voices( mask ); } + +inline void Snes_Spc::set_gain( double v ) { dsp.set_gain( v ); } + +#endif + diff --git a/include/gme/Spc_Cpu.h b/include/gme/Spc_Cpu.h new file mode 100644 index 0000000000..32ec4c22f9 --- /dev/null +++ b/include/gme/Spc_Cpu.h @@ -0,0 +1,60 @@ + +// Super Nintendo (SNES) SPC-700 CPU emulator + +// Game_Music_Emu 0.3.0 + +#ifndef SPC_CPU_H +#define SPC_CPU_H + +#include "blargg_common.h" + +typedef unsigned spc_addr_t; +typedef long spc_time_t; + +class Snes_Spc; + +class Spc_Cpu { + typedef BOOST::uint8_t uint8_t; + uint8_t* const ram; +public: + // Keeps pointer to 64K RAM + Spc_Cpu( Snes_Spc* spc, uint8_t* ram ); + + // SPC-700 registers. *Not* kept updated during a call to run(). + struct registers_t { + long pc; // more than 16 bits to allow overflow detection + uint8_t a; + uint8_t x; + uint8_t y; + uint8_t status; + uint8_t sp; + } r; + + // Run CPU for at least 'count' cycles. Return the number of cycles remaining + // when emulation stopped (negative if extra cycles were emulated). Emulation + // stops when there are no more remaining cycles or an unhandled instruction + // is encountered (STOP, SLEEP, and any others not yet implemented). In the + // latter case, the return value is greater than zero. + spc_time_t run( spc_time_t count ); + + // Number of clock cycles remaining for current run() call + spc_time_t remain() const; + + // Access memory as the emulated CPU does + int read ( spc_addr_t ); + void write( spc_addr_t, int ); + +private: + // noncopyable + Spc_Cpu( const Spc_Cpu& ); + Spc_Cpu& operator = ( const Spc_Cpu& ); + unsigned mem_bit( spc_addr_t ); + + spc_time_t remain_; + Snes_Spc& emu; +}; + +inline spc_time_t Spc_Cpu::remain() const { return remain_; } + +#endif + diff --git a/include/gme/Spc_Dsp.h b/include/gme/Spc_Dsp.h new file mode 100644 index 0000000000..010ca654f8 --- /dev/null +++ b/include/gme/Spc_Dsp.h @@ -0,0 +1,155 @@ + +// Super Nintendo (SNES) SPC DSP emulator + +// Game_Music_Emu 0.3.0 + +#ifndef SPC_DSP_H +#define SPC_DSP_H + +#include "blargg_common.h" + +class Spc_Dsp { + typedef BOOST::int8_t int8_t; + typedef BOOST::uint8_t uint8_t; +public: + + // Keeps pointer to 64K ram + Spc_Dsp( uint8_t* ram ); + + // Mute voice n if bit n (1 << n) of mask is clear. + enum { voice_count = 8 }; + void mute_voices( int mask ); + + // Clear state and silence everything. + void reset(); + + // Set gain, where 1.0 is normal. When greater than 1.0, output is clamped to + // the 16-bit sample range. + void set_gain( double ); + + // If true, prevent channels and global volumes from being phase-negated + void disable_surround( bool disable ); + + // Read/write register 'n', where n ranges from 0 to register_count - 1. + enum { register_count = 128 }; + int read ( int n ); + void write( int n, int ); + + // Run DSP for 'count' samples. Write resulting samples to 'buf' if not NULL. + void run( long count, short* buf = NULL ); + + +// End of public interface +private: + + struct raw_voice_t { + int8_t left_vol; + int8_t right_vol; + uint8_t rate [2]; + uint8_t waveform; + uint8_t adsr [2]; // envelope rates for attack, decay, and sustain + uint8_t gain; // envelope gain (if not using ADSR) + int8_t envx; // current envelope level + int8_t outx; // current sample + int8_t unused [6]; + }; + + union { + raw_voice_t voice [voice_count]; + + uint8_t reg [register_count]; + + struct { + int8_t unused1 [12]; + int8_t left_volume; // 0C Main Volume Left (-.7) + int8_t echo_feedback; // 0D Echo Feedback (-.7) + int8_t unused2 [14]; + int8_t right_volume; // 1C Main Volume Right (-.7) + int8_t unused3 [15]; + int8_t left_echo_volume; // 2C Echo Volume Left (-.7) + uint8_t pitch_mods; // 2D Pitch Modulation on/off for each voice + int8_t unused4 [14]; + int8_t right_echo_volume; // 3C Echo Volume Right (-.7) + uint8_t noise_enables; // 3D Noise output on/off for each voice + int8_t unused5 [14]; + uint8_t key_ons; // 4C Key On for each voice + uint8_t echo_ons; // 4D Echo on/off for each voice + int8_t unused6 [14]; + uint8_t key_offs; // 5C key off for each voice (instantiates release mode) + uint8_t wave_page; // 5D source directory (wave table offsets) + int8_t unused7 [14]; + uint8_t flags; // 6C flags and noise freq + uint8_t echo_page; // 6D + int8_t unused8 [14]; + uint8_t wave_ended; // 7C + uint8_t echo_delay; // 7D ms >> 4 + char unused9 [2]; + } g; + }; + + uint8_t* const ram; + + // Cache of echo FIR values for faster access + short fir_coeff [voice_count]; + + // fir_buf [i + 8] == fir_buf [i], to avoid wrap checking in FIR code + short fir_buf [16] [2]; + int fir_offset; // (0 to 7) + + enum { emu_gain_bits = 8 }; + int emu_gain; + + int keyed_on; // 8-bits for 8 voices + int keys; + + int echo_ptr; + int noise_amp; + int noise; + int noise_count; + + int surround_threshold; + + static const BOOST::int16_t gauss []; + + enum state_t { + state_attack, + state_decay, + state_sustain, + state_release + }; + + struct voice_t { + short volume [2]; + short fraction;// 12-bit fractional position + short interp3; // most recent four decoded samples + short interp2; + short interp1; + short interp0; + short block_remain; // number of nybbles remaining in current block + unsigned short addr; + short block_header; // header byte from current block + short envcnt; + short envx; + short on_cnt; + short enabled; // 7 if enabled, 31 if disabled + short envstate; + short unused; // pad to power of 2 + }; + + voice_t voice_state [voice_count]; + + int clock_envelope( int ); +}; + +inline void Spc_Dsp::disable_surround( bool disable ) { surround_threshold = disable ? 0 : -0x7FFF; } + +inline void Spc_Dsp::set_gain( double v ) { emu_gain = (int) (v * (1 << emu_gain_bits)); } + +inline int Spc_Dsp::read( int i ) +{ + assert( (unsigned) i < register_count ); + return reg [i]; +} + +#endif + diff --git a/include/gme/Spc_Emu.h b/include/gme/Spc_Emu.h new file mode 100644 index 0000000000..8e17adbe56 --- /dev/null +++ b/include/gme/Spc_Emu.h @@ -0,0 +1,86 @@ + +// Super Nintendo (SNES) SPC music file emulator + +// Game_Music_Emu 0.3.0 + +#ifndef SPC_EMU_H +#define SPC_EMU_H + +#include "Fir_Resampler.h" +#include "Music_Emu.h" +#include "Snes_Spc.h" + +class Spc_Emu : public Music_Emu { + enum { trailer_offset = 0x10200 }; +public: + // A gain of 1.0 results in almost no clamping. Default gain roughly + // matches volume of other emulators. + Spc_Emu( double gain = 1.4 ); + + // The Super Nintendo hardware samples at 32kHz. Other sample rates are + // handled by resampling the 32kHz output; emulation accuracy is not affected. + enum { native_sample_rate = 32000 }; + + // SPC file header + struct header_t + { + char tag [35]; + byte format; + byte version; + byte pc [2]; + byte a, x, y, psw, sp; + byte unused [2]; + char song [32]; + char game [32]; + char dumper [16]; + char comment [32]; + byte date [11]; + char len_secs [3]; + byte fade_msec [5]; + char author [32]; + byte mute_mask; + byte emulator; + byte unused2 [45]; + + enum { track_count = 1 }; + enum { copyright = 0 }; // no copyright field + }; + BOOST_STATIC_ASSERT( sizeof (header_t) == 0x100 ); + + // Load SPC data + blargg_err_t load( Data_Reader& ); + + // Load SPC using already-loaded header and remaining data + blargg_err_t load( header_t const&, Data_Reader& ); + + // Header for currently loaded SPC + header_t const& header() const { return *(header_t*) spc_data.begin(); } + + // Pointer and size for trailer data + byte const* trailer() const { return &spc_data [trailer_offset]; } + long trailer_size() const { return spc_data.size() - trailer_offset; } + + // If true, prevents channels and global volumes from being phase-negated + void disable_surround( bool disable = true ); + +public: + ~Spc_Emu(); + blargg_err_t set_sample_rate( long ); + void mute_voices( int ); + void start_track( int ); + void play( long, sample_t* ); + void skip( long ); + const char** voice_names() const; +public: + // deprecated + blargg_err_t init( long r, double gain = 1.4 ) { return set_sample_rate( r ); } +private: + blargg_vector spc_data; + Fir_Resampler<24> resampler; + Snes_Spc apu; +}; + +inline void Spc_Emu::disable_surround( bool b ) { apu.disable_surround( b ); } + +#endif + diff --git a/include/gme/Vgm_Emu.h b/include/gme/Vgm_Emu.h new file mode 100644 index 0000000000..bd35bd7a4c --- /dev/null +++ b/include/gme/Vgm_Emu.h @@ -0,0 +1,118 @@ + +// Multi-format VGM music emulator with support for SMS PSG and Mega Drive FM + +// Game_Music_Emu 0.3.0 + +#ifndef VGM_EMU_H +#define VGM_EMU_H + +#include "abstract_file.h" +#include "Vgm_Emu_Impl.h" + +// Emulates VGM music using SN76489/SN76496 PSG, YM2612, and YM2413 FM sound chips. +// Supports custom sound buffer and frequency equalization when VGM uses just the PSG. +// FM sound chips can be run at their proper rates, or slightly higher to reduce +// aliasing on high notes. Currently YM2413 support requires that you supply a +// YM2413 sound chip emulator. I can provide one I've modified to work with the library. +class Vgm_Emu : public Vgm_Emu_Impl { +public: + + // Oversample runs FM chips at higher than normal rate. Tempo adjusts speed of + // music, but not pitch. + Vgm_Emu( bool oversample = true, double tempo = 1.0 ); + + // VGM header format + struct header_t + { + char tag [4]; + byte data_size [4]; + byte version [4]; + byte psg_rate [4]; + byte ym2413_rate [4]; + byte gd3_offset [4]; + byte track_duration [4]; + byte loop_offset [4]; + byte loop_duration [4]; + byte frame_rate [4]; + byte noise_feedback [2]; + byte noise_width; + byte unused1; + byte ym2612_rate [4]; + byte ym2151_rate [4]; + byte data_offset [4]; + byte unused2 [8]; + + enum { track_count = 1 }; // one track per file + enum { time_rate = 44100 }; // all times specified at this rate + + // track information is in gd3 data + enum { game = 0 }; + enum { song = 0 }; + enum { author = 0 }; + enum { copyright = 0 }; + }; + BOOST_STATIC_ASSERT( sizeof (header_t) == 64 ); + + // Load VGM data + blargg_err_t load( Data_Reader& ); + + // Load VGM using already-loaded header and remaining data + blargg_err_t load( header_t const&, Data_Reader& ); + + // Load VGM using pointer to file data. Keeps pointer to data. + blargg_err_t load( void const* data, long size ); + + // Header for currently loaded VGM + header_t const& header() const { return header_; } + + // Pointer to gd3 data, or NULL if none. Optionally returns size of data. + // Checks for GD3 header and that version is less than 2.0. + byte const* gd3_data( int* size_out = NULL ) const; + + // to do: find better name for this + // True if Classic_Emu operations are supported + bool is_classic_emu() const { return !uses_fm; } + +public: + ~Vgm_Emu(); + blargg_err_t set_sample_rate( long sample_rate ); + void start_track( int ); + void mute_voices( int mask ); + const char** voice_names() const; + void play( long count, sample_t* ); +public: + // deprecated + int track_length( const byte** end_out = NULL, int* remain_out = NULL ) const + { + return (header().track_duration [3]*0x1000000L + + header().track_duration [2]*0x0010000L + + header().track_duration [1]*0x0000100L + + header().track_duration [0]) / header_t::time_rate; + } +protected: + // Classic_Emu + void set_voice( int, Blip_Buffer*, Blip_Buffer*, Blip_Buffer* ); + void update_eq( blip_eq_t const& ); + blip_time_t run( int, bool* ); +private: + header_t header_; + blargg_vector mem; + long vgm_rate; + bool oversample; + bool uses_fm; + + blargg_err_t init_( long sample_rate ); + blargg_err_t load_( const header_t&, void const* data, long size ); + blargg_err_t setup_fm(); + void unload(); +}; + +inline blargg_err_t Vgm_Emu::load( void const* data, long size ) +{ + unload(); + return load_( *(header_t*) data, (char*) data + sizeof (header_t), + size - sizeof (header_t) ); +} + +#endif + diff --git a/include/gme/Vgm_Emu_Impl.h b/include/gme/Vgm_Emu_Impl.h new file mode 100644 index 0000000000..06ea4d4147 --- /dev/null +++ b/include/gme/Vgm_Emu_Impl.h @@ -0,0 +1,74 @@ + +// Game_Music_Emu 0.3.0 + +#ifndef VGM_EMU_IMPL_H +#define VGM_EMU_IMPL_H + +#include "Dual_Resampler.h" +#include "Classic_Emu.h" +#include "Ym2413_Emu.h" +#include "Ym2612_Emu.h" +#include "Sms_Apu.h" + +template +class Ym_Emu : public Emu { +protected: + int last_time; + short* out; + enum { disabled_time = -1 }; +public: + Ym_Emu() : last_time( disabled_time ), out( NULL ) { } + void enable( bool b ) { last_time = b ? 0 : disabled_time; } + bool enabled() const { return last_time != disabled_time; } + void begin_frame( short* p ); + int run_until( int time ); +}; + +class Vgm_Emu_Impl : public Classic_Emu, private Dual_Resampler { +public: + typedef Classic_Emu::sample_t sample_t; + typedef BOOST::uint8_t byte; + +protected: + enum { stereo = 2 }; + + typedef int vgm_time_t; + + enum { fm_time_bits = 12 }; + typedef int fm_time_t; + long fm_time_offset; + int fm_time_factor; + fm_time_t to_fm_time( vgm_time_t ) const; + + enum { blip_time_bits = 12 }; + int blip_time_factor; + blip_time_t to_blip_time( vgm_time_t ) const; + + byte const* data; + byte const* loop_begin; + byte const* data_end; + void update_fm_rates( long* ym2413_rate, long* ym2612_rate ) const; + + vgm_time_t vgm_time; + byte const* pos; + blip_time_t run_commands( vgm_time_t ); + int play_frame( blip_time_t blip_time, int sample_count, sample_t* buf ); + + byte const* pcm_data; + byte const* pcm_pos; + int dac_amp; + int dac_disabled; // -1 if disabled + void write_pcm( vgm_time_t, int amp ); + + Ym_Emu ym2612; + Ym_Emu ym2413; + + Blip_Buffer blip_buf; + Sms_Apu psg; + Blip_Synth dac_synth; + + friend class Vgm_Emu; +}; + +#endif + diff --git a/include/gme/Ym2413_Emu.h b/include/gme/Ym2413_Emu.h new file mode 100644 index 0000000000..918a032be1 --- /dev/null +++ b/include/gme/Ym2413_Emu.h @@ -0,0 +1,36 @@ + +// YM2413 FM sound chip emulator interface + +// Game_Music_Emu 0.3.0 + +#ifndef YM2413_EMU_H +#define YM2413_EMU_H + +class Ym2413_Emu { + struct OPLL* opll; +public: + Ym2413_Emu(); + ~Ym2413_Emu(); + + // Set output sample rate and chip clock rates, in Hz. Returns non-zero + // if error. + int set_rate( double sample_rate, double clock_rate ); + + // Reset to power-up state + void reset(); + + // Mute voice n if bit n (1 << n) of mask is set + enum { channel_count = 14 }; + void mute_voices( int mask ); + + // Write 'data' to 'addr' + void write( int addr, int data ); + + // Run and write pair_count samples to output + typedef short sample_t; + enum { out_chan_count = 2 }; // stereo + void run( int pair_count, sample_t* out ); +}; + +#endif + diff --git a/include/gme/Ym2612_Emu.h b/include/gme/Ym2612_Emu.h new file mode 100644 index 0000000000..9449855738 --- /dev/null +++ b/include/gme/Ym2612_Emu.h @@ -0,0 +1,41 @@ + +// YM2612 FM sound chip emulator interface + +// Game_Music_Emu 0.3.0 + +#ifndef YM2612_EMU_H +#define YM2612_EMU_H + +struct Ym2612_Impl; + +class Ym2612_Emu { + Ym2612_Impl* impl; +public: + Ym2612_Emu() { impl = 0; } + ~Ym2612_Emu(); + + // Set output sample rate and chip clock rates, in Hz. Returns non-zero + // if error. + const char* set_rate( double sample_rate, double clock_rate ); + + // Reset to power-up state + void reset(); + + // Mute voice n if bit n (1 << n) of mask is set + enum { channel_count = 6 }; + void mute_voices( int mask ); + + // Write addr to register 0 then data to register 1 + void write0( int addr, int data ); + + // Write addr to register 2 then data to register 3 + void write1( int addr, int data ); + + // Run and add pair_count samples into current output buffer contents + typedef short sample_t; + enum { out_chan_count = 2 }; // stereo + void run( int pair_count, sample_t* out ); +}; + +#endif + diff --git a/include/gme/abstract_file.h b/include/gme/abstract_file.h new file mode 100644 index 0000000000..7f370f9e88 --- /dev/null +++ b/include/gme/abstract_file.h @@ -0,0 +1,177 @@ + +// Abstract file access interfaces + +#ifndef ABSTRACT_FILE_H +#define ABSTRACT_FILE_H + +#include + +// Supports reading and finding out how many bytes are remaining +class Data_Reader { +public: + Data_Reader() { } + virtual ~Data_Reader() { } + + // NULL on success, otherwise error string + typedef const char* error_t; + + // Read at most 'n' bytes. Return number of bytes read, zero or negative + // if error. + virtual long read_avail( void*, long n ) = 0; + + // Read exactly 'n' bytes (error if fewer are available). + virtual error_t read( void*, long ); + + // Number of bytes remaining + virtual long remain() const = 0; + + // Skip forwards by 'n' bytes. + virtual error_t skip( long n ); + + // to do: bytes remaining = LONG_MAX when unknown? + +private: + // noncopyable + Data_Reader( const Data_Reader& ); + Data_Reader& operator = ( const Data_Reader& ); +}; + +// Adds seeking operations +class File_Reader : public Data_Reader { +public: + // Size of file + virtual long size() const = 0; + + // Current position in file + virtual long tell() const = 0; + + // Change position in file + virtual error_t seek( long ) = 0; + + virtual long remain() const; + + error_t skip( long n ); +}; + +// Limit access to a subset of data +class Subset_Reader : public Data_Reader { + Data_Reader* in; + long remain_; +public: + Subset_Reader( Data_Reader*, long size ); + long remain() const; + long read_avail( void*, long ); +}; + +// Treat range of memory as a file +class Mem_File_Reader : public File_Reader { + const char* const begin; + long pos; + const long size_; +public: + Mem_File_Reader( const void*, long size ); + + long size() const; + long read_avail( void*, long ); + + long tell() const; + error_t seek( long ); +}; + +// File reader based on C FILE +class Std_File_Reader : public File_Reader { + FILE* file_; +protected: + void reset( FILE* f ) { file_ = f; } + //FILE* owned_file; +public: + Std_File_Reader(); + ~Std_File_Reader(); + + error_t open( const char* ); + + FILE* file() const { return file_; } + + // Forward read requests to file. Caller must close file later. + //void forward( FILE* ); + + long size() const; + long read_avail( void*, long ); + + long tell() const; + error_t seek( long ); + + void close(); +}; + +// Supports writing +class Data_Writer { +public: + Data_Writer() { } + virtual ~Data_Writer() { } + + typedef const char* error_t; + + // Write 'n' bytes. NULL on success, otherwise error string. + virtual error_t write( const void*, long n ) = 0; + + void satisfy_lame_linker_(); +private: + // noncopyable + Data_Writer( const Data_Writer& ); + Data_Writer& operator = ( const Data_Writer& ); +}; + +class Std_File_Writer : public Data_Writer { + FILE* file_; +protected: + void reset( FILE* f ) { file_ = f; } +public: + Std_File_Writer(); + ~Std_File_Writer(); + + error_t open( const char* ); + + FILE* file() const { return file_; } + + // Forward writes to file. Caller must close file later. + //void forward( FILE* ); + + error_t write( const void*, long ); + + void close(); +}; + +// Write data to memory +class Mem_Writer : public Data_Writer { + char* data_; + long size_; + long allocated; + enum { expanding, fixed, ignore_excess } mode; +public: + // Keep all written data in expanding block of memory + Mem_Writer(); + + // Write to fixed-size block of memory. If ignore_excess is false, returns + // error if more than 'size' data is written, otherwise ignores any excess. + Mem_Writer( void*, long size, int ignore_excess = 0 ); + + error_t write( const void*, long ); + + // Pointer to beginning of written data + char* data() { return data_; } + + // Number of bytes written + long size() const { return size_; } + + ~Mem_Writer(); +}; + +// Written data is ignored +class Null_Writer : public Data_Writer { +public: + error_t write( const void*, long ); +}; + +#endif + diff --git a/include/gme/blargg_common.h b/include/gme/blargg_common.h new file mode 100644 index 0000000000..a91fa3f766 --- /dev/null +++ b/include/gme/blargg_common.h @@ -0,0 +1,242 @@ + +// Sets up common environment for Shay Green's libraries. +// +// To change configuration options, modify blargg_config.h, not this file. + +#ifndef BLARGG_COMMON_H +#define BLARGG_COMMON_H + +// HAVE_CONFIG_H: If defined, include user's "config.h" first (which *can* +// re-include blargg_common.h if it needs to) +#ifdef HAVE_CONFIG_H + #undef BLARGG_COMMON_H + #include "config.h" + #define BLARGG_COMMON_H +#endif + +// BLARGG_NONPORTABLE: If defined to 1, platform-specific (and possibly non-portable) +// optimizations are used. Defaults to off. Report any problems that occur only when +// this is enabled. +#ifndef BLARGG_NONPORTABLE + #define BLARGG_NONPORTABLE 0 +#endif + +// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only +// one must be #defined to 1. Only needed if something actually depends on byte order. +#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) + #if defined (MSB_FIRST) || defined (__powerc) || defined (macintosh) || \ + defined (WORDS_BIGENDIAN) || defined (__BIG_ENDIAN__) + #define BLARGG_BIG_ENDIAN 1 + #else + #define BLARGG_LITTLE_ENDIAN 1 + #endif +#endif + +// Determine compiler's language support + +// Metrowerks CodeWarrior +#if defined (__MWERKS__) + #define BLARGG_COMPILER_HAS_NAMESPACE 1 + #if !__option(bool) + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + #define STATIC_CAST(T,expr) static_cast< T > (expr) + +// Microsoft Visual C++ +#elif defined (_MSC_VER) + #if _MSC_VER < 1100 + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + +// GNU C++ +#elif defined (__GNUC__) + #if __GNUC__ > 2 + #define BLARGG_COMPILER_HAS_NAMESPACE 1 + #endif + +// Mingw +#elif defined (__MINGW32__) + // empty + +// Pre-ISO C++ compiler +#elif __cplusplus < 199711 + #ifndef BLARGG_COMPILER_HAS_BOOL + #define BLARGG_COMPILER_HAS_BOOL 0 + #endif + +#endif + +/* BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compilers. + If errors occur here, add the following line to your config.h file: + #define BLARGG_COMPILER_HAS_BOOL 0 +*/ +#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL + typedef int bool; + const bool true = 1; + const bool false = 0; +#endif + +// BLARGG_USE_NAMESPACE: If 1, use headers rather than +#if BLARGG_USE_NAMESPACE || (!defined (BLARGG_USE_NAMESPACE) && BLARGG_COMPILER_HAS_NAMESPACE) + #include + #include + #include + #include + #define STD std +#else + #include + #include + #include + #include + #define STD +#endif + +// BLARGG_NEW is used in place of 'new' to create objects. By default, plain new is used. +// To prevent an exception if out of memory, #define BLARGG_NEW new (std::nothrow) +#ifndef BLARGG_NEW + #define BLARGG_NEW new +#endif + +// BOOST::int8_t etc. + +// HAVE_STDINT_H: If defined, use for int8_t etc. +#if defined (HAVE_STDINT_H) + #include + #define BOOST + +// HAVE_INTTYPES_H: If defined, use for int8_t etc. +#elif defined (HAVE_INTTYPES_H) + #include + #define BOOST + +#else + struct BOOST + { + #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F + typedef signed char int8_t; + typedef unsigned char uint8_t; + #else + // No suitable 8-bit type available + typedef struct see_blargg_common_h int8_t; + typedef struct see_blargg_common_h uint8_t; + #endif + + #if USHRT_MAX == 0xFFFF + typedef short int16_t; + typedef unsigned short uint16_t; + #else + // No suitable 16-bit type available + typedef struct see_blargg_common_h int16_t; + typedef struct see_blargg_common_h uint16_t; + #endif + + #if ULONG_MAX == 0xFFFFFFFF + typedef long int32_t; + typedef unsigned long uint32_t; + #elif UINT_MAX == 0xFFFFFFFF + typedef int int32_t; + typedef unsigned int uint32_t; + #else + // No suitable 32-bit type available + typedef struct see_blargg_common_h int32_t; + typedef struct see_blargg_common_h uint32_t; + #endif + }; +#endif + +// BLARGG_SOURCE_BEGIN: Library sources #include this after other #includes. +#ifndef BLARGG_SOURCE_BEGIN + #define BLARGG_SOURCE_BEGIN "blargg_source.h" +#endif + +// BLARGG_ENABLE_OPTIMIZER: Library sources #include this for speed-critical code +#ifndef BLARGG_ENABLE_OPTIMIZER + #define BLARGG_ENABLE_OPTIMIZER "blargg_common.h" +#endif + +// BLARGG_CPU_*: Used to select between some optimizations +#if !defined (BLARGG_CPU_POWERPC) && !defined (BLARGG_CPU_X86) + #if defined (__powerc) + #define BLARGG_CPU_POWERPC 1 + #elif defined (_MSC_VER) && defined (_M_IX86) + #define BLARGG_CPU_X86 1 + #endif +#endif + +// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. +#ifndef BOOST_STATIC_ASSERT + #ifdef _MSC_VER + // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / ((expr) ? 1 : 0) - 1] ) + #else + // Some other compilers fail when declaring same function multiple times in class, + // so differentiate them by line + #define BOOST_STATIC_ASSERT( expr ) \ + void blargg_failed_( int (*arg) [2 / ((expr) ? 1 : 0) - 1] [__LINE__] ) + #endif +#endif + +// STATIC_CAST(T,expr): Used in place of static_cast (expr) +#ifndef STATIC_CAST + #define STATIC_CAST(T,expr) ((T) (expr)) +#endif + +// blargg_err_t (NULL on success, otherwise error string) +#ifndef blargg_err_t + typedef const char* blargg_err_t; +#endif +const char* const blargg_success = 0; + +// blargg_vector: Simple array that does *not* work for types with a constructor (non-POD). +template +class blargg_vector { + T* begin_; + STD::size_t size_; +public: + blargg_vector() : begin_( 0 ), size_( 0 ) { } + ~blargg_vector() { STD::free( begin_ ); } + + typedef STD::size_t size_type; + + blargg_err_t resize( size_type n ) + { + void* p = STD::realloc( begin_, n * sizeof (T) ); + if ( !p && n ) + return "Out of memory"; + begin_ = (T*) p; + size_ = n; + return 0; + } + + void clear() + { + void* p = begin_; + begin_ = 0; + size_ = 0; + STD::free( p ); + } + + size_type size() const { return size_; } + + T* begin() { return begin_; } + T* end() { return begin_ + size_; } + + const T* begin() const { return begin_; } + const T* end() const { return begin_ + size_; } + + T& operator [] ( size_type n ) + { + assert( n <= size_ ); // allow for past-the-end value + return begin_ [n]; + } + + const T& operator [] ( size_type n ) const + { + assert( n <= size_ ); // allow for past-the-end value + return begin_ [n]; + } +}; + +#endif + diff --git a/include/gme/blargg_endian.h b/include/gme/blargg_endian.h new file mode 100644 index 0000000000..2dccb5ca08 --- /dev/null +++ b/include/gme/blargg_endian.h @@ -0,0 +1,156 @@ + +// CPU Byte Order Utilities + +// Game_Music_Emu 0.3.0 + +#ifndef BLARGG_ENDIAN +#define BLARGG_ENDIAN + +#include "blargg_common.h" + +#if 0 + // Read 16/32-bit little-endian integer from memory + unsigned GET_LE16( void const* ); + unsigned long GET_LE32( void const* ); + + // Read 16/32-bit big-endian integer from memory + unsigned GET_BE16( void const* ); + unsigned long GET_BE32( void const* ); + + // Write 16/32-bit integer to memory in little-endian format + void SET_LE16( void*, unsigned ); + void SET_LE32( void*, unsigned ); + + // Write 16/32-bit integer to memory in big-endian format + void SET_BE16( void*, unsigned long ); + void SET_BE32( void*, unsigned long ); +#endif + +inline unsigned get_le16( void const* p ) +{ + return ((unsigned char*) p) [1] * 0x100 + + ((unsigned char*) p) [0]; +} + +inline unsigned get_be16( void const* p ) +{ + return ((unsigned char*) p) [0] * 0x100 + + ((unsigned char*) p) [1]; +} + +inline unsigned long get_le32( void const* p ) +{ + return ((unsigned char*) p) [3] * 0x01000000 + + ((unsigned char*) p) [2] * 0x00010000 + + ((unsigned char*) p) [1] * 0x00000100 + + ((unsigned char*) p) [0]; +} + +inline unsigned long get_be32( void const* p ) +{ + return ((unsigned char*) p) [0] * 0x01000000 + + ((unsigned char*) p) [1] * 0x00010000 + + ((unsigned char*) p) [2] * 0x00000100 + + ((unsigned char*) p) [3]; +} + +inline void set_le16( void* p, unsigned n ) +{ + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be16( void* p, unsigned n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 8); + ((unsigned char*) p) [1] = (unsigned char) n; +} + +inline void set_le32( void* p, unsigned long n ) +{ + ((unsigned char*) p) [3] = (unsigned char) (n >> 24); + ((unsigned char*) p) [2] = (unsigned char) (n >> 16); + ((unsigned char*) p) [1] = (unsigned char) (n >> 8); + ((unsigned char*) p) [0] = (unsigned char) n; +} + +inline void set_be32( void* p, unsigned long n ) +{ + ((unsigned char*) p) [0] = (unsigned char) (n >> 24); + ((unsigned char*) p) [1] = (unsigned char) (n >> 16); + ((unsigned char*) p) [2] = (unsigned char) (n >> 8); + ((unsigned char*) p) [3] = (unsigned char) n; +} + +#ifndef GET_LE16 + // Optimized implementation if byte order is known + #if BLARGG_NONPORTABLE && BLARGG_LITTLE_ENDIAN + #define GET_LE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_LE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_LE16( addr, data ) (void (*(BOOST::uint16_t*) (addr) = (data))) + #define SET_LE32( addr, data ) (void (*(BOOST::uint32_t*) (addr) = (data))) + + #elif BLARGG_NONPORTABLE && BLARGG_CPU_POWERPC + // PowerPC has special byte-reversed instructions + // to do: assumes that PowerPC is running in big-endian mode + #define GET_LE16( addr ) (__lhbrx( (addr), 0 )) + #define GET_LE32( addr ) (__lwbrx( (addr), 0 )) + #define SET_LE16( addr, data ) (__sthbrx( (data), (addr), 0 )) + #define SET_LE32( addr, data ) (__stwbrx( (data), (addr), 0 )) + + #define GET_BE16( addr ) (*(BOOST::uint16_t*) (addr)) + #define GET_BE32( addr ) (*(BOOST::uint32_t*) (addr)) + #define SET_BE16( addr, data ) (void (*(BOOST::uint16_t*) (addr) = (data))) + #define SET_BE32( addr, data ) (void (*(BOOST::uint32_t*) (addr) = (data))) + + #endif +#endif + +#ifndef GET_LE16 + #define GET_LE16( addr ) get_le16( addr ) +#endif + +#ifndef GET_LE32 + #define GET_LE32( addr ) get_le32( addr ) +#endif + +#ifndef SET_LE16 + #define SET_LE16( addr, data ) set_le16( addr, data ) +#endif + +#ifndef SET_LE32 + #define SET_LE32( addr, data ) set_le32( addr, data ) +#endif + +#ifndef GET_BE16 + #define GET_BE16( addr ) get_be16( addr ) +#endif + +#ifndef GET_BE32 + #define GET_BE32( addr ) get_be32( addr ) +#endif + +#ifndef SET_BE16 + #define SET_BE16( addr, data ) set_be16( addr, data ) +#endif + +#ifndef SET_BE32 + #define SET_BE32( addr, data ) set_be32( addr, data ) +#endif + +// auto-selecting versions + +inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } +inline void set_le( BOOST::uint32_t* p, unsigned long n ) { SET_LE32( p, n ); } + +inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } +inline void set_be( BOOST::uint32_t* p, unsigned long n ) { SET_BE32( p, n ); } + +inline unsigned get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); } +inline unsigned long get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); } + +inline unsigned get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); } +inline unsigned long get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); } + +#endif + diff --git a/include/gme/blargg_source.h b/include/gme/blargg_source.h new file mode 100644 index 0000000000..c8d39d1b6a --- /dev/null +++ b/include/gme/blargg_source.h @@ -0,0 +1,76 @@ + +// By default, #included at beginning of library source files. +// Can be overridden by #defining BLARGG_SOURCE_BEGIN to path of alternate file. + +// Copyright (C) 2005 Shay Green. + +#ifndef BLARGG_SOURCE_H +#define BLARGG_SOURCE_H + +// If debugging is enabled, abort program if expr is false. Meant for checking +// internal state and consistency. A failed assertion indicates a bug in the module. +// void assert( bool expr ); +#include + +// If debugging is enabled and expr is false, abort program. Meant for checking +// caller-supplied parameters and operations that are outside the control of the +// module. A failed requirement indicates a bug outside the module. +// void require( bool expr ); +#undef require +#define require( expr ) assert( expr ) + +// Like printf() except output goes to debug log file. Might be defined to do +// nothing (not even evaluate its arguments). +// void dprintf( const char* format, ... ); +#undef dprintf +#ifdef BLARGG_DPRINTF + #define dprintf BLARGG_DPRINTF +#else + inline void blargg_dprintf_( const char*, ... ) { } + #define dprintf (1) ? (void) 0 : blargg_dprintf_ +#endif + +// If enabled, evaluate expr and if false, make debug log entry with source file +// and line. Meant for finding situations that should be examined further, but that +// don't indicate a problem. In all cases, execution continues normally. +#undef check +#ifdef BLARGG_CHECK + #define check( expr ) BLARGG_CHECK( expr ) +#else + #define check( expr ) ((void) 0) +#endif + +// If expr returns non-NULL error string, return it from current function, otherwise continue. +#define BLARGG_RETURN_ERR( expr ) do { \ + blargg_err_t blargg_return_err_ = (expr); \ + if ( blargg_return_err_ ) return blargg_return_err_; \ + } while ( 0 ) + +// If ptr is NULL, return out of memory error string. +#define BLARGG_CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) + +// Avoid any macros which evaluate their arguments multiple times +#undef min +#undef max + +// using const references generates crappy code, and I am currenly only using these +// for built-in types, so they take arguments by value + +template +inline T min( T x, T y ) +{ + if ( x < y ) + return x; + return y; +} + +template +inline T max( T x, T y ) +{ + if ( x < y ) + return y; + return x; +} + +#endif + diff --git a/include/jpgalleg-2.5/dct.h b/include/jpgalleg-2.5/dct.h new file mode 100644 index 0000000000..9fd7e0b974 --- /dev/null +++ b/include/jpgalleg-2.5/dct.h @@ -0,0 +1,53 @@ +/* + * __ _____ ______ ______ ___ ___ + * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ + * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ + * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ + * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ + * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ + * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ + * /\____/ + * \_/__/ + * + * Version 2.5, by Angelo Mottola, 2000-2004 + * + * Fast Discrete Cosine Transform coefficients. + * + * See the readme.txt file for instructions on using this package in your + * own programs. + */ + + +#ifndef _JPGALLEG_DCT_H_ +#define _JPGALLEG_DCT_H_ + +#ifndef M_PI +#define M_PI 3.1415926535897932384626 +#endif +#define SQRT_2 1.4142135623730950488016 + +#define SCALE_FACTOR(i) ((i) == 0 ? 1.0 : (cos((i) * M_PI / 16.0) * SQRT_2)) +#define AAN_FACTOR(i) (SCALE_FACTOR(i / 8) * SCALE_FACTOR(i % 8)) + + +#define FIX_0_298631336 2446 +#define FIX_0_390180644 3196 +#define FIX_0_541196100 4433 +#define FIX_0_765366865 6270 +#define FIX_0_899976223 7373 +#define FIX_1_175875602 9633 +#define FIX_1_501321110 12299 +#define FIX_1_847759065 15137 +#define FIX_1_961570560 16069 +#define FIX_2_053119869 16819 +#define FIX_2_562915447 20995 +#define FIX_3_072711026 25172 + + +#define IFIX_1_082392200 277 +#define IFIX_1_414213562 362 +#define IFIX_1_847759065 473 +#define IFIX_2_613125930 669 + + +#endif diff --git a/include/jpgalleg-2.5/internal.h b/include/jpgalleg-2.5/internal.h new file mode 100644 index 0000000000..0964e0b9d3 --- /dev/null +++ b/include/jpgalleg-2.5/internal.h @@ -0,0 +1,216 @@ +/* + * __ _____ ______ ______ ___ ___ + * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ + * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ + * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ + * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ + * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ + * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ + * /\____/ + * \_/__/ + * + * Version 2.5, by Angelo Mottola, 2000-2004 + * + * Internal library definitions. + * + * See the readme.txt file for instructions on using this package in your + * own programs. + */ + + +#ifndef _JPGALLEG_INTERNAL_H_ +#define _JPGALLEG_INTERNAL_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TRACE + #undef TRACE +#endif +#ifdef DEBUG + #define TRACE fprintf(stderr, "[JPGalleg: %s]", __FUNCTION__); _jpeg_trace +#else + #define TRACE 1 ? (void)0 : _jpeg_trace +#endif + + +#define CHUNK_SOI 0xffd8 +#define CHUNK_EOI 0xffd9 + +#define CHUNK_JPG0 0xf0 +#define CHUNK_JPG13 0xfd +#define CHUNK_DHP 0xde +#define CHUNK_EXP 0xdf +#define CHUNK_DNL 0xdc +#define CHUNK_DAC 0xcc +#define CHUNK_SOF3 0xc3 +#define CHUNK_SOF5 0xc5 +#define CHUNK_SOF6 0xc6 +#define CHUNK_SOF7 0xc7 +#define CHUNK_SOF9 0xc9 +#define CHUNK_SOF10 0xca +#define CHUNK_SOF11 0xcb +#define CHUNK_SOF13 0xcd +#define CHUNK_SOF14 0xce +#define CHUNK_SOF15 0xcf +#define CHUNK_APP0 0xe0 +#define CHUNK_APP1 0xe1 +#define CHUNK_APP2 0xe2 +#define CHUNK_APP3 0xe3 +#define CHUNK_APP4 0xe4 +#define CHUNK_APP5 0xe5 +#define CHUNK_APP6 0xe6 +#define CHUNK_APP7 0xe7 +#define CHUNK_APP8 0xe8 +#define CHUNK_APP9 0xe9 +#define CHUNK_APP10 0xea +#define CHUNK_APP11 0xeb +#define CHUNK_APP12 0xec +#define CHUNK_APP13 0xed +#define CHUNK_APP14 0xee +#define CHUNK_APP15 0xef + +#define CHUNK_TEM 0x01 +#define CHUNK_RST0 0xffd0 +#define CHUNK_RST1 0xffd1 +#define CHUNK_RST2 0xffd2 +#define CHUNK_RST3 0xffd3 +#define CHUNK_RST4 0xffd4 +#define CHUNK_RST5 0xffd5 +#define CHUNK_RST6 0xffd6 +#define CHUNK_RST7 0xffd7 + +#define CHUNK_JPG 0xc8 + +#define CHUNK_SOF0 0xc0 +#define CHUNK_SOF1 0xc1 +#define CHUNK_SOF2 0xc2 +#define CHUNK_DHT 0xc4 +#define CHUNK_SOS 0xda +#define CHUNK_DQT 0xdb +#define CHUNK_DRI 0xdd +#define CHUNK_COM 0xfe + +#define SOF0_DEFINED 0x01 +#define DHT_DEFINED 0x02 +#define SOS_DEFINED 0x04 +#define DQT_DEFINED 0x08 +#define APP0_DEFINED 0x10 +#define APP1_DEFINED 0x20 +#define DRI_DEFINED 0x40 +#define IS_PROGRESSIVE 0x80 + +#define JFIF_OK (SOF0_DEFINED | DHT_DEFINED | SOS_DEFINED | DQT_DEFINED | APP0_DEFINED) +#define EXIF_OK (SOF0_DEFINED | DHT_DEFINED | SOS_DEFINED | DQT_DEFINED | APP1_DEFINED) + +#define LUMINANCE 0 +#define CHROMINANCE 1 + +#define PASS_WRITE 0 +#define PASS_COMPUTE_HUFFMAN 1 + + +/* This expression is made to return: + * Quality = 100 -> Factor = 10 + * Quality = 1 -> Factor = 0.1 + * Other values follow a logarithmic curve + */ +#define QUALITY_FACTOR(q) (pow(10.0, ((q) - 50.5) / 49.5)) + +/* Default quality/flags values for save_jpg() and save_memory_jpg() */ +#define DEFAULT_QUALITY 75 +#define DEFAULT_FLAGS JPG_SAMPLING_444 + + + +typedef struct HUFFMAN_ENTRY +{ + int encoded_value; + int value; + int bits_length; + int frequency; +} HUFFMAN_ENTRY; + + +typedef struct HUFFMAN_TABLE +{ + HUFFMAN_ENTRY entry[257]; + HUFFMAN_ENTRY *entry_of_length[16]; + HUFFMAN_ENTRY *code[256]; +} HUFFMAN_TABLE; + + +typedef struct HUFFMAN_NODE +{ + HUFFMAN_ENTRY *entry; + int frequency; + struct HUFFMAN_NODE *parent; + struct HUFFMAN_NODE *left, *right; + struct HUFFMAN_NODE *prev, *next; +} HUFFMAN_NODE; + + +typedef struct HUFFMAN_TREE +{ + HUFFMAN_NODE *node; + HUFFMAN_NODE *head, *tail; + int depth; +} HUFFMAN_TREE; + + +typedef struct DATA_BUFFER +{ + short data[64]; +} DATA_BUFFER; + + +typedef struct IO_BUFFER +{ + unsigned char *buffer; + unsigned char *buffer_start, *buffer_end; + int current_bit; +} IO_BUFFER; + + +extern int _jpeg_getc(void); +extern int _jpeg_putc(int); +extern int _jpeg_getw(void); +extern int _jpeg_putw(int); +extern INLINE int _jpeg_get_bit(void); +extern int _jpeg_put_bit(int); +extern void _jpeg_flush_bits(void); +extern void _jpeg_open_chunk(void); +extern void _jpeg_close_chunk(void); +extern int _jpeg_eoc(void); +extern void _jpeg_new_chunk(int); +extern void _jpeg_write_chunk(void); +extern void _jpeg_chunk_putc(int); +extern void _jpeg_chunk_putw(int); +extern void _jpeg_chunk_puts(unsigned char *, int); + +extern BITMAP *_jpeg_decode(RGB *, void (*)(int)); +extern void _jpeg_mmx_idct(short *, short *, short *, short *); +extern void _jpeg_mmx_ycbcr2rgb(int, int, int, int, int, int, int, int, int, int, int, int, int); +extern void _jpeg_mmx_ycbcr2bgr(int, int, int, int, int, int, int, int, int, int, int, int, int); + +extern int _jpeg_encode(BITMAP *, AL_CONST RGB *, int, int, void (*)(int)); +extern void _jpeg_mmx_rgb2ycbcr(int, short *, short *, short *, short *, short *, short *); +extern void _jpeg_mmx_bgr2ycbcr(int, short *, short *, short *, short *, short *, short *); + +extern void _jpeg_trace(const char *, ...); + +extern HUFFMAN_TABLE _jpeg_huffman_ac_table[]; +extern HUFFMAN_TABLE _jpeg_huffman_dc_table[]; +extern IO_BUFFER _jpeg_io; +extern const unsigned char _jpeg_zigzag_scan[]; +extern const char *_jpeg_component_name[]; + + +#endif diff --git a/include/jpgalleg-2.5/jpgalleg.h b/include/jpgalleg-2.5/jpgalleg.h new file mode 100644 index 0000000000..1cb0221894 --- /dev/null +++ b/include/jpgalleg-2.5/jpgalleg.h @@ -0,0 +1,85 @@ +/* + * __ _____ ______ ______ ___ ___ + * /\ \ /\ _ `\ /\ ___\ /\ _ \ /\_ \ /\_ \ + * \ \ \\ \ \L\ \\ \ \__/ \ \ \L\ \\//\ \ \//\ \ __ __ + * __ \ \ \\ \ __| \ \ \ __\ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\ + * /\ \_\/ / \ \ \/ \ \ \L\ \\ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ + * \ \____// \ \_\ \ \____/ \ \_\ \_\/\____\/\____\ \____\ \____ \ + * \/____/ \/_/ \/___/ \/_/\/_/\/____/\/____/\/____/\/___L\ \ + * /\____/ + * \_/__/ + * + * Version 2.5, by Angelo Mottola, 2000-2004 + * + * Public header file. + * + * See the readme.txt file for instructions on using this package in your + * own programs. + */ + +#ifndef _JPGALLEG_H_ +#define _JPGALLEG_H_ + +#include + +/* Library version constat and string */ +#define JPGALLEG_VERSION 0x0205 +#define JPGALLEG_VERSION_STRING "JPGalleg 2.5, by Angelo Mottola, 2000-2004" + + +/* Subsampling mode */ +#define JPG_SAMPLING_444 0 +#define JPG_SAMPLING_422 1 +#define JPG_SAMPLING_411 2 + +/* Force greyscale when saving */ +#define JPG_GREYSCALE 0x10 + +/* Use optimized encoding */ +#define JPG_OPTIMIZE 0x20 + + +/* Error codes */ +#define JPG_ERROR_NONE 0 +#define JPG_ERROR_READING_FILE -1 +#define JPG_ERROR_WRITING_FILE -2 +#define JPG_ERROR_INPUT_BUFFER_TOO_SMALL -3 +#define JPG_ERROR_OUTPUT_BUFFER_TOO_SMALL -4 +#define JPG_ERROR_HUFFMAN -5 +#define JPG_ERROR_NOT_JPEG -6 +#define JPG_ERROR_UNSUPPORTED_ENCODING -7 +#define JPG_ERROR_UNSUPPORTED_COLOR_SPACE -8 +#define JPG_ERROR_UNSUPPORTED_DATA_PRECISION -9 +#define JPG_ERROR_BAD_IMAGE -10 +#define JPG_ERROR_OUT_OF_MEMORY -11 + + +/* Datafile object type for JPG images */ +#define DAT_JPEG DAT_ID('J','P','E','G') + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern int jpgalleg_init(void); + +extern BITMAP *load_jpg(AL_CONST char *filename, RGB *palette); +extern BITMAP *load_jpg_ex(AL_CONST char *filename, RGB *palette, void (*callback)(int progress)); +extern BITMAP *load_memory_jpg(void *buffer, int size, RGB *palette); +extern BITMAP *load_memory_jpg_ex(void *buffer, int size, RGB *palette, void (*callback)(int progress)); + +extern int save_jpg(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette); +extern int save_jpg_ex(AL_CONST char *filename, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)); +extern int save_memory_jpg(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette); +extern int save_memory_jpg_ex(void *buffer, int *size, BITMAP *image, AL_CONST RGB *palette, int quality, int flags, void (*callback)(int progress)); + +extern int jpgalleg_error; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/jpgalleg-2.5/mmx.h b/include/jpgalleg-2.5/mmx.h new file mode 100644 index 0000000000..ce1f4bc5ff --- /dev/null +++ b/include/jpgalleg-2.5/mmx.h @@ -0,0 +1 @@ +#define JPGALLEG_MMX diff --git a/include/loadpng/loadpng.h b/include/loadpng/loadpng.h new file mode 100644 index 0000000000..993da07be7 --- /dev/null +++ b/include/loadpng/loadpng.h @@ -0,0 +1,75 @@ +/* loadpng.h */ +/* This file is hereby placed in the public domain. */ +#ifndef _included_loadpng_h_ +#define _included_loadpng_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* Overkill :-) */ +#define LOADPNG_VERSION 1 +#define LOADPNG_SUBVERSION 5 +#define LOADPNG_VERSIONSTR "1.5" + + +/* _png_screen_gamma is slightly overloaded (sorry): + * + * A value of 0.0 means: Don't do any gamma correction in load_png() + * and load_memory_png(). This meaning was introduced in v1.4. + * + * A value of -1.0 means: Use the value from the environment variable + * SCREEN_GAMMA (if available), otherwise fallback to a value of 2.2 + * (a good guess for PC monitors, and the value for sRGB colourspace). + * This is the default. + * + * Otherwise, the value of _png_screen_gamma is taken as-is. + */ +extern double _png_screen_gamma; + + +/* Choose zlib compression level for saving file. + * Default is Z_BEST_COMPRESSION. + */ +extern int _png_compression_level; + + +/* Load a PNG from disk. */ +extern BITMAP *load_png(AL_CONST char *filename, RGB *pal); + +/* Load a PNG from some place. */ +extern BITMAP *load_png_pf(PACKFILE *fp, RGB *pal); + +/* Load a PNG from memory. */ +extern BITMAP *load_memory_png(AL_CONST void *buffer, int buffer_size, RGB *pal); + +/* Save a bitmap to disk in PNG format. */ +extern int save_png(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal); + +/* Adds `PNG' to Allegro's internal file type table. + * You can then just use load_bitmap and save_bitmap as usual. + */ +extern void register_png_file_type(void); + +/* Register an datafile type ID with Allegro, so that when an object + * with that type ID is encountered while loading a datafile, that + * object will be loaded as a PNG file. + */ +extern void register_png_datafile_object(int id); + +/* This is supposed to resemble jpgalleg_init in JPGalleg 2.0, just in + * case you are lazier than lazy. It contains these 3 lines of code: + * register_png_datafile_object(DAT_ID('P','N','G',' ')); + * register_png_file_type(); + * return 0; + */ +extern int loadpng_init(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* _included_loadpng_h */ diff --git a/include/lpng1212/png.h b/include/lpng1212/png.h new file mode 100644 index 0000000000..42af5b63a8 --- /dev/null +++ b/include/lpng1212/png.h @@ -0,0 +1,3481 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.2.12 - June 27, 2006 + * Copyright (c) 1998-2006 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.2.12 - June 27, 2006: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 10.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 10.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-8 13 10210 12.so.0.10[.0] + * 1.2.10rc1-3 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.0.19rc1-5 10 10019 10.so.0.19[.0] + * 1.2.11rc1-5 13 10211 12.so.0.11[.0] + * 1.0.19 10 10019 10.so.0.19[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.0.20 10 10020 10.so.0.20[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng.txt or libpng.3 for more information. The PNG specification + * is available as a W3C Recommendation and as an ISO Specification, + * defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_uint_32 rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. + */ +typedef struct png_struct_def png_struct; +typedef png_struct FAR * png_structp; + +typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); +typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); +typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); +typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, + int)); +typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, + int)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); +typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, + png_uint_32, int)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, + png_row_infop, png_bytep)); +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) +typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp)); +#endif +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* WRITE only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t)); +typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application, except to store + * the jmp_buf. + */ + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf jmpbuf; /* used in png_error */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + png_size_t zbuf_size; /* size of zbuf */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_uint_32 rowbytes; /* size of row in bytes */ + png_uint_32 irowbytes; /* size of current interlaced row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +#ifdef PNG_LEGACY_SUPPORTED + png_byte filler; /* filler byte for pixel expansion */ +#else + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif +#endif + +#if defined(PNG_bKGD_SUPPORTED) + png_byte background_gamma_type; +# ifdef PNG_FLOATING_POINT_SUPPORTED + float background_gamma; +# endif + png_color_16 background; /* background color in screen gamma space */ +#if defined(PNG_READ_GAMMA_SUPPORTED) + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) + png_flush_ptr output_flush_fn;/* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits 16-bit gamma */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + float gamma; /* file gamma value */ + float screen_gamma; /* screen gamma value (display_exponent) */ +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans; /* transparency values for paletted files */ + png_color_16 trans_values; /* transparency values for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after each prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# if defined(PNG_TEXT_SUPPORTED) + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* for the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) + png_bytep palette_lookup; /* lookup table for dithering */ + png_bytep dither_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + +#ifdef PNG_FREE_ME_SUPPORTED + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#endif + +#if defined(PNG_USER_CHUNKS_SUPPORTED) + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* changed from png_byte to png_uint_32 at version 1.2.0 */ +#ifdef PNG_1_0_X + png_byte mng_features_permitted; +#else + png_uint_32 mng_features_permitted; +#endif /* PNG_1_0_X */ +#endif + +/* New member added in libpng-1.0.7 */ +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_fixed_point int_gamma; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) + png_byte filter_type; +#endif + +#if defined(PNG_1_0_X) || (defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)) +/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */ + png_uint_32 row_buf_size; +#endif + +/* New members added in libpng-1.2.0 */ +#if !defined(PNG_1_0_X) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) + png_byte mmx_bitdepth_threshold; + png_uint_32 mmx_rowbytes_threshold; + png_uint_32 asm_flags; +#endif + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep dither_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is */ + /* in the palette */ + png_bytep palette_to_index; /* which original index points to this */ + /* palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; +#endif + +}; + + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef png_structp version_1_2_12; + +typedef png_struct FAR * FAR * png_structpp; + +/* Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + */ + +/* Returns the version number of the library */ +extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, + int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)); + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +extern PNG_EXPORT(png_structp,png_create_read_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +extern PNG_EXPORT(png_structp,png_create_write_struct) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn)); + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_WRITE_SUPPORTED +extern PNG_EXPORT(void,png_set_compression_buffer_size) + PNGARG((png_structp png_ptr, png_uint_32 size)); +#endif + +/* Reset the compression stream */ +extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_structp,png_create_read_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +extern PNG_EXPORT(png_structp,png_create_write_struct_2) + PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +#endif + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, + png_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +extern PNG_EXPORT(png_infop,png_create_info_struct) + PNGARG((png_structp png_ptr)); + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize the info structure (old interface - DEPRECATED) */ +extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr)); +#undef png_info_init +#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\ + png_sizeof(png_info)); +#endif + +extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the information before the actual image data. */ +extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#if defined(PNG_TIME_RFC1123_SUPPORTED) +extern PNG_EXPORT(png_charp,png_convert_to_rfc1123) + PNGARG((png_structp png_ptr, png_timep ptime)); +#endif + +#if !defined(_WIN32_WCE) +/* "time.h" functions are not supported on WindowsCE */ +#if defined(PNG_WRITE_tIME_SUPPORTED) +/* convert from a struct tm to png_time */ +extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, + struct tm FAR * ttime)); + +/* convert from time_t to png_time. Uses gmtime() */ +extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, + time_t ttime)); +#endif /* PNG_WRITE_tIME_SUPPORTED */ +#endif /* _WIN32_WCE */ + +#if defined(PNG_READ_EXPAND_SUPPORTED) +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp + png_ptr)); +#endif +extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated */ +extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)); +#endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +/* Expand the grayscale to 24-bit RGB if necessary. */ +extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +/* Reduce RGB to grayscale. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, + int error_action, double red, double green )); +#endif +extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green )); +extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp + png_ptr)); +#endif + +extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, + png_colorp palette)); + +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +#define PNG_FILLER_BEFORE 0 +#define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#if !defined(PNG_1_0_X) +extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, + png_uint_32 filler, int flags)); +#endif +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, + png_color_8p true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. */ +extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +/* Handle alpha and tRNS by replacing with a background color. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, + png_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +#endif +#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +#define PNG_BACKGROUND_GAMMA_SCREEN 1 +#define PNG_BACKGROUND_GAMMA_FILE 2 +#define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +/* strip the second byte of information from a 16-bit depth file. */ +extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +/* Turn on dithering, and reduce the palette to the number of colors available. */ +extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette, int maximum_colors, + png_uint_16p histogram, int full_dither)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, + double screen_gamma, double default_file_gamma)); +#endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */ +/* Deprecated and will be removed. Use png_permit_mng_features() instead. */ +extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr, + int empty_plte_permitted)); +#endif +#endif + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +/* Set how many lines between output flushes - 0 for no flushing */ +extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); +#endif + +/* optional update palette with requested transformations */ +extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); + +/* optional call to update the users info structure */ +extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read one or more rows of image data. */ +extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read a row of data. */ +extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, + png_bytep row, + png_bytep display_row)); +#endif + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the whole image into memory at once. */ +extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, + png_bytepp image)); +#endif + +/* write a row of image data */ +extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, + png_bytep row)); + +/* write a few rows of image data */ +extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, + png_bytepp row, png_uint_32 num_rows)); + +/* write the image data */ +extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, + png_bytepp image)); + +/* writes the end of the PNG file. */ +extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED +/* read the end of the PNG file. */ +extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +/* free any memory associated with the png_info_struct */ +extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp + png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* free all memory used by the read (old method - NOT DLL EXPORTED) */ +extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr)); + +/* free any memory associated with the png_struct and the png_info_structs */ +extern PNG_EXPORT(void,png_destroy_write_struct) + PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); + +/* free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +extern void png_write_destroy PNGARG((png_structp png_ptr)); + +/* set the libpng method of handling chunk CRC errors */ +extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, + int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() to say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, + int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, + int heuristic_method, int num_weights, png_doublep filter_weights, + png_doublep filter_costs)); +#endif +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, + int level)); + +extern PNG_EXPORT(void,png_set_compression_mem_level) + PNGARG((png_structp png_ptr, int mem_level)); + +extern PNG_EXPORT(void,png_set_compression_strategy) + PNGARG((png_structp png_ptr, int strategy)); + +extern PNG_EXPORT(void,png_set_compression_window_bits) + PNGARG((png_structp png_ptr, int window_bits)); + +extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng.txt for + * more information. + */ + +#if !defined(PNG_NO_STDIO) +/* Initialize the input/output for the PNG file to the default functions. */ +extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + */ +extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, + png_voidp io_ptr, png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); + +extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr read_user_transform_fn)); +#endif + +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp + png_ptr, png_user_transform_ptr write_user_transform_fn)); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_LEGACY_SUPPORTED) +extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp + png_ptr, png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr) + PNGARG((png_structp png_ptr)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp + png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, + png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn)); + +/* returns the user pointer associated with the push read functions */ +extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) + PNGARG((png_structp png_ptr)); + +/* function to be called when data becomes available */ +extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); + +/* function that combines rows. Not very much different than the + * png_combine_row() call. Is this even used????? + */ +extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, + png_bytep old_row, png_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, + png_uint_32 size)); + +#if defined(PNG_1_0_X) +# define png_malloc_warn png_malloc +#else +/* Added at libpng version 1.2.4 */ +extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, + png_uint_32 size)); +#endif + +/* frees a pointer allocated by png_malloc() */ +extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); + +#if defined(PNG_1_0_X) +/* Function to allocate memory for zlib. */ +extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items, + uInt size)); + +/* Function to free memory for zlib */ +extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr)); +#endif + +/* Free data that was allocated internally */ +extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 free_me, int num)); +#ifdef PNG_FREE_ME_SUPPORTED +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, + png_infop info_ptr, int freer, png_uint_32 mask)); +#endif +/* assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, + png_uint_32 size)); +extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, + png_voidp ptr)); +#endif + +extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr, + png_voidp s1, png_voidp s2, png_uint_32 size)); + +extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr, + png_voidp s1, int value, png_uint_32 size)); + +#if defined(USE_FAR_KEYWORD) /* memory model conversion function */ +extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +/* Fatal error in PNG image of libpng - can't continue */ +extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* The same, but the chunk name is prepended to the error string. */ +extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, + png_const_charp error_message)); + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, + png_const_charp warning_message)); + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* Returns row_pointers, which is an array of pointers to scanlines that was +returned from png_read_png(). */ +extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, +png_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use +by png_write_png(). */ +extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image height in pixels. */ +extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image bit_depth. */ +extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image color_type. */ +extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image filter_type. */ +extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image interlace_type. */ +extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image compression_type. */ +extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +#endif + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp +png_ptr, png_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p *background)); +#endif + +#if defined(PNG_bKGD_SUPPORTED) +extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_16p background)); +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point + *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point + *int_blue_x, png_fixed_point *int_blue_y)); +#endif +#endif + +#if defined(PNG_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, double white_x, double white_y, double red_x, + double red_y, double green_x, double green_y, double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double *file_gamma)); +#endif +extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point *int_file_gamma)); +#endif + +#if defined(PNG_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +#endif +extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p *hist)); +#endif + +#if defined(PNG_hIST_SUPPORTED) +extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_16p hist)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, int *interlace_method, + int *compression_method, int *filter_method)); + +extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_method, int compression_method, + int filter_method)); + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, + int *unit_type)); +#endif + +#if defined(PNG_oFFs_SUPPORTED) +extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, + int unit_type)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, png_charp *units, png_charpp *params)); +#endif + +#if defined(PNG_pCAL_SUPPORTED) +extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, png_charp units, png_charpp params)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#if defined(PNG_pHYs_SUPPORTED) +extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp *palette, int *num_palette)); + +extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_colorp palette, int num_palette)); + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p *sig_bit)); +#endif + +#if defined(PNG_sBIT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_color_8p sig_bit)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *intent)); +#endif + +#if defined(PNG_sRGB_SUPPORTED) +extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, + png_infop info_ptr, int intent)); +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charpp name, int *compression_type, + png_charpp profile, png_uint_32 *proflen)); + /* Note to maintainer: profile should be png_bytepp */ +#endif + +#if defined(PNG_iCCP_SUPPORTED) +extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_charp name, int compression_type, + png_charp profile, png_uint_32 proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tpp entries)); +#endif + +#if defined(PNG_sPLT_SUPPORTED) +extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_sPLT_tp entries, int nentries)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) +/* png_get_text also returns the number of text chunks in *num_text */ +extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp *text_ptr, int *num_text)); +#endif + +/* + * Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#if defined(PNG_TEXT_SUPPORTED) +extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep *mod_time)); +#endif + +#if defined(PNG_tIME_SUPPORTED) +extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_timep mod_time)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep *trans, int *num_trans, + png_color_16p *trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_bytep trans, int num_trans, + png_color_16p trans_values)); +#endif + +#if defined(PNG_tRNS_SUPPORTED) +#endif + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, double *width, double *height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED */ + +#if defined(PNG_sCAL_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, + png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); +#endif +#endif +#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) +/* provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behavour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp + png_ptr, int keep, png_bytep chunk_list, int num_chunks)); +extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, + png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); +extern PNG_EXPORT(void, png_set_unknown_chunk_location) + PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp + png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); +#endif +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep + chunk_name)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + If you need to turn it off for a chunk that your application has freed, + you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ +extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, + png_infop info_ptr, int mask)); + +#if defined(PNG_INFO_IMAGE_SUPPORTED) +/* The "params" pointer is currently not used and is for future expansion. */ +extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, + png_infop info_ptr, + int transforms, + png_voidp params)); +#endif + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + */ +#ifdef PNG_DEBUG +#if (PNG_DEBUG > 0) +#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +#include +#if (PNG_DEBUG > 1) +#define png_debug(l,m) _RPT0(_CRT_WARN,m) +#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m,p1) +#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m,p1,p2) +#endif +#else /* PNG_DEBUG_FILE || !_MSC_VER */ +#ifndef PNG_DEBUG_FILE +#define PNG_DEBUG_FILE stderr +#endif /* PNG_DEBUG_FILE */ +#if (PNG_DEBUG > 1) +#define png_debug(l,m) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ +} +#define png_debug1(l,m,p1) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ +} +#define png_debug2(l,m,p1,p2) \ +{ \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ +} +#endif /* (PNG_DEBUG > 1) */ +#endif /* _MSC_VER */ +#endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +#define png_debug(l, m) +#endif +#ifndef png_debug1 +#define png_debug1(l, m, p1) +#endif +#ifndef png_debug2 +#define png_debug2(l, m, p1, p2) +#endif + +#if 0 +extern PNG_EXPORT(png_bytep,png_sig_bytes) PNGARG((void)); +#endif + +extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr)); +extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp + png_ptr, png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Added to version 1.2.0 */ +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */ +#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04 +#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08 +#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10 +#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20 +#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40 +#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80 +#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */ + +#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ + | PNG_ASM_FLAG_MMX_READ_INTERLACE \ + | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ + | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ + | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ + | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ) +#define PNG_MMX_WRITE_FLAGS ( 0 ) + +#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \ + | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \ + | PNG_MMX_READ_FLAGS \ + | PNG_MMX_WRITE_FLAGS ) + +#define PNG_SELECT_READ 1 +#define PNG_SELECT_WRITE 2 + +#if !defined(PNG_1_0_X) +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask) + PNGARG((int flag_select, int *compilerID)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask) + PNGARG((int flag_select)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_asm_flags) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold) + PNGARG((png_structp png_ptr)); + +/* pngget.c */ +extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold) + PNGARG((png_structp png_ptr)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_asm_flags) + PNGARG((png_structp png_ptr, png_uint_32 asm_flags)); + +/* pngset.c */ +extern PNG_EXPORT(void,png_set_mmx_thresholds) + PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold, + png_uint_32 mmx_rowbytes_threshold)); + +#endif /* PNG_1_0_X */ +#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */ + +#if !defined(PNG_1_0_X) +/* png.c, pnggccrd.c, or pngvcrd.c */ +extern PNG_EXPORT(int,png_mmx_support) PNGARG((void)); + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp + png_ptr, png_uint_32 strip_mode)); +#endif + +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp + png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); +extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp + png_ptr)); +extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp + png_ptr)); +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project defs */ + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 - \ + (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L - \ + (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) + +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +/* Inline macros to do direct reads of bytes from the input buffer. These + * require that you are using an architecture that uses PNG byte ordering + * (MSB first) and supports unaligned data storage. I think that PowerPC + * in big-endian mode and 680x0 are the only ones that will support this. + * The x86 line of processors definitely do not. The png_get_int_32() + * routine also assumes we are using two's complement format for negative + * values, which is almost certainly true. + */ +#if defined(PNG_READ_BIG_ENDIAN_SUPPORTED) +# define png_get_uint_32(buf) ( *((png_uint_32p) (buf))) +# define png_get_uint_16(buf) ( *((png_uint_16p) (buf))) +# define png_get_int_32(buf) ( *((png_int_32p) (buf))) +#else +extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); +extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); +#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */ +extern PNG_EXPORT(png_uint_32,png_get_uint_31) + PNGARG((png_structp png_ptr, png_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). + */ +extern PNG_EXPORT(void,png_save_uint_32) + PNGARG((png_bytep buf, png_uint_32 i)); +extern PNG_EXPORT(void,png_save_int_32) + PNGARG((png_bytep buf, png_int_32 i)); + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +extern PNG_EXPORT(void,png_save_uint_16) + PNGARG((png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ + +/* ************************************************************************* */ + +/* These next functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +#if defined(PNG_INTERNAL) + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_DITHER 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_SHIFT 8 +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_SHIFT 3 +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 +#define PNG_FLAG_FREE_PLTE 0x1000 +#define PNG_FLAG_FREE_TRNS 0x2000 +#define PNG_FLAG_FREE_HIST 0x4000 +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x800000L unused */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \ + (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + ideal-delta..ideal+delta. Each argument is evaluated twice. + "ideal" and "delta" should be constants, normally simple + integers, "value" a variable. Added to libpng-1.2.6 JB */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* variables declared in png.c - only it needs to define PNG_NO_EXTERN */ +#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN) +/* place to hold the signature string for a PNG file. */ +#ifdef PNG_USE_GLOBAL_ARRAYS + PNG_EXPORT_VAR (const png_byte FARDATA) png_sig[8]; +#else +#if 0 +#define png_sig png_sig_bytes(NULL) +#endif +#endif +#endif /* PNG_NO_EXTERN */ + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro in png.c and + * wherever it's needed. + */ +#define PNG_IHDR const png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT const png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND const png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE const png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD const png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM const png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA const png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST const png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP const png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt const png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs const png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL const png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL const png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs const png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT const png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT const png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB const png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_tEXt const png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME const png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS const png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt const png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + +#ifdef PNG_USE_GLOBAL_ARRAYS +PNG_EXPORT_VAR (const png_byte FARDATA) png_IHDR[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IDAT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_IEND[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_PLTE[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_bKGD[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_cHRM[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_gAMA[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_hIST[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iCCP[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_iTXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_oFFs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sCAL[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_pHYs[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sBIT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sPLT[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_sRGB[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tEXt[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tIME[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_tRNS[5]; +PNG_EXPORT_VAR (const png_byte FARDATA) png_zTXt[5]; +#endif /* PNG_USE_GLOBAL_ARRAYS */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for reading, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_read_struct instead). + */ +extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr)); +#undef png_read_init +#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Initialize png_ptr struct for writing, and allocate any other memory. + * (old interface - DEPRECATED - use png_create_write_struct instead). + */ +extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr)); +#undef png_write_init +#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \ + PNG_LIBPNG_VER_STRING, png_sizeof(png_struct)); +#endif + +extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size)); +extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr, + png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t + png_info_size)); + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN png_voidp png_create_struct PNGARG((int type)); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr + malloc_fn, png_voidp mem_ptr)); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +#ifndef PNG_1_0_X +/* Function to allocate memory for zlib. */ +PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items, uInt size)); + +/* Function to free memory for zlib */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +#ifdef PNG_SIZE_T +/* Function to convert a sizeof an item to png_sizeof item */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +#endif + +/* Next four functions are used internally as callbacks. PNGAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3. */ + +PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +#if !defined(PNG_NO_STDIO) +PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr)); +#endif +#endif +#else /* PNG_1_0_X */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif +#endif /* PNG_1_0_X */ + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using. */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN png_charp png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_charp chunkdata, png_size_t chunklength, + png_size_t prefix_length, png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr, + png_size_t length)); + +#if defined(PNG_WRITE_FLUSH_SUPPORTED) +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* simple function to write the signature */ +PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)); + +/* write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette, + png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#if defined(PNG_WRITE_gAMA_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, png_fixed_point + file_gamma)); +#endif +#endif + +#if defined(PNG_WRITE_sBIT_SUPPORTED) +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit, + int color_type)); +#endif + +#if defined(PNG_WRITE_cHRM_SUPPORTED) +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +#endif +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif +#endif + +#if defined(PNG_WRITE_sRGB_SUPPORTED) +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#if defined(PNG_WRITE_iCCP_SUPPORTED) +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_charp name, int compression_type, + png_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#if defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_sPLT_tp palette)); +#endif + +#if defined(PNG_WRITE_tRNS_SUPPORTED) +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans, + png_color_16p values, int number, int color_type)); +#endif + +#if defined(PNG_WRITE_bKGD_SUPPORTED) +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_color_16p values, int color_type)); +#endif + +#if defined(PNG_WRITE_hIST_SUPPORTED) +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist, + int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_charp key, png_charpp new_key)); +#endif + +#if defined(PNG_WRITE_tEXt_SUPPORTED) +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len)); +#endif + +#if defined(PNG_WRITE_zTXt_SUPPORTED) +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key, + png_charp text, png_size_t text_len, int compression)); +#endif + +#if defined(PNG_WRITE_iTXt_SUPPORTED) +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_charp key, png_charp lang, png_charp lang_key, + png_charp text)); +#endif + +#if defined(PNG_TEXT_SUPPORTED) /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_textp text_ptr, int num_text)); +#endif + +#if defined(PNG_WRITE_oFFs_SUPPORTED) +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#if defined(PNG_WRITE_pCAL_SUPPORTED) +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_charp units, png_charpp params)); +#endif + +#if defined(PNG_WRITE_pHYs_SUPPORTED) +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#if defined(PNG_WRITE_tIME_SUPPORTED) +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_timep mod_time)); +#endif + +#if defined(PNG_WRITE_sCAL_SUPPORTED) +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) +PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr, + int unit, double width, double height)); +#else +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_charp width, png_charp height)); +#endif +#endif +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)); +#endif + +/* combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) +/* expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* these are the functions that do the transformations */ +#if defined(PNG_READ_FILLER_SUPPORTED) +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop + row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_READ_DITHER_SUPPORTED) +PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info, + png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup)); + +# if defined(PNG_CORRECT_PALETTE_SUPPORTED) +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row)); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, + png_color_8p bit_depth)); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background, + png_color_16p background_1, + png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1, + png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1, + png_uint_16pp gamma_16_to_1, int gamma_shift)); +#else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row, + png_color_16p trans_values, png_color_16p background)); +#endif +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row, + png_bytep gamma_table, png_uint_16pp gamma_16_table, + int gamma_shift)); +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_colorp palette, png_bytep trans, int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_color_16p trans_value)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#if defined(PNG_READ_bKGD_SUPPORTED) +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_cHRM_SUPPORTED) +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_gAMA_SUPPORTED) +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_hIST_SUPPORTED) +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_iCCP_SUPPORTED) +extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_oFFs_SUPPORTED) +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pCAL_SUPPORTED) +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_pHYs_SUPPORTED) +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sBIT_SUPPORTED) +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sCAL_SUPPORTED) +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_sPLT_SUPPORTED) +extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#if defined(PNG_READ_sRGB_SUPPORTED) +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tIME_SUPPORTED) +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_tRNS_SUPPORTED) +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_bytep chunk_name)); + +/* handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +#if defined(PNG_READ_tEXt_SUPPORTED) +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_zTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif +#if defined(PNG_READ_iTXt_SUPPORTED) +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +#endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) +/* png.c */ /* PRIVATE */ +PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr, +png_infop info_ptr)); + +#if defined(PNG_pHYs_SUPPORTED) +PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr, +png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +#endif /* PNG_INTERNAL */ + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* do not put anything past this line */ +#endif /* PNG_H */ diff --git a/include/lpng1212/pngconf.h b/include/lpng1212/pngconf.h new file mode 100644 index 0000000000..5daf602b36 --- /dev/null +++ b/include/lpng1212/pngconf.h @@ -0,0 +1,1472 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.2.12 - June 27, 2006 + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2005 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +#define PNG_1_2_X + +/* + * PNG_USER_CONFIG has to be defined on the compiler command line. This + * includes the resource compiler for Windows DLL configurations. + */ +#ifdef PNG_USER_CONFIG +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD +# endif +#include "pngusr.h" +#endif + +/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */ +#ifdef PNG_CONFIGURE_LIBPNG +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#endif + +/* + * Added at libpng-1.2.8 + * + * If you create a private DLL you need to define in "pngusr.h" the followings: + * #define PNG_USER_PRIVATEBUILD + * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." + * #define PNG_USER_DLLFNAME_POSTFIX + * e.g. // private DLL "libpng13gx.dll" + * #define PNG_USER_DLLFNAME_POSTFIX "gx" + * + * The following macros are also at your disposal if you want to complete the + * DLL VERSIONINFO structure. + * - PNG_USER_VERSIONINFO_COMMENTS + * - PNG_USER_VERSIONINFO_COMPANYNAME + * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS + */ + +#ifdef __STDC__ +#ifdef SPECIALBUILD +# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ + are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") +#endif + +#ifdef PRIVATEBUILD +# pragma message("PRIVATEBUILD is deprecated.\ + Use PNG_USER_PRIVATEBUILD instead.") +# define PNG_USER_PRIVATEBUILD PRIVATEBUILD +#endif +#endif /* __STDC__ */ + +#ifndef PNG_VERSION_INFO_ONLY + +/* End of material added to libpng-1.2.8 */ + +/* This is the size of the compression buffer, and thus the size of + * an IDAT chunk. Make this whatever size you feel is best for your + * machine. One of these will be allocated per png_struct. When this + * is full, it writes the data to the disk, and does some other + * calculations. Making this an extremely small size will slow + * the library down, but you may want to experiment to determine + * where it becomes significant, if you are concerned with memory + * usage. Note that zlib allocates at least 32Kb also. For readers, + * this describes the size of the buffer available to read the data in. + * Unless this gets smaller than the size of a row (compressed), + * it should not make much difference how big this is. + */ + +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +/* Enable if you want a write-only libpng */ + +#ifndef PNG_NO_READ_SUPPORTED +# define PNG_READ_SUPPORTED +#endif + +/* Enable if you want a read-only libpng */ + +#ifndef PNG_NO_WRITE_SUPPORTED +# define PNG_WRITE_SUPPORTED +#endif + +/* Enabled by default in 1.2.0. You can disable this if you don't need to + support PNGs that are embedded in MNG datastreams */ +#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES) +# ifndef PNG_MNG_FEATURES_SUPPORTED +# define PNG_MNG_FEATURES_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_FLOATING_POINT_SUPPORTED +# ifndef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FLOATING_POINT_SUPPORTED +# endif +#endif + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. +#define PNG_MAX_MALLOC_64K + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Special munging to support doing things the 'cygwin' way: + * 'Normal' png-on-win32 defines/defaults: + * PNG_BUILD_DLL -- building dll + * PNG_USE_DLL -- building an application, linking to dll + * (no define) -- building static library, or building an + * application and linking to the static lib + * 'Cygwin' defines/defaults: + * PNG_BUILD_DLL -- (ignored) building the dll + * (no define) -- (ignored) building an application, linking to the dll + * PNG_STATIC -- (ignored) building the static lib, or building an + * application that links to the static lib. + * ALL_STATIC -- (ignored) building various static libs, or building an + * application that links to the static libs. + * Thus, + * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and + * this bit of #ifdefs will define the 'correct' config variables based on + * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but + * unnecessary. + * + * Also, the precedence order is: + * ALL_STATIC (since we can't #undef something outside our namespace) + * PNG_BUILD_DLL + * PNG_STATIC + * (nothing) == PNG_USE_DLL + * + * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent + * of auto-import in binutils, we no longer need to worry about + * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, + * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes + * to __declspec() stuff. However, we DO need to worry about + * PNG_BUILD_DLL and PNG_STATIC because those change some defaults + * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed. + */ +#if defined(__CYGWIN__) +# if defined(ALL_STATIC) +# if defined(PNG_BUILD_DLL) +# undef PNG_BUILD_DLL +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# if !defined(PNG_STATIC) +# define PNG_STATIC +# endif +# else +# if defined (PNG_BUILD_DLL) +# if defined(PNG_STATIC) +# undef PNG_STATIC +# endif +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# else +# if defined(PNG_STATIC) +# if defined(PNG_USE_DLL) +# undef PNG_USE_DLL +# endif +# if defined(PNG_DLL) +# undef PNG_DLL +# endif +# else +# if !defined(PNG_USE_DLL) +# define PNG_USE_DLL +# endif +# if !defined(PNG_DLL) +# define PNG_DLL +# endif +# endif +# endif +# endif +#endif + +/* This protects us against compilers that run on a windowing system + * and thus don't have or would rather us not use the stdio types: + * stdin, stdout, and stderr. The only one currently used is stderr + * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will + * prevent these from being compiled and used. #defining PNG_NO_STDIO + * will also prevent these, plus will prevent the entire set of stdio + * macros and functions (FILE *, printf, etc.) from being compiled and used, + * unless (PNG_DEBUG > 0) has been #defined. + * + * #define PNG_NO_CONSOLE_IO + * #define PNG_NO_STDIO + */ + +#if defined(_WIN32_WCE) +# include + /* Console I/O functions are not supported on WindowsCE */ +# define PNG_NO_CONSOLE_IO +# ifdef PNG_DEBUG +# undef PNG_DEBUG +# endif +#endif + +#ifdef PNG_BUILD_DLL +# ifndef PNG_CONSOLE_IO_SUPPORTED +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# endif +#endif + +# ifdef PNG_NO_STDIO +# ifndef PNG_NO_CONSOLE_IO +# define PNG_NO_CONSOLE_IO +# endif +# ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# include +# endif +# endif +# else +# if !defined(_WIN32_WCE) +/* "stdio.h" functions are not supported on WindowsCE */ +# include +# endif +# endif + +/* This macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +#ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +#else + +#ifdef _NO_PROTO +# define PNGARG(arglist) () +# ifndef PNG_TYPECAST_NULL +# define PNG_TYPECAST_NULL +# endif +#else +# define PNGARG(arglist) arglist +#endif /* _NO_PROTO */ + +#endif /* OF */ + +#endif /* PNGARG */ + +/* Try to determine if we are compiling on a Mac. Note that testing for + * just __MWERKS__ is not good enough, because the Codewarrior is now used + * on non-Mac platforms. + */ +#ifndef MACOS +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) +# define MACOS +# endif +#endif + +/* enough people need this for various reasons to include it here */ +#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE) +# include +#endif + +#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) +# define PNG_SETJMP_SUPPORTED +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This is an attempt to force a single setjmp behaviour on Linux. If + * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. + */ + +# ifdef __linux__ +# ifdef _BSD_SOURCE +# define PNG_SAVE_BSD_SOURCE +# undef _BSD_SOURCE +# endif +# ifdef _SETJMP_H + /* If you encounter a compiler error here, see the explanation + * near the end of INSTALL. + */ + __png.h__ already includes setjmp.h; + __dont__ include it again.; +# endif +# endif /* __linux__ */ + + /* include setjmp.h for error handling */ +# include + +# ifdef __linux__ +# ifdef PNG_SAVE_BSD_SOURCE +# define _BSD_SOURCE +# undef PNG_SAVE_BSD_SOURCE +# endif +# endif /* __linux__ */ +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef BSD +# include +#else +# include +#endif + +/* Other defines for things like memory and the like can go here. */ +#ifdef PNG_INTERNAL + +#include + +/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it is + * possible to have run-time registry of chunk-handling functions, some of + * these will be made available again. +#define PNG_EXTERN extern + */ +#define PNG_EXTERN + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) +# if defined(MACOS) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* Codewarrior on NT has linking problems without this. */ +#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__) +# define PNG_ALWAYS_EXTERN +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +/* I have no idea why is this necessary... */ +#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \ + defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__)) +# include +#endif + +/* This controls how fine the dithering gets. As this allocates + * a largish chunk of memory (32K), those who are not as concerned + * with dithering quality can decrease some or all of these. + */ +#ifndef PNG_DITHER_RED_BITS +# define PNG_DITHER_RED_BITS 5 +#endif +#ifndef PNG_DITHER_GREEN_BITS +# define PNG_DITHER_GREEN_BITS 5 +#endif +#ifndef PNG_DITHER_BLUE_BITS +# define PNG_DITHER_BLUE_BITS 5 +#endif + +/* This controls how fine the gamma correction becomes when you + * are only interested in 8 bits anyway. Increasing this value + * results in more memory being used, and more pow() functions + * being called to fill in the gamma tables. Don't set this value + * less then 8, and even that may not work (I haven't tested it). + */ + +#ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +#endif + +/* This controls how much a difference in gamma we can tolerate before + * we actually start doing gamma conversion. + */ +#ifndef PNG_GAMMA_THRESHOLD +# define PNG_GAMMA_THRESHOLD 0.05 +#endif + +#endif /* PNG_INTERNAL */ + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + */ + +#ifndef PNG_NO_CONST +# define PNG_CONST const +#else +# define PNG_CONST +#endif + +/* The following defines give you the ability to remove code from the + * library that you will not be using. I wish I could figure out how to + * automate this, but I can't do that without making it seriously hard + * on the users. So if you are not using an ability, change the #define + * to and #undef, and that part of the library will not be compiled. If + * your linker can't find a function, you may want to make sure the + * ability is defined here. Some of these depend upon some others being + * defined. I haven't figured out all the interactions here, so you may + * have to experiment awhile to get everything to compile. If you are + * creating or using a shared library, you probably shouldn't touch this, + * as it will affect the size of the structures, and this will cause bad + * things to happen if the library and/or application ever change. + */ + +/* Any features you will not be using can be undef'ed here */ + +/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user + * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS + * on the compile line, then pick and choose which ones to define without + * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED + * if you only want to have a png-compliant reader/writer but don't need + * any of the extra transformations. This saves about 80 kbytes in a + * typical installation of the library. (PNG_NO_* form added in version + * 1.0.1c, for consistency) + */ + +/* The size of the png_text structure changed in libpng-1.0.6 when + * iTXt support was added. iTXt support was turned off by default through + * libpng-1.2.x, to support old apps that malloc the png_text structure + * instead of calling png_set_text() and letting libpng malloc it. It + * was turned on by default in libpng-1.3.0. + */ + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +# ifndef PNG_NO_iTXt_SUPPORTED +# define PNG_NO_iTXt_SUPPORTED +# endif +# ifndef PNG_NO_READ_iTXt +# define PNG_NO_READ_iTXt +# endif +# ifndef PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_iTXt +# endif +#endif + +#if !defined(PNG_NO_iTXt_SUPPORTED) +# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt) +# define PNG_READ_iTXt +# endif +# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt) +# define PNG_WRITE_iTXt +# endif +#endif + +/* The following support, added after version 1.0.0, can be turned off here en + * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility + * with old applications that require the length of png_struct and png_info + * to remain unchanged. + */ + +#ifdef PNG_LEGACY_SUPPORTED +# define PNG_NO_FREE_ME +# define PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_NO_READ_USER_CHUNKS +# define PNG_NO_READ_iCCP +# define PNG_NO_WRITE_iCCP +# define PNG_NO_READ_iTXt +# define PNG_NO_WRITE_iTXt +# define PNG_NO_READ_sCAL +# define PNG_NO_WRITE_sCAL +# define PNG_NO_READ_sPLT +# define PNG_NO_WRITE_sPLT +# define PNG_NO_INFO_IMAGE +# define PNG_NO_READ_RGB_TO_GRAY +# define PNG_NO_READ_USER_TRANSFORM +# define PNG_NO_WRITE_USER_TRANSFORM +# define PNG_NO_USER_MEM +# define PNG_NO_READ_EMPTY_PLTE +# define PNG_NO_MNG_FEATURES +# define PNG_NO_FIXED_POINT_SUPPORTED +#endif + +/* Ignore attempt to turn off both floating and fixed point support */ +#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ + !defined(PNG_NO_FIXED_POINT_SUPPORTED) +# define PNG_FIXED_POINT_SUPPORTED +#endif + +#ifndef PNG_NO_FREE_ME +# define PNG_FREE_ME_SUPPORTED +#endif + +#if defined(PNG_READ_SUPPORTED) + +#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_TRANSFORMS) +# define PNG_READ_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_READ_EXPAND +# define PNG_READ_EXPAND_SUPPORTED +# endif +# ifndef PNG_NO_READ_SHIFT +# define PNG_READ_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACK +# define PNG_READ_PACK_SUPPORTED +# endif +# ifndef PNG_NO_READ_BGR +# define PNG_READ_BGR_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP +# define PNG_READ_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_PACKSWAP +# define PNG_READ_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT +# define PNG_READ_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_READ_DITHER +# define PNG_READ_DITHER_SUPPORTED +# endif +# ifndef PNG_NO_READ_BACKGROUND +# define PNG_READ_BACKGROUND_SUPPORTED +# endif +# ifndef PNG_NO_READ_16_TO_8 +# define PNG_READ_16_TO_8_SUPPORTED +# endif +# ifndef PNG_NO_READ_FILLER +# define PNG_READ_FILLER_SUPPORTED +# endif +# ifndef PNG_NO_READ_GAMMA +# define PNG_READ_GAMMA_SUPPORTED +# endif +# ifndef PNG_NO_READ_GRAY_TO_RGB +# define PNG_READ_GRAY_TO_RGB_SUPPORTED +# endif +# ifndef PNG_NO_READ_SWAP_ALPHA +# define PNG_READ_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_INVERT_ALPHA +# define PNG_READ_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_STRIP_ALPHA +# define PNG_READ_STRIP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_READ_USER_TRANSFORM +# define PNG_READ_USER_TRANSFORM_SUPPORTED +# endif +# ifndef PNG_NO_READ_RGB_TO_GRAY +# define PNG_READ_RGB_TO_GRAY_SUPPORTED +# endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_PROGRESSIVE_READ) && \ + !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ +# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ +#endif /* about interlacing capability! You'll */ + /* still have interlacing unless you change the following line: */ + +#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ + +#ifndef PNG_NO_READ_COMPOSITE_NODIV +# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ +# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ +# endif +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, will be removed from version 2.0.0. + Use PNG_MNG_FEATURES_SUPPORTED instead. */ +#ifndef PNG_NO_READ_EMPTY_PLTE +# define PNG_READ_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_WRITE_SUPPORTED) + +# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_TRANSFORMS) +# define PNG_WRITE_TRANSFORMS_SUPPORTED +#endif + +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED +# ifndef PNG_NO_WRITE_SHIFT +# define PNG_WRITE_SHIFT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACK +# define PNG_WRITE_PACK_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_BGR +# define PNG_WRITE_BGR_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_SWAP +# define PNG_WRITE_SWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_PACKSWAP +# define PNG_WRITE_PACKSWAP_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT +# define PNG_WRITE_INVERT_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_FILLER +# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ +# endif +# ifndef PNG_NO_WRITE_SWAP_ALPHA +# define PNG_WRITE_SWAP_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_INVERT_ALPHA +# define PNG_WRITE_INVERT_ALPHA_SUPPORTED +# endif +# ifndef PNG_NO_WRITE_USER_TRANSFORM +# define PNG_WRITE_USER_TRANSFORM_SUPPORTED +# endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ + +#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ + !defined(PNG_WRITE_INTERLACING_SUPPORTED) +#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant + encoders, but can cause trouble + if left undefined */ +#endif + +#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ + !defined(PNG_WRITE_WEIGHTED_FILTER) && \ + defined(PNG_FLOATING_POINT_SUPPORTED) +# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED +#endif + +#ifndef PNG_NO_WRITE_FLUSH +# define PNG_WRITE_FLUSH_SUPPORTED +#endif + +#if defined(PNG_1_0_X) || defined (PNG_1_2_X) +/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */ +#ifndef PNG_NO_WRITE_EMPTY_PLTE +# define PNG_WRITE_EMPTY_PLTE_SUPPORTED +#endif +#endif + +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef PNG_1_0_X +# ifndef PNG_NO_ERROR_NUMBERS +# define PNG_ERROR_NUMBERS_SUPPORTED +# endif +#endif /* PNG_1_0_X */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +# ifndef PNG_NO_USER_TRANSFORM_PTR +# define PNG_USER_TRANSFORM_PTR_SUPPORTED +# endif +#endif + +#ifndef PNG_NO_STDIO +# define PNG_TIME_RFC1123_SUPPORTED +#endif + +/* This adds extra functions in pngget.c for accessing data from the + * info pointer (added in version 0.99) + * png_get_image_width() + * png_get_image_height() + * png_get_bit_depth() + * png_get_color_type() + * png_get_compression_type() + * png_get_filter_type() + * png_get_interlace_type() + * png_get_pixel_aspect_ratio() + * png_get_pixels_per_meter() + * png_get_x_offset_pixels() + * png_get_y_offset_pixels() + * png_get_x_offset_microns() + * png_get_y_offset_microns() + */ +#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) +# define PNG_EASY_ACCESS_SUPPORTED +#endif + +/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0 + even when PNG_USE_PNGVCRD or PNG_USE_PNGGCCRD is not defined */ +#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE) +# ifndef PNG_ASSEMBLER_CODE_SUPPORTED +# define PNG_ASSEMBLER_CODE_SUPPORTED +# endif +# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE) && \ + defined(__MMX__) +# define PNG_MMX_CODE_SUPPORTED +# endif +# if !defined(PNG_USE_PNGGCCRD) && !defined(PNG_NO_MMX_CODE) && \ + !defined(PNG_USE_PNGVCRD) && defined(__MMX__) +# define PNG_USE_PNGGCCRD +# endif +#endif + +/* If you are sure that you don't need thread safety and you are compiling + with PNG_USE_PNGCCRD for an MMX application, you can define this for + faster execution. See pnggccrd.c. +#define PNG_THREAD_UNSAFE_OK +*/ + +#if !defined(PNG_1_0_X) +#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) +# define PNG_USER_MEM_SUPPORTED +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.2.6 */ +#if !defined(PNG_1_0_X) +#ifndef PNG_SET_USER_LIMITS_SUPPORTED +#if !defined(PNG_NO_SET_USER_LIMITS) && !defined(PNG_SET_USER_LIMITS_SUPPORTED) +# define PNG_SET_USER_LIMITS_SUPPORTED +#endif +#endif +#endif /* PNG_1_0_X */ + +/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter + * how large, set these limits to 0x7fffffffL + */ +#ifndef PNG_USER_WIDTH_MAX +# define PNG_USER_WIDTH_MAX 1000000L +#endif +#ifndef PNG_USER_HEIGHT_MAX +# define PNG_USER_HEIGHT_MAX 1000000L +#endif + +/* These are currently experimental features, define them if you want */ + +/* very little testing */ +/* +#ifdef PNG_READ_SUPPORTED +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# endif +#endif +*/ + +/* This is only for PowerPC big-endian and 680x0 systems */ +/* some testing */ +/* +#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED +# define PNG_READ_BIG_ENDIAN_SUPPORTED +#endif +*/ + +/* Buggy compilers (e.g., gcc 2.7.2.2) need this */ +/* +#define PNG_NO_POINTER_INDEXING +*/ + +/* These functions are turned off by default, as they will be phased out. */ +/* +#define PNG_USELESS_TESTS_SUPPORTED +#define PNG_CORRECT_PALETTE_SUPPORTED +*/ + +/* Any chunks you are not interested in, you can undef here. The + * ones that allocate memory may be expecially important (hIST, + * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info + * a bit smaller. + */ + +#if defined(PNG_READ_SUPPORTED) && \ + !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_READ_ANCILLARY_CHUNKS) +# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#if defined(PNG_WRITE_SUPPORTED) && \ + !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ + !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) +# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#endif + +#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_READ_TEXT +# define PNG_NO_READ_iTXt +# define PNG_NO_READ_tEXt +# define PNG_NO_READ_zTXt +#endif +#ifndef PNG_NO_READ_bKGD +# define PNG_READ_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +#endif +#ifndef PNG_NO_READ_cHRM +# define PNG_READ_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +#endif +#ifndef PNG_NO_READ_gAMA +# define PNG_READ_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +#endif +#ifndef PNG_NO_READ_hIST +# define PNG_READ_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +#endif +#ifndef PNG_NO_READ_iCCP +# define PNG_READ_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +#endif +#ifndef PNG_NO_READ_iTXt +# ifndef PNG_READ_iTXt_SUPPORTED +# define PNG_READ_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_READ_oFFs +# define PNG_READ_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +#endif +#ifndef PNG_NO_READ_pCAL +# define PNG_READ_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_sCAL +# define PNG_READ_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +#endif +#ifndef PNG_NO_READ_pHYs +# define PNG_READ_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +#endif +#ifndef PNG_NO_READ_sBIT +# define PNG_READ_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sPLT +# define PNG_READ_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +#endif +#ifndef PNG_NO_READ_sRGB +# define PNG_READ_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +#endif +#ifndef PNG_NO_READ_tEXt +# define PNG_READ_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_tIME +# define PNG_READ_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +#endif +#ifndef PNG_NO_READ_tRNS +# define PNG_READ_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +#endif +#ifndef PNG_NO_READ_zTXt +# define PNG_READ_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +#endif +#ifndef PNG_NO_READ_UNKNOWN_CHUNKS +# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +#endif +#if !defined(PNG_NO_READ_USER_CHUNKS) && \ + defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) +# define PNG_READ_USER_CHUNKS_SUPPORTED +# define PNG_USER_CHUNKS_SUPPORTED +# ifdef PNG_NO_READ_UNKNOWN_CHUNKS +# undef PNG_NO_READ_UNKNOWN_CHUNKS +# endif +# ifdef PNG_NO_HANDLE_AS_UNKNOWN +# undef PNG_NO_HANDLE_AS_UNKNOWN +# endif +#endif +#ifndef PNG_NO_READ_OPT_PLTE +# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ +#endif /* optional PLTE chunk in RGB and RGBA images */ +#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ + defined(PNG_READ_zTXt_SUPPORTED) +# define PNG_READ_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +#endif + +#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ + +#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED + +#ifdef PNG_NO_WRITE_TEXT +# define PNG_NO_WRITE_iTXt +# define PNG_NO_WRITE_tEXt +# define PNG_NO_WRITE_zTXt +#endif +#ifndef PNG_NO_WRITE_bKGD +# define PNG_WRITE_bKGD_SUPPORTED +# ifndef PNG_bKGD_SUPPORTED +# define PNG_bKGD_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_cHRM +# define PNG_WRITE_cHRM_SUPPORTED +# ifndef PNG_cHRM_SUPPORTED +# define PNG_cHRM_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_gAMA +# define PNG_WRITE_gAMA_SUPPORTED +# ifndef PNG_gAMA_SUPPORTED +# define PNG_gAMA_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_hIST +# define PNG_WRITE_hIST_SUPPORTED +# ifndef PNG_hIST_SUPPORTED +# define PNG_hIST_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iCCP +# define PNG_WRITE_iCCP_SUPPORTED +# ifndef PNG_iCCP_SUPPORTED +# define PNG_iCCP_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_iTXt +# ifndef PNG_WRITE_iTXt_SUPPORTED +# define PNG_WRITE_iTXt_SUPPORTED +# endif +# ifndef PNG_iTXt_SUPPORTED +# define PNG_iTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_oFFs +# define PNG_WRITE_oFFs_SUPPORTED +# ifndef PNG_oFFs_SUPPORTED +# define PNG_oFFs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pCAL +# define PNG_WRITE_pCAL_SUPPORTED +# ifndef PNG_pCAL_SUPPORTED +# define PNG_pCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sCAL +# define PNG_WRITE_sCAL_SUPPORTED +# ifndef PNG_sCAL_SUPPORTED +# define PNG_sCAL_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_pHYs +# define PNG_WRITE_pHYs_SUPPORTED +# ifndef PNG_pHYs_SUPPORTED +# define PNG_pHYs_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sBIT +# define PNG_WRITE_sBIT_SUPPORTED +# ifndef PNG_sBIT_SUPPORTED +# define PNG_sBIT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sPLT +# define PNG_WRITE_sPLT_SUPPORTED +# ifndef PNG_sPLT_SUPPORTED +# define PNG_sPLT_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_sRGB +# define PNG_WRITE_sRGB_SUPPORTED +# ifndef PNG_sRGB_SUPPORTED +# define PNG_sRGB_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tEXt +# define PNG_WRITE_tEXt_SUPPORTED +# ifndef PNG_tEXt_SUPPORTED +# define PNG_tEXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tIME +# define PNG_WRITE_tIME_SUPPORTED +# ifndef PNG_tIME_SUPPORTED +# define PNG_tIME_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_tRNS +# define PNG_WRITE_tRNS_SUPPORTED +# ifndef PNG_tRNS_SUPPORTED +# define PNG_tRNS_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_zTXt +# define PNG_WRITE_zTXt_SUPPORTED +# ifndef PNG_zTXt_SUPPORTED +# define PNG_zTXt_SUPPORTED +# endif +#endif +#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS +# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED +# define PNG_UNKNOWN_CHUNKS_SUPPORTED +# endif +# ifndef PNG_NO_HANDLE_AS_UNKNOWN +# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +# endif +# endif +#endif +#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ + defined(PNG_WRITE_zTXt_SUPPORTED) +# define PNG_WRITE_TEXT_SUPPORTED +# ifndef PNG_TEXT_SUPPORTED +# define PNG_TEXT_SUPPORTED +# endif +#endif + +#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ + +/* Turn this off to disable png_read_png() and + * png_write_png() and leave the row_pointers member + * out of the info structure. + */ +#ifndef PNG_NO_INFO_IMAGE +# define PNG_INFO_IMAGE_SUPPORTED +#endif + +/* need the time information for reading tIME chunks */ +#if defined(PNG_tIME_SUPPORTED) +# if !defined(_WIN32_WCE) + /* "time.h" functions are not supported on WindowsCE */ +# include +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may + * want to have unsigned int for png_uint_32 instead of unsigned long. + */ + +typedef unsigned long png_uint_32; +typedef long png_int_32; +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +/* This is usually size_t. It is typedef'ed just in case you need it to + change (I'm not sure if you will or not, so I thought I'd be safe) */ +#ifdef PNG_SIZE_T + typedef PNG_SIZE_T png_size_t; +# define png_sizeof(x) png_convert_size(sizeof (x)) +#else + typedef size_t png_size_t; +# define png_sizeof(x) sizeof (x) +#endif + +/* The following is needed for medium model support. It cannot be in the + * PNG_INTERNAL section. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + defines FAR. (SJT) */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#if defined(FAR) +# if defined(M_I86MM) +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + to fixed-point with a multiple of 100,000, e.g., int_gamma */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef png_byte FAR * png_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST char FAR * png_const_charp; +typedef char FAR * png_charp; +typedef png_fixed_point FAR * png_fixed_point_p; + +#ifndef PNG_NO_STDIO +#if defined(_WIN32_WCE) +typedef HANDLE png_FILE_p; +#else +typedef FILE * png_FILE_p; +#endif +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) +/* SPC - Is this stuff deprecated? */ +/* It'll be removed as of libpng-1.3.0 - GR-P */ +/* libpng typedefs for types in zlib. If zlib changes + * or another compression library is used, then change these. + * Eliminates need to change all the source files. + */ +typedef charf * png_zcharp; +typedef charf * FAR * png_zcharpp; +typedef z_stream FAR * png_zstreamp; +#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */ + +/* + * Define PNG_BUILD_DLL if the module being built is a Windows + * LIBPNG DLL. + * + * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. + * It is equivalent to Microsoft predefined macro _DLL that is + * automatically defined when you compile using the share + * version of the CRT (C Run-Time library) + * + * The cygwin mods make this behavior a little different: + * Define PNG_BUILD_DLL if you are building a dll for use with cygwin + * Define PNG_STATIC if you are building a static library for use with cygwin, + * -or- if you are building an application that you want to link to the + * static library. + * PNG_USE_DLL is defined by default (no user action needed) unless one of + * the other flags is defined. + */ + +#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) +# define PNG_DLL +#endif +/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib. + * When building a static lib, default to no GLOBAL ARRAYS, but allow + * command-line override + */ +#if defined(__CYGWIN__) +# if !defined(PNG_STATIC) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +# else +# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS) +# if defined(PNG_USE_GLOBAL_ARRAYS) +# undef PNG_USE_GLOBAL_ARRAYS +# endif +# endif +# endif +# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# define PNG_USE_LOCAL_ARRAYS +# endif +#endif + +/* Do not use global arrays (helps with building DLL's) + * They are no longer used in libpng itself, since version 1.0.5c, + * but might be required for some pre-1.0.5c applications. + */ +#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS) +# if defined(PNG_NO_GLOBAL_ARRAYS) || (defined(__GNUC__) && defined(PNG_DLL)) +# define PNG_USE_LOCAL_ARRAYS +# else +# define PNG_USE_GLOBAL_ARRAYS +# endif +#endif + +#if defined(__CYGWIN__) +# undef PNGAPI +# define PNGAPI __cdecl +# undef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", + * you may get warnings regarding the linkage of png_zalloc and png_zfree. + * Don't ignore those warnings; you must also reset the default calling + * convention in your compiler to match your PNGAPI, and you must build + * zlib and your applications the same way you build libpng. + */ + +#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) +# ifndef PNG_NO_MODULEDEF +# define PNG_NO_MODULEDEF +# endif +#endif + +#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) +# define PNG_IMPEXP +#endif + +#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ + (( defined(_Windows) || defined(_WINDOWS) || \ + defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) + +# ifndef PNGAPI +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGAPI __cdecl +# else +# define PNGAPI _cdecl +# endif +# endif + +# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ + 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) +# define PNG_IMPEXP +# endif + +# if !defined(PNG_IMPEXP) + +# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol +# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol + + /* Borland/Microsoft */ +# if defined(_MSC_VER) || defined(__BORLANDC__) +# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) +# define PNG_EXPORT PNG_EXPORT_TYPE1 +# else +# define PNG_EXPORT PNG_EXPORT_TYPE2 +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __export +# else +# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in + VC++ */ +# endif /* Exists in Borland C++ for + C++ classes (== huge) */ +# endif +# endif + +# if !defined(PNG_IMPEXP) +# if defined(PNG_BUILD_DLL) +# define PNG_IMPEXP __declspec(dllexport) +# else +# define PNG_IMPEXP __declspec(dllimport) +# endif +# endif +# endif /* PNG_IMPEXP */ +#else /* !(DLL || non-cygwin WINDOWS) */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# ifndef PNGAPI +# define PNGAPI _System +# endif +# else +# if 0 /* ... other platforms, with other meanings */ +# endif +# endif +#endif + +#ifndef PNGAPI +# define PNGAPI +#endif +#ifndef PNG_IMPEXP +# define PNG_IMPEXP +#endif + +#ifdef PNG_BUILDSYMS +# ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END +# endif +# ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT +# endif +# endif +#endif + +#ifndef PNG_EXPORT +# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol +#endif + +#ifdef PNG_USE_GLOBAL_ARRAYS +# ifndef PNG_EXPORT_VAR +# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type +# endif +#endif + +/* User may want to use these so they are not in PNG_INTERNAL. Any library + * functions that are passed far data must be model independent. + */ + +#ifndef PNG_ABORT +# define PNG_ABORT() abort() +#endif + +#ifdef PNG_SETJMP_SUPPORTED +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED) +#endif + +#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ +/* use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +#else /* use the usual functions */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +#endif +/* End of memory model independent support */ + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +#ifdef PNG_READ_SUPPORTED +/* Prior to libpng-1.0.9, this block was in pngasmrd.h */ +#if defined(PNG_INTERNAL) + +/* These are the default thresholds before the MMX code kicks in; if either + * rowbytes or bitdepth is below the threshold, plain C code is used. These + * can be overridden at runtime via the png_set_mmx_thresholds() call in + * libpng 1.2.0 and later. The values below were chosen by Intel. + */ + +#ifndef PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT +# define PNG_MMX_ROWBYTES_THRESHOLD_DEFAULT 128 /* >= */ +#endif +#ifndef PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT +# define PNG_MMX_BITDEPTH_THRESHOLD_DEFAULT 9 /* >= */ +#endif + +/* Set this in the makefile for VC++ on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pngvcrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGVCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif + +/* Set this in the makefile for gcc/as on Pentium, not here. */ +/* Platform must be Pentium. Makefile must assemble and load pnggccrd.c . + * MMX will be detected at run time and used if present. + */ +#ifdef PNG_USE_PNGGCCRD +# define PNG_HAVE_ASSEMBLER_COMBINE_ROW +# define PNG_HAVE_ASSEMBLER_READ_INTERLACE +# define PNG_HAVE_ASSEMBLER_READ_FILTER_ROW +#endif +/* - see pnggccrd.c for info about what is currently enabled */ + +#endif /* PNG_INTERNAL */ +#endif /* PNG_READ_SUPPORTED */ + +/* Added at libpng-1.2.8 */ +#endif /* PNG_VERSION_INFO_ONLY */ + +#endif /* PNGCONF_H */ diff --git a/include/pthread/pthread.h b/include/pthread/pthread.h new file mode 100644 index 0000000000..9f2868bccb --- /dev/null +++ b/include/pthread/pthread.h @@ -0,0 +1,1368 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,8,0,0 +#define PTW32_VERSION_STRING "2, 8, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +#include + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/include/pthread/sched.h b/include/pthread/sched.h new file mode 100644 index 0000000000..10ecb5d7ea --- /dev/null +++ b/include/pthread/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/include/pthread/semaphore.h b/include/pthread/semaphore.h new file mode 100644 index 0000000000..ea42ce3703 --- /dev/null +++ b/include/pthread/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/include/zlib123/crc32.h b/include/zlib123/crc32.h new file mode 100644 index 0000000000..5de49bc978 --- /dev/null +++ b/include/zlib123/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const unsigned long FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/include/zlib123/deflate.h b/include/zlib123/deflate.h new file mode 100644 index 0000000000..222c53e043 --- /dev/null +++ b/include/zlib123/deflate.h @@ -0,0 +1,331 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2004 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define EXTRA_STATE 69 +#define NAME_STATE 73 +#define COMMENT_STATE 91 +#define HCRC_STATE 103 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + uInt pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + uInt gzindex; /* where in extra, name, or comment */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/include/zlib123/inffast.h b/include/zlib123/inffast.h new file mode 100644 index 0000000000..614fa7877d --- /dev/null +++ b/include/zlib123/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/include/zlib123/inffixed.h b/include/zlib123/inffixed.h new file mode 100644 index 0000000000..423d5c5b50 --- /dev/null +++ b/include/zlib123/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. It + is part of the implementation of the compression library and + is subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/include/zlib123/inflate.h b/include/zlib123/inflate.h new file mode 100644 index 0000000000..fbbc871432 --- /dev/null +++ b/include/zlib123/inflate.h @@ -0,0 +1,115 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/include/zlib123/inftrees.h b/include/zlib123/inftrees.h new file mode 100644 index 0000000000..dc0fd567ea --- /dev/null +++ b/include/zlib123/inftrees.h @@ -0,0 +1,55 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1444 code structures (852 for length/literals + and 592 for distances, the latter actually the result of an + exhaustive search). The true maximum is not known, but the value + below is more than safe. */ +#define ENOUGH 2048 +#define MAXD 592 + +/* Type of code to build for inftable() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/include/zlib123/trees.h b/include/zlib123/trees.h new file mode 100644 index 0000000000..1ca868b848 --- /dev/null +++ b/include/zlib123/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/include/zlib123/zconf.h b/include/zlib123/zconf.h new file mode 100644 index 0000000000..e3b0c962e3 --- /dev/null +++ b/include/zlib123/zconf.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/include/zlib123/zconf.in.h b/include/zlib123/zconf.in.h new file mode 100644 index 0000000000..e3b0c962e3 --- /dev/null +++ b/include/zlib123/zconf.in.h @@ -0,0 +1,332 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define deflateBound z_deflateBound +# define deflatePrime z_deflatePrime +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateCopy z_inflateCopy +# define inflateReset z_inflateReset +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table +# define zError z_zError + +# define alloc_func z_alloc_func +# define free_func z_free_func +# define in_func z_in_func +# define out_func z_out_func +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# ifdef VMS +# include /* for off_t */ +# endif +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +#if defined(__OS400__) +# define NO_vsnprintf +#endif + +#if defined(__MVS__) +# define NO_vsnprintf +# ifdef FAR +# undef FAR +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(deflateBound,"DEBND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(compressBound,"CMBND") +# pragma map(inflate_table,"INTABL") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/include/zlib123/zlib.h b/include/zlib123/zlib.h new file mode 100644 index 0000000000..62d0e4675b --- /dev/null +++ b/include/zlib123/zlib.h @@ -0,0 +1,1357 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.3" +#define ZLIB_VERNUM 0x1230 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip streams in memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field (though see inflate()) */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumualte before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + the value returned by deflateBound (see below). If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not + fatal, and deflate() can be called again with more input and more output + space to continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, + Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() stop + if and when it gets to the next deflate block boundary. When decoding the + zlib or gzip format, this will cause inflate() to return immediately after + the header and before the first block. When doing a raw inflate, inflate() + will go ahead and process the first block, and will return when it gets to + the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + Also to assist in this, on return inflate() will set strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 + if inflate() is currently decoding the last block in the deflate stream, + plus 128 if inflate() returned immediately after decoding an end-of-block + code or decoding the complete header up to just before the first byte of the + deflate stream. The end-of-block will not be indicated until all of the + uncompressed data from that block has been written to strm->next_out. The + number of unused bits may in general be greater than seven, except when + bit 7 of data_type is set, in which case the number of unused bits will be + less than eight. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster approach + may be used for the single inflate() call. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the only effect of the flush parameter in this implementation + is on the return value of inflate(), as noted below, or when it returns early + because Z_BLOCK is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the adler32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the adler32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed adler32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() will decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically. Any information + contained in the gzip header is not retained, so applications that need that + information should instead use raw inflate, see inflateInit2() below, or + inflateBack() and perform their own processing of the gzip header and + trailer. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value), Z_STREAM_ERROR if the stream structure was inconsistent (for example + if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, + Z_BUF_ERROR if no progress is possible or if there was not enough room in the + output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may then + call inflateSync() to look for a good compression block if a partial recovery + of the data is desired. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute an adler32 check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), + no header crc, and the operating system will be set to 255 (unknown). If a + gzip stream is being written, strm->adler is a crc32 instead of an adler32. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as + Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy + parameter only affects the compression ratio but not the correctness of the + compressed output even if it is not set appropriately. Z_FIXED prevents the + use of dynamic Huffman codes, allowing for a simpler decoder for special + applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. In addition, the + current implementation of deflate will use at most the window size minus + 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + adler32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() + or deflateInit2(). This would be used to allocate an output buffer + for deflation in a single pass, and so would be called before deflate(). +*/ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the + bits leftover from a previous deflate stream when appending to it. As such, + this function can only be used for raw deflate, and must be used before the + first deflate() call after a deflateInit2() or deflateReset(). bits must be + less than or equal to 16, and that many of the least significant bits of + value will be inserted in the output. + + deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an adler32 or a crc32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is + a crc32 instead of an adler32. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg + is set to null if there is no error message. inflateInit2 does not perform + any decompression apart from reading the zlib header if present: this will + be done by inflate(). (So next_in and avail_in may be modified, but next_out + and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the adler32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called + immediately after inflateInit2() or inflateReset() and before any call of + inflate() to set the dictionary. The application must insure that the + dictionary that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK can be used to + force inflate() to return immediately after header processing is complete + and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When + any of extra, name, or comment are not Z_NULL and the respective field is + not present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the paramaters are invalid, Z_MEM_ERROR if the internal state could not + be allocated, or Z_VERSION_ERROR if the version of the library does not + match the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is more efficient than inflate() for + file i/o applications in that it avoids copying between the output and the + sliding window by simply making the window itself the output buffer. This + function trusts the application to not change the output buffer passed by + the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free + the allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects + only the raw deflate stream to decompress. This is different from the + normal behavior of inflate(), which expects either a zlib or gzip header and + trailer around the deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero--buf is ignored in that + case--and inflateBack() will return a buffer error. inflateBack() will call + out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() + should return zero on success, or non-zero on failure. If out() returns + non-zero, inflateBack() will return with an error. Neither in() nor out() + are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format + error in the deflate stream (in which case strm->msg is set to indicate the + nature of the error), or Z_STREAM_ERROR if the stream was not properly + initialized. In the case of Z_BUF_ERROR, an input or output error can be + distinguished using strm->next_in which will be Z_NULL only if in() returned + an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to + out() returning non-zero. (in() will always be called before out(), so + strm->next_in is assured to be defined if out() returns non-zero.) Note + that inflateBack() cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least the value returned + by compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before + a compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h", or 'R' for run-length encoding + as in "wb1R". (See the description of deflateInit2 for more information + about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). The number of + uncompressed bytes written is limited to 4095. The caller should assure that + this limit is not exceeded. If it is exceeded, then gzprintf() will return + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read again later. + Only one character of push-back is allowed. gzungetc() returns the + character pushed, or -1 on failure. gzungetc() will fail if a + character has been pushed but not read yet, or if c is -1. The pushed + character will be discarded if the stream is repositioned with gzseek() + or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns 1 if file is being read directly without decompression, otherwise + zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); +/* + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is NULL, this function returns the required initial + value for the for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + +/* + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) +#define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/include/zlib123/zutil.h b/include/zlib123/zutil.h new file mode 100644 index 0000000000..0ba6e02087 --- /dev/null +++ b/include/zlib123/zutil.h @@ -0,0 +1,269 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2005 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#define ZLIB_INTERNAL +#include "zlib.h" + +#ifdef STDC +# ifndef _WIN32_WCE +# include +# endif +# include +# include +#endif +#ifdef NO_ERRNO_H +# ifdef _WIN32_WCE + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. We rename it to + * avoid conflict with other libraries that use the same workaround. + */ +# define errno z_errno +# endif + extern int errno; +#else +# ifndef _WIN32_WCE +# include +# endif +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +# ifdef M_I86 + #include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#ifdef WIN32 +# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ +# define OS_CODE 0x0b +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0f +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS + /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 + /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# define vsnprintf _vsnprintf +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +#endif +#ifdef VMS +# define NO_vsnprintf +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* ZUTIL_H */ diff --git a/libs/mingw/deleteme.txt b/libs/mingw/deleteme.txt new file mode 100644 index 0000000000..12de16d9d3 --- /dev/null +++ b/libs/mingw/deleteme.txt @@ -0,0 +1 @@ +deleteme \ No newline at end of file diff --git a/libs/win32/al_gif.lib b/libs/win32/al_gif.lib new file mode 100644 index 0000000000..2773749da9 Binary files /dev/null and b/libs/win32/al_gif.lib differ diff --git a/libs/win32/aldmb.lib b/libs/win32/aldmb.lib new file mode 100644 index 0000000000..28cee970f4 Binary files /dev/null and b/libs/win32/aldmb.lib differ diff --git a/libs/win32/alleg_crt.lib b/libs/win32/alleg_crt.lib new file mode 100644 index 0000000000..0ceb4d5117 Binary files /dev/null and b/libs/win32/alleg_crt.lib differ diff --git a/libs/win32/almp3.lib b/libs/win32/almp3.lib new file mode 100644 index 0000000000..74c5adcb6b Binary files /dev/null and b/libs/win32/almp3.lib differ diff --git a/libs/win32/alogg.lib b/libs/win32/alogg.lib new file mode 100644 index 0000000000..2c91856280 Binary files /dev/null and b/libs/win32/alogg.lib differ diff --git a/libs/win32/alspc.lib b/libs/win32/alspc.lib new file mode 100644 index 0000000000..67484679f9 Binary files /dev/null and b/libs/win32/alspc.lib differ diff --git a/libs/win32/dumb.lib b/libs/win32/dumb.lib new file mode 100644 index 0000000000..64fa012ed2 Binary files /dev/null and b/libs/win32/dumb.lib differ diff --git a/libs/win32/gme.lib b/libs/win32/gme.lib new file mode 100644 index 0000000000..d2ce84ebce Binary files /dev/null and b/libs/win32/gme.lib differ diff --git a/libs/win32/libjpgal.lib b/libs/win32/libjpgal.lib new file mode 100644 index 0000000000..8ab4c3710e Binary files /dev/null and b/libs/win32/libjpgal.lib differ diff --git a/libs/win32/libpng.lib b/libs/win32/libpng.lib new file mode 100644 index 0000000000..5fef5aba20 Binary files /dev/null and b/libs/win32/libpng.lib differ diff --git a/libs/win32/loadpng.lib b/libs/win32/loadpng.lib new file mode 100644 index 0000000000..e482866f4e Binary files /dev/null and b/libs/win32/loadpng.lib differ diff --git a/libs/win32/pthread.lib b/libs/win32/pthread.lib new file mode 100644 index 0000000000..2b2fcd449d Binary files /dev/null and b/libs/win32/pthread.lib differ diff --git a/libs/win32/zcsound.lib b/libs/win32/zcsound.lib new file mode 100644 index 0000000000..47d0b859ce Binary files /dev/null and b/libs/win32/zcsound.lib differ diff --git a/libs/win32/zlib.lib b/libs/win32/zlib.lib new file mode 100644 index 0000000000..9352666346 Binary files /dev/null and b/libs/win32/zlib.lib differ diff --git a/libs/win32dbg/al_gif.lib b/libs/win32dbg/al_gif.lib new file mode 100644 index 0000000000..949413db2d Binary files /dev/null and b/libs/win32dbg/al_gif.lib differ diff --git a/libs/win32dbg/aldmd.lib b/libs/win32dbg/aldmd.lib new file mode 100644 index 0000000000..cb7d971e6f Binary files /dev/null and b/libs/win32dbg/aldmd.lib differ diff --git a/libs/win32dbg/alld_crt.lib b/libs/win32dbg/alld_crt.lib new file mode 100644 index 0000000000..56df8cd62f Binary files /dev/null and b/libs/win32dbg/alld_crt.lib differ diff --git a/libs/win32dbg/almp3.lib b/libs/win32dbg/almp3.lib new file mode 100644 index 0000000000..c0d9ecb3b0 Binary files /dev/null and b/libs/win32dbg/almp3.lib differ diff --git a/libs/win32dbg/alogg.lib b/libs/win32dbg/alogg.lib new file mode 100644 index 0000000000..720d1280af Binary files /dev/null and b/libs/win32dbg/alogg.lib differ diff --git a/libs/win32dbg/alspc.lib b/libs/win32dbg/alspc.lib new file mode 100644 index 0000000000..87821bce44 Binary files /dev/null and b/libs/win32dbg/alspc.lib differ diff --git a/libs/win32dbg/dumbd.lib b/libs/win32dbg/dumbd.lib new file mode 100644 index 0000000000..c2871e0270 Binary files /dev/null and b/libs/win32dbg/dumbd.lib differ diff --git a/libs/win32dbg/gme.lib b/libs/win32dbg/gme.lib new file mode 100644 index 0000000000..aac6dbcc0f Binary files /dev/null and b/libs/win32dbg/gme.lib differ diff --git a/libs/win32dbg/libjpgal.lib b/libs/win32dbg/libjpgal.lib new file mode 100644 index 0000000000..9e860ff101 Binary files /dev/null and b/libs/win32dbg/libjpgal.lib differ diff --git a/libs/win32dbg/libpng.lib b/libs/win32dbg/libpng.lib new file mode 100644 index 0000000000..38d3fd4e9e Binary files /dev/null and b/libs/win32dbg/libpng.lib differ diff --git a/libs/win32dbg/loadpng.lib b/libs/win32dbg/loadpng.lib new file mode 100644 index 0000000000..2c32c083bc Binary files /dev/null and b/libs/win32dbg/loadpng.lib differ diff --git a/libs/win32dbg/pthread.lib b/libs/win32dbg/pthread.lib new file mode 100644 index 0000000000..5d6bd6c772 Binary files /dev/null and b/libs/win32dbg/pthread.lib differ diff --git a/libs/win32dbg/zcsoundd.lib b/libs/win32dbg/zcsoundd.lib new file mode 100644 index 0000000000..f2e7b0f972 Binary files /dev/null and b/libs/win32dbg/zcsoundd.lib differ diff --git a/libs/win32dbg/zlibd.lib b/libs/win32dbg/zlibd.lib new file mode 100644 index 0000000000..d35cdfe963 Binary files /dev/null and b/libs/win32dbg/zlibd.lib differ diff --git a/license.txt b/license.txt new file mode 100644 index 0000000000..818433ecc0 --- /dev/null +++ b/license.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/makefile b/makefile new file mode 100644 index 0000000000..272ce9c4df --- /dev/null +++ b/makefile @@ -0,0 +1,804 @@ +-include makefile.inc + +AUDIO_LIBS = -lgme -lalogg -lalmp3 -laldmb -ldumb +IMAGE_LIBS = -ljpgal -lldpng -lpng -lz +# -lSDLmain -lSDL +#LINKOPTS = -pg -g +#LINKOPTS = -pg +#OPTS = -pg -g +#OPTS = -pg +#OPTS = -O3 +#OPTS = -DPTW32_STATIC_LIB -O3 +#COMPRESS = 1 + +ifdef USE_ENCRYPTION + OPTS = -DPTW32_STATIC_LIB -O3 -DUSE_ENCRYPTION + ENCRYPTION_CPP = encryptionEnabled.cpp +else + OPTS = -DPTW32_STATIC_LIB -O3 + ENCRYPTION_CPP = encryptionDisabled.cpp +endif + +CFLAGBASE2 = -Wno-long-long -W -Wall -Wshadow -Wpointer-arith +#CFLAGBASE2 = -Wno-long-long -Wno-write-strings + +ifndef COMPILE_FOR_MACOSX + CFLAGBASE = $(CFLAGBASE2) +else + CFLAGBASE = $(CFLAGBASE2) +endif + +ifdef COMPILE_FOR_WIN + SINGLE_QUOTE_HELPER = ^" + REPO_LOCATION = _zcrepo + ALLEG_LIB = -lalleg -lws2_32 + SFLAG = -s + WINFLAG = -mwindows -static-libgcc -static-libstdc++ + PLATEXT = -w + EXEEXT = .exe + ZC_ICON = zc_icon.o + ZC_ICON_DEPS = zc_icon.rc zc_icon.ico + ZC_ICON_CMD = windres --use-temp-file -J rc -O coff -i zc_icon.rc -o zc_icon.o + ZQ_ICON = zq_icon.o + ZQ_ICON_DEPS = zq_icon.rc zq_icon.ico + ZQ_ICON_CMD = windres --use-temp-file -J rc -O coff -i zq_icon.rc -o zq_icon.o + RV_ICON = rv_icon.o + RV_ICON_DEPS = rv_icon.rc rv_icon.ico + RV_ICON_CMD = windres --use-temp-file -J rc -O coff -i rv_icon.rc -o rv_icon.o + ZC_PLATFORM = Windows + CC = g++ + CFLAG = $(CFLAGBASE) `pkg-config --cflags gtk+-3.0` -pedantic -I./include/dumb/ -I./include/alogg/ -I./include/almp3 -I./include/lpng1212/ -I./include/loadpng/ -I./include/lpng1212/ -I./include/jpgalleg-2.5/ -I./include/zlib123/ -I./gme -I. + LIBDIR = -L./libs/mingw `pkg-config --libs gtk+-3.0` + + ZCSOUND_SO = libs/mingw/libzcsound.dll + ZCSOUND_LIB = -Wl,-rpath,. -lzcsound + ZCSOUND_LINKOPTS = $(LINKOPTS) -shared -Wl,-soname,zcsound.dll + ZCSOUND_ALLEG_LIB = $(ALLEG_LIB) +else +ifdef COMPILE_FOR_LINUX + PLATEXT = -l + ALLEG_LIB = `allegro-config --libs --static` + SFLAG = -s + ZC_ICON = zc_icon.o + ZC_ICON_DEPS = zc_icon.c + ZC_ICON_CMD = $(CC) $(OPTS) $(CFLAG) -c zc_icon.c -o zc_icon.o $(SFLAG) + ZQ_ICON = zq_icon.o + ZQ_ICON_DEPS = zq_icon.c + ZQ_ICON_CMD = $(CC) $(OPTS) $(CFLAG) -c zq_icon.c -o zq_icon.o $(SFLAG) + RV_ICON = rv_icon.o + RV_ICON_DEPS = rv_icon.c + RV_ICON_CMD = $(CC) $(OPTS) $(CFLAG) -c rv_icon.c -o rv_icon.o $(SFLAG) + ZC_PLATFORM = Linux + CC = g++ + CFLAG = `pkg-config --cflags gtk+-3.0` -I./include -I../include -I./include/alogg -I./include/almp3 -I. + LIBDIR = -L./libs/linux `pkg-config --libs gtk+-3.0` + SINGLE_INSTANCE_O = single_instance.o + + ZCSOUND_SO = libs/linux/libzcsound.so + ZCSOUND_LIB = -Wl,-rpath,. -lzcsound + ZCSOUND_LINKOPTS = $(LINKOPTS) -shared -Wl,-soname,zcsound.so +else +ifdef COMPILE_FOR_DOS + ALLEG_LIB = -lalleg + STDCXX_LIB = -lstdcxx + EXEEXT = .exe + ZC_PLATFORM = DOS + CC = gpp + CFLAG = $(CFLAGBASE) -Werror +else +ifdef COMPILE_FOR_MACOSX + ECHO_HELPER = \ + SINGLE_QUOTE_HELPER = \" + PLATEXT = -m + ALLEG_LIB = -framework Cocoa -framework Allegro -lalleg-main -arch i386 + ZC_PLATFORM = Mac OS X + CFLAG = $(CFLAGBASE) `pkg-config --cflags gtk+-3.0` -pedantic -arch i386 -I./include/dumb/ -I./include/alogg/ -I./include/almp3/ -I./include/libjpgal/ -I. + CC = g++ + LIBDIR= -L./libs/osx `pkg-config --libs gtk+-3.0` + DATA = output/common/ + #SINGLE_INSTANCE_O = single_instance.o + + ZCSOUND_SO = libs/osx/libzcsound.dylib + ZCSOUND_LIB = -lzcsound + ZCSOUND_LINKOPTS = $(LINKOPTS) -shared + ZCSOUND_ALLEG_LIB = $(ALLEG_LIB) +else +ifdef COMPILE_FOR_MACOSX_UNIVERSAL + ECHO_HELPER = \ + SINGLE_QUOTE_HELPER = \" + PLATEXT = -mu + ALLEG_LIB = -framework Cocoa -framework Allegro -lalleg-main + ZC_PLATFORM = Mac OS X Universal + CFLAG = `pkg-config --cflags gtk+-3.0` -pedantic -Wno-long-long -Wall -arch i386 -arch ppc -DMACOSX_ + CC = g++ + LIBDIR= -L./libs/osx `pkg-config --libs gtk+-3.0` + DATA = output/common/ + LINKOPTS = -arch i386 -arch ppc + #SINGLE_INSTANCE_O = single_instance.o + + ZCSOUND_SO = libs/osx/libzcsound.dylib + ZCSOUND_LIB = -lzcsound + ZCSOUND_LINKOPTS = $(LINKOPTS) -shared + ZCSOUND_ALLEG_LIB = $(ALLEG_LIB) +else +ifdef COMPILE_FOR_MACOSX_SNOW_LEOPARD + PLATEXT = -msl + ALLEG_LIB = -framework Cocoa -framework Allegro -lalleg-main + ZC_PLATFORM = Mac OS X Universal + CFLAG = `pkg-config --cflags gtk+-3.0` -pedantic -Wno-long-long -Wall -arch i386 -arch ppc -DMACOSX_ + CC = g++ + LIBDIR= -L./libs/osx `pkg-config --libs gtk+-3.0` + DATA = output/common/ + LINKOPTS = -arch i386 -arch ppc + #SINGLE_INSTANCE_O = single_instance.o + + ZCSOUND_SO = libs/osx/libzcsound.dylib + ZCSOUND_LIB = -lzcsound + ZCSOUND_LINKOPTS = $(LINKOPTS) -shared + ZCSOUND_ALLEG_LIB = $(ALLEG_LIB) +else +ifdef COMPILE_FOR_GP2X + PLATEXT = -g + EXEEXT = .gpe + ALLEG_LIB = -lalleg -lpthread -static + ZC_PLATFORM = GP2X + CFLAG = $(CFLAGBASE) -Werror -I/devkitGP2X/include + CC = arm-linux-g++ + AUDIO_LIBS = -L/devkitGP2X/lib -lalspc -lalogg -lalmp3 -laldmb -ldumb + IMAGE_LIBS = -L/devkitGP2X/lib -ljpgal -lldpng -lpng -lz + SINGLE_INSTANCE_O = single_instance.o +endif +endif +endif +endif +endif +endif +endif + +ZELDA_PREFIX = zelda +ZQUEST_PREFIX = zquest +ROMVIEW_PREFIX = romview + +ZELDA_EXE = $(ZELDA_PREFIX)$(PLATEXT)$(EXEEXT) +ZQUEST_EXE = $(ZQUEST_PREFIX)$(PLATEXT)$(EXEEXT) +ROMVIEW_EXE = $(ROMVIEW_PREFIX)$(PLATEXT)$(EXEEXT) + +GTK_GUI_OBJECTS = gui/gtk/bitmap.o gui/gtk/button.o gui/gtk/buttonRow.o gui/gtk/checkbox.o gui/gtk/controller.o gui/gtk/factory.o gui/gtk/frame.o gui/gtk/manager.o gui/gtk/serialContainer.o gui/gtk/spinner.o gui/gtk/tabPanel.o gui/gtk/text.o gui/gtk/textBox.o gui/gtk/textField.o gui/gtk/util.o gui/gtk/widget.o gui/gtk/window.o + +ALLEGRO_GUI_OBJECTS = gui/allegro/bitmap.o gui/allegro/button.o gui/allegro/checkbox.o gui/allegro/column.o gui/allegro/common.o gui/allegro/controller.o gui/allegro/dummy.o gui/allegro/editableText.o gui/allegro/factory.o gui/allegro/renderer.o gui/allegro/row.o gui/allegro/scrollbar.o gui/allegro/scrollingPane.o gui/allegro/serialContainer.o gui/allegro/standardWidget.o gui/allegro/tab.o gui/allegro/tabBar.o gui/allegro/tabPanel.o gui/allegro/text.o gui/allegro/textField.o gui/allegro/window.o + +ZELDA_OBJECTS = aglogo.o colors.o debug.o decorations.o defdata.o editbox.o EditboxModel.o EditboxView.o encryption.o ending.o enemyAttack.o ffc.o ffscript.o fontClass.o gamedata.o gui.o guys.o init.o items.o jwin.o jwinfsel.o link.o linkHandler.o linkZScriptInterface.o load_gif.o maps.o matrix.o md5.o message.o messageManager.o messageRenderer.o messageStream.o midi.o pal.o particles.o qst.o refInfo.o room.o save_gif.o screenFreezeState.o screenWipe.o script_drawing.o sequence.o $(SINGLEINSTANCE_O) sfxAllegro.o sfxClass.o sfxManager.o sound.o sprite.o subscr.o tab_ctl.o tiles.o title.o weapons.o zc_custom.o zc_init.o zc_items.o zc_sprite.o zc_subscr.o zc_sys.o zelda.o zscriptversion.o zsys.o \ +item/clock.o item/dinsFire.o item/hookshot.o item/faroresWind.o item/itemEffect.o item/nayrusLove.o \ +sequence/gameOver.o sequence/ganonIntro.o sequence/getBigTriforce.o sequence/getTriforce.o sequence/potion.o sequence/whistle.o \ +angelscript/aszc.o angelscript/scriptData.o angelscript/util.o angelscript/scriptarray/scriptarray.o angelscript/scriptbuilder/scriptbuilder.o angelscript/scriptmath/scriptmath.o angelscript/scriptstdstring/scriptstdstring.o \ +tempStuff.o \ +$(ZC_ICON) + +ZQUEST_OBJECTS = zquest.o colors.o defdata.o dummyZQ.o editbox.o EditboxModel.o EditboxView.o encryption.o ffc.o gamedata.o gui.o init.o items.o jwin.o jwinfsel.o load_gif.o md5.o messageList.o midi.o particles.o qst.o questReport.o refInfo.o save_gif.o sprite.o subscr.o tab_ctl.o tiles.o zc_custom.o zq_class.o zq_cset.o zq_custom.o zq_doors.o zq_files.o zq_items.o zq_init.o zq_misc.o zq_sprite.o zq_strings.o zq_subscr.o zq_tiles.o zqscale.o zsys.o ffasm.o parser/AST.o parser/BuildVisitors.o parser/ByteCode.o parser/DataStructs.o parser/GlobalSymbols.o parser/lex.yy.o parser/ParseError.o parser/ScriptParser.o parser/SymbolVisitors.o parser/TypeChecker.o parser/UtilVisitors.o parser/y.tab.o \ +guiBitmapRenderer.o \ +gui/alert.o gui/contents.o gui/controller.o gui/dialog.o gui/manager.o \ +$(ALLEGRO_GUI_OBJECTS) \ +dialog/bitmap/tilePreview.o dialog/bitmap/tileSelector.o \ +dialog/zquest/cheatEditor.o dialog/zquest/infoShopEditor.o dialog/zquest/paletteViewer.o dialog/zquest/questRules.o dialog/zquest/shopEditor.o dialog/zquest/simpleListSelector.o dialog/zquest/tileEditor.o dialog/zquest/tileSelector.o dialog/zquest/tileSelectorBackend.o dialog/zquest/zscriptEditor.o dialog/zquest/zscriptMain.o \ +angelscript/scriptData.o \ +$(ZQ_ICON) + +ROMVIEW_OBJECTS = editbox.o EditboxModel.o EditboxView.o gui.o jwin.o jwinfsel.o load_gif.o romview.o save_gif.o tab_ctl.o zqscale.o zsys.o \ +$(RV_ICON) + +ZCSOUND_OBJECTS = zcmusic.o zcmusicd.o + +.PHONY: default veryclean clean all msg dos win windows linux gp2x test done + +default: all +msg: + @echo Compiling Zelda Classic for $(ZC_PLATFORM)... +done: + @echo Done! +clean: + rm -f $(ZELDA_OBJECTS) $(ZQUEST_OBJECTS) $(ROMVIEW_OBJECTS) $(ZCSOUND_OBJECTS) +veryclean: clean + rm -f $(ZELDA_EXE) $(ZQUEST_EXE) $(ROMVIEW_EXE) $(ZCSOUND_SO) + +test: +ifndef COMPILE_FOR_WIN +ifndef COMPILE_FOR_DOS +ifndef COMPILE_FOR_LINUX +ifndef COMPILE_FOR_MACOSX +ifndef COMPILE_FOR_GP2X +ifndef COMPILE_FOR_MACOSX_UNIVERSAL +ifndef COMPILE_FOR_MACOSX_SNOW_LEOPARD + #change this if you want to change the default platform + @make win +endif +endif +endif +endif +endif +endif +endif + + +dos: + @echo COMPILE_FOR_DOS=1 > makefile.inc + @make +windows: win +win: + @echo COMPILE_FOR_WIN=1 > makefile.inc + @make +linux: + @echo COMPILE_FOR_LINUX=1 > makefile.inc + @make +macosx: + @echo COMPILE_FOR_MACOSX=1 > makefile.inc + @make +gp2x: + @echo COMPILE_FOR_GP2X=1 > makefile.inc + @make +macosx-u: + @echo COMPILE_FOR_MACOSX_UNIVERSAL=1 > makefile.inc + @make +macosx-sl: + @echo COMPILE_FOR_MACOSX_SNOW_LEOPARD=1 > makefile.inc + @make + +all: test msg $(ZCSOUND_SO) $(ZELDA_EXE) $(ZQUEST_EXE) $(ROMVIEW_EXE) done + +$(ZCSOUND_SO): $(ZCSOUND_OBJECTS) + $(CC) $(ZCSOUND_LINKOPTS) -o $(ZCSOUND_SO) $(ZCSOUND_OBJECTS) $(LIBDIR) $(AUDIO_LIBS) $(ZCSOUND_ALLEG_LIB) $(SFLAG) $(WINFLAG) +zcmusic.o: zcmusic.cpp mutex.h zc_alleg.h zcmusic.h zsys.h + $(CC) $(OPTS) $(CFLAG) -fpic -c zcmusic.cpp -o zcmusic.o $(SFLAG) $(WINFLAG) +zcmusicd.o: zcmusicd.cpp zcmusic.h + $(CC) $(OPTS) $(CFLAG) -fpic -c zcmusicd.cpp -o zcmusicd.o $(SFLAG) $(WINFLAG) + +$(ZELDA_EXE): $(ZELDA_OBJECTS) + $(CC) $(LINKOPTS) -o $(ZELDA_EXE) $(ZELDA_OBJECTS) $(LIBDIR) $(IMAGE_LIBS) $(ZCSOUND_LIB) $(ALLEG_LIB) $(STDCXX_LIB) $(ZC_ICON) $(SFLAG) $(WINFLAG) +ifdef COMPRESS + upx --best $(ZELDA_EXE) +endif +ifdef 0 + rm zc/zelda-m + cp zelda-m zc/zelda-m + zc/zelda-m +endif +ifdef COMPILE_FOR_MACOSX + rm -rf "Zelda Classic.app" + fixbundle $(ZELDA_EXE) -e + cp Info1.plist $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' Zelda Classic' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' zc_icon.icns' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' com.armageddon.Zelda Classic' >> $(ZELDA_EXE).app/Contents/tempinfo + cat $(ZELDA_EXE).app/Contents/tempinfo Info2.plist > $(ZELDA_EXE).app/Contents/Info.plist + rm $(ZELDA_EXE).app/Contents/tempinfo + cp "zc_icon.icns" $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)zelda.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)sfx.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)qst.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)zelda.nsf $(ZELDA_EXE).app/Contents/Resources/ + cp "ag_nofull.cfg" $(ZELDA_EXE).app/Contents/Resources/ag.cfg + cp $(DATA)1st.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)2nd.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)3rd.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)4th.qst $(ZELDA_EXE).app/Contents/Resources/ + + cp libs/osx/libzcsound.dylib $(ZELDA_EXE).app/Contents/Frameworks/ + install_name_tool -change libs/osx/libzcsound.dylib @executable_path/../Frameworks/libzcsound.dylib $(ZELDA_EXE).app/Contents/MacOS/$(ZELDA_EXE) + + mv $(ZELDA_EXE).app/Contents/MacOS/$(ZELDA_EXE) "$(ZELDA_EXE).app/Contents/MacOS/Zelda Classic" + mv $(ZELDA_EXE).app "Zelda Classic.app" +endif +ifdef COMPILE_FOR_MACOSX_UNIVERSAL + rm -rf "Zelda Classic.app" + fixbundle $(ZELDA_EXE) -e + cp Info1.plist $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' Zelda Classic' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' zc_icon.icns' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ZELDA_EXE).app/Contents/tempinfo + echo ' com.armageddon.Zelda Classic' >> $(ZELDA_EXE).app/Contents/tempinfo + cat $(ZELDA_EXE).app/Contents/tempinfo Info2.plist > $(ZELDA_EXE).app/Contents/Info.plist + rm $(ZELDA_EXE).app/Contents/tempinfo + cp "zc_icon.icns" $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)zelda.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)sfx.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)qst.dat $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)zelda.nsf $(ZELDA_EXE).app/Contents/Resources/ + cp "ag_nofull.cfg" $(ZELDA_EXE).app/Contents/Resources/ag.cfg + cp $(DATA)1st.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)2nd.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)3rd.qst $(ZELDA_EXE).app/Contents/Resources/ + cp $(DATA)4th.qst $(ZELDA_EXE).app/Contents/Resources/ + + cp libs/osx/libzcsound.dylib $(ZELDA_EXE).app/Contents/Frameworks/ + install_name_tool -change libs/osx/libzcsound.dylib @executable_path/../Frameworks/libzcsound.dylib $(ZELDA_EXE).app/Contents/MacOS/$(ZELDA_EXE) + + mv $(ZELDA_EXE).app/Contents/MacOS/$(ZELDA_EXE) "$(ZELDA_EXE).app/Contents/MacOS/Zelda Classic" + mv $(ZELDA_EXE).app "Zelda Classic.app" +endif + +$(ZQUEST_EXE): $(ZQUEST_OBJECTS) + $(CC) $(LINKOPTS) -o $(ZQUEST_EXE) $(ZQUEST_OBJECTS) $(LIBDIR) $(IMAGE_LIBS) $(ZCSOUND_LIB) $(ALLEG_LIB) $(STDCXX_LIB) $(ZQ_ICON) $(SFLAG) $(WINFLAG) +ifdef COMPRESS + upx --best $(ZQUEST_EXE) +endif +ifdef COMPILE_FOR_MACOSX + rm -rf "ZQuest Editor.app" + fixbundle $(ZQUEST_EXE) -e + chmod 755 $(ZQUEST_EXE) + cp Info1.plist $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' ZQuest Editor' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' zq_icon.icns' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' com.armageddon.ZQuest Editor' >> $(ZQUEST_EXE).app/Contents/tempinfo + cat $(ZQUEST_EXE).app/Contents/tempinfo Info2.plist > $(ZQUEST_EXE).app/Contents/Info.plist + rm $(ZQUEST_EXE).app/Contents/tempinfo + cp "zq_icon.icns" $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zquest.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)sfx.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)qst.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zelda.nsf $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zquest.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zscript.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zstrings.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std_constants.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std_functions.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)string.zh $(ZQUEST_EXE).app/Contents/Resources/ + + cp libs/osx/libzcsound.dylib $(ZQUEST_EXE).app/Contents/Frameworks/ + install_name_tool -change libs/osx/libzcsound.dylib @executable_path/../Frameworks/libzcsound.dylib $(ZQUEST_EXE).app/Contents/MacOS/$(ZQUEST_EXE) + + mv $(ZQUEST_EXE).app/Contents/MacOS/$(ZQUEST_EXE) "$(ZQUEST_EXE).app/Contents/MacOS/ZQuest Editor" + mv $(ZQUEST_EXE).app "ZQuest Editor.app" +endif +ifdef COMPILE_FOR_MACOSX_UNIVERSAL + rm -rf "ZQuest Editor.app" + fixbundle $(ZQUEST_EXE) -e + chmod 755 $(ZQUEST_EXE) + cp Info1.plist $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' ZQuest Editor' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' zq_icon.icns' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ZQUEST_EXE).app/Contents/tempinfo + echo ' com.armageddon.ZQuest Editor' >> $(ZQUEST_EXE).app/Contents/tempinfo + cat $(ZQUEST_EXE).app/Contents/tempinfo Info2.plist > $(ZQUEST_EXE).app/Contents/Info.plist + rm $(ZQUEST_EXE).app/Contents/tempinfo + cp "zq_icon.icns" $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zquest.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)sfx.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)qst.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zelda.nsf $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zquest.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zscript.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)zstrings.txt $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std_constants.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)std_functions.zh $(ZQUEST_EXE).app/Contents/Resources/ + cp $(DATA)string.zh $(ZQUEST_EXE).app/Contents/Resources/ + + cp libs/osx/libzcsound.dylib $(ZQUEST_EXE).app/Contents/Frameworks/ + install_name_tool -change libs/osx/libzcsound.dylib @executable_path/../Frameworks/libzcsound.dylib $(ZQUEST_EXE).app/Contents/MacOS/$(ZQUEST_EXE) + + mv $(ZQUEST_EXE).app/Contents/MacOS/$(ZQUEST_EXE) "$(ZQUEST_EXE).app/Contents/MacOS/ZQuest Editor" + mv $(ZQUEST_EXE).app "ZQuest Editor.app" +endif + +$(ROMVIEW_EXE): $(ROMVIEW_OBJECTS) + $(CC) $(LINKOPTS) -o $(ROMVIEW_EXE) $(ROMVIEW_OBJECTS) $(LIBDIR) $(IMAGE_LIBS) $(ALLEG_LIB) $(STDCXX_LIB) $(RV_ICON) $(SFLAG) $(WINFLAG) +ifdef COMPRESS + upx --best $(ZQUEST_EXE) +endif +ifdef COMPILE_FOR_MACOSX + rm -rf "ROM Viewer.app" + fixbundle $(ROMVIEW_EXE) -e + chmod 755 $(ROMVIEW_EXE) + cp Info1.plist $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' ROM Viewer' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' rv_icon.icns' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' com.armageddon.ROMView' >> $(ROMVIEW_EXE).app/Contents/tempinfo + cat $(ROMVIEW_EXE).app/Contents/tempinfo Info2.plist > $(ROMVIEW_EXE).app/Contents/Info.plist + rm $(ROMVIEW_EXE).app/Contents/tempinfo + cp "rv_icon.icns" $(ROMVIEW_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ROMVIEW_EXE).app/ + mv $(ROMVIEW_EXE).app/Contents/MacOS/$(ROMVIEW_EXE) "$(ROMVIEW_EXE).app/Contents/MacOS/ROMView" + mv $(ROMVIEW_EXE).app "ROM Viewer.app" +endif +ifdef COMPILE_FOR_MACOSX_UNIVERSAL + rm -rf "ROM Viewer.app" + fixbundle $(ROMVIEW_EXE) -e + chmod 755 $(ROMVIEW_EXE) + cp Info1.plist $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleExecutable' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' ROM Viewer' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleIconFile' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' rv_icon.icns' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' CFBundleIdentifier' >> $(ROMVIEW_EXE).app/Contents/tempinfo + echo ' com.armageddon.ROMView' >> $(ROMVIEW_EXE).app/Contents/tempinfo + cat $(ROMVIEW_EXE).app/Contents/tempinfo Info2.plist > $(ROMVIEW_EXE).app/Contents/Info.plist + rm $(ROMVIEW_EXE).app/Contents/tempinfo + cp "rv_icon.icns" $(ROMVIEW_EXE).app/Contents/Resources/ + cp $(DATA)fonts.dat $(ROMVIEW_EXE).app/ + mv $(ROMVIEW_EXE).app/Contents/MacOS/$(ROMVIEW_EXE) "$(ROMVIEW_EXE).app/Contents/MacOS/ROMView" + mv $(ROMVIEW_EXE).app "ROM Viewer.app" +endif + + +aglogo.o: aglogo.cpp gamedata.h zc_alleg.h zdefs.h zeldadat.h + $(CC) $(OPTS) $(CFLAG) -c aglogo.cpp -o aglogo.o $(SFLAG) $(WINFLAG) +colors.o: colors.cpp colors.h gamedata.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c colors.cpp -o colors.o $(SFLAG) $(WINFLAG) +debug.o: debug.cpp zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c debug.cpp -o debug.o $(SFLAG) $(WINFLAG) +decorations.o: decorations.cpp decorations.h gamedata.h jwin.h maps.h sfx.h sprite.h tab_ctl.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c decorations.cpp -o decorations.o $(SFLAG) $(WINFLAG) +defdata.o: defdata.cpp defdata.h gamedata.h guys.h items.h sfx.h sprite.h weapons.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c defdata.cpp -o defdata.o $(SFLAG) $(WINFLAG) +dummyZQ.o: dummyZQ.cpp + $(CC) $(OPTS) $(CFLAG) -c dummyZQ.cpp -o dummyZQ.o $(SFLAG) $(WINFLAG) +editbox.o: editbox.cpp EditboxNew.h jwin.h tab_ctl.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c editbox.cpp -o editbox.o $(SFLAG) $(WINFLAG) +EditboxModel.o: EditboxModel.cpp editbox.h EditboxNew.h gamedata.h gui.h jwin.h tab_ctl.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c EditboxModel.cpp -o EditboxModel.o $(SFLAG) $(WINFLAG) +EditboxView.o: EditboxView.cpp EditboxNew.h jwin.h tab_ctl.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c EditboxView.cpp -o EditboxView.o $(SFLAG) $(WINFLAG) +encryption.o: $(ENCRYPTION_CPP) encryption.h zdefs.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c $(ENCRYPTION_CPP) -o encryption.o $(SFLAG) $(WINFLAG) +ending.o: ending.cpp aglogo.h colors.h ending.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h title.h weapons.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h init.h + $(CC) $(OPTS) $(CFLAG) -c ending.cpp -o ending.o $(SFLAG) $(WINFLAG) +enemyAttack.o: enemyAttack.cpp enemyAttack.h guys.h link.h zdefs.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c enemyAttack.cpp -o enemyAttack.o $(SFLAG) $(WINFLAG) +ffasm.o: ffasm.cpp ffasm.h ffscript.h gamedata.h jwin.h jwinfsel.h midi.h sprite.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c ffasm.cpp -o ffasm.o $(SFLAG) $(WINFLAG) +ffc.o: ffc.cpp ffc.h refInfo.h types.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c ffc.cpp -o ffc.o $(SFLAG) $(WINFLAG) +ffscript.o: ffscript.cpp aglogo.h colors.h ffc.h ffscript.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_init.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h rendertarget.h + $(CC) $(OPTS) $(CFLAG) -c ffscript.cpp -o ffscript.o $(SFLAG) $(WINFLAG) +font.o: /allegro/tools/datedit.h font.cpp font.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c font.cpp -o font.o $(SFLAG) $(WINFLAG) +fontClass.o: fontClass.cpp fontClass.h + $(CC) $(OPTS) $(CFLAG) -c fontClass.cpp -o fontClass.o $(SFLAG) $(WINFLAG) +gamedata.o: gamedata.cpp gamedata.h items.h jwin.h sfx.h sprite.h tab_ctl.h zc_alleg.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c gamedata.cpp -o gamedata.o $(SFLAG) $(WINFLAG) +gui.o: gui.cpp colors.h debug.h gamedata.h gui.h items.h jwin.h jwinfsel.h midi.h pal.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c gui.cpp -o gui.o $(SFLAG) $(WINFLAG) +guys.o: guys.cpp aglogo.h colors.h defdata.h ffscript.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h room.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h angelscript/scriptData.h + $(CC) $(OPTS) $(CFLAG) -c guys.cpp -o guys.o $(SFLAG) $(WINFLAG) +init.o: init.cpp gamedata.h gui.h init.h jwin.h sfx.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(CFLAG) -c init.cpp -o init.o $(SFLAG) $(WINFLAG) +items.o: items.cpp gamedata.h items.h jwin.h maps.h sfx.h sound.h sprite.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c items.cpp -o items.o $(SFLAG) $(WINFLAG) +jmenu.o: jmenu.cpp gamedata.h jwin.h sfx.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c jmenu.cpp -o jmenu.o $(SFLAG) $(WINFLAG) +jwin.o: jwin.cpp editbox.h gamedata.h jwin.h tab_ctl.h zc_alleg.h zdefs.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c jwin.cpp -o jwin.o $(SFLAG) $(WINFLAG) +jwinfsel.o: jwinfsel.cpp jwin.h jwinfsel.h tab_ctl.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c jwinfsel.cpp -o jwinfsel.o $(SFLAG) $(WINFLAG) +link.o: link.cpp aglogo.h colors.h decorations.h ffc.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h screenWipe.h sfx.h sound.h sprite.h tab_ctl.h tiles.h title.h weapons.h zc_alleg.h zc_custom.h zc_subscr.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h item/itemEffect.h + $(CC) $(OPTS) $(CFLAG) -c link.cpp -o link.o $(SFLAG) $(WINFLAG) +linkHandler.o: linkHandler.cpp linkHandler.h decorations.h guys.h link.h sequence.h sfxManager.h zc_sys.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c linkHandler.cpp -o linkHandler.o $(SFLAG) $(WINFLAG) +linkZScriptInterface.o: linkZScriptInterface.cpp linkZScriptInterface.h link.h zdefs.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c linkZScriptInterface.cpp -o linkZScriptInterface.o $(SFLAG) $(WINFLAG) +load_gif.o: load_gif.cpp load_gif.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c load_gif.cpp -o load_gif.o $(SFLAG) $(WINFLAG) +maps.o: maps.cpp aglogo.h colors.h ffc.h ffscript.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h particles.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_subscr.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h rendertarget.h + $(CC) $(OPTS) -O3 $(CFLAG) -c maps.cpp -o maps.o $(SFLAG) $(WINFLAG) +matrix.o: matrix.cpp gamedata.h matrix.h zc_alleg.h zc_sys.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c matrix.cpp -o matrix.o $(SFLAG) $(WINFLAG) +md5.o: md5.cpp md5.h + $(CC) $(OPTS) $(CFLAG) -c md5.cpp -o md5.o $(SFLAG) $(WINFLAG) +message.o: message.cpp message.h fontClass.h link.h messageManager.h messageStream.h pal.h sound.h zc_sys.h zdefs.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c message.cpp -o message.o $(SFLAG) $(WINFLAG) +messageManager.o: messageManager.cpp messageManager.h link.h message.h weapons.h zc_sys.h zdefs.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c messageManager.cpp -o messageManager.o $(SFLAG) $(WINFLAG) +messageRenderer.o: messageRenderer.cpp messageRenderer.h subscr.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c messageRenderer.cpp -o messageRenderer.o $(SFLAG) $(WINFLAG) +messageStream.o: messageStream.cpp messageStream.h + $(CC) $(OPTS) $(CFLAG) -c messageStream.cpp -o messageStream.o $(SFLAG) $(WINFLAG) +midi.o: midi.cpp gamedata.h jwin.h midi.h tab_ctl.h zc_alleg.h zdefs.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c midi.cpp -o midi.o $(SFLAG) $(WINFLAG) +pal.o: pal.cpp aglogo.h colors.h gamedata.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c pal.cpp -o pal.o $(SFLAG) $(WINFLAG) +particles.o: particles.cpp gamedata.h particles.h sprite.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c particles.cpp -o particles.o $(SFLAG) $(WINFLAG) +qst.o: qst.cpp colors.h defdata.h encryption.h ffc.h font.h gamedata.h guys.h items.h jwin.h jwinfsel.h md5.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zcmusic.h zdefs.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c qst.cpp -o qst.o $(SFLAG) $(WINFLAG) +questReport.o: questReport.cpp questReport.h editbox.h EditboxNew.h gui.h jwin.h mem_debug.h tiles.h zc_alleg.h zdefs.h zsys.h zq_class.h zq_misc.h zquest.h + $(CC) $(OPTS) $(CFLAG) -c questReport.cpp -o questReport.o $(SFLAG) $(WINFLAG) +refInfo.o: refInfo.cpp refInfo.h types.h + $(CC) $(OPTS) $(CFLAG) -c refInfo.cpp -o refInfo.o $(SFLAG) $(WINFLAG) +romview.o: romview.cpp fontsdat.h gamedata.h jwin.h jwinfsel.h load_gif.h save_gif.h tab_ctl.h zc_alleg.h zdefs.h zqscale.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c romview.cpp -o romview.o $(SFLAG) $(WINFLAG) +room.o: room.cpp room.h gamedata.h guys.h items.h link.h maps.h messageManager.h sound.h zc_sys.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c room.cpp -o room.o $(SFLAG) $(WINFLAG) +rv_icon.o: $(RV_ICON_DEPS) + $(RV_ICON_CMD) +save_gif.o: save_gif.cpp save_gif.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c save_gif.cpp -o save_gif.o $(SFLAG) $(WINFLAG) +screenFreezeState.o: screenFreezeState.cpp screenFreezeState.h maps.h messageManager.h tiles.h zdefs.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c screenFreezeState.cpp -o screenFreezeState.o $(SFLAG) $(WINFLAG) +screenWipe.o: screenWipe.cpp screenWipe.h zc_alleg.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c screenWipe.cpp -o screenWipe.o $(SFLAG) $(WINFLAG) +script_drawing.o: script_drawing.cpp ffscript.h maps.h rendertarget.h script_drawing.h tiles.h zc_alleg.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c script_drawing.cpp -o script_drawing.o $(SFLAG) $(WINFLAG) +sequence.o: sequence.cpp sequence.h link.h sfx.h sfxManager.h sequence/sequence.h sequence/gameOver.h sequence/ganonIntro.h sequence/getBigTriforce.h sequence/getTriforce.h sequence/potion.h sequence/whistle.h + $(CC) $(OPTS) $(CFLAG) -c sequence.cpp -o sequence.o $(SFLAG) $(WINFLAG) +sfxAllegro.o: sfxAllegro.cpp sfxAllegro.h sound.h + $(CC) $(OPTS) $(CFLAG) -c sfxAllegro.cpp -o sfxAllegro.o $(SFLAG) $(WINFLAG) +sfxClass.o: sfxClass.cpp sfxClass.h sfxAllegro.h + $(CC) $(OPTS) $(CFLAG) -c sfxClass.cpp -o sfxClass.o $(SFLAG) $(WINFLAG) +sfxManager.o: sfxManager.cpp sfxManager.h sfxAllegro.h sfxClass.h + $(CC) $(OPTS) $(CFLAG) -c sfxManager.cpp -o sfxManager.o $(SFLAG) $(WINFLAG) +$(SINGLEINSTANCE_O): $(SINGLEINSTANCE_CPP) single_instance.h + $(CC) $(OPTS) $(CFLAG) -c $(SINGLEINSTANCE_CPP) -o $(SINGLEINSTANCE_O) $(SFLAG) $(WINFLAG) +sound.o: sound.cpp sound.h zc_alleg.h zc_sys.h zelda.h zeldadat.h + $(CC) $(OPTS) $(CFLAG) -c sound.cpp -o sound.o $(SFLAG) $(WINFLAG) +sprite.o: sprite.cpp sprite.h entityPtr.h gamedata.h tiles.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c sprite.cpp -o sprite.o $(SFLAG) $(WINFLAG) +subscr.o: subscr.cpp aglogo.h colors.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c subscr.cpp -o subscr.o $(SFLAG) $(WINFLAG) +tab_ctl.o: tab_ctl.cpp tab_ctl.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c tab_ctl.cpp -o tab_ctl.o $(SFLAG) $(WINFLAG) +tiles.o: tiles.cpp gamedata.h jwin.h tab_ctl.h tiles.h zc_alleg.h zdefs.h zsys.h + $(CC) $(OPTS) -O3 $(CFLAG) -c tiles.cpp -o tiles.o $(SFLAG) $(WINFLAG) +title.o: title.cpp aglogo.h colors.h encryption.h gamedata.h gui.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h title.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c title.cpp -o title.o $(SFLAG) $(WINFLAG) +weapons.o: weapons.cpp aglogo.h colors.h gamedata.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c weapons.cpp -o weapons.o $(SFLAG) $(WINFLAG) +zc_custom.o: zc_custom.cpp gamedata.h jwin.h sfx.h tab_ctl.h zc_alleg.h zc_custom.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_custom.cpp -o zc_custom.o $(SFLAG) $(WINFLAG) +zc_icon.o: $(ZC_ICON_DEPS) + $(ZC_ICON_CMD) +zc_init.o: zc_init.cpp aglogo.h colors.h gamedata.h gui.h init.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h midi.h pal.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zc_custom.h zc_init.h zcmusic.h zdefs.h zelda.h zeldadat.h zq_init.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_init.cpp -o zc_init.o $(SFLAG) $(WINFLAG) +zc_items.o: zc_items.cpp gamedata.h guys.h jwin.h maps.h sfx.h sprite.h tab_ctl.h weapons.h zc_alleg.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_items.cpp -o zc_items.o $(SFLAG) $(WINFLAG) +zc_sprite.o: zc_sprite.cpp gamedata.h jwin.h maps.h sfx.h sound.h sprite.h tab_ctl.h tiles.h zc_alleg.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_sprite.cpp -o zc_sprite.o $(SFLAG) $(WINFLAG) +zc_subscr.o: zc_subscr.cpp aglogo.h colors.h gamedata.h guys.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h pal.h qst.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zc_subscr.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_subscr.cpp -o zc_subscr.o $(SFLAG) $(WINFLAG) +zc_sys.o: zc_sys.cpp aglogo.h colors.h debug.h gamedata.h gui.h guys.h init.h items.h jwin.h jwinfsel.h link.h maps.h matrix.h midi.h pal.h particles.h qst.h screenWipe.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h title.h weapons.h zc_alleg.h zc_custom.h zc_init.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zc_sys.cpp -o zc_sys.o $(SFLAG) $(WINFLAG) +zelda.o: zelda.cpp aglogo.h colors.h ending.h ffc.h ffscript.h fontsdat.h gamedata.h guys.h init.h items.h jwin.h jwinfsel.h link.h load_gif.h maps.h matrix.h pal.h particles.h qst.h save_gif.h sfx.h sound.h sprite.h subscr.h tab_ctl.h tiles.h title.h weapons.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zelda.h zeldadat.h zsys.h rendertarget.h + $(CC) $(OPTS) $(CFLAG) -c zelda.cpp -o zelda.o $(SFLAG) $(WINFLAG) +zq_class.o: zq_class.cpp colors.h encryption.h ffc.h gamedata.h gui.h items.h jwin.h jwinfsel.h maps.h md5.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zc_custom.h zc_sys.h zcmusic.h zdefs.h zq_class.h zq_misc.h zq_subscr.h zquest.h zquestdat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_class.cpp -o zq_class.o $(SFLAG) $(WINFLAG) +zq_cset.o: zq_cset.cpp colors.h gamedata.h gfxpal.h gui.h jwin.h jwinfsel.h midi.h pal.h sfx.h sprite.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zq_cset.h zq_misc.h zq_tiles.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_cset.cpp -o zq_cset.o $(SFLAG) $(WINFLAG) +zq_custom.o: zq_custom.cpp defdata.h ffasm.h ffscript.h gamedata.h gui.h guys.h init.h items.h jwin.h jwinfsel.h midi.h sfx.h sprite.h tab_ctl.h tiles.h weapons.h zc_alleg.h zc_custom.h zcmusic.h zdefs.h zq_custom.h zq_misc.h zq_tiles.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_custom.cpp -o zq_custom.o $(SFLAG) $(WINFLAG) +zq_doors.o: zq_doors.cpp gamedata.h gui.h jwin.h jwinfsel.h midi.h sfx.h sprite.h tab_ctl.h tiles.h zc_alleg.h zc_sys.h zcmusic.h zdefs.h zq_class.h zq_misc.h zq_tiles.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_doors.cpp -o zq_doors.o $(SFLAG) $(WINFLAG) +zq_files.o: zq_files.cpp gamedata.h gui.h items.h jwin.h jwinfsel.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zcmusic.h zdefs.h zq_class.h zq_custom.h zq_files.h zq_misc.h zq_tiles.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_files.cpp -o zq_files.o $(SFLAG) $(WINFLAG) +zq_icon.o: $(ZQ_ICON_DEPS) + $(ZQ_ICON_CMD) +zq_init.o: zq_init.cpp gamedata.h gui.h init.h jwin.h jwinfsel.h midi.h sprite.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zq_init.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_init.cpp -o zq_init.o $(SFLAG) $(WINFLAG) +zq_items.o: zq_items.cpp gamedata.h zc_alleg.h zdefs.h zq_class.h + $(CC) $(OPTS) $(CFLAG) -c zq_items.cpp -o zq_items.o $(SFLAG) $(WINFLAG) +zq_misc.o: zq_misc.cpp colors.h gamedata.h items.h jwin.h jwinfsel.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h zc_alleg.h zcmusic.h zdefs.h zq_class.h zq_misc.h zquest.h zquestdat.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_misc.cpp -o zq_misc.o $(SFLAG) $(WINFLAG) +zq_sprite.o: zq_sprite.cpp gamedata.h sprite.h zc_alleg.h zdefs.h + $(CC) $(OPTS) $(CFLAG) -c zq_sprite.cpp -o zq_sprite.o $(SFLAG) $(WINFLAG) +zq_strings.o: zq_strings.cpp zq_strings.h zquest.h + $(CC) $(OPTS) $(CFLAG) -c zq_strings.cpp -o zq_strings.o $(SFLAG) $(WINFLAG) +zq_subscr.o: zq_subscr.cpp gamedata.h gui.h init.h items.h jwin.h jwinfsel.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zcmusic.h zdefs.h zq_misc.h zq_subscr.h zquest.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zq_subscr.cpp -o zq_subscr.o $(SFLAG) $(WINFLAG) +zq_tiles.o: zq_tiles.cpp colors.h gamedata.h gui.h items.h jwin.h jwinfsel.h midi.h qst.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zc_custom.h zcmusic.h zdefs.h zq_class.h zq_misc.h zq_tiles.h zqscale.h zquest.h zquestdat.h zsys.h + $(CC) $(OPTS) -D_ZQUEST_SCALE_ $(CFLAG) -c zq_tiles.cpp -o zq_tiles.o $(SFLAG) $(WINFLAG) +zqscale.o: zqscale.cpp + $(CC) $(OPTS) $(CFLAG) -c zqscale.cpp -o zqscale.o $(SFLAG) $(WINFLAG) +zquest.o: zquest.cpp colors.h editbox.h EditboxNew.h ffasm.h ffc.h ffscript.h fontsdat.h gamedata.h gui.h items.h jwin.h jwinfsel.h load_gif.h midi.h parser/Compiler.h qst.h save_gif.h sfx.h sprite.h subscr.h tab_ctl.h tiles.h zc_alleg.h zcmusic.h zdefs.h zq_class.h zq_cset.h zq_custom.h zq_doors.h zq_files.h zq_init.h zq_misc.h zq_subscr.h zq_tiles.h zquest.h zquestdat.h zsys.h + $(CC) $(OPTS) -D_ZQUEST_SCALE_ $(CFLAG) -c zquest.cpp -o zquest.o $(SFLAG) $(WINFLAG) +zscriptversion.o: zscriptversion.cpp zelda.h link.h + $(CC) $(OPTS) $(CFLAG) -c zscriptversion.cpp -o zscriptversion.o $(SFLAG) $(WINFLAG) +zsys.o: zsys.cpp gamedata.h jwin.h tab_ctl.h zc_alleg.h zc_sys.h zdefs.h zsys.h + $(CC) $(OPTS) $(CFLAG) -c zsys.cpp -o zsys.o $(SFLAG) $(WINFLAG) + +angelscript/aszc.o: angelscript/aszc.cpp angelscript/aszc.h zc_alleg.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/aszc.cpp -o angelscript/aszc.o $(SFLAG) $(WINFLAG) +angelscript/scriptData.o: angelscript/scriptData.cpp angelscript/scriptData.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/scriptData.cpp -o angelscript/scriptData.o $(SFLAG) $(WINFLAG) +angelscript/util.o: angelscript/util.cpp angelscript/util.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/util.cpp -o angelscript/util.o $(SFLAG) $(WINFLAG) +angelscript/scriptarray/scriptarray.o: angelscript/scriptarray/scriptarray.cpp angelscript/scriptarray/scriptarray.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/scriptarray/scriptarray.cpp -o angelscript/scriptarray/scriptarray.o $(SFLAG) $(WINFLAG) +angelscript/scriptbuilder/scriptbuilder.o: angelscript/scriptbuilder/scriptbuilder.cpp angelscript/scriptbuilder/scriptbuilder.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/scriptbuilder/scriptbuilder.cpp -o angelscript/scriptbuilder/scriptbuilder.o $(SFLAG) $(WINFLAG) +angelscript/scriptmath/scriptmath.o: angelscript/scriptmath/scriptmath.cpp angelscript/scriptmath/scriptmath.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/scriptmath/scriptmath.cpp -o angelscript/scriptmath/scriptmath.o $(SFLAG) $(WINFLAG) +angelscript/scriptstdstring/scriptstdstring.o: angelscript/scriptstdstring/scriptstdstring.cpp angelscript/scriptstdstring/scriptstdstring.h + $(CC) $(OPTS) $(CFLAG) -c angelscript/scriptstdstring/scriptstdstring.cpp -o angelscript/scriptstdstring/scriptstdstring.o $(SFLAG) $(WINFLAG) + +item/clock.o: item/clock.cpp item/clock.h link.h + $(CC) $(OPTS) $(CFLAG) -c item/clock.cpp -o item/clock.o $(SFLAG) $(WINFLAG) +item/dinsFire.o: item/dinsFire.cpp item/dinsFire.h entityPtr.h link.h zc_sys.h zdefs.h zelda.h item/itemAction.h + $(CC) $(OPTS) $(CFLAG) -c item/dinsFire.cpp -o item/dinsFire.o $(SFLAG) $(WINFLAG) +item/faroresWind.o: item/faroresWind.cpp item/faroresWind.h link.h particles.h zc_sys.h zelda.h item/itemAction.h + $(CC) $(OPTS) $(CFLAG) -c item/faroresWind.cpp -o item/faroresWind.o $(SFLAG) $(WINFLAG) +item/hookshot.o: item/hookshot.cpp item/hookshot.h link.h zelda.h item/itemAction.h + $(CC) $(OPTS) $(CFLAG) -c item/hookshot.cpp -o item/hookshot.o $(SFLAG) $(WINFLAG) +item/itemEffect.o: item/itemEffect.cpp item/itemEffect.h debug.h items.h sfxManager.h zelda.h + $(CC) $(OPTS) $(CFLAG) -c item/itemEffect.cpp -o item/itemEffect.o $(SFLAG) $(WINFLAG) +item/nayrusLove.o: item/nayrusLove.cpp item/nayrusLove.h decorations.h entityPtr.h link.h sfxClass.h sound.h zc_sys.h zdefs.h zelda.h item/itemAction.h item/itemEffect.h + $(CC) $(OPTS) $(CFLAG) -c item/nayrusLove.cpp -o item/nayrusLove.o $(SFLAG) $(WINFLAG) + +parser/AST.o: parser/AST.cpp parser/AST.h parser/Compiler.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/AST.cpp -o parser/AST.o $(SFLAG) $(WINFLAG) +parser/BuildVisitors.o: parser/BuildVisitors.cpp zsyssimple.h parser/AST.h parser/BuildVisitors.h parser/ByteCode.h parser/Compiler.h parser/DataStructs.h parser/ParseError.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/BuildVisitors.cpp -o parser/BuildVisitors.o $(SFLAG) $(WINFLAG) +parser/ByteCode.o: parser/ByteCode.cpp zsyssimple.h parser/AST.h parser/ByteCode.h parser/Compiler.h parser/DataStructs.h parser/ParseError.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/ByteCode.cpp -o parser/ByteCode.o $(SFLAG) $(WINFLAG) +parser/DataStructs.o: parser/DataStructs.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/DataStructs.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/DataStructs.cpp -o parser/DataStructs.o $(SFLAG) $(WINFLAG) +parser/GlobalSymbols.o: parser/GlobalSymbols.cpp zsyssimple.h parser/AST.h parser/ByteCode.h parser/Compiler.h parser/DataStructs.h parser/GlobalSymbols.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/GlobalSymbols.cpp -o parser/GlobalSymbols.o $(SFLAG) $(WINFLAG) +parser/lex.yy.o: parser/lex.yy.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/lex.yy.cpp -o parser/lex.yy.o $(SFLAG) $(WINFLAG) +parser/ParseError.o: parser/ParseError.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/ParseError.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/ParseError.cpp -o parser/ParseError.o $(SFLAG) $(WINFLAG) +parser/ScriptParser.o: parser/ScriptParser.cpp zsyssimple.h parser/AST.h parser/BuildVisitors.h parser/ByteCode.h parser/Compiler.h parser/DataStructs.h parser/GlobalSymbols.h parser/ParseError.h parser/SymbolVisitors.h parser/TypeChecker.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/ScriptParser.cpp -o parser/ScriptParser.o $(SFLAG) $(WINFLAG) +parser/SymbolVisitors.o: parser/SymbolVisitors.cpp parser/AST.h parser/Compiler.h parser/DataStructs.h parser/ParseError.h parser/SymbolVisitors.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/SymbolVisitors.cpp -o parser/SymbolVisitors.o $(SFLAG) $(WINFLAG) +parser/TypeChecker.o: parser/TypeChecker.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/DataStructs.h parser/GlobalSymbols.h parser/ParseError.h parser/TypeChecker.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/TypeChecker.cpp -o parser/TypeChecker.o $(SFLAG) $(WINFLAG) +parser/UtilVisitors.o: parser/UtilVisitors.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/ParseError.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/UtilVisitors.cpp -o parser/UtilVisitors.o $(SFLAG) $(WINFLAG) +parser/y.tab.o: parser/y.tab.cpp zsyssimple.h parser/AST.h parser/Compiler.h parser/UtilVisitors.h parser/y.tab.hpp + $(CC) $(OPTS) $(CFLAG) -c parser/y.tab.cpp -o parser/y.tab.o $(SFLAG) $(WINFLAG) + +guiBitmapRenderer.o: guiBitmapRenderer.cpp guiBitmapRenderer.h + $(CC) $(OPTS) $(CFLAG) -c guiBitmapRenderer.cpp -o guiBitmapRenderer.o $(SFLAG) $(WINFLAG) + +gui/alert.o: gui/alert.cpp gui/alert.h gui/dialog.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c gui/alert.cpp -o gui/alert.o $(SFLAG) $(WINFLAG) +gui/contents.o: gui/contents.cpp gui/contents.h + $(CC) $(OPTS) $(CFLAG) -c gui/contents.cpp -o gui/contents.o $(SFLAG) $(WINFLAG) +gui/controller.o: gui/controller.cpp gui/controller.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c gui/controller.cpp -o gui/controller.o $(SFLAG) $(WINFLAG) +gui/dialog.o: gui/dialog.cpp gui/dialog.h gui/controller.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c gui/dialog.cpp -o gui/dialog.o $(SFLAG) $(WINFLAG) +gui/manager.o: gui/manager.cpp gui/manager.h gui/alert.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c gui/manager.cpp -o gui/manager.o $(SFLAG) $(WINFLAG) + +gui/allegro/bitmap.o: gui/allegro/bitmap.cpp gui/allegro/bitmap.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/bitmap.cpp -o gui/allegro/bitmap.o $(SFLAG) $(WINFLAG) +gui/allegro/button.o: gui/allegro/button.cpp gui/allegro/button.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/button.cpp -o gui/allegro/button.o $(SFLAG) $(WINFLAG) +gui/allegro/checkbox.o: gui/allegro/checkbox.cpp gui/allegro/checkbox.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/checkbox.cpp -o gui/allegro/checkbox.o $(SFLAG) $(WINFLAG) +gui/allegro/column.o: gui/allegro/column.cpp gui/allegro/column.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/column.cpp -o gui/allegro/column.o $(SFLAG) $(WINFLAG) +gui/allegro/comboBox.o: gui/allegro/comboBox.cpp gui/allegro/comboBox.h gui/allegro/list.h gui/list.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/comboBox.cpp -o gui/allegro/comboBox.o $(SFLAG) $(WINFLAG) +gui/allegro/controller.o: gui/allegro/controller.cpp gui/allegro/controller.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/controller.cpp -o gui/allegro/controller.o $(SFLAG) $(WINFLAG) +gui/allegro/dummy.o: gui/allegro/dummy.cpp gui/allegro/dummy.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/dummy.cpp -o gui/allegro/dummy.o $(SFLAG) $(WINFLAG) +gui/allegro/editableText.o: gui/allegro/editableText.cpp gui/allegro/editableText.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/editableText.cpp -o gui/allegro/editableText.o $(SFLAG) $(WINFLAG) +gui/allegro/factory.o: gui/allegro/factory.cpp gui/allegro/factory.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/factory.cpp -o gui/allegro/factory.o $(SFLAG) $(WINFLAG) +gui/allegro/frame.o: gui/allegro/frame.cpp gui/allegro/frame.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/frame.cpp -o gui/allegro/frame.o $(SFLAG) $(WINFLAG) +gui/allegro/list.o: gui/allegro/list.cpp gui/allegro/list.h gui/allegro/scrollingPane.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/list.cpp -o gui/allegro/list.o $(SFLAG) $(WINFLAG) +gui/allegro/renderer.o: gui/allegro/renderer.cpp gui/allegro/renderer.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/renderer.cpp -o gui/allegro/renderer.o $(SFLAG) $(WINFLAG) +gui/allegro/row.o: gui/allegro/row.cpp gui/allegro/row.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/row.cpp -o gui/allegro/row.o $(SFLAG) $(WINFLAG) +gui/allegro/scrollbar.o: gui/allegro/scrollbar.cpp gui/allegro/scrollbar.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/scrollbar.cpp -o gui/allegro/scrollbar.o $(SFLAG) $(WINFLAG) +gui/allegro/scrollingPane.o: gui/allegro/scrollingPane.cpp gui/allegro/scrollingPane.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/scrollingPane.cpp -o gui/allegro/scrollingPane.o $(SFLAG) $(WINFLAG) +gui/allegro/serialContainer.o: gui/allegro/serialContainer.cpp gui/allegro/serialContainer.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/serialContainer.cpp -o gui/allegro/serialContainer.o $(SFLAG) $(WINFLAG) +gui/allegro/standardWidget.o: gui/allegro/standardWidget.cpp gui/allegro/standardWidget.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/standardWidget.cpp -o gui/allegro/standardWidget.o $(SFLAG) $(WINFLAG) +gui/allegro/tab.o: gui/allegro/tab.cpp gui/allegro/tab.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/tab.cpp -o gui/allegro/tab.o $(SFLAG) $(WINFLAG) +gui/allegro/tabBar.o: gui/allegro/tabBar.cpp gui/allegro/tabBar.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/tabBar.cpp -o gui/allegro/tabBar.o $(SFLAG) $(WINFLAG) +gui/allegro/tabPanel.o: gui/allegro/tabPanel.cpp gui/allegro/tabPanel.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/tabPanel.cpp -o gui/allegro/tabPanel.o $(SFLAG) $(WINFLAG) +gui/allegro/text.o: gui/allegro/text.cpp gui/allegro/text.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/text.cpp -o gui/allegro/text.o $(SFLAG) $(WINFLAG) +gui/allegro/textField.o: gui/allegro/textField.cpp gui/allegro/textField.h gui/allegro/editableText.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/textField.cpp -o gui/allegro/textField.o $(SFLAG) $(WINFLAG) +gui/allegro/common.o: gui/allegro/common.cpp gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/common.cpp -o gui/allegro/common.o $(SFLAG) $(WINFLAG) +gui/allegro/window.o: gui/allegro/window.cpp gui/allegro/window.h gui/allegro/common.h + $(CC) $(OPTS) $(CFLAG) -c gui/allegro/window.cpp -o gui/allegro/window.o $(SFLAG) $(WINFLAG) + +gui/gtk/bitmap.o: gui/gtk/bitmap.cpp gui/gtk/bitmap.h guiBitmapRenderer.h gui/mouse.h gui/widget.h gui/bitmap.h gui/gtk/util.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/bitmap.cpp -o gui/gtk/bitmap.o $(SFLAG) $(WINFLAG) +gui/gtk/button.o: gui/gtk/button.cpp gui/gtk/button.h gui/gtk/util.h gui/widget.h gui/button.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/button.cpp -o gui/gtk/button.o $(SFLAG) $(WINFLAG) +gui/gtk/buttonRow.o: gui/gtk/buttonRow.cpp gui/gtk/buttonRow.h gui/gtk/util.h gui/widget.h gui/serialContainer.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/buttonRow.cpp -o gui/gtk/buttonRow.o $(SFLAG) $(WINFLAG) +gui/gtk/checkbox.o: gui/gtk/checkbox.cpp gui/gtk/checkbox.h gui/gtk/util.h gui/widget.h gui/checkbox.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/checkbox.cpp -o gui/gtk/checkbox.o $(SFLAG) $(WINFLAG) +gui/gtk/controller.o: gui/gtk/controller.cpp gui/gtk/controller.h gui/controller.h gui/widget.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/controller.cpp -o gui/gtk/controller.o $(SFLAG) $(WINFLAG) +gui/gtk/factory.o: gui/gtk/factory.cpp gui/gtk/factory.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/factory.cpp -o gui/gtk/factory.o $(SFLAG) $(WINFLAG) +gui/gtk/frame.o: gui/gtk/frame.cpp gui/gtk/frame.h gui/gtk/util.h gui/widget.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/frame.cpp -o gui/gtk/frame.o $(SFLAG) $(WINFLAG) +gui/gtk/manager.o: gui/gtk/manager.cpp gui/gtk/manager.h gui/manager.h gui/gtk/factory.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/manager.cpp -o gui/gtk/manager.o $(SFLAG) $(WINFLAG) +gui/gtk/serialContainer.o: gui/gtk/serialContainer.cpp gui/gtk/factory.h gui/gtk/util.h gui/widget.h gui/serialContainer.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/serialContainer.cpp -o gui/gtk/serialContainer.o $(SFLAG) $(WINFLAG) +gui/gtk/spinner.o: gui/gtk/spinner.cpp gui/gtk/spinner.h gui/widget.h gui/spinner.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/spinner.cpp -o gui/gtk/spinner.o $(SFLAG) $(WINFLAG) +gui/gtk/tabPanel.o: gui/gtk/tabPanel.cpp gui/gtk/tabPanel.h gui/gtk/util.h gui/widget.h gui/tabPanel.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/tabPanel.cpp -o gui/gtk/tabPanel.o $(SFLAG) $(WINFLAG) +gui/gtk/text.o: gui/gtk/text.cpp gui/gtk/text.h gui/gtk/util.h gui/widget.h gui/text.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/text.cpp -o gui/gtk/text.o $(SFLAG) $(WINFLAG) +gui/gtk/textBox.o: gui/gtk/textBox.cpp gui/gtk/textBox.h gui/gtk/util.h gui/widget.h gui/textBox.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/textBox.cpp -o gui/gtk/textBox.o $(SFLAG) $(WINFLAG) +gui/gtk/textField.o: gui/gtk/textField.cpp gui/gtk/window.h gui/gtk/util.h gui/widget.h gui/textField.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/textField.cpp -o gui/gtk/textField.o $(SFLAG) $(WINFLAG) +gui/gtk/util.o: gui/gtk/util.cpp gui/gtk/util.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/util.cpp -o gui/gtk/util.o $(SFLAG) $(WINFLAG) +gui/gtk/widget.o: gui/gtk/widget.cpp gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/widget.cpp -o gui/gtk/widget.o $(SFLAG) $(WINFLAG) +gui/gtk/window.o: gui/gtk/window.cpp gui/gtk/window.h gui/key.h gui/gtk/util.h gui/widget.h gui/window.h gui/gtk/widget.h + $(CC) $(OPTS) $(CFLAG) -c gui/gtk/window.cpp -o gui/gtk/window.o $(SFLAG) $(WINFLAG) + +dialog/bitmap/tilePreview.o: dialog/bitmap/tilePreview.cpp dialog/bitmap/tilePreview.h + $(CC) $(OPTS) $(CFLAG) -c dialog/bitmap/tilePreview.cpp -o dialog/bitmap/tilePreview.o $(SFLAG) $(WINFLAG) +dialog/bitmap/tileSelector.o: dialog/bitmap/tileSelector.cpp dialog/bitmap/tileSelector.h dialog/zquest/tileSelector.h gui/bitmap.h + $(CC) $(OPTS) $(CFLAG) -c dialog/bitmap/tileSelector.cpp -o dialog/bitmap/tileSelector.o $(SFLAG) $(WINFLAG) + +dialog/zquest/cheatEditor.o: dialog/zquest/cheatEditor.cpp dialog/zquest/cheatEditor.h gui/dialog.h zdefs.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/cheatEditor.cpp -o dialog/zquest/cheatEditor.o $(SFLAG) $(WINFLAG) +dialog/zquest/infoShopEditor.o: dialog/zquest/infoShopEditor.cpp dialog/zquest/infoShopEditor.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/infoShopEditor.cpp -o dialog/zquest/infoShopEditor.o $(SFLAG) $(WINFLAG) +dialog/zquest/paletteViewer.o: dialog/zquest/paletteViewer.cpp dialog/zquest/paletteViewer.h gui/dialog.h gui/bitmap.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/paletteViewer.cpp -o dialog/zquest/paletteViewer.o $(SFLAG) $(WINFLAG) +dialog/zquest/questRules.o: dialog/zquest/questRules.cpp dialog/zquest/questRules.h zdefs.h zsys.h gui/dialog.h gui/factory.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/questRules.cpp -o dialog/zquest/questRules.o $(SFLAG) $(WINFLAG) +dialog/zquest/shopEditor.o: dialog/zquest/shopEditor.cpp dialog/zquest/shopEditor.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/shopEditor.cpp -o dialog/zquest/shopEditor.o $(SFLAG) $(WINFLAG) +dialog/zquest/simpleListSelector.o: dialog/zquest/simpleListSelector.cpp dialog/zquest/simpleListSelector.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/simpleListSelector.cpp -o dialog/zquest/simpleListSelector.o $(SFLAG) $(WINFLAG) +dialog/zquest/tileEditor.o: dialog/zquest/tileEditor.cpp dialog/zquest/tileEditor.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/tileEditor.cpp -o dialog/zquest/tileEditor.o $(SFLAG) $(WINFLAG) +dialog/zquest/tileSelector.o: dialog/zquest/tileSelector.cpp dialog/zquest/tileSelector.h dialog/bitmap/tileSelector.h gui/dialog.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/tileSelector.cpp -o dialog/zquest/tileSelector.o $(SFLAG) $(WINFLAG) +dialog/zquest/tileSelectorBackend.o: dialog/zquest/tileSelectorBackend.cpp dialog/zquest/tileSelectorBackend.cpp dialog/zquest/tileSelector.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/tileSelectorBackend.cpp -o dialog/zquest/tileSelectorBackend.o $(SFLAG) $(WINFLAG) +dialog/zquest/zscriptEditor.o: dialog/zquest/zscriptEditor.cpp dialog/zquest/zscriptEditor.h gui/dialog.h gui/factory.h gui/manager.h gui/text.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/zscriptEditor.cpp -o dialog/zquest/zscriptEditor.o $(SFLAG) $(WINFLAG) +dialog/zquest/zscriptMain.o: dialog/zquest/zscriptMain.cpp dialog/zquest/zscriptMain.h dialog/zquest/zscriptEditor.h gui/dialog.h gui/factory.h gui/manager.h gui/text.h + $(CC) $(OPTS) $(CFLAG) -c dialog/zquest/zscriptMain.cpp -o dialog/zquest/zscriptMain.o $(SFLAG) $(WINFLAG) + +sequence/gameOver.o: sequence/gameOver.cpp sequence/gameOver.h link.h sfx.h sound.h zelda.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/gameOver.cpp -o sequence/gameOver.o $(SFLAG) $(WINFLAG) +sequence/ganonIntro.o: sequence/ganonIntro.cpp sequence/ganonIntro.h guys.h link.h sfx.h sound.h zc_sys.h zelda.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/ganonIntro.cpp -o sequence/ganonIntro.o $(SFLAG) $(WINFLAG) +sequence/getBigTriforce.o: sequence/getBigTriforce.cpp sequence/getBigTriforce.h link.h sound.h zelda.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/getBigTriforce.cpp -o sequence/getBigTriforce.o $(SFLAG) $(WINFLAG) +sequence/getTriforce.o: sequence/getTriforce.cpp sequence/getTriforce.h link.h sound.h zelda.h zc_alleg.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/getTriforce.cpp -o sequence/getTriforce.o $(SFLAG) $(WINFLAG) +sequence/potion.o: sequence/potion.cpp sequence/potion.h link.h sfxClass.h zelda.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/potion.cpp -o sequence/potion.o $(SFLAG) $(WINFLAG) +sequence/whistle.o: sequence/whistle.cpp sequence/whistle.h link.h sfxClass.h weapons.h zc_sys.h zelda.h sequence/sequence.h + $(CC) $(OPTS) $(CFLAG) -c sequence/whistle.cpp -o sequence/whistle.o $(SFLAG) $(WINFLAG) + diff --git a/output/common/WARNING-READ.txt b/output/common/WARNING-READ.txt new file mode 100644 index 0000000000..882adc6174 --- /dev/null +++ b/output/common/WARNING-READ.txt @@ -0,0 +1,6 @@ +WARNING: THIS IS AN AUTOMATIC ALPHA BUILD +It is work in progress, released without careful inspection by the developers. It may be unstable, contain missing, partially implemented, or broken features, or corrupt your quests. Active development of quests on this build is not recommended. + +***THE DEVELOPERS TAKE NO RESPONSIBILTY FOR ANY DAMAGE THAT THIS BUILD MIGHT DO TO YOUR COMPUTER OR YOUR QUESTS.*** + +This build is intended for testing only and is NOT suitable for redistribution. If you obtained this build from anywhere other than Armageddon Games (www.armageddongames.com), the official home of Zelda Classic, please contact the developers at evouga@gmail.com. \ No newline at end of file diff --git a/output/common/angelscript/aquamentus.as b/output/common/angelscript/aquamentus.as new file mode 100644 index 0000000000..02ac35891f --- /dev/null +++ b/output/common/angelscript/aquamentus.as @@ -0,0 +1,144 @@ +class Aquamentus: enemy +{ + private int moveTimer; + + Aquamentus() + { + y=64; + + if(dmisc1==0) // Facing left + x=176; + else // Facing right + { + x=64; + if(!questRuleEnabled(qr_NEWENEMYTILES)) + flip=1; + } + + yofs=playing_field_offset+1; + clk3=32; + clk2=0; + moveTimer=clk; + dir=left; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + clk3-=1; + if(clk3==0) + fireWeapon(); + + if(clk3<-80 && (rand()&63)==0) + clk3=32; + + if(((moveTimer+1)&63)==0) + { + int d2=(rand()%3)+1; + + if(d2>=left) + dir=d2; + + if(dmisc1!=0) + { + if(x<=40) + dir=right; + + if(x>=104) + dir=left; + } + else + { + if(x<=136) + dir=right; + + if(x>=200) + dir=left; + } + } + + if(moveTimer>=-1 && ((moveTimer+1)&7)==0) + { + if(dir==left) + x-=1; + else + x+=1; + } + + moveTimer=(moveTimer+1)%256; + + return enemy::animate(index); + } + + void Draw() + { + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + xofs=((dmisc1!=0)?-16:0); + tile=o_tile+((clk&24)>>2)+(clk3>-32?(clk3>0?40:80):0); + + if(dying) + { + xofs=0; + enemy::draw(); + } + else + drawblock(); + } + else + { + int xblockofs=((dmisc1!=0)?-16:16); + xofs=0; + + if(clk<0 || dying) + { + enemy::draw(); + return; + } + + // face (0=firing, 2=resting) + tile=o_tile+((clk3>0)?0:2); + enemy::draw(); + // tail ( + tile=o_tile+(((clk&16)!=0)?1:3); + xofs=xblockofs; + enemy::draw(); + // body + yofs+=16; + xofs=0; + tile=o_tile+(((clk&16)!=0)?20:22); + enemy::draw(); + xofs=xblockofs; + tile=o_tile+(((clk&16)!=0)?21:23); + enemy::draw(); + yofs-=16; + } + } + + bool Hit(weapon@ w) + { + if((w.scriptcoldet&1)==0) + return false; + + switch(w.id) + { + case wBeam: + case wRefBeam: + case wMagic: + hysz=32; + } + + bool ret = (dying || hclk>0) ? false : sprite::hit(w); + hysz=16; + return ret; + + } +} + diff --git a/output/common/angelscript/common.as b/output/common/angelscript/common.as new file mode 100644 index 0000000000..813728d0f3 --- /dev/null +++ b/output/common/angelscript/common.as @@ -0,0 +1,1004 @@ +LinkClass@ Link; + +const double PI = 3.14159265358979323846; + +const int up = 0; +const int down = 1; +const int left = 2; +const int right = 3; +const int l_up = 4; +const int r_up = 5; +const int l_down = 6; +const int r_down = 7; + +const int MAXITEMS = 256; +const int MAXWPNS = 256; +const int MAXGUYS = 512; + +const int WAV_ARROW = 1; +const int WAV_BEAM = 2; +const int WAV_BOMB = 3; +const int WAV_BRANG = 4; +const int WAV_CHIME = 5; +const int WAV_CHINK = 6; +const int WAV_CLEARED = 7; +const int WAV_DODONGO = 8; +const int WAV_DOOR = 9; +const int WAV_EDEAD = 10; +const int WAV_EHIT = 11; +const int WAV_ER = 12; +const int WAV_FIRE = 13; +const int WAV_GANON = 14; +const int WAV_GASP = 15; +const int WAV_HAMMER = 16; +const int WAV_HOOKSHOT = 17; +const int WAV_MSG = 18; +const int WAV_OUCH = 19; +const int WAV_PICKUP = 20; +const int WAV_PLACE = 21; +const int WAV_PLINK = 22; +const int WAV_REFILL = 23; +const int WAV_ROAR = 24; +const int WAV_SCALE = 25; +const int WAV_SEA = 26; +const int WAV_SECRET = 27; +const int WAV_SPIRAL = 28; +const int WAV_STAIRS = 29; +const int WAV_SWORD = 30; +const int WAV_VADER = 31; +const int WAV_WAND = 32; +const int WAV_WHISTLE = 33; +const int WAV_ZELDA = 34; +const int WAV_ZN1CHARGE = 35; +const int WAV_ZN1CHARGE2 = 36; +const int WAV_ZN1DINSFIRE = 37; +const int WAV_ZN1FALL = 38; +const int WAV_ZN1FARORESWIND = 39; +const int WAV_ZN1FIREBALL = 40; +const int WAV_ZN1GRASSCUT = 41; +const int WAV_ZN1HAMMERPOST = 42; +const int WAV_ZN1HOVER = 43; +const int WAV_ZN1ICE = 44; +const int WAV_ZN1JUMP = 45; +const int WAV_ZN1LENSOFF = 46; +const int WAV_ZN1LENSON = 47; +const int WAV_ZN1NAYRUSLOVE1 = 48; +const int WAV_ZN1NAYRUSLOVE2 = 49; +const int WAV_ZN1PUSHBLOCK = 50; +const int WAV_ZN1ROCK = 51; +const int WAV_ZN1ROCKETDOWN = 52; +const int WAV_ZN1ROCKETUP = 53; +const int WAV_ZN1SPINATTACK = 54; +const int WAV_ZN1SPLASH = 55; +const int WAV_ZN1SUMMON = 56; +const int WAV_ZN1TAP = 57; +const int WAV_ZN1TAP2 = 58; +const int WAV_ZN1WHIRLWIND = 59; +const int WAV_ZN2CANE = 60; +const int Z35 = 61; + +enum mapFlags +{ + mfNONE, mfPUSHUD, mfPUSH4, mfWHISTLE, mfBCANDLE, mfARROW, mfBOMB, mfFAIRY, + mfRAFT, mfARMOS_SECRET, mfARMOS_ITEM, mfSBOMB, mfRAFT_BRANCH, mfDIVE_ITEM, + mfLENSMARKER, mfZELDA, + mfSECRETS01, mfSECRETS02, mfSECRETS03, mfSECRETS04, /*16*/ + mfSECRETS05, mfSECRETS06, mfSECRETS07, mfSECRETS08, + mfSECRETS09, mfSECRETS10, mfSECRETS11, mfSECRETS12, + mfSECRETS13, mfSECRETS14, mfSECRETS15, mfSECRETS16, + mfTRAP_H, mfTRAP_V, mfTRAP_4, mfTRAP_LR, mfTRAP_UD, /*32*/ + mfENEMY0, mfENEMY1, mfENEMY2, mfENEMY3, mfENEMY4, /*37*/ + mfENEMY5, mfENEMY6, mfENEMY7, mfENEMY8, mfENEMY9, + mfPUSHLR, mfPUSHU, mfPUSHD, mfPUSHL, mfPUSHR, + mfPUSHUDNS, mfPUSHLRNS, mfPUSH4NS, mfPUSHUNS, + mfPUSHDNS, mfPUSHLNS, mfPUSHRNS, mfPUSHUDINS, + mfPUSHLRINS, mfPUSH4INS, mfPUSHUINS, + mfPUSHDINS, mfPUSHLINS, mfPUSHRINS, + mfBLOCKTRIGGER, mfNOBLOCKS, mfBRANG, mfMBRANG, + mfFBRANG, mfSARROW, mfGARROW, mfRCANDLE, mfWANDFIRE, mfDINSFIRE, + mfWANDMAGIC, mfREFMAGIC, mfREFFIREBALL, mfSWORD, mfWSWORD, + mfMSWORD, mfXSWORD, mfSWORDBEAM, mfWSWORDBEAM, mfMSWORDBEAM, + mfXSWORDBEAM, mfHOOKSHOT, mfWAND, mfHAMMER, mfSTRIKE, mfBLOCKHOLE, + mfMAGICFAIRY, mfALLFAIRY, mfSINGLE, mfSINGLE16, + mfNOENEMY, mfNOGROUNDENEMY, mfSCRIPT1, mfSCRIPT2, mfSCRIPT3, mfSCRIPT4, mfSCRIPT5, + mfRAFT_BOUNCE, mfMAX, mfPUSHED +}; + +enum questRules +{ + // 1st byte out of 20 + qr_SOLIDBLK, qr_NOTMPNORET, qr_ALWAYSRET, qr_MEANTRAPS, + qr_BSZELDA, qr_FADE, qr_FADECS5, qr_FASTDNGN, + // 2 + qr_NOLEVEL3FIX, qr_COOLSCROLL, qr_NOSCROLL, qr_4TRI, + qr_EXPLICIT_RAFTING, qr_FASTFILL, qr_CAVEEXITNOSTOPMUSIC, qr_3TRI, + // 3 + qr_TIME, qr_FREEFORM, qr_KILLALL, qr_NOFLICKER, + qr_CONTFULL_DEP/*DEPRECATED*/, qr_RLFIX, qr_LENSHINTS, qr_LINKDUNGEONPOSFIX, + // 4 + qr_HOLDITEMANIMATION, qr_HESITANTPUSHBLOCKS, qr_HIDECARRIEDITEMS, qr_FFCSCROLL, + qr_RAFTLENS, qr_SMOOTHVERTICALSCROLLING, qr_WHIRLWINDMIRROR, qr_NOFLASHDEATH, + // 5 + qr_HOLDNOSTOPMUSIC, qr_FIREPROOFLINK, qr_OUCHBOMBS, qr_NOCLOCKS_DEP/*DEPRECATED*/, + qr_TEMPCLOCKS_DEP/*DEPRECATED*/, qr_BRKBLSHLDS_DEP/*DEPRECATED*/, qr_BRKNSHLDTILES, qr_MEANPLACEDTRAPS, + // 6 + qr_PHANTOMPLACEDTRAPS, qr_ALLOWFASTMSG, qr_LINKEDCOMBOS/*DEPRECATED*/, qr_NOGUYFIRES, + qr_HEARTRINGFIX, qr_NOHEARTRING, qr_OVERWORLDTUNIC, qr_SWORDWANDFLIPFIX, + // 7 + qr_ENABLEMAGIC, qr_MAGICWAND_DEP/*DEPRECATED*/, qr_MAGICCANDLE_DEP/*DEPRECATED*/, qr_MAGICBOOTS_DEP/*DEPRECATED*/, + qr_NONBUBBLEMEDICINE, qr_NONBUBBLEFAIRIES, qr_NONBUBBLETRIFORCE, qr_NEWENEMYTILES, + // 8 + qr_NOROPE2FLASH_DEP/*DEPRECATED*/, qr_NOBUBBLEFLASH_DEP/*DEPRECATED*/, qr_GHINI2BLINK_DEP, qr_WPNANIMFIX /* UNIMPLEMENTED */, + qr_PHANTOMGHINI2_DEP/*DEPRECATED*/, qr_Z3BRANG_HSHOT, qr_NOITEMMELEE, qr_SHADOWS, + // 9 + qr_TRANSSHADOWS, qr_QUICKSWORD, qr_BOMBHOLDFIX, qr_EXPANDEDLTM, + qr_NOPOTIONCOMBINE_DEP/*DEPRECATED*/, qr_LINKFLICKER, qr_SHADOWSFLICKER, qr_WALLFLIERS, + // 10 + qr_NOBOMBPALFLASH, qr_HEARTSREQUIREDFIX, qr_PUSHBLOCKCSETFIX, qr_TRANSLUCENTNAYRUSLOVEROCKET_DEP/*DEPRECATED*/, + qr_FLICKERINGNAYRUSLOVEROCKET_DEP/*DEPRECATED*/, qr_CMBCYCLELAYERS, qr_DMGCOMBOPRI, qr_WARPSIGNOREARRIVALPOINT, + // 11 + qr_LTTPCOLLISION, qr_LTTPWALK, qr_SLOWENEMYANIM_DEP/*DEPRECATED*/, qr_TRUEARROWS, + qr_NOSAVE, qr_NOCONTINUE, qr_QUARTERHEART, qr_NOARRIVALPOINT, + // 12 + qr_NOGUYPOOF, qr_ALLOWMSGBYPASS, qr_NODIVING, qr_LAYER12UNDERCAVE, + qr_NOSCROLLCONTINUE, qr_SMARTSCREENSCROLL, qr_RINGAFFECTDAMAGE, qr_ALLOW10RUPEEDROPS_DEP/*DEPRECATED*/, + // 13 + qr_TRAPPOSFIX, qr_TEMPCANDLELIGHT, qr_REDPOTIONONCE_DEP/*DEPRECATED*/, qr_OLDSTYLEWARP, + qr_NOBORDER, qr_OLDTRIBBLES_DEP/*DEPRECATED*/, qr_REFLECTROCKS /*DEPRECATED*/, qr_OLDPICKUP, + // 14 + qr_ENEMIESZAXIS, qr_SAFEENEMYFADE, qr_MORESOUNDS, qr_BRANGPICKUP, + qr_HEARTPIECEINCR_DEP/*DEPRECATED*/, qr_ITEMSONEDGES, qr_EATSMALLSHIELD_DEP/*DEPRECATED*/, qr_MSGFREEZE, + // 15 + qr_SLASHFLIPFIX, qr_FIREMAGICSPRITE_DEP/*DEPRECATED*/, qr_SLOWCHARGINGWALK, qr_NOWANDMELEE, + qr_SLOWBOMBFUSES_DEP/*DEPRECATED*/, qr_SWORDMIRROR, qr_SELECTAWPN, qr_LENSSEESENEMIES, + // 16 + qr_INSTABURNFLAGS, qr_DROWN, qr_MSGDISAPPEAR, qr_SUBSCREENOVERSPRITES, + qr_BOMBDARKNUTFIX, qr_LONGBOMBBOOM_DEP/*DEPRECATED*/, qr_OFFSETEWPNCOLLISIONFIX, qr_DMGCOMBOLAYERFIX, + // 17 + qr_ITEMSINPASSAGEWAYS, qr_LOG, qr_FIREPROOFLINK2, qr_NOITEMOFFSET, + qr_ITEMBUBBLE, qr_GOTOLESSNOTEQUAL /* Compatibility */, qr_LADDERANYWHERE, qr_HOOKSHOTLAYERFIX, + // 18 + qr_REPLACEOPENDOORS /* Compatibility */, qr_OLDLENSORDER /* Compatibility */, qr_NOFAIRYGUYFIRES /* Compatibility */, qr_SCRIPTERRLOG, + qr_TRIGGERSREPEAT /* Compatibility */, qr_ENEMIESFLICKER, qr_OVALWIPE, qr_TRIANGLEWIPE, + // 19 + qr_SMASWIPE, qr_NOSOLIDDAMAGECOMBOS /* Compatibility */, qr_SHOPCHEAT, qr_HOOKSHOTDOWNBUG /* Compatibility */, + qr_OLDHOOKSHOTGRAB /* Compatibility */, qr_PEAHATCLOCKVULN /* Compatibility */, qr_VERYFASTSCROLLING, qr_OFFSCREENWEAPONS /* Compatibility */, + qr_MAX +}; + +enum comboTypes +{ + cNONE, cSTAIR, cCAVE, cWATER, cARMOS, cGRAVE, cDOCK, + cUNDEF, cPUSH_WAIT, cPUSH_HEAVY, cPUSH_HW, cL_STATUE, cR_STATUE, + cWALKSLOW, cCVUP, cCVDOWN, cCVLEFT, cCVRIGHT, cSWIMWARP, cDIVEWARP, + cLADDERHOOKSHOT, cTRIGNOFLAG, cTRIGFLAG, cZELDA, cSLASH, cSLASHITEM, + cPUSH_HEAVY2, cPUSH_HW2, cPOUND, cHSGRAB, cHSBRIDGE, cDAMAGE1, + cDAMAGE2, cDAMAGE3, cDAMAGE4, cC_STATUE, cTRAP_H, cTRAP_V, cTRAP_4, + cTRAP_LR, cTRAP_UD, cPIT, cHOOKSHOTONLY, cOVERHEAD, cNOFLYZONE, cMIRROR, + cMIRRORSLASH, cMIRRORBACKSLASH, cMAGICPRISM, cMAGICPRISM4, + cMAGICSPONGE, cCAVE2, cEYEBALL_A, cEYEBALL_B, cNOJUMPZONE, cBUSH, + cFLOWERS, cTALLGRASS, cSHALLOWWATER, cLOCKBLOCK, cLOCKBLOCK2, + cBOSSLOCKBLOCK, cBOSSLOCKBLOCK2, cLADDERONLY, cBSGRAVE, + cCHEST, cCHEST2, cLOCKEDCHEST, cLOCKEDCHEST2, cBOSSCHEST, cBOSSCHEST2, + cRESET, cSAVE, cSAVE2, /*cVERTICAL,*/ cCAVEB, cCAVEC, cCAVED, + cSTAIRB, cSTAIRC, cSTAIRD, cPITB, cPITC, cPITD, + cCAVE2B, cCAVE2C, cCAVE2D, cSWIMWARPB, cSWIMWARPC, cSWIMWARPD, + cDIVEWARPB, cDIVEWARPC, cDIVEWARPD, cSTAIRR, cPITR, + cAWARPA, cAWARPB, cAWARPC, cAWARPD, cAWARPR, + cSWARPA, cSWARPB, cSWARPC, cSWARPD, cSWARPR, cSTRIGNOFLAG, cSTRIGFLAG, + cSTEP, cSTEPSAME, cSTEPALL, cSTEPCOPY, cNOENEMY, cBLOCKARROW1, cBLOCKARROW2, + cBLOCKARROW3, cBLOCKBRANG1, cBLOCKBRANG2, cBLOCKBRANG3, cBLOCKSBEAM, cBLOCKALL, + cBLOCKFIREBALL, cDAMAGE5, cDAMAGE6, cDAMAGE7, cCHANGE/**DEPRECATED**/, cSPINTILE1, cSPINTILE2, + cSCREENFREEZE, cSCREENFREEZEFF, cNOGROUNDENEMY, cSLASHNEXT, cSLASHNEXTITEM, cBUSHNEXT, + cSLASHTOUCHY, cSLASHITEMTOUCHY, cBUSHTOUCHY, cFLOWERSTOUCHY, cTALLGRASSTOUCHY, + cSLASHNEXTTOUCHY, cSLASHNEXTITEMTOUCHY, cBUSHNEXTTOUCHY, cEYEBALL_4, cTALLGRASSNEXT, + cSCRIPT1, cSCRIPT2, cSCRIPT3, cSCRIPT4, cSCRIPT5, cMAX +}; + +enum specialWalkFlags +{ + spw_none, spw_door, spw_clipright, spw_floater, spw_trap, spw_halfstep, + spw_water, spw_wizzrobe, spw_clipbottomright +}; + +// game.maps[] flags +const int mDOOR_UP = 1; // only dungeons use this +const int mDOOR_DOWN = 2; // '' +const int mDOOR_LEFT = 4; // '' +const int mDOOR_RIGHT = 8; // '' +const int mITEM = 16; // item (main screen) +const int mBELOW = 32; // special item (underground) +const int mNEVERRET = 64; // enemy never returns +const int mTMPNORET = 128; // enemies don't return until you leave the dungeon +const int mLOCKBLOCK = 256; // if the lockblock on the screen has been triggered +const int mBOSSLOCKBLOCK = 512; // if the bosslockblock on the screen has been triggered +const int mCHEST = 1024; // if the unlocked check on this screen has been opened +const int mLOCKEDCHEST = 2048; // if the locked chest on this screen has been opened +const int mBOSSCHEST = 4096; // if the boss chest on this screen has been opened +const int mSECRET = 8192; // only overworld and caves use this +const int mVISITED = 16384; // only overworld uses this + +// Screen flags +// flags2 +const int wfUP = 0x101; +const int wfDOWN = 0x102; +const int wfLEFT = 0x104; +const int wfRIGHT = 0x108; +const int fSECRET = 0x110; // play "secret" sfx upon entering this screen +const int fAIRCOMBOS = 0x120; +const int fFLOATTRAPS = 0x140; +const int fCLEARSECRET = 0x180; // clear all enemies to trigger secret entrance (Enemies->Secret) + +// flags3 +const int fHOLDITEM = 0x201; +const int fCYCLEONINIT = 0x202; +const int fINVISROOM = 0x204; +const int fINVISLINK = 0x208; +const int fNOSUBSCR = 0x210; +const int fIWARPFULLSCREEN = 0x220; // instawarps affect all sprites +const int fNOSUBSCROFFSET = 0x240; // don't offset the screen when fNOSUBSCR is true +const int fENEMIESRETURN = 0x280; // enemies always return + +//flags7 +const int fLAYER3BG = 0x601; +const int fLAYER2BG = 0x602; +const int fITEMFALLS = 0x604; +const int fSIDEVIEW = 0x608; +const int fNOLINKMARK = 0x610; +const int fSPECITEMMARK = 0x620; +const int fWHISTLEPAL = 0x640; +const int fWHISTLEWATER = 0x680; + +enum itemType +{ + // 0 + itype_sword, itype_brang, itype_arrow, itype_candle, itype_whistle, + itype_bait, itype_letter, itype_potion, itype_wand, itype_ring, + itype_wallet, itype_amulet, itype_shield, itype_bow, itype_raft, + itype_ladder, itype_book, itype_magickey, itype_bracelet, itype_flippers, + // 20 + itype_boots, itype_hookshot, itype_lens, itype_hammer, itype_dinsfire, + itype_faroreswind, itype_nayruslove, itype_bomb, itype_sbomb, itype_clock, + itype_key, itype_magiccontainer, itype_triforcepiece, itype_map, itype_compass, + itype_bosskey, itype_quiver, itype_lkey, itype_cbyrna, itype_rupee, + // 40 + itype_arrowammo, itype_fairy, itype_magic, itype_heart, itype_heartcontainer, + itype_heartpiece, itype_killem, itype_bombammo, itype_bombbag, itype_rocs, + itype_hoverboots, itype_spinscroll,itype_crossscroll, itype_quakescroll,itype_whispring, + itype_chargering, itype_perilscroll, itype_wealthmedal,itype_heartring,itype_magicring, + // 60 + itype_spinscroll2, itype_quakescroll2, itype_agony, itype_stompboots, itype_whimsicalring, + itype_perilring, itype_misc, + // 67 + itype_custom1, itype_custom2, itype_custom3, itype_custom4, itype_custom5, + itype_custom6, itype_custom7, itype_custom8, itype_custom9, itype_custom10, + itype_custom11, itype_custom12, itype_custom13, itype_custom14, itype_custom15, + itype_custom16, itype_custom17, itype_custom18, itype_custom19, itype_custom20, + // 87 + itype_bowandarrow, itype_letterpotion, + itype_last, itype_max=255 +}; + +enum weaponType +{ + // 0 + wNone,wSword,wBeam,wBrang, + wBomb,wSBomb,wLitBomb,wLitSBomb, + // 8 + wArrow,wFire,wWhistle,wBait, + wWand,wMagic,wCatching,wWind, + // 16 + wRefMagic,wRefFireball,wRefRock, wHammer, + wHookshot, wHSHandle, wHSChain, wSSparkle, + // 24 + wFSparkle, wSmack, wPhantom, wCByrna, + wRefBeam, wStomp, + lwMax, + // Dummy weapons - must be between lwMax and wEnemyWeapons! + wScript1, wScript2, wScript3, wScript4, + wScript5, wScript6, wScript7, wScript8, + wScript9, wScript10, + // Enemy weapons + wEnemyWeapons=128, + //129 + ewFireball,ewArrow,ewBrang,ewSword, + ewRock,ewMagic,ewBomb,ewSBomb, + //137 + ewLitBomb,ewLitSBomb,ewFireTrail,ewFlame, + ewWind,ewFlame2,ewFlame2Trail, + //145 + ewIce,ewFireball2, + wMax +}; + +enum weapons // Also sprites +{ + wSWORD, wWSWORD, wMSWORD, wXSWORD, wBRANG, + wMBRANG, wFBRANG, wBOMB, wSBOMB, wBOOM, +// 10 + wARROW, wSARROW, wFIRE, wWIND, wBAIT, + wWAND, wMAGIC, ewFIREBALL, ewROCK, ewARROW, +// 20 + ewSWORD, ewMAGIC, iwSpawn, iwDeath, iwSwim, + wHAMMER, wHSHEAD, wHSCHAIN_H, wHSHANDLE, wSSPARKLE, +// 30 + wGSPARKLE, wMSPARKLE, wFSPARKLE, iwHammerSmack, wGARROW, + ewFLAME, ewWIND, iwMMeter, wDINSFIRE1A, wDINSFIRE1B, +// 40 + wDINSFIRES1A, wDINSFIRES1B, wHSCHAIN_V, iwMore, iwBossMarker, + iwLinkSlash, wSWORDSLASH, wWSWORDSLASH, wMSWORDSLASH, wXSWORDSLASH, +// 50 + iwShadow, iwLargeShadow, iwBushLeaves, iwFlowerClippings, iwGrassClippings, + iwTallGrass, iwRipples, iwNPCs, wNAYRUSLOVE1A, wNAYRUSLOVE1B, +// 60 + wNAYRUSLOVES1A, wNAYRUSLOVES1B, wNAYRUSLOVE2A, wNAYRUSLOVE2B, wNAYRUSLOVES2A, + wNAYRUSLOVES2B, iwNayrusLoveShieldFront, iwNayrusLoveShieldBack, iwSubscreenVine, wCBYRNA, +// 70 + wCBYRNASLASH, wLSHEAD, wLSCHAIN_H, wLSHANDLE, wLSCHAIN_V, + wSBOOM, ewBOMB, ewSBOMB, ewBOOM, ewSBOOM, +// 80 + ewFIRETRAIL, ewFLAME2, ewFLAME2TRAIL, ewICE, iwHover, + wFIREMAGIC, iwQuarterHearts, wCBYRNAORB, //iwSideLadder, iwSideRaft, + + wLast, wMAX=256 +}; + +enum enemies // Also guys +{ + eNONE=0, + gNONE=0, gABEI, gAMA, gDUDE, gMOBLIN, + gFIRE, gFAIRY, gGORIYA, gZELDA, gABEI2, + //10 + gEMPTY, gDUMMY1, gDUMMY2, gDUMMY3, gDUMMY4, + gDUMMY5, gDUMMY6, gDUMMY7, gDUMMY8, gDUMMY9, + //20 + eSTART=20, + eOCTO1S=20, eOCTO2S, eOCTO1F, eOCTO2F, eTEK1, + eTEK2, eLEV1, eLEV2, eMOBLIN1, eMOBLIN2, + //30 + eLYNEL1, eLYNEL2, ePEAHAT, eZORA, eROCK, + eGHINI1, eGHINI2, eARMOS, eKEESE1, eKEESE2, + //40 + eKEESE3, eSTALFOS, eGEL, eZOL, eROPE, + eGORIYA1, eGORIYA2, eTRAP, eWALLM, eDKNUT1, + //50 + eDKNUT2, eBUBBLEST, eVIRE, eLIKE, eGIBDO, + ePOLSV, eWIZ1, eWIZ2, eRAQUAM, eMOLDORM, + //60 + eDODONGO, eMANHAN, eGLEEOK1, eGLEEOK2, eGLEEOK3, + eGLEEOK4, eDIG1, eDIG3, eDIGPUP1, eDIGPUP2, + //70 + eDIGPUP3, eDIGPUP4, eGOHMA1, eGOHMA2, eCENT1, + eCENT2, ePATRA1, ePATRA2, eGANON, eSTALFOS2, + //80 + eROPE2, eBUBBLESP, eBUBBLESR, eSHOOTFBALL, eITEMFAIRY, + eFIRE, eOCTO5, eDKNUT5, eGELTRIB, eZOLTRIB, + //90 + eKEESETRIB, eVIRETRIB, eDKNUT3, eLAQUAM, eMANHAN2, + eTRAP_H, eTRAP_V, eTRAP_LR, eTRAP_UD, eFWIZ, + //100 + eWWIZ, eCEILINGM, eFLOORM, ePATRABS, ePATRAL2, + ePATRAL3, eBAT, eBATROBE, eBATROBEKING, eGLEEOK1F, + //110 + eGLEEOK2F, eGLEEOK3F, eGLEEOK4F, eMWIZ, eDODONGOBS, + eDODONGOF, eTRIGGER, eBUBBLEIT, eBUBBLEIP, eBUBBLEIR, + //120 + eSTALFOS3, eGOHMA3, eGOHMA4, eNPCSTAND1, eNPCSTAND2, + eNPCSTAND3, eNPCSTAND4, eNPCSTAND5, eNPCSTAND6, eNPCWALK1, + //130 + eNPCWALK2, eNPCWALK3, eNPCWALK4, eNPCWALK5, eNPCWALK6, + eBOULDER, eGORIYA3, eLEV3, eOCTO3S, eOCTO3F, + //140 + eOCTO4S, eOCTO4F, eTRAP_8WAY, eTRAP_DIAGONAL, eTRAP_SLASH_C, + eTRAP_SLASH_LOS, eTRAP_BACKSLASH_C, eTRAP_BACKSLASH_LOS, eTRAP_CW_C, eTRAP_CW_LOS, + //150 + eTRAP_CCW_C, eTRAP_CCW_LOS, eSUMMONER, eIWIZ, eSHOOTMAGIC, + eSHOOTROCK, eSHOOTSPEAR, eSHOOTSWORD, eSHOOTFLAME, eSHOOTFLAME2, + //160 + eBOMBCHU, eFGEL, eFZOL, eFGELTRIB, eFZOLTRIB, + eTEK3, eSPINTILE1, eSPINTILE2, eLYNEL3, eFPEAHAT, + //170 + eMPOLSV, eWPOLSV, eDKNUT4, eFGHINI, eMGHINI, + eGRAPBUGHP, eGRAPBUGMP, e177, + + eMAXGUYS = MAXGUYS +}; + +enum enemyFamily +{ + eeGUY=0, eeWALK, + eeSHOOT/*DEPRECATED*/, + eeTEK, eeLEV, eePEAHAT, eeZORA, eeROCK, + eeGHINI, eeARMOS/*DEPRECATED*/, eeKEESE, eeGEL/*DEPRECATED*/, eeZOL/*DEPRECATED*/, eeROPE/*DEPRECATED*/, eeGORIYA/*DEPRECATED*/, eeTRAP, + eeWALLM, eeBUBBLE/*DEPRECATED*/, eeVIRE/*DEPRECATED*/, eeLIKE/*DEPRECATED*/, eePOLSV/*DEPRECATED*/, eeWIZZ, eeAQUA, eeMOLD, + eeDONGO, eeMANHAN, eeGLEEOK, eeDIG, eeGHOMA, eeLANM, eePATRA, eeGANON, + eePROJECTILE, eeGELTRIB/*DEPRECATED*/, eeZOLTRIB/*DEPRECATED*/, eeVIRETRIB/*DEPRECATED*/, eeKEESETRIB/*DEPRECATED*/, eeSPINTILE, eeNONE, + eeFAIRY, eeFIRE, eeOTHER, + eeMAX +}; + +enum enemyMisc1 +{ + e1tNORMAL, e1tEACHTILE, e1tCONSTANT, e1tHOMINGBRANG=2, + e1tFAST, e1tSLANT, e1t3SHOTS, e1t4SHOTS, + e1t5SHOTS, e1t3SHOTSFAST, e1tFIREOCTO, e1t8SHOTS, + e1tSUMMON, e1tSUMMONLAYER, e1tLAST +}; + +enum enemyMisc2 +{ + e2tNORMAL, e2tSPLITHIT, e2tKEESETRIB=1, e2tSPLIT, + e2tFIREOCTO, e2tBOMBCHU, e2tTRIBBLE, e2tLAST +}; + +enum enemyMisc7 +{ + e7tNORMAL, e7tTEMPJINX, e7tPERMJINX, e7tUNJINX, e7tTAKEMAGIC, e7tTAKERUPEES, e7tDRUNK, +// all from this point involve engulfing + e7tEATITEMS, e7tEATMAGIC, e7tEATRUPEES, e7tEATHURT, +// all from this point involve dragging + e7tWALLMASTER, e7tLAST +}; + +enum enemyMisc9 +{ + e9tNORMAL, e9tROPE, e9tVIRE, e9tPOLSVOICE, e9tARMOS, + // remainder unimplemented + e9tLEEVER, e9tZ3LEEVER, e9tZ3WALK, e9tZ3STALFOS, e9tLAST +}; + +enum enemyAnim +{ + aNONE, aFLIP, aUNUSED1, a2FRM, aUNUSED2, + aOCTO, aTEK, aLEV, aWALK, aZORA, + aNEWZORA, aGHINI, aARMOS, aROPE, aWALLM, + aNEWWALLM, aDWALK, aVIRE, a3FRM, aWIZZ, + aAQUA, aDONGO, aMANHAN, aGLEEOK, aDIG, + aGHOMA, aLANM, a2FRMPOS, a4FRM4EYE,a4FRM8EYE, + a4FRM4DIRF, a4FRM4DIR, a4FRM8DIRF, aARMOS4, a4FRMPOS4DIR, + a4FRMPOS8DIR, aUNUSED3, a4FRM8DIRB, aNEWTEK, a3FRM4DIR, + a2FRM4DIR, aNEWLEV, a2FRM4EYE, aNEWWIZZ, aNEWDONGO, + aDONGOBS, a4FRMPOS8DIRF, a4FRMPOS4DIRF, a4FRMNODIR, aGANON, a2FRMB, aMAX +}; +// deprecated styles +const int aFLIPSLOW = 1; +const int a2FRMSLOW = 3; +const int aNEWDWALK = 42; +const int aNEWPOLV = 39; +const int a4FRM3TRAP = 36; + +// Enemy flags +const uint guy_bhit = 0x00000001; +const uint guy_invisible = 0x00000002; +const uint guy_neverret = 0x00000004; +const uint guy_doesntcount = 0x00000008; +const uint guy_fadeflicker = 0x00000010; +const uint guy_fadeinstant = 0x00000020; +const uint inv_front = 0x01000000; +const uint inv_left = 0x02000000; +const uint inv_right = 0x04000000; +const uint inv_back = 0x08000000; +const uint guy_bkshield = 0x10000000; // Shield can't be broken +const uint lens_only = 0x80000000; + +// Enemy flags2 +const uint guy_flashing = 0x00000001; +const uint eneflag_zora = 0x00000002; +const uint eneflag_rock = 0x00000004; +const uint eneflag_trap = 0x00000008; +const uint cmbflag_trph = 0x00000010; +const uint cmbflag_trpv = 0x00000020; +const uint cmbflag_trp4 = 0x00000040; +const uint cmbflag_trplr = 0x00000080; +const uint cmbflag_trpud = 0x00000100; +const uint eneflag_trp2 = 0x00000200; +const uint eneflag_fire = 0x00000400; +const uint cmbflag_armos = 0x00000800; +const uint cmbflag_ghini = 0x00001000; +const uint eneflag_ganon = 0x00002000; +const uint guy_blinking = 0x00004000; +const uint guy_transparent = 0x00008000; + +enum fadeEffects +{ + fade_none, fade_flicker, fade_invisible, fade_flash_die, fade_blue_poof +}; + +enum itemSets +{ + isNONE, isDEFAULT, isBOMBS, isMONEY, isLIFE, isBOMB100, isSBOMB100, + isMAGIC, isMAGICBOMBS, isMAGICMONEY, isMAGICLIFE, isMAGIC2, isTALLGRASS, isMAX +}; + +enum items // value matters because of current quest file data +{ + iRupy, i5Rupies, iHeart, iBombs, iClock, + iSword, iWSword, iMSword, iShield, iKey, + // 10 + iBCandle, iRCandle, iLetter, iArrow, iSArrow, + iBow, iBait, iBRing, iRRing, iBracelet, + // 20 + iTriforce, iMap, iCompass, iBrang, iMBrang, + iWand, iRaft,iLadder,iHeartC, iBPotion, + // 30 + iRPotion, iWhistle,iBook, iMKey, iFairyMoving, + iFBrang, iXSword, iMShield, i20Rupies, i50Rupies, + // 40 + i200Rupies, iWallet500, iWallet999, iPile, iBigTri, + iSelectA, iMisc1, iMisc2, iSBomb, iHCPiece, + // 50 + iAmulet, iFlippers, iHookshot, iLens, iHammer, + iBoots, iL2Bracelet, iGArrow, iMagicC, iSMagic, + // 60 + iLMagic, iGRing, iKillAll, iL2Amulet, iDinsFire, + iFaroresWind, iNayrusLove, iBossKey, iBow2, iFairyStill, + // 70 + i1ArrowAmmo, i5ArrowAmmo, i10ArrowAmmo, i30ArrowAmmo, iQuiver, + iQuiverL2, iQuiverL3, i1BombAmmo, i4BombAmmo, i8BombAmmo, + // 80 + i30BombAmmo, iBombBag, iBombBagL2, iBombBagL3, iLevelKey, + iSelectB, i10Rupies, i100Rupies, iCByrna, iLongshot, + // 90 + iLetterUsed,iRocsFeather,iHoverBoots,iSShield,iSpinScroll, + iCrossScroll,iQuakeScroll,iL2QuakeScroll,iL2SpinScroll,iWhispRing, + // 100 + iL2WhispRing, iChargeRing, iL2ChargeRing, iPerilScroll, iWalletL3, + iQuiverL4, iBombBagL4, iOldGlove, iL2Ladder,iWealthMedal, + // 110 + iL2WealthMedal, iL3WealthMedal,iHeartRing, iL2HeartRing, iL3HeartRing, + iMagicRing, iL2MagicRing, iL3MagicRing, iL4MagicRing, iStoneAgony, + // 120 + iStompBoots, iPerilRing, iWhimsicalRing, + iCustom1, iCustom2, iCustom3, iCustom4, iCustom5, + iCustom6, iCustom7, iCustom8, iCustom9, iCustom10, + iCustom11, iCustom12, iCustom13, iCustom14, iCustom15, + iCustom16, iCustom17, iCustom18, iCustom19, iCustom20, + iLast, + iMax=256 +}; + +// Item flags +const int ITEM_GAMEDATA = 0x0001; // Whether this item sets the corresponding gamedata value or not +const int ITEM_EDIBLE = 0x0002; // can be eaten by Like Like +const int ITEM_COMBINE = 0x0004; // blue potion + blue potion = red potion +const int ITEM_DOWNGRADE = 0x0008; +const int ITEM_FLAG1 = 0x0010; +const int ITEM_FLAG2 = 0x0020; +const int ITEM_KEEPOLD = 0x0040; +const int ITEM_RUPEE_MAGIC = 0x0080; +const int ITEM_UNUSED = 0x0100; +const int ITEM_GAINOLD = 0x0200; +const int ITEM_FLAG3 = 0x0400; +const int ITEM_FLAG4 = 0x0800; +const int ITEM_FLAG5 = 0x1000; + +// Item pickup flags +const int ipBIGRANGE = 1; // Collision rectangle is large +const int ipHOLDUP = 2; // Link holds up item when he gets it +const int ipONETIME = 4; // Getting this item sets mITEM +const int ipDUMMY = 8; // Dummy item. Can't get this. +const int ipCHECK = 16; // Check restrictions (money in a shop, etc.) +const int ipMONEY = 32; // This item causes money loss (bomb upgrade, swindle room, etc.) +const int ipFADE = 64; // Blinks if fadeclk>0 +const int ipENEMY = 128; // Enemy is carrying it around +const int ipTIMER = 256; // Disappears after a while +const int ipBIGTRI = 512; // Large collision rectangle (used for large triforce) +const int ipNODRAW = 1024; // Don't draw this (for underwater items) +const int ipONETIME2 = 2048; // Getting this item sets mBELOW +const int ipSPECIAL = 4096; // This is the item in a Special Item room + + +// lvlitems flags +const int liTRIFORCE = 1; +const int liMAP = 2; +const int liCOMPASS = 4; +const int liBOSS = 8; +const int liBOSSKEY = 16; + + +enum spritePalettes +{ + spAQUA, spGLEEOK, spDIG, spGANON, spBROWN, spPILE, spBLUE, spRED, + spGOLD, spICON1, spICON2, spICON3, spICON4, spGLEEOKF, spFROZEN +}; + +enum secrets +{ + sBCANDLE, sARROW, sBOMB, sSTAIRS, sSECRET01, sSECRET02, sSECRET03, + sSECRET04, sSECRET05, sSECRET06, sSECRET07, sSECRET08, sSECRET09, + sSECRET10, sSECRET11, sSECRET12, sSECRET13, sSECRET14, sSECRET15, + sSECRET16, sRCANDLE, sWANDFIRE, sDINSFIRE, sSARROW, sGARROW, + sSBOMB, sBRANG, sMBRANG, sFBRANG, sWANDMAGIC, sREFMAGIC, sREFFIREBALL, + sSWORD, sWSWORD, sMSWORD, sXSWORD, sSWORDBEAM, sWSWORDBEAM, + sMSWORDBEAM, sXSWORDBEAM, sHOOKSHOT, sWAND, sHAMMER, sSTRIKE +}; + +enum decorations +{ + dBUSHLEAVES, dFLOWERCLIPPINGS, dGRASSCLIPPINGS, dHAMMERSMACK, + dTALLGRASS, dRIPPLES, dNAYRUSLOVESHIELD, dHOVER, dMAXDECORATIONS +} + +enum scriptTypes +{ + SCRIPT_GLOBAL, SCRIPT_FFC, SCRIPT_SCREEN, SCRIPT_LINK, SCRIPT_ITEM, + SCRIPT_LWPN, SCRIPT_NPC, SCRIPT_SUBSCREEN, SCRIPT_EWPN +} + +// Miscellaneous +const int DAMAGE_MULTIPLIER = 2; +const int csBOSS = 14; +const int TILES_PER_ROW = 20; + + +// Special enemy flags +const int asf_ALWAYSDIE = 0x0001; // Invincibility doesn't prevent death by ringleader +const int asf_PATRADEFENSE = 0x0002; // Center eye is invincible + +// Arguments to getGuyProp() +const int GUYPROP_FAMILY = 0; +const int GUYPROP_HP = 1; +const int GUYPROP_STEP = 2; +const int GUYPROP_MISC2 = 3; +const int GUYPROP_MISC9 = 4; +const int GUYPROP_MISC10 = 5; +const int GUYPROP_FLAGS2 = 6; +const int GUYPROP_BOSSPAL = 7; + +// Arguments to getItemProp() +enum itemProp +{ + ITEMPROP_FAMILY, ITEMPROP_LEVEL, ITEMPROP_POWER, ITEMPROP_MAGIC, + ITEMPROP_TILE, ITEMPROP_CSETS, ITEMPROP_SOUND, ITEMPROP_FLAGS, + ITEMPROP_MISC1, ITEMPROP_WPN2, ITEMPROP_PICKUP_SCRIPT +} + +// Arguments to getWeaponProp() +enum weaponProp +{ + WPNPROP_TILE, WPNPROP_CSETS, WPNPROP_FRAMES +} + +enum comboProp +{ + COMBOPROP_TYPE +} + +// Arguments to getComboClassProp() +enum comboClassProp +{ + CCPROP_BLOCK_ENEMIES +} + +// Link's actions +enum actiontype +{ + none, walking, attacking, freeze, landhold1, landhold2, + rafting, gothit, inwind, scrolling, won, swimming, hopping, + swimhit, waterhold1, waterhold2, casting, climbcovertop, + climbcoverbottom, dying, drowning, climbing, + // Fake actiontypes: used by ZScripts + ischarging, isspinning, isdiving +} + +int vbound(int num, int min, int max) +{ + if(nummax) + return max; + return num; +} + +float vbound(float num, float min, float max) +{ + if(nummax) + return max; + return num; +} + +fix vbound(fix num, fix min, fix max) +{ + if(nummax) + return max; + return num; +} + +int zc_min(int a, int b) +{ + return (ab) ? a : b; +} + +fix zc_max(fix a, fix b) +{ + return (a>b) ? a : b; +} + +fix distance(int x1, int y1, int x2, int y2) +{ + return fix(sqrt(pow(abs(x1-x2),2)+pow(abs(y1-y2),2))); +} + +int wpnsfx(int wpn) +{ + switch(wpn) + { + case ewFireTrail: + case ewFlame: + case ewFlame2Trail: + case ewFlame2: + return WAV_FIRE; + + case ewWind: + case ewMagic: + return WAV_WAND; + + case ewIce: + return WAV_ZN1ICE; + + case ewRock: + if(questRuleEnabled(qr_MORESOUNDS)) return WAV_ZN1ROCK; + + case ewFireball2: + case ewFireball: + if(questRuleEnabled(qr_MORESOUNDS)) return WAV_ZN1FIREBALL; + } + + return -1; +} + +int addenemy(int x, int y, int id, int clk) +{ + return addenemy(x, y, 0, id, clk); +} + +void never_return(int index) +{ + if(!questRuleEnabled(qr_KILLALL)) + { + setmapflag(mNEVERRET); + return; + } + + for(int i=0; i(__getGuy(index)); +} + +item@ loadItem(int index) +{ + return cast(__getItem(index)); +} + +weapon@ getEwpn(int index) +{ + return cast(__getEwpn(index)); +} + +int numEwpnsWithID(int id) +{ + int count=0; + for(int i=numEwpns()-1; i>=0; i--) + { + if(getEwpn(i).id==id) + count++; + } + return count; +} + +weapon@ getLwpn(int index) +{ + return cast(__getLwpn(index)); +} + +int idOfFirstLwpnOfType(int type) +{ + for(int i=0; i(__getLwpn(i)); + if(w.type==type) + return i; + } + + return -1; +} + +void additem(int x, int y, int id, int pickup, int clk=0) +{ + if(questRuleEnabled(qr_NOITEMOFFSET)) + y--; + placeitem(x, y, id, pickup, clk); +} + + +bool tooclose(int x,int y,int d) +{ + return (abs(int(LinkX())-x)=(frate>>1))?1:0); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + switch(dir-8) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case l_up: //d + flip=0; + tile+=8; + break; + + case l_down: //l + flip=0; + tile+=40; + break; + + case left: //r + flip=0; + tile+=48; + break; + + case r_down: //ul + flip=0; + tile+=80; + break; + + case down: //ur + flip=0; + tile+=88; + + break; + + case r_up: //dl + flip=0; + tile+=120; + break; + + case right: //dr + flip=0; + tile+=128; + break; + } + + tile+=(f2*2); + } + else + { + tile+=(f2!=0)?0:2; + flip=((clk&1)!=0)?1:0; + } + + xofs-=8; + yofs-=8; + drawblock(); + xofs+=8; + yofs+=8; + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + + if(wpnId==wWhistle && misc==0) + misc=1; + + return 0; + } +} + +class DigdoggerKid: enemy +{ + DigdoggerKid() + { + count_enemy=(id==(id&0xFFF)); + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(misc<=128) + { + misc+=1; + if((misc&31)==0) + step+=0.25; + } + + variable_walk_8(rate, homing, hrate, spw_floater); + return enemy::animate(index); + } + + void Draw() + { + tile = o_tile; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + int f2=questRuleEnabled(qr_NEWENEMYTILES)? + efrate:((clk>=(frate>>1))?1:0); + + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + switch(dir-8) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case l_up: //d + flip=0; + tile+=4; + break; + + case l_down: //l + flip=0; + tile+=8; + break; + + case left: //r + flip=0; + tile+=12; + break; + + case r_down: //ul + flip=0; + tile+=20; + break; + + case down: //ur + flip=0; + tile+=24; + break; + + case r_up: //dl + flip=0; + tile+=28; + break; + + case right: //dr + flip=0; + tile+=32; + break; + } + + tile+=f2; + } + else + { + tile+=(clk>=6)?1:0; + } + + enemy::draw(); + } +} diff --git a/output/common/angelscript/dodongo.as b/output/common/angelscript/dodongo.as new file mode 100644 index 0000000000..1aacbf39dc --- /dev/null +++ b/output/common/angelscript/dodongo.as @@ -0,0 +1,195 @@ +class Dodongo: enemy +{ + Dodongo() + { + fading=fade_flash_die; + + if(dir==down&&y>=128) + { + dir=up; + } + + if(dir==right&&x>=208) + { + dir=left; + } + } + + bool Update(int index) + { + if(dying) + { + return Dead(index); + } + + if(clk==0) + { + removearmos(x,y); + } + + if(clk2!=0) // ate a bomb + { + clk2-=1; + if(clk2==0) + hp-=misc; // store bomb's power in misc + } + else if(dmisc10!=1) // NES Dodongo + constant_walk(rate, homing, spw_clipright); + else // BS Dodongo + constant_walk(rate,homing,spw_clipbottomright); + + if(dmisc10!=1) + hxsz = (dir<=down) ? 16 : 32; + else + { + hxsz=(dir<=down) ? 16 : 32; + hysz=(dir>=left) ? 16 : 32; + hxofs=(dir>=left) ? -8 : 0; + hyofs=(dir0 || (superman!=0 && !(superman>1 && wpnId==wSBomb))) + return 0; + } + else + { + if(dying || clk<0 || clk2>0 || superman!=0) + return 0; + } + + switch(wpnId) + { + case wPhantom: + return 0; + + case wFire: + case wBait: + case wWhistle: + case wWind: + case wSSparkle: + case wFSparkle: + return 0; + + case wLitBomb: + case wLitSBomb: + if(abs(wpnx-getHitX()) > 7 || abs(wpny-getHitY()) > 7) + return 0; + + clk2=96; + misc=power; + + if(wpnId==wLitSBomb) + item_set=isSBOMB100; + + return 1; + case wBomb: + case wSBomb: + if(abs(wpnx-getHitX()) > 8 || abs(wpny-getHitY()) > 8) + return 0; + + stunclk=160; + misc=wpnId; // store wpnId + return 1; + case wSword: + if(stunclk!=0) + { + sfx(WAV_EHIT, x); + hp=0; + item_set = (misc==wSBomb) ? isSBOMB100 : isBOMB100; + fading=0; // don't flash + return 1; + } + + default: + sfx(WAV_CHINK, x); + } + + return 1; + } + + fix getHitX() + { + if(dmisc10!=1) + { + if(dir==right) + return x+16; + else + return x; + } + else + { + if(dir==left) + return x-8; + else if(dir==right) + return x+8; + else + return x; + } + } + + fix getHitY() + { + if(dmisc10!=1) + return y; + else + { + if(dir==up) + return y-8; + else if(dir==down) + return y+8; + else + return y; + } + } +} + diff --git a/output/common/angelscript/enemy.as b/output/common/angelscript/enemy.as new file mode 100644 index 0000000000..36a3b01a66 --- /dev/null +++ b/output/common/angelscript/enemy.as @@ -0,0 +1,2827 @@ +class enemy: sprite +{ + __RealEnemy@ realEnemy; + + enemy() + { + @realEnemy=__getRealEnemy(); + + clk3=0; + movestatus=0; + posframe=0; + dummy_int2=0; + dummy_int3=0; + dummy_bool0=false; + dummy_bool1=false; + dummy_bool2=false; + ox=0; + oy=0; + } + + // Properties ============================================================== + + int o_tile + { + get const { return realEnemy.o_tile; } + set { realEnemy.o_tile=value; } + } + + int frate + { + get const { return realEnemy.frate; } + set { realEnemy.frate=value; } + } + + int hp + { + get const { return realEnemy.hp; } + set { realEnemy.hp=value; } + } + + int hclk + { + get const { return realEnemy.hclk; } + set { realEnemy.hclk=value; } + } + + int clk3; + + int stunclk + { + get const { return realEnemy.stunclk; } + set { realEnemy.stunclk=value; } + } + + int fading + { + get const { return realEnemy.fading; } + set { realEnemy.fading=value; } + } + + int superman + { + get const { return realEnemy.superman; } + set { realEnemy.superman=value; } + } + + bool mainguy + { + get const { return realEnemy.mainguy; } + set { realEnemy.mainguy=value; } + } + + bool did_armos + { + get const { return realEnemy.did_armos; } + set { realEnemy.did_armos=value; } + } + + uint8 movestatus; + + uint8 item_set + { + get const { return realEnemy.item_set; } + set { realEnemy.item_set=value; } + } + + uint8 grumble + { + get const { return realEnemy.grumble; } + set { realEnemy.grumble=value; } + } + + uint8 posframe; + + bool itemguy + { + get const { return realEnemy.itemguy; } + set { realEnemy.itemguy=value; } + } + + bool count_enemy + { + get const { return realEnemy.count_enemy; } + set { realEnemy.count_enemy=value; } + } + + fix step + { + get const { return realEnemy.step; } + set { realEnemy.step=value; } + } + + fix floor_y + { + get const { return realEnemy.floor_y; } + set { realEnemy.floor_y=value; } + } + + bool dying + { + get const { return realEnemy.dying; } + set { realEnemy.dying=value; } + } + + bool ceiling + { + get const { return realEnemy.ceiling; } + set { realEnemy.ceiling=value; } + } + + bool leader + { + get const { return realEnemy.leader; } + set { realEnemy.leader=value; } + } + + bool scored + { + get const { return realEnemy.scored; } + set { realEnemy.scored=value; } + } + + bool script_spawned + { + get const { return realEnemy.script_spawned; } + set { realEnemy.script_spawned=value; } + } + + uint flags + { + get const { return realEnemy.flags; } + set { realEnemy.flags=value; } + } + + uint flags2 + { + get const { return realEnemy.flags2; } + set { realEnemy.flags2=value; } + } + + int16 family + { + get const { return realEnemy.family; } + set { realEnemy.family=value; } + } + + int16 dcset + { + get const { return realEnemy.dcset; } + set { realEnemy.dcset=value; } + } + + int16 anim + { + get const { return realEnemy.anim; } + set { realEnemy.anim=value; } + } + + int16 dp + { + get const { return realEnemy.dp; } + set { realEnemy.dp=value; } + } + + int16 wpn + { + get const { return realEnemy.wpn; } + set { realEnemy.wpn=value; } + } + + int16 rate + { + get const { return realEnemy.rate; } + set { realEnemy.rate=value; } + } + + int16 hrate + { + get const { return realEnemy.hrate; } + set { realEnemy.hrate=value; } + } + + int16 homing + { + get const { return realEnemy.homing; } + set { realEnemy.homing=value; } + } + + fix dstep + { + get const { return realEnemy.dstep; } + set { realEnemy.dstep=value; } + } + + int dmisc1 + { + get const { return realEnemy.dmisc1; } + set { realEnemy.dmisc1=value; } + } + + int dmisc2 + { + get const { return realEnemy.dmisc2; } + set { realEnemy.dmisc2=value; } + } + + int dmisc3 + { + get const { return realEnemy.dmisc3; } + set { realEnemy.dmisc3=value; } + } + + int dmisc4 + { + get const { return realEnemy.dmisc4; } + set { realEnemy.dmisc4=value; } + } + + int dmisc5 + { + get const { return realEnemy.dmisc5; } + set { realEnemy.dmisc5=value; } + } + + int dmisc6 + { + get const { return realEnemy.dmisc6; } + set { realEnemy.dmisc6=value; } + } + + int dmisc7 + { + get const { return realEnemy.dmisc7; } + set { realEnemy.dmisc7=value; } + } + + int dmisc8 + { + get const { return realEnemy.dmisc8; } + set { realEnemy.dmisc8=value; } + } + + int dmisc9 + { + get const { return realEnemy.dmisc9; } + set { realEnemy.dmisc9=value; } + } + + int dmisc10 + { + get const { return realEnemy.dmisc10; } + set { realEnemy.dmisc10=value; } + } + + int bgsfx + { + get const { return realEnemy.bgsfx; } + set { realEnemy.bgsfx=value; } + } + + int dummy_int1 // This one's still used for traps in C++... + { + get const { return realEnemy.dummy_int1; } + set { realEnemy.dummy_int1=value; } + } + + int dummy_int2, dummy_int3; + bool dummy_bool0, dummy_bool1, dummy_bool2; + + int clk2 + { + get const { return realEnemy.clk2; } + set { realEnemy.clk2=value; } + } + + int sclk + { + get const { return realEnemy.sclk; } + set { realEnemy.sclk=value; } + } + + int ox; + int oy; + + uint16 s_tile + { + get const { return realEnemy.s_tile; } + set { realEnemy.s_tile=value; } + } + + int scriptFlags + { + get const { return realEnemy.scriptFlags; } + set { realEnemy.scriptFlags=value; } + } + + // Methods ================================================================= + + // Supplemental animation code that all derived classes should call + // as a return value for animate(). + // Handles the death animation and returns true when enemy is finished. + bool Dead(int index) + { + if(dying) + { + clk2-=1; + + if(clk2==12 && hp>-1000) // not killed by ringleader + playDeathSFX(); + + if(clk2==0) + { + if((flags&guy_neverret)!=0) + never_return(index); + + if(leader) + kill_em_all(); + + leave_item(); + } + + stopBGSFX(); + return (clk2==0); + } + + return false; + } + + // Basic animation code that all derived classes should call. + // The one with an index is the one that is called by + // the guys sprite list; index is the enemy's index in the list. + bool animate(int index) + { + int nx = real_x(x); + int ny = real_y(y); + + if(ox!=nx || oy!=ny) + { + posframe=(posframe+1)%(questRuleEnabled(qr_NEWENEMYTILES)?4:2); + } + + ox = nx; + oy = ny; + + // Maybe they fell off the bottom in sideview, or were moved by a script. + if(OUTOFBOUNDS()) + hp=-1000; + + //fall down + if(canfall(id) && fading != fade_flicker && clk>=0) + { + if(screenFlagSet(fSIDEVIEW)) + { + if(!ON_SIDEPLATFORM()) + { + y+=fall/100; + + if(fall <= getTerminalVelocity()) + fall += getGravity(); + } + else + { + if(fall!=0) // Only fix pos once + y-=int(y)%8; // Fix position + + fall = 0; + } + } + else + { + if(fall!=0) + z-=(fall/100); + + if(z<0) + { + z = 0; + fall = 0; + } + else if(fall <= getTerminalVelocity()) + fall += getGravity(); + } + } + + // clk is incremented here + clk+=1; + if(clk >= frate) + clk=0; + + // hit and death handling + if(hclk>0) + hclk-=1; + + if(stunclk>0) + stunclk-=1; + + if(ceiling && z<=0) + ceiling = false; + + if(!dying && hp<=0) + { + if(itemguy && (hasitem&2)!=0) + { + for(int i=0; i0) ? false : sprite::hit(w); + } + + int takehit(weapon@ w) + { + return realEnemy.takehit(w.realWeapon); + } + + void move(fix dx,fix dy) + { + if(!watch && (!screenFlagSet(fSIDEVIEW) || ON_SIDEPLATFORM() || !canfall(id))) + { + x+=dx; + y+=dy; + } + } + + void move(fix s) + { + if(!watch && (!screenFlagSet(fSIDEVIEW) || ON_SIDEPLATFORM() || !canfall(id))) + sprite::move(s); + } + + void removearmos(int ax,int ay) + { + if(did_armos) + { + return; + } + + did_armos=true; + ax&=0xF0; + ay&=0xF0; + int cd = (ax>>4)+ay; + int f = MAPFLAG(ax,ay); + int f2 = MAPCOMBOFLAG(ax,ay); + mapscr@ tmpscr=getTmpscr(0); + + if(getComboProp(tmpscr.data[cd], COMBOPROP_TYPE)!=cARMOS) + { + return; + } + + tmpscr.data[cd] = tmpscr.undercombo; + tmpscr.cset[cd] = tmpscr.undercset; + tmpscr.sflag[cd] = 0; + + if(f == mfARMOS_SECRET || f2 == mfARMOS_SECRET) + { + tmpscr.data[cd] = tmpscr.secretcombo[sSTAIRS]; + tmpscr.cset[cd] = tmpscr.secretcset[sSTAIRS]; + tmpscr.sflag[cd]=tmpscr.secretflag[sSTAIRS]; + sfx(tmpscr.secretsfx); + } + + if(f == mfARMOS_ITEM || f2 == mfARMOS_ITEM) + { + if(!getmapflag()) + { + additem(ax,ay,tmpscr.catchall, (ipONETIME2 + ipBIGRANGE) | (screenFlagSet(fHOLDITEM) ? ipHOLDUP : 0)); + sfx(tmpscr.secretsfx); + } + } + + // WEIRDNESS + // This doesn't appear to do anything useful. + //putcombo(scrollbuf,ax,ay,tmpscr->data[cd],tmpscr->cset[cd]); + } + + void leave_item() + { + realEnemy.leave_item(); + } + + // returns true if Link is within 'range' pixels of the enemy + bool LinkInRange(int range) + { + int lx = Link.x; + int ly = Link.y; + return abs(lx-int(x))<=range && abs(ly-int(y))<=range; + } + + // place the enemy in line with Link (red wizzrobes) + void place_on_axis(bool floater, bool solid_ok) + { + int lx=zc_min(zc_max(int(Link.x)&0xF0,32),208); + int ly=zc_min(zc_max(int(Link.x)&0xF0,32),128); + int pos2=rand()%23; + int tried=0; + bool last_resort,placed=false; + + do + { + if(pos2<14) + { + x=(pos2<<4)+16; + y=ly; + } + else + { + x=lx; + y=((pos2-14)<<4)+16; + } + + // Don't commit to a last resort if position is out of bounds. + last_resort= !(x<32 || y<32 || x>=224 || y>=144); + + if(abs(lx-int(x))>16 || abs(ly-int(y))>16) + { + // Red Wizzrobes should be able to appear on water, but not other + // solid combos; however, they could appear on solid combos in 2.10, + // and some quests depend on that. + if((solid_ok || !m_walkflag(x,y,floater ? spw_water : spw_door)) + && !flyerblocked(x,y,floater ? spw_floater : spw_door)) + placed=true; + } + + if(!placed && tried>=22 && last_resort) + { + placed=true; + } + + ++tried; + pos2=(pos2+3)%23; + } + while(!placed); + + if(y==ly) + dir=(x=0) + { + tile=s_tile; + t=s_tile; + } + + break; + + case eeTRAP: + if(dummy_int1!=0 && (getGuyProp(id, GUYPROP_FLAGS2) & eneflag_trp2)!=0) // Just to make sure + { + tile=s_tile; + t=s_tile; + } + + break; + + case eeSPINTILE: + if(misc>=96) + { + tile=o_tile+frames*ndir; + t=tile; + } + + break; + } + + if(ndir!=0) switch(frames) + { + case 2: + tiledir_small(dir,ndir==4); + break; + + case 3: + tiledir_three(dir); + break; + + case 4: + tiledir(dir,ndir==4); + break; + } + + if(family==eeWALK) + tile=zc_min(tile+f4, t+frames*(zc_max(dir, 0)+1)-1); + else + tile+=f4; + } + + void tiledir_three(int ndir) + { + flip=0; + + switch(ndir) + { + case right: + tile+=3; // fallthrough + + case left: + tile+=3; // fallthrough + + case down: + tile+=3; // fallthrough + + case up: + break; + } + } + + void tiledir_small(int ndir, bool fourdir) + { + flip=0; + + switch(ndir) + { + case 8: + case up: + break; + + case 12: + case down: + tile+=2; + break; + + case 14: + case left: + tile+=4; + break; + + case 10: + case right: + tile+=6; + break; + + case 9: + case r_up: + if(fourdir) + break; + + tile+=10; + break; + + case 11: + case r_down: + if(fourdir) + tile+=2; + else + tile+=14; + + break; + + case 13: + case l_down: + if(fourdir) + tile+=2; + else + tile+=12; + + break; + + case 15: + case l_up: + if(fourdir) + break; + + tile+=8; + break; + + default: + break; + } + } + + void tiledir(int ndir, bool fourdir) + { + flip=0; + + switch(ndir) + { + case 8: + case up: + break; + + case 12: + case down: + tile+=4; + break; + + case 14: + case left: + tile+=8; + break; + + case 10: + case right: + tile+=12; + break; + + case 9: + case r_up: + if(fourdir) + break; + else + tile+=24; + + break; + + case 11: + case r_down: + if(fourdir) + tile+=4; + else + tile+=32; + + break; + + case 13: + case l_down: + if(fourdir) + tile+=4; + else + tile+=28; + + break; + + case 15: + case l_up: + if(fourdir) + break; + else + tile+=20; + + break; + + default: + break; + } + } + + void tiledir_big(int ndir, bool fourdir) + { + flip=0; + + switch(ndir) + { + case 8: + case up: + break; + + case 12: + case down: + tile+=8; + break; + + case 14: + case left: + tile+=40; + break; + + case 10: + case right: + tile+=48; + break; + + case 9: + case r_up: + if(fourdir) + break; + + tile+=88; + break; + + case 11: + case r_down: + if(fourdir) + tile+=8; + else + tile+=128; + + break; + + case 13: + case l_down: + if(fourdir) + tile+=8; + else + tile+=120; + + break; + + case 15: + case l_up: + if(fourdir) + break; + + tile+=80; + break; + + default: + break; + } + } + + void update_enemy_frame() + { + int newfrate = zc_max(frate,4); + int f4=clk/(newfrate/4); // casts clk to [0,1,2,3] + int f2=clk/(newfrate/2); // casts clk to [0,1] + int fx = questRuleEnabled(qr_NEWENEMYTILES) ? f4 : f2; + tile = o_tile; + int tilerows = 1; // How many rows of tiles? The Extend code needs to know. + + switch(anim) + { + case aDONGO: + { + int fr = stunclk>0 ? 16 : 8; + + if(!dying && clk2>0 && clk2<=64) + { + // bloated + switch(dir) + { + case up: + tile+=9; + flip=0; + xofs=0; + dummy_int1=0; //no additional tiles + break; + + case down: + tile+=7; + flip=0; + xofs=0; + dummy_int1=0; //no additional tiles + break; + + case left: + flip=1; + tile+=4; + xofs=16; + dummy_int1=1; //second tile is next tile + break; + + case right: + flip=0; + tile+=5; + xofs=16; + dummy_int1=-1; //second tile is previous tile + break; + } + } + else if(!dying || clk2>19) + { + // normal + switch(dir) + { + case up: + tile+=8; + flip=(clk&fr)!=0?1:0; + xofs=0; + dummy_int1=0; //no additional tiles + break; + + case down: + tile+=6; + flip=(clk&fr)!=0?1:0; + xofs=0; + dummy_int1=0; //no additional tiles + break; + + case left: + flip=1; + tile+=(clk&fr)!=0?2:0; + xofs=16; + dummy_int1=1; //second tile is next tile + break; + + case right: + flip=0; + tile+=(clk&fr)!=0?3:1; + xofs=16; + dummy_int1=-1; //second tile is next tile + break; + } + } + } + break; + + case aNEWDONGO: + { + int fr4=0; + + if(!dying && clk2>0 && clk2<=64) + { + // bloated + if(clk2>=0) + { + fr4=3; + } + + if(clk2>=16) + { + fr4=2; + } + + if(clk2>=32) + { + fr4=1; + } + + if(clk2>=48) + { + fr4=0; + } + + switch(dir) + { + case up: + xofs=0; + tile+=8+fr4; + dummy_int1=0; //no additional tiles + break; + + case down: + xofs=0; + tile+=12+fr4; + dummy_int1=0; //no additional tiles + break; + + case left: + tile+=29+(2*fr4); + xofs=16; + dummy_int1=-1; //second tile is previous tile + break; + + case right: + tile+=49+(2*fr4); + xofs=16; + dummy_int1=-1; //second tile is previous tile + break; + } + } + else if(!dying || clk2>19) + { + // normal + switch(dir) + { + case up: + xofs=0; + tile+=((clk&12)>>2); + dummy_int1=0; //no additional tiles + break; + + case down: + xofs=0; + tile+=4+((clk&12)>>2); + dummy_int1=0; //no additional tiles + break; + + case left: + tile+=21+((clk&12)>>1); + xofs=16; + dummy_int1=-1; //second tile is previous tile + break; + + case right: + flip=0; + tile+=41+((clk&12)>>1); + xofs=16; + dummy_int1=-1; //second tile is previous tile + break; + } + } + } + break; + + case aDONGOBS: + { + int fr4=0; + + if(!dying && clk2>0 && clk2<=64) + { + // bloated + if(clk2>=0) + { + fr4=3; + } + + if(clk2>=16) + { + fr4=2; + } + + if(clk2>=32) + { + fr4=1; + } + + if(clk2>=48) + { + fr4=0; + } + + switch(dir) + { + case up: + tile+=28+fr4; + yofs+=8; + dummy_int1=-20; //second tile change + dummy_int2=0; //new xofs change + dummy_int3=-16; //new xofs change + break; + + case down: + tile+=12+fr4; + yofs-=8; + dummy_int1=20; //second tile change + dummy_int2=0; //new xofs change + dummy_int3=16; //new xofs change + break; + + case left: + tile+=49+(2*fr4); + xofs+=8; + dummy_int1=-1; //second tile change + dummy_int2=-16; //new xofs change + dummy_int3=0; //new xofs change + break; + + case right: + tile+=69+(2*fr4); + xofs+=8; + dummy_int1=-1; //second tile change + dummy_int2=-16; //new xofs change + dummy_int3=0; //new xofs change + break; + } + } + else if(!dying || clk2>19) + { + // normal + switch(dir) + { + case up: + tile+=20+((clk&24)>>3); + yofs+=8; + dummy_int1=-20; //second tile change + dummy_int2=0; //new xofs change + dummy_int3=-16; //new xofs change + break; + + case down: + tile+=4+((clk&24)>>3); + yofs-=8; + dummy_int1=20; //second tile change + dummy_int2=0; //new xofs change + dummy_int3=16; //new xofs change + break; + + case left: + xofs=-8; + tile+=40+((clk&24)>>2); + dummy_int1=1; //second tile change + dummy_int2=16; //new xofs change + dummy_int3=0; //new xofs change + break; + + case right: + tile+=60+((clk&24)>>2); + xofs=-8; + dummy_int1=1; //second tile change + dummy_int2=16; //new xofs change + dummy_int3=0; //new xofs change + break; + } + } + } + break; + + case aWIZZ: + { + if(dmisc1!=0) + { + if((clk&8)!=0) + { + tile+=1; + } + } + else + { + if((frame&4)!=0) + { + tile+=1; + } + } + + switch(dir) + { + case 9: + case 15: + case up: + tile+=2; + break; + + case down: + break; + + case 13: + case left: + flip=1; + break; + + default: + flip=0; + break; + } + } + break; + + case aNEWWIZZ: + { + tiledir(dir,true); + + if(dmisc1!=0) //walking wizzrobe + { + if((clk&8)!=0) + { + tile+=2; + } + + if((clk&4)!=0) + { + tile+=1; + } + + if(!(dummy_bool1||dummy_bool2)) //should never be charging or firing for these wizzrobes + { + if(dummy_int1>0) + { + tile+=40; + } + } + } + else + { + if(dummy_bool1||dummy_bool2) + { + tile+=20; + + if(dummy_bool2) + { + tile+=20; + } + } + + tile+=((frame>>1)&3); + } + } + break; + + case a3FRM: + { + n_frame_n_dir(3, 0, (f4==3) ? 1 : f4); + } + break; + + case a3FRM4DIR: + { + n_frame_n_dir(3, 4, (f4==3) ? 1 : f4); + } + break; + + case aVIRE: + { + if(dir==up) + { + tile+=2; + } + + tile+=fx; + } + break; + + case aROPE: + { + tile+=(1-fx); + flip = dir==left ? 1:0; + } + break; + + case aZORA: + { + int dl; + + if(clk<36) + { + dl=clk+5; + tile=((dl/11)&1)+s_tile; + break; + } + + if(clk<36+66) + tile=(dir==up)?o_tile+1:o_tile; + else + { + dl=clk-36-66; + tile=((dl/11)&1)+s_tile; + } + } + break; + + case aNEWZORA: + { + f4=(clk/16)%4; + + tiledir(dir,true); + int dl; + + if((clk>35)&&(clk<36+67)) //surfaced + { + if((clk>=(35+10))&&(clk<(38+56))) //mouth open + { + tile+=80; + } //mouth closed + else + { + tile+=40; + } + + tile+=f4; + } + else + { + if(clk<36) + { + dl=clk+5; + } + else + { + dl=clk-36-66; + } + + tile+=((dl/5)&3); + } + } + break; + + case a4FRM4EYE: + case a2FRM4EYE: + case a4FRM8EYE: + { + tilerows = 2; + double ddir=atan2(y-Link.y, Link.x-x); + int lookat=rand()&15; + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + lookat=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + lookat=down; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + lookat=r_down; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + lookat=right; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + lookat=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + lookat=up; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + lookat=l_up; + } + else + { + lookat=left; + } + + int dir2 = dir; + dir = lookat; + n_frame_n_dir(anim==a2FRM4EYE ? 2:4, anim==a4FRM8EYE ? 8 : 4, anim==a2FRM4EYE ? (f2&1):f4); + dir = dir2; + } + break; + + case aFLIP: + { + flip = f2&1; + } + break; + + case a2FRM: + { + tile += (1-f2); + } + break; + + case a2FRMB: + { + tile+= 2*(1-f2); + } + break; + + case a2FRM4DIR: + { + n_frame_n_dir(2, 4, f2&1); + } + break; + + case a4FRM4DIRF: + { + n_frame_n_dir(4,4,f4); + + if(clk2>0) //stopped to fire + { + tile+=20; + + if(clk2<17) //firing + { + tile+=20; + } + } + } + break; + + case a4FRM4DIR: + { + n_frame_n_dir(4,4,f4); + } + break; + + case a4FRM8DIRF: + { + tilerows = 2; + n_frame_n_dir(4,8,f4); + + if(clk2>0) //stopped to fire + { + tile+=40; + + if(clk2<17) //firing + { + tile+=40; + } + } + } + break; + + case a4FRM8DIRB: + { + tilerows = 2; + tiledir_big(dir,false); + tile+=2*f4; + } + break; + + case aOCTO: + { + switch(dir) + { + case up: + flip = 2; + break; + + case down: + flip = 0; + break; + + case left: + flip = 0; + tile += 2; + break; + + case right: + flip = 1; + tile += 2; + break; + } + + tile+=f2; + } + break; + + case aWALK: + { + switch(dir) + { + case up: + tile+=3; + flip = f2; + break; + + case down: + tile+=2; + flip = f2; + break; + + case left: + flip=1; + tile += f2; + break; + + case right: + flip=0; + tile += f2; + break; + } + } + break; + + case aDWALK: + { + if(questRuleEnabled(qr_BRKNSHLDTILES) && dummy_bool1) + { + tile=s_tile; + } + + switch(dir) + { + case up: + tile+=2; + flip=f2; + break; + + case down: + flip=0; + tile+=(1-f2); + break; + + case left: + flip=1; + tile+=(3+f2); + break; + + case right: + flip=0; + tile+=(3+f2); + break; + } + } + break; + + case aTEK: + { + if(misc==0) + { + tile += f2; + } + else if(misc!=1) + { + tile+=1; + } + } + break; + + case aNEWTEK: + { + if(step<0) //up + { + switch(clk3) + { + case left: + flip=0; + tile+=20; + break; + + case right: + flip=0; + tile+=24; + break; + } + } + else if(step==0) + { + switch(clk3) + { + case left: + flip=0; + tile+=8; + break; + + case right: + flip=0; + tile+=12; + break; + } + } //down + else + { + switch(clk3) + { + case left: + flip=0; + tile+=28; + break; + + case right: + flip=0; + tile+=32; + break; + } + } + + if(misc==0) + { + tile+=f4; + } + else if(misc!=1) + { + tile+=2; + } + } + break; + + case aARMOS: + { + if(fading==0) + { + tile += fx; + + if(dir==up) + tile += 2; + } + } + break; + + case aARMOS4: + { + switch(dir) + { + case up: + flip=0; + break; + + case down: + flip=0; + tile+=4; + break; + + case left: + flip=0; + tile+=8; + break; + + case right: + flip=0; + tile+=12; + break; + } + + if(fading==0) + { + tile+=f4; + } + } + break; + + case aGHINI: + { + switch(dir) + { + case 8: + case 9: + case up: + tile+=1; + flip=0; + break; + + case 15: + tile+=1; + flip=1; + break; + + case 10: + case 11: + case right: + flip=1; + break; + + default: + flip=0; + break; + } + } + break; + + case a2FRMPOS: + { + tile+=posframe; + } + break; + + case a4FRMPOS4DIR: + { + n_frame_n_dir(4,4,0); + tile+=posframe; + } + break; + + case a4FRMPOS4DIRF: + { + n_frame_n_dir(4,4,0); + + if(clk2>0) //stopped to fire + { + tile+=20; + + if(clk2<17) //firing + { + tile+=20; + } + } + + tile+=posframe; + } + break; + + case a4FRMPOS8DIR: + { + tilerows = 2; + n_frame_n_dir(4,8,0); + tile+=posframe; + } + break; + + case a4FRMPOS8DIRF: + { + tilerows = 2; + n_frame_n_dir(4,8,f4); + + if(clk2>0) //stopped to fire + { + tile+=40; + + if(clk2<17) //firing + { + tile+=40; + } + } + + tile+=posframe; + } + break; + + case aNEWLEV: + { + tiledir(dir,true); + + switch(misc) + { + case -1: + case 0: + return; + + case 1: + + case 5: + cs = dmisc2; + break; + + case 2: + case 4: + tile += 20; + break; + + case 3: + tile += 40; + break; + } + + tile+=f4; + } + break; + + case aLEV: + { + f4 = ((clk/5)&1); + + switch(misc) + { + case -1: + case 0: + return; + + case 1: + + case 5: + tile += (f2!=0) ? 1 : 0; + cs = dmisc2; + break; + + case 2: + case 4: + tile += 2; + break; + + case 3: + tile += (f4!=0) ? 4 : 3; + break; + } + } + break; + + case aWALLM: + { + if(!dummy_bool1) + { + tile += f2; + } + } + break; + + case aNEWWALLM: + { + int tempdir=0; + + switch(misc) + { + case 1: + case 2: + tempdir=clk3; + break; + + case 3: + case 4: + case 5: + tempdir=dir; + break; + + case 6: + case 7: + tempdir=clk3^1; + break; + } + + tiledir(tempdir,true); + + if(!dummy_bool1) + { + tile+=f4; + } + } + break; + + case a4FRMNODIR: + { + tile+=f4; + } + break; + + } // switch(d->anim) + + // flashing + if((flags2 & guy_flashing)!=0) + { + cs = (frame&3) + 6; + } + + if((flags2&guy_transparent)!=0) + { + drawstyle=1; + } + + int change = tile-o_tile; + + if(extend > 2) + { + if(o_tile/TILES_PER_ROW==(o_tile+((txsz*change)/tilerows))/TILES_PER_ROW) + { + tile=o_tile+txsz*change; + } + else + { + tile=o_tile+(txsz*change)+((tysz-1)*TILES_PER_ROW)*((o_tile+txsz*change)/TILES_PER_ROW)-(o_tile/TILES_PER_ROW); + } + } + else + { + tile=o_tile+change; + } + } + + void fireWeapon() + { + realEnemy.fireWeapon(); + } + + bool isFiring() const + { + return realEnemy.isFiring(); + } + + void updateFiring() + { + realEnemy.updateFiring(); + } + + void setBreathTimer(int time) + { + realEnemy.setBreathTimer(time); + } + + void setAttackOwner(int index) + { + realEnemy.setAttackOwner(index); + } + + void activateDeathAttack() + { + realEnemy.activateDeathAttack(); + } + + int defenditemclass(int wpnId, int power) + { + return realEnemy.defenditemclass(wpnId, power); + } + + int getDefendedItemPower() + { + return realEnemy.getDefendedItemPower(); + } + + bool dont_draw() + { + if(fading==fade_invisible || (((flags2&guy_blinking)!=0||(fading==fade_flicker)) && (clk&1)!=0)) + return true; + + if((flags&guy_invisible)!=0) + return true; + + if((flags&lens_only)!=0 && lensclk==0) + return true; + + return false; + } + void draw() + { + realEnemy.draw(); + } + + void drawshadow() + { + realEnemy.drawshadow(); + } + + void drawblock() + { + realEnemy.drawblock(); + } + + void masked_draw(int mx, int my, int mw, int mh) + { + realEnemy.masked_draw(mx, my, mw, mh); + } + + void overtilecloaked16(int tile, int x, int y, int flip) + { + realEnemy.overtilecloaked16(tile, x, y, flip); + } + + void overtile16(int tile, int x, int y, int cset, int flip) + { + realEnemy.overtile16(tile, x, y, cset, flip); + } + + void stopBGSFX() + { + realEnemy.stopBGSFX(); + } + + void playDeathSFX() + { + realEnemy.playDeathSFX(); + } + + void playHitSFX(int x) + { + realEnemy.playHitSFX(x); + } + + bool canmove(int ndir, fix s, int special, int dx1, int dy1, int dx2, int dy2) + { + return realEnemy.canmove(ndir, s, special, dx1, dy1, dx2, dy2); + } + + bool canmove(int ndir,fix s,int special) + { + return realEnemy.canmove(ndir, s, special, 0, -8, 15, 15); + } + + bool canmove(int ndir,int special) + { + bool dodongo_move=true; //yes, it's an ugly hack, but we're going to rewrite everything later anyway - DN + + if(special==spw_clipright && ndir==right) + dodongo_move=realEnemy.canmove(ndir, 1, special, 0, -8, 31, 15); + + return dodongo_move && realEnemy.canmove(ndir, 1, special, 0, -8, 15, 15); + } + + bool canmove(int ndir) + { + return realEnemy.canmove(ndir, 1, spw_none, 0, -8, 15, 15); + } + + // makes the enemy slide backwards when hit + // sclk: first byte is clk, second byte is dir + bool slide() + { + if(sclk==0 || hp<=0) + return false; + + if((sclk&255)==16 && !canmove(sclk>>8, 12, 0)) + { + sclk=0; + return false; + } + + sclk-=1; + + switch(sclk>>8) + { + case up: + if(y<=16) + { + sclk=0; + return false; + } + + break; + + case down: + if(y>=160) + { + sclk=0; + return false; + } + + break; + + case left: + if(x<=16) + { + sclk=0; + return false; + } + + break; + + case right: + if(x>=240) + { + sclk=0; + return false; + } + + break; + } + + switch(sclk>>8) + { + case up: + y-=4; + break; + + case down: + y+=4; + break; + + case left: + x-=4; + break; + + case right: + x+=4; + break; + } + + if(!canmove(sclk>>8, 0, 0)) + { + switch(sclk>>8) + { + case up: + case down: + if((int(y)&15) > 7) + y=(int(y)&0xF0)+16; + else + y=(int(y)&0xF0); + + break; + + case left: + case right: + if((int(x)&15) > 7) + x=(int(x)&0xF0)+16; + else + x=(int(x)&0xF0); + + break; + } + + sclk=0; + } + + if((sclk&255)==0) + sclk=0; + + return true; + } + + // changes enemy's direction, checking restrictions + // rate: 0 = no random changes, 16 = always random change + // homing: 0 = none, 256 = always + // grumble 0 = none, 4 = strongest appetite + void newdir(int newrate, int newhoming, int special) + { + int ndir=-1; + + if(grumble!=0 && uint8(rand()&3)=0) + { + weapon@ bait=getLwpn(w); + int bx = bait.x; + int by = bait.y; + + if(abs(int(y)-by)>14) + { + ndir = (by=0 && canmove(ndir,special)) + { + dir=ndir; + return; + } + } + + int i=0; + + for(; i<32; i++) + { + int r=rand(); + + if((r&15)>4)&3; + else + ndir=dir; + + if(canmove(ndir,special)) + break; + } + + if(i==32) + { + for(ndir=0; ndir<4; ndir++) + { + if(canmove(ndir,special)) + { + dir=ndir; + return; + } + } + + ndir = screenFlagSet(fSIDEVIEW) ? ((rand()&1)!=0 ? left : right) : -1; // Sideview enemies get trapped if their dir becomes -1 + } + + dir=ndir; + } + + void newdir() + { + newdir(4, 0, spw_none); + } + + void fix_coords(bool bound=false) + { + if(bound) + { + x=vbound(x, 0, 240); + y=vbound(y, 0, 160); + } + + if(!OUTOFBOUNDS()) + { + x=(int(x)&0xF0)+((int(x)&8)!=0?16:0); + + if(screenFlagSet(fSIDEVIEW)) + y=(int(y)&0xF8)+((int(y)&4)!=0?8:0); + else + y=(int(y)&0xF0)+((int(y)&8)!=0?16:0); + } + } + + /* + // 8-directional + void newdir_8(int newrate, int newhoming, int special, int dx1, int dy1, int dx2, int dy2) + { + realEnemy.newdir_8(newrate, newhoming, special, dx1, dy1, dx2, dy2); + } + */ + + // 8-directional + void newdir_8(int newrate, int newhoming, int special, int dx1, int dy1, int dx2, int dy2) + { + int ndir=0; + + // can move straight, check if it wants to turn + if(canmove(dir,step,special,dx1,dy1,dx2,dy2)) + { + if(grumble!=0 && uint8(rand()&4)=0) + { + weapon@ bait=getLwpn(w); + int bx = bait.x; + int by = bait.y; + + ndir = (bx14) + { + if(ndir>0) // Already left or right + { + // Making the diagonal directions + ndir += (by=0 && canmove(ndir,special)) + { + dir=ndir; + } + + return; + } + + int r=rand(); + + if(newrate>0 && (r%newrate)==0) + { + ndir = ((dir+(((r&64)!=0)?-1:1))&7)+8; + int ndir2=((dir+(((r&64)!=0)?1:-1))&7)+8; + + if(canmove(ndir,step,special,dx1,dy1,dx2,dy2)) + dir=ndir; + else if(canmove(ndir2,step,special,dx1,dy1,dx2,dy2)) + dir=ndir2; + + if(dir==ndir && (newrate>=4)) // newrate>=4, otherwise movement is biased toward upper-left + // due to numerous lost fractional components. -L + { + x.vAND(0xFFFF0000); + y.vAND(0xFFFF0000); + } + } + + return; + } + + // can't move straight, must turn + int i=0; + + for(; i<32; i++) // Try random dir + { + ndir=(rand()&7)+8; + + if(canmove(ndir,step,special,dx1,dy1,dx2,dy2)) + break; + } + + if(i==32) + { + for(ndir=8; ndir<16; ndir++) + { + if(canmove(ndir,step,special,dx1,dy1,dx2,dy2)) + { + dir=ndir; + x.vAND(0xFFFF0000); + y.vAND(0xFFFF0000); + return; + } + } + + ndir = screenFlagSet(fSIDEVIEW) ? (rand()&1)!=0 ? left : right : -1; // Sideview enemies get trapped if their dir becomes -1 + } + + dir=ndir; + x.vAND(0xFFFF0000); + y.vAND(0xFFFF0000); + } + + void newdir_8(int newrate, int newhoming, int special) + { + newdir_8(newrate, newhoming, special, 0, -8, 15, 15); + } + + // keeps walking around + void constant_walk(int newrate, int newhoming, int special) + { + if(slide()) + return; + + if(clk<0 || dying || stunclk!=0 || watch || ceiling) + return; + + if(clk3<=0) + { + fix_coords(true); + newdir(newrate, newhoming, special); + + if(step==0) + clk3=0; + else + clk3=int(16.0/step); + } + else if(scored) + { + dir^=1; + clk3=int(16.0/step)-clk3; + } + + clk3-=1; + move(step); + } + + void constant_walk() + { + constant_walk(4, 0, spw_none); + } + + int pos(int newx, int newy) + { + return (newy<<8)+newx; + } + + // for variable step rates + void variable_walk(int newrate, int newhoming, int special) + { + if(slide()) + return; + + if(clk<0 || dying || stunclk!=0 || watch || step==0 || ceiling) + return; + + fix dx = 0; + fix dy = 0; + + switch(dir) + { + case 8: + case up: + dy-=step; + break; + + case 12: + case down: + dy+=step; + break; + + case 14: + case left: + dx-=step; + break; + + case 10: + case right: + dx+=step; + break; + + case 15: + case l_up: + dx-=step; + dy-=step; + break; + + case 9: + case r_up: + dx+=step; + dy-=step; + break; + + case 13: + case l_down: + dx-=step; + dy+=step; + break; + + case 11: + case r_down: + dx+=step; + dy+=step; + break; + } + + if(((int(x)&15)==0 && (int(y)&15)==0 && clk3!=pos(x,y)) || + m_walkflag(int(x+dx),int(y+dy), spw_halfstep)) + { + fix_coords(); + newdir(newrate,newhoming,special); + clk3=pos(x,y); + } + + move(step); + } + + // pauses for a while after it makes a complete move (to a new square) + void halting_walk(int newrate, int newhoming, int special, int newhrate, int haltcnt) + { + if(sclk!=0 && clk2!=0) + { + clk3=0; + } + + if(slide() || clk<0 || dying || stunclk!=0 || watch || ceiling) + { + return; + } + + if(clk2>0) + { + clk2-=1; + return; + } + + if(clk3<=0) + { + fix_coords(true); + newdir(newrate,newhoming,special); + clk3=int(16.0/step); + + if(clk2<0) + { + clk2=0; + } + else if((rand()&15)=p) + { + movestatus=1; + clk2=0; + } + + break; + + case 1: // speeding up + if(clk248 && (rand()%768)==0) + { + step=ss*s; + movestatus=3; + clk2=0; + } + + break; + + case 3: // slowing down + if(clk2<=g*s) + { + if((clk2%g)==0) + step-=ss; + } + else + { + movestatus=0; + step=0; + clk2=0; + } + + break; + } + + variable_walk_8((movestatus==2)?newrate:0,homing,newclk,spw_floater); + } + + void floater_walk(int newrate, int newclk, fix s) + { + floater_walk(newrate, newclk, s, 0.125, 3, 80, 32); + } + + // Checks if enemy is lined up with Link. If so, returns direction Link is + // at as compared to enemy. Returns -1 if not lined up. Range is inclusive. + int lined_up(int range, bool dir8) + { + int lx = Link.x; + int ly = Link.y; + + if(abs(lx-int(x))<=range) + { + if(ly((screenFlagSet(fSIDEVIEW) && canfall(id))?192:352) || y<-176 || x<-256 || x > 512); + } +} // End enemy class + + +bool isjumper(int id) +{ + switch(getGuyProp(id, GUYPROP_FAMILY)) + { + case eeROCK: + case eeTEK: + return true; + + case eeWALK: + if(getGuyProp(id, GUYPROP_MISC9)==e9tVIRE || getGuyProp(id, GUYPROP_MISC9)==e9tPOLSVOICE) + return true; + } + + return false; +} + + +bool isfixedtogrid(int id) +{ + switch(getGuyProp(id, GUYPROP_FAMILY)) + { + case eeWALK: + case eeLEV: + case eeZORA: + case eeDONGO: + case eeGANON: + case eeROCK: + case eeGLEEOK: + case eeAQUA: + case eeLANM: + return true; + } + + return false; +} + +// Can't fall, can have Z value. +bool isflier(int id) +{ + switch(getGuyProp(id, GUYPROP_FAMILY)) + { + case eePEAHAT: + case eeKEESE: + case eePATRA: + case eeFAIRY: + case eeGHINI: + + // Could theoretically have their Z set by a script + case eeFIRE: + return true; + } + + return false; +} + +// Can't have Z position +bool never_in_air(int id) +{ + switch(getGuyProp(id, GUYPROP_FAMILY)) + { + case eeMANHAN: + case eeMOLD: + case eeLANM: + case eeGLEEOK: + case eeZORA: + case eeLEV: + case eeAQUA: + case eeROCK: + case eeGANON: + case eeTRAP: + case eePROJECTILE: + case eeSPINTILE: + return true; + } + + return false; +} + + +bool canfall(int id) +{ + switch(getGuyProp(id, GUYPROP_FAMILY)) + { + case eeGUY: + { + if(id < eOCTO1S) + return false; + + switch(getGuyProp(id, GUYPROP_MISC10)) + { + case 1: + case 2: + return true; + + case 0: + case 3: + default: + return false; + } + } + case eeGHOMA: + case eeDIG: + return false; + } + + return !never_in_air(id) && !isflier(id) && !isjumper(id); +} + +// Returns true iff enemy is floating and blocked by a combo type or flag. +bool flyerblocked(int dx, int dy, int special) +{ + return ((special==spw_floater)&& + ((COMBOTYPE(dx,dy)==cNOFLYZONE)|| + (getComboClassProp(COMBOTYPE(dx,dy), CCPROP_BLOCK_ENEMIES)&4)!=0|| + (MAPFLAG(dx,dy)==mfNOENEMY)|| + (MAPCOMBOFLAG(dx,dy)==mfNOENEMY))); +} + +// For Link's hit detection. Don't count them if they are stunned or are guys. +int GuyHit(int tx,int ty,int tz,int txsz,int tysz,int tzsz) +{ + for(int i=0; i 0) + return -1; + + bool d = e.dying; + int hc = e.hclk; + e.dying = false; + e.hclk = 0; + bool hit = e.hit(tx,ty,tz,txsz,tysz,tzsz); + e.dying = d; + e.hclk = hc; + + return hit ? index : -1; +} + diff --git a/output/common/angelscript/fairy.as b/output/common/angelscript/fairy.as new file mode 100644 index 0000000000..40ced96b40 --- /dev/null +++ b/output/common/angelscript/fairy.as @@ -0,0 +1,36 @@ +class Fairy: enemy +{ + Fairy() + { + step=getGuyProp(id, GUYPROP_STEP)/100; + superman=1; + dir=8; + hxofs=1000; + mainguy=false; + count_enemy=false; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + misc=1; + bool w=watch; + watch=false; + variable_walk_8((misc!=0) ? 3 : 0, 0, 8, spw_floater); + watch=w; + + if(clk==0) + { + removearmos(x,y); + } + + return enemy::animate(index); + } + + void Draw() + { + // Nothin'. + } +} diff --git a/output/common/angelscript/fallingRock.as b/output/common/angelscript/fallingRock.as new file mode 100644 index 0000000000..05e8a77cdb --- /dev/null +++ b/output/common/angelscript/fallingRock.as @@ -0,0 +1,175 @@ +class FallingRock: enemy +{ + private bool small; + private int bounceDir; + private int drawDir; + + FallingRock() + { + clk=0; + mainguy=false; + clk2=-14; + + if(dmisc10!=1) + { + small=true; + hxofs=-2; + hyofs=-2; + hxsz=20; + hysz=20; + } + else + { + small=false; + hxofs=-10; + hyofs=-10; + hxsz=36; + hysz=36; + hzsz=16; //can't be jumped + } + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + clk2+=1; + if(clk2==0) // start it + { + x=rand()&0xF0; + y=small ? 0 : -32; + clk3=0; + clk2=rand()&15; + } + + if(clk2>16) // move it + { + if(clk3<=0) // start bounce + { + if(x<32) + dir=1; + else if(x>208) + dir=0; + else + dir=rand()&1; + } + + if(clk3<29) + { + x+=(dir==1) ? 1 : -1; //right, left + bounceDir=dir; + + if(clk3<2) + { + y-=2; //up + drawDir=(bounceDir==1)?r_up:l_up; + } + else if(clk3<5) + { + y--; //up + drawDir=(bounceDir==1)?r_up:l_up; + } + else if(clk3<8) + { + drawDir=(bounceDir==1)?right:left; + } + else if(clk3<11) + { + y++; //down + drawDir=(bounceDir==1)?r_down:l_down; + } + else + { + y+=2; //down + drawDir=(bounceDir==1)?r_down:l_down; + } + + clk3+=1; + } + else if(y<176) + clk3=0; // next bounce + else + clk2 = -(rand()&63); // back to top + } + + return enemy::animate(index); + } + + void Draw() + { + if(clk2<0) + return; + + int tempdir=dir; + dir=drawDir; + update_enemy_frame(); + if(small) + enemy::draw(); + else + { + xofs-=8; + yofs-=8; + drawblock(); + xofs+=8; + yofs+=8; + } + dir=tempdir; + } + + void DrawShadow() + { + if(clk2<0) + return; + + if(small) + { + int tempy=yofs; + flip = 0; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + int f2=questRuleEnabled(qr_NEWENEMYTILES) ? + efrate : ((clk>=(frate>>1))?1:0); + shadowtile=getSpriteTile(iwShadow)+f2; + + yofs+=8; + yofs+=vbound(clk3, 0, 29-clk3); + enemy::drawshadow(); + yofs=tempy; + } + else + { + int tempy=yofs; + flip = 0; + int f2=((clk<<2)/frate)<<1; + shadowtile=getSpriteTile(iwLargeShadow)+f2; + yofs+=vbound(clk3, 0, 29-clk3); + + yofs+=8; + xofs-=8; + enemy::drawshadow(); + xofs+=16; + shadowtile+=1; + enemy::drawshadow(); + yofs+=16; + shadowtile+=20; + enemy::drawshadow(); + xofs-=16; + shadowtile-=1; + enemy::drawshadow(); + xofs+=8; + yofs=tempy; + } + } + + int takehit(weapon@ w) + { + return 0; + } +} + diff --git a/output/common/angelscript/fire.as b/output/common/angelscript/fire.as new file mode 100644 index 0000000000..108bc9de70 --- /dev/null +++ b/output/common/angelscript/fire.as @@ -0,0 +1,97 @@ +class Fire: enemy +{ + int clk4; + bool shield; + + Fire() + { + clk4=0; + shield=(flags&(inv_left | inv_right | inv_back |inv_front))!=0; + + // Spawn type + if((flags & guy_fadeflicker)!=0) + { + clk=0; + superman = 1; + fading=fade_flicker; + count_enemy=false; + dir=down; + + if(!canmove(down,8,spw_none)) + clk3=int(13.0/step); + } + else if((flags & guy_fadeinstant)!=0) + { + clk=0; + } + } + + bool Update(int index) + { + if(fading!=0) + { + if(++clk4 > 60) + { + clk4=0; + superman=0; + fading=0; + + if((flags2&cmbflag_armos)!=0 && z==0) + removearmos(x,y); + + clk2=0; + + if(!canmove(down,8,spw_none)) + { + dir=0; + y.vAND(0xF00000); + } + + return Dead(index); + } + else if((flags2&cmbflag_armos)!=0 && z==0 && clk==0) + removearmos(x,y); + } + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + int wpnDir = w.dir; + + if(wpnId==wHammer && shield && (flags & guy_bkshield)!=0 + && (((flags&inv_front)!=0 && wpnDir==(dir^down)) || ((flags&inv_back)!=0 && wpnDir==(dir^up)) + || ((flags&inv_left)!=0 && wpnDir==(dir^left)) || ((flags&inv_right)!=0 && wpnDir==(dir^right)))) + { + shield = false; + flags &= ~(inv_left|inv_right|inv_back|inv_front); + + if(questRuleEnabled(qr_BRKNSHLDTILES)) + o_tile=s_tile; + } + + int ret = enemy::takehit(w); + return ret; + } + + void break_shield() + { + if(!shield) + return; + + flags&=~(inv_front | inv_back | inv_left | inv_right); + shield=false; + + if(questRuleEnabled(qr_BRKNSHLDTILES)) + o_tile=s_tile; + } +} + diff --git a/output/common/angelscript/ganon.as b/output/common/angelscript/ganon.as new file mode 100644 index 0000000000..0b21f7b672 --- /dev/null +++ b/output/common/angelscript/ganon.as @@ -0,0 +1,214 @@ +class Ganon: enemy +{ + int ganonstunclk; + + Ganon() + { + hxofs=8; + hyofs=8; + hzsz=16; //can't be jumped. + clk2=70; + misc=-1; + ganonstunclk=0; + mainguy=!getmapflag(); + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + switch(misc) + { + case -1: + misc=0; + + case 0: + clk2+=1; + if(clk2>72 && (rand()&3)==0) + { + fireWeapon(); + clk2=0; + } + + ganonstunclk=0; + constant_walk(rate,homing,spw_none); + break; + + case 1: + case 2: + if(--ganonstunclk<=0) + { + int r=rand(); + + if((r&1)!=0) + { + y=96; + + if((r&2)!=0) + x=160; + else + x=48; + + if(tooclose(x,y,48)) + x=208-x; + } + + loadpalset(csBOSS, pSprite(getGuyProp(id, GUYPROP_BOSSPAL))); + misc=0; + } + + break; + + case 3: + if(hclk>0) + break; + + misc=4; + clk=0; + hxofs=1000; + loadpalset(9, pSprite(spPILE)); + music_stop(); + stop_sfx(WAV_ROAR); + + playDeathSFX(); + + sfx(WAV_GANON); + placeitem(x+8, y+8, iPile, ipDUMMY); + break; + + case 4: + if(clk>=80) + { + misc=5; + + if(getmapflag()) + { + setLevelItem(dlevel, liBOSS); + playLevelMusic(); + return true; + } + + sfx(WAV_CLEARED); + placeitem(x+8, y+8, iBigTri, ipBIGTRI); + setmapflag(); + } + + break; + } + + return enemy::animate(index); + } + + + int takehit(weapon@ w) + { + //these are here to bypass compiler warnings about unused arguments + int wpnId = w.id; + int power = w.power; + int enemyHitWeapon = w.parentitem; + + switch(misc) + { + case 0: + if(wpnId!=wSword) + return 0; + + hp-=power; + + if(hp>0) + { + misc=1; + ganonstunclk=64; + } + else + { + loadpalset(csBOSS, pSprite(spBROWN)); + misc=2; + ganonstunclk=284; + hp=getGuyProp(id, GUYPROP_HP); + } + + sfx(WAV_EHIT, x); + playHitSFX(x); + + return 1; + + case 2: + if(wpnId!=wArrow || (enemyHitWeapon>-1 ? getItemProp(enemyHitWeapon, ITEMPROP_POWER) : current_item_power(itype_arrow))<4) + return 0; + + misc=3; + hclk=81; + loadpalset(9, pSprite(spBROWN)); + return 1; + } + + return 0; + } + + void Draw() + { + switch(misc) + { + case 0: + if((clk&3)==3) + tile=(rand()%5)*2+o_tile; + + if(db!=999) + break; + + case 2: + if(ganonstunclk<64 && (ganonstunclk&1)!=0) + break; + + case -1: + tile=o_tile; + + //fall through + case 1: + case 3: + drawblock(); + break; + + case 4: + draw_guts(); + draw_flash(); + break; + } + } + + void draw_guts() + { + int c = zc_min(clk>>3,8); + tile = clk<24 ? 74 : 75; + overtile16(tile,x+8,y+c+playing_field_offset,9,0); + overtile16(tile,x+8,y+16-c+playing_field_offset,9,0); + overtile16(tile,x+c,y+8+playing_field_offset,9,0); + overtile16(tile,x+16-c,y+8+playing_field_offset,9,0); + overtile16(tile,x+c,y+c+playing_field_offset,9,0); + overtile16(tile,x+16-c,y+c+playing_field_offset,9,0); + overtile16(tile,x+c,y+16-c+playing_field_offset,9,0); + overtile16(tile,x+16-c,y+16-c+playing_field_offset,9,0); + } + + void draw_flash() + { + int c = clk-(clk>>2); + cs = (frame&3)+6; + overtile16(194,x+8,y+8-clk+playing_field_offset,cs,0); + overtile16(194,x+8,y+8+clk+playing_field_offset,cs,2); + overtile16(195,x+8-clk,y+8+playing_field_offset,cs,0); + overtile16(195,x+8+clk,y+8+playing_field_offset,cs,1); + overtile16(196,x+8-c,y+8-c+playing_field_offset,cs,0); + overtile16(196,x+8+c,y+8-c+playing_field_offset,cs,1); + overtile16(196,x+8-c,y+8+c+playing_field_offset,cs,2); + overtile16(196,x+8+c,y+8+c+playing_field_offset,cs,3); + } +} + diff --git a/output/common/angelscript/ghini.as b/output/common/angelscript/ghini.as new file mode 100644 index 0000000000..d1d28bebd7 --- /dev/null +++ b/output/common/angelscript/ghini.as @@ -0,0 +1,54 @@ +class Ghini: enemy +{ + int clk4; + + Ghini() + { + scriptFlags= asf_ALWAYSDIE; + + fading=fade_flicker; + count_enemy=false; + dir=12; + movestatus=1; + step=0; + clk=0; + clk4=0; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(dmisc1!=0) + { + if(misc!=0) + { + if(clk4>160) + misc=2; + + floater_walk((misc==1)?0:rate,hrate,dstep/100.0,dstep/1000.0,10,120,10); + removearmos(x,y); + } + else if(clk4>=60) + { + misc=1; + clk3=32; + fading=0; + setGuyGridAt(x, y, 0); + removearmos(x,y); + } + } + + clk4++; + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } +} + diff --git a/output/common/angelscript/gleeok.as b/output/common/angelscript/gleeok.as new file mode 100644 index 0000000000..bf456099aa --- /dev/null +++ b/output/common/angelscript/gleeok.as @@ -0,0 +1,492 @@ +class Gleeok: enemy +{ + int necktile; + + Gleeok() + { + x=120; + y=48; + + hzsz = 32; // can't be jumped. + misc=clk; // total head count + clk3=clk; // live head count + clk=0; + clk2=60; // fire ball clock + hp=getGuyProp(id, GUYPROP_MISC2)*(misc-1)*DAMAGE_MULTIPLIER+getGuyProp(id, GUYPROP_HP); + dir = down; + hxofs=4; + hxsz=8; + fading=fade_blue_poof; + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + necktile=o_tile+dmisc6; + } + else + { + necktile=s_tile; + } + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + // Check if a head was killed somehow... + if(index+1+clk3>=numGuys()) + clk3=numGuys()-index-1; + if(index+1+misc>=numGuys()) + misc=numGuys()-index-1; + + //fix for the "kill all enemies" item + if(hp==-1000) + { + for(int i=0; i72 && (rand()&3)==0) + { + int i=rand()%misc; + setAttackOwner(index+i+1); + fireWeapon(); + clk2=0; + } + } + else + { + clk2+=1; + if(clk2>100 && (rand()&3)==0) + { + enemy@ head = getGuy(rand()%misc+index+1); + head.fireWeapon(); + clk2=0; + } + } + + if(hp<=0) + { + for(int i=0; i>3); + } + + if(hp > 0 && !dont_draw()) + { + if(screenFlagSet(fINVISROOM) && current_item(itype_amulet)==0) + sprite::drawcloaked(); + else + sprite::draw(); + } + } +} + +class GleeokHead: enemy +{ + array nx, ny; //neck x and y? + int headtile; + int flyingheadtile; + int necktile; + Gleeok@ parent; //parent Gleeok to whose neck this segment is attached + fix xoffset, yoffset; //coords relative to the parent Gleeok + array nxoffset, nyoffset; //random "jiggling" of the next tiles + + GleeokHead() + { + // Find parent first + for(int i=numGuys()-1; i>=0; i--) + { + @parent=cast(getGuy(i)); + if(parent !is null) + break; + } + + // Any chance parent is null here? That would be bad... + + xoffset=0; + yoffset=dmisc5*4+2; + // fixing + hp=1000; + step=1; + item_set=0; + x = xoffset+parent.x; + y = yoffset+parent.y; + hxofs=4; + hxsz=8; + yofs=playing_field_offset; + clk2=clk; // how long to wait before moving first time + clk=0; + mainguy=false; + count_enemy=false; + dir=rand(); + clk3=((dir&2)>>1)+2; // left or right + dir&=1; // up or down + dmisc5=vbound(dmisc5,1,255); + + for(int i=0; i>3); + } + + switch(misc) + { + case 0: // live head + // set up the attached head tiles + tile=headtile; + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + tile+=((clk&24)>>3); + } + + clk2+=1; + if(clk2>=0 && (clk2&3)==0) + { + if(y<= int(parent.y) + 8) dir=down; + + if(y>= int(parent.y) + dmisc5*8) dir = up; + + if(y<= int(parent.y) + 10 && (rand()&31)==0) + { + dir^=1; + } + + fix tempx = x; + fix tempy = y; + + sprite::move(step); + xoffset += (x-tempx); + yoffset += (y-tempy); + + if(clk2>=4) + { + clk3^=1; + clk2=-4; + } + else + { + if(x <= int(parent.x)-(dmisc5*6)) + { + clk3=right; + } + + if(x >= int(parent.x)+(dmisc5*6)) + { + clk3=left; + } + + if(y <= int(parent.y)+(dmisc5*6) && (rand()&15)==0) + { + clk3^=1; // x jig + } + else + { + if(y<=int(parent.y)+(dmisc5*4) && (rand()&31)==0) + { + clk3^=1; // x switch back + } + + clk2=-4; + } + } + + int temp=dir; + dir=clk3; + clk3=temp; + tempx = x; + tempy = y; + sprite::move(step); + xoffset += (x-tempx); + yoffset += (y-tempy); + temp=dir; + dir=clk3; + clk3=temp; + + for(int i=1; i=0) + + { + variable_walk_8(rate,homing,hrate,spw_floater); + } + + break; + + // the following are messages sent from the main guy... + case -1: // got chopped off + { + misc=1; + superman=1; + hxofs=0; + xofs=0; + hxsz=16; + cs=8; + clk=-24; + clk2=40; + dir=(rand()&7)+8; + step=8.0/9.0; + } + break; + + case -2: // the big guy is dead + return true; + } + + updateFiring(); + + return enemy::animate(index); + } + + int takehit(weapon@ w) + { + int ret = enemy::takehit(w); + + if(ret==-1) + return 2; // force it to wait a frame before checking sword attacks again + + return ret; + } + + void Draw() + { + switch(misc) + { + case 0: //neck + if(!dont_draw()) + { + for(int i=1; i>3); + break; + } + } + } + + void Draw2() + { + enemy::draw(); + } +} diff --git a/output/common/angelscript/gohma.as b/output/common/angelscript/gohma.as new file mode 100644 index 0000000000..ee8f505d1c --- /dev/null +++ b/output/common/angelscript/gohma.as @@ -0,0 +1,164 @@ +class Gohma: enemy +{ + int clk4; + + Gohma() + { + x=128; + y=48; + clk=0; + + hxofs=-16; + hxsz=48; + clk4=0; + yofs=playing_field_offset+1; + dir=rand()%3+1; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + // Movement clk must be separate from animation clk because of the Clock item + if(!watch) + clk4++; + + if((clk4&63)==0) + { + if((clk4&64)!=0) + dir^=1; + else + dir=rand()%3+1; + } + + if(dmisc1!=2) + { + if((clk&63)==3) + fireWeapon(); + } + else if(clk3>=16 && clk3<116) // Breath + updateFiring(); + + if((clk4&1)!=0) + move(1); + + clk3+=1; + if(clk3>=400) + { + clk3=0; + + if(dmisc1==2) + // Reset for the next cycle + setBreathTimer(104); + } + + return enemy::animate(index); + } + + void Draw() + { + tile=o_tile; + + if(clk<0 || dying) + { + enemy::draw(); + return; + } + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + // left side + xofs=-16; + flip=0; + tile+=(3*((clk&48)>>4)); + enemy::draw(); + + // right side + xofs=16; + tile=o_tile; + tile+=(3*((clk&48)>>4))+2; + enemy::draw(); + + // body + xofs=0; + tile=o_tile; + + if(clk3<16) + tile+=7; + else if(clk3<116) + tile+=10; + else if(clk3<132) + tile+=7; + else + tile+=(((clk3-132)&24)!=0)?4:1; + + enemy::draw(); + + } + else + { + // left side + xofs=-16; + flip=0; + + if((clk&16)==0) + { + tile+=2; + flip=1; + } + + enemy::draw(); + + // right side + tile=o_tile; + xofs=16; + + if((clk&16)!=0) tile+=2; + + enemy::draw(); + + // body + tile=o_tile; + xofs=0; + + if(clk3<16) + tile+=4; + else if(clk3<116) + tile+=5; + else if(clk3<132) + tile+=4; + else tile+=(((clk3-132)&8)!=0)?3:1; + + enemy::draw(); + + } + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + int wpnx = w.x; + int wpnDir = w.dir; + + // Really got to come up with a better way to handle this... + int def = defenditemclass(wpnId, w.power); + int power = getDefendedItemPower(); + + if(def < 0) + { + if(!((wpnDir==up || wpnDir==l_up || wpnDir==r_up) && abs(int(x)-wpnx)<=8 && clk3>=16 && clk3<116)) + { + sfx(WAV_CHINK, x); + return 1; + } + } + + return enemy::takehit(w); + } +} diff --git a/output/common/angelscript/guy.as b/output/common/angelscript/guy.as new file mode 100644 index 0000000000..9e5edf86ea --- /dev/null +++ b/output/common/angelscript/guy.as @@ -0,0 +1,61 @@ +class Guy: enemy +{ + // good guys, fires, fairy, and other non-enemies + // based on enemy class b/c guys in dungeons act sort of like enemies + // also easier to manage all the guys this way + Guy() + { + mainguy=(id&0x8000)!=0; + id&=0xFFF; + canfreeze=false; + dir=down; + yofs=playing_field_offset; + hxofs=2; + hzsz=8; + hxsz=12; + hysz=17; + + if(superman==0 && (!isdungeon() || id==gFAIRY || id==gFIRE || id==gZELDA)) + { + superman = 1; + hxofs=1000; + } + } + + bool Update(int index) + { + if(mainguy && clk==0 && misc==0) + { + setupscreen(); + misc = 1; + } + + if(mainguy && fadeclk==0) + return true; + + hp=256; // good guys never die... + + if(hclk!=0 && clk2==0) + { + // but if they get hit... + clk2+=1; // only do this once + + if(!questRuleEnabled(qr_NOGUYFIRES)) + { + addenemy(BSZ?64:72,68,eSHOOTFBALL,0); + addenemy(BSZ?176:168,68,eSHOOTFBALL,0); + } + } + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + + if(!mainguy || fadeclk<0 || (fadeclk&1)!=0) + enemy::draw(); + } +} + diff --git a/output/common/angelscript/item.as b/output/common/angelscript/item.as new file mode 100644 index 0000000000..ec797697a2 --- /dev/null +++ b/output/common/angelscript/item.as @@ -0,0 +1,22 @@ +class item: sprite +{ + __RealItem@ realItem; + + item() + { + @realItem=__getRealItem(); + } + + int pickup + { + get const { return realItem.pickup; } + set { realItem.pickup=value; } + } + + int clk2 + { + get const { return realItem.clk2; } + set { realItem.clk2=value; } + } +} + diff --git a/output/common/angelscript/keese.as b/output/common/angelscript/keese.as new file mode 100644 index 0000000000..5b7dffbc3c --- /dev/null +++ b/output/common/angelscript/keese.as @@ -0,0 +1,100 @@ +class Keese: enemy +{ + int clk4; + + Keese() + { + dir=(rand()&7)+8; + step=0; + movestatus=1; + hxofs=2; + hxsz=12; + hyofs=4; + hysz=8; + clk4=0; + dummy_int1=0; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(dmisc1!=0) + { + floater_walk(rate, hrate, dstep/100, 0, 10, 0, 0); + } + else + { + floater_walk(rate, hrate, dstep/100, dstep/1000, 10, 120, 16); + } + + if(dmisc2 == e2tKEESETRIB) + { + if(++clk4==256) + { + if(!m_walkflag(x, y, 0)) + { + int kids = numGuys(); + bool success = false; + int id2=dmisc3; + success = 0 != addenemy(x, y, id2, -24); + + if(success) + { + if(itemguy) // Hand down the carried item + { + guycarryingitem = numGuys()-1; + enemy@ en=getGuy(guycarryingitem); + en.itemguy = true; + itemguy = false; + } + + enemy@ en=getGuy(kids); + en.count_enemy = count_enemy; + } + + return true; + } + else + { + clk4=0; + } + } + } + // Keese Tribbles stay on the ground, so there's no problem when they transform. + else if(questRuleEnabled(qr_ENEMIESZAXIS) && !screenFlagSet(fSIDEVIEW)) + { + z=int(step/(dstep/100.0)); + // Some variance in keese flight heights when away from Link + z+=int(step*zc_max(0,(distance(x,y,LinkX(),LinkY())-128)/10)); + } + + return enemy::animate(index); + } + + void DrawShadow() + { + int tempy=yofs; + flip = 0; + shadowtile = getSpriteTile(iwShadow)+posframe; + yofs+=8; + + if(!questRuleEnabled(qr_ENEMIESZAXIS)) + yofs+=int(step/(dstep/1000.0)); + + enemy::drawshadow(); + yofs=tempy; + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } +} diff --git a/output/common/angelscript/lanmola.as b/output/common/angelscript/lanmola.as new file mode 100644 index 0000000000..5523f828d3 --- /dev/null +++ b/output/common/angelscript/lanmola.as @@ -0,0 +1,334 @@ +class LanmolaBase: enemy +{ + array prevStateX; + array prevStateY; + array prevStateDir; + + void pushFrontX(fix x) + { + prevStateX.insertAt(0, x); + } + + void pushBackX(fix x) + { + prevStateX.insertLast(x); + } + + fix getFrontX() + { + return prevStateX[0]; + } + + fix popFrontX() + { + fix ret=prevStateX[0]; + prevStateX.removeAt(0); + return ret; + } + + void pushFrontY(fix y) + { + prevStateY.insertAt(0, y); + } + + void pushBackY(fix y) + { + prevStateY.insertLast(y); + } + + fix getFrontY() + { + return prevStateY[0]; + } + + fix popFrontY() + { + fix ret=prevStateY[0]; + prevStateY.removeAt(0); + return ret; + } + + void pushFrontDir(int dir) + { + prevStateDir.insertAt(0, dir); + } + + void pushBackDir(int dir) + { + prevStateDir.insertLast(dir); + } + + int getFrontDir() + { + return prevStateDir[0]; + } + + int popFrontDir() + { + int ret=prevStateDir[0]; + prevStateDir.removeAt(0); + return ret; + } +} + +class LanmolaController: LanmolaBase +{ + int segcnt; + + LanmolaController() + { + x=64; + y=80; + dir=up; + superman=1; + fading=fade_invisible; + hxofs=1000; + segcnt=clk; + clk=0; + + //set up move history + for(int i=0; i <= (1<, int>(std::pair(x,y), dir)); + + // This could cause a crash with Moldorms. I didn't see the same problem + // with Lanmolas, but it looks like it ought to be possible, so here's + // the same solution. - Saf + if(index+segcnt>=numGuys()) + segcnt=numGuys()-index-1; + + for(int i=index+1; i=0) + { + hxofs=4; + + if(!watch) + { + // TODO: Maybe try not to crash if the previous enemy isn't actually a Lanmola part for some reason + LanmolaBase@ prev=cast(getGuy(index-1)); + x=prev.getFrontX(); + y=prev.getFrontY(); + dir=prev.getFrontDir(); + popFrontX(); + popFrontY(); + popFrontDir(); + pushBackX(x); + pushBackY(y); + pushBackDir(dir); + } + } + + return enemy::animate(index); + } + + int takehit(weapon@ w) + { + if(enemy::takehit(w)!=0) + return (w.id==wSBomb) ? 1 : 2; // force it to wait a frame before checking sword attacks again + + return 0; + } + + void Draw() + { + tile=o_tile; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + + int f2=questRuleEnabled(qr_NEWENEMYTILES)? + efrate:((clk>=(frate>>1))?1:0); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + if(id>=0x2000) + { + tile+=20; + + if(dummy_int1==1) + { + tile+=20; + } + } + + switch(dir) + { + case up: + flip=0; + break; + + case down: + flip=0; + tile+=4; + break; + + case left: + flip=0; + tile+=8; + break; + + case right: + flip=0; + tile+=12; + break; + } + + tile+=f2; + } + else + { + if(id>=0x2000) + { + tile+=1; + } + } + + if(clk>=0) + enemy::draw(); + } +} diff --git a/output/common/angelscript/leever.as b/output/common/angelscript/leever.as new file mode 100644 index 0000000000..a98d125f53 --- /dev/null +++ b/output/common/angelscript/leever.as @@ -0,0 +1,221 @@ +class Leever: enemy +{ + Leever() + { + if(dmisc1==0) + { + misc=-1; //Line of Sight leevers + clk-=16; + } + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(clk>=0 && !slide()) + { + switch(dmisc1) + { + case 0: //line of sight + case 2: + switch(misc) //is this leever active + { + case -1: //submerged + { + if((dmisc1==2)&&(rand()&255)!=0) + { + break; + } + + int active=0; + + for(int i=0; i=0) + { + ++active; + } + } + + if(active<((dmisc1==2)?1:2)) + { + misc=0; //activate this one + } + } + break; + + case 0: + { + int s=0; + + for(int i=0; i0) + { + break; + } + + int d2=rand()&1; + + if(LinkDir()>=left) + { + d2+=2; + } + + if(canplace(d2) || canplace(d2^1)) + { + misc=1; + clk2=0; + clk=0; + } + } + break; + + case 1: + clk2+=1; + if(clk2>16) misc=2; + + break; + + case 2: + clk2+=1; + if(clk2>24) misc=3; + + break; + + // case 3: if(stunclk) break; if(scored) dir^=1; if(!canmove(dir)) misc=4; else move((fix)(d->step/100.0)); break; + case 3: + if(stunclk!=0) break; + + if(scored) dir^=1; + + if(!canmove(dir)) misc=4; + else move(dstep/100.0); + + break; + + case 4: + clk2-=1; + if(clk2==16) + { + misc=5; + clk=8; + } + + break; + + case 5: + clk2-=1; + if(clk2==0) misc=((dmisc1==2)?-1:0); + + break; + } // switch(misc) + + break; + + default: //random + step=dmisc3/100.0; + clk2+=1; + + if(clk2<32) misc=1; + else if(clk2<48) misc=2; + else if(clk2<300) + { + misc=3; + step = dstep/100.0; + } + else if(clk2<316) misc=2; + else if(clk2<412) misc=1; + else if(clk2<540) + { + misc=0; + step=0; + } + else clk2=0; + + if(clk2==48) clk=0; + + variable_walk(rate, homing, 0); + } // switch(dmisc1) + } + + hxofs=(misc>=2)?0:1000; + return enemy::animate(index); + } + + bool canplace(int d2) + { + int nx=LinkX(); + int ny=LinkY(); + + if(d2=left) + if(m_walkflag(LinkX(),LinkY(),spw_halfstep)||m_walkflag(LinkX(),LinkY()-8,spw_halfstep)) /*none*/ + return false; + + x=nx; + y=ny; + dir=d2^1; + return true; + } + + void Draw() + { + cs=dcset; + update_enemy_frame(); + + switch(misc) + { + case -1: + case 0: + return; + } + + enemy::draw(); + } +} diff --git a/output/common/angelscript/link.as b/output/common/angelscript/link.as new file mode 100644 index 0000000000..6e9163484e --- /dev/null +++ b/output/common/angelscript/link.as @@ -0,0 +1,1648 @@ +const int SWORDCHARGEFRAME = 20; +const int SWORDTAPFRAME = SWORDCHARGEFRAME-8; +const int HAMMERCHARGEFRAME = 11; +const int WANDCHARGEFRAME = 12; + +class LinkClass: sprite +{ + __RealLink@ realLink; + + LinkClass() + { + @realLink=__getRealLink(); + @Link=this; + } + + // Properties ============================================================== + + // Used in checking slashable/poundable/etc. combos to remember + // if a combo or FFC was already hit. + array screengrid(176); + array ffcgrid(32); + + bool tapping + { + get const { return realLink.tapping; } + set { realLink.tapping=value; } + } + + bool stomping + { + get const { return realLink.stomping; } + set { realLink.stomping=value; } + } + + int ladderx + { + get const { return realLink.ladderx; } + set { realLink.ladderx=value; } + } + + int laddery + { + get const { return realLink.laddery; } + set { realLink.laddery=value; } + } + + int charging + { + get const { return realLink.charging; } + set { realLink.charging=value; } + } + + int spins + { + get const { return realLink.spins; } + set { realLink.spins=value; } + } + + int drunkclk + { + get const { return realLink.drunkclk; } + set { realLink.drunkclk=value; } + } + + int hoverclk + { + get const { return realLink.hoverclk; } + set { realLink.hoverclk=value; } + } + + int hclk + { + get const { return realLink.hclk; } + set { realLink.hclk=value; } + } + + int attackclk + { + get const { return realLink.attackclk; } + set { realLink.attackclk=value; } + } + + int attack + { + get const { return realLink.attack; } + set { realLink.attack=value; } + } + + int attackid + { + get const { return realLink.attackid; } + set { realLink.attackid=value; } + } + + int drownclk + { + get const { return realLink.drownclk; } + set { realLink.drownclk=value; } + } + + int slashxofs + { + get const { return realLink.slashxofs; } + set { realLink.slashxofs=value; } + } + + int slashyofs + { + get const { return realLink.slashyofs; } + set { realLink.slashyofs=value; } + } + + uint8 hopclk + { + get const { return realLink.hopclk; } + set { realLink.hopclk=value; } + } + + uint8 diveclk + { + get const { return realLink.diveclk; } + set { realLink.diveclk=value; } + } + + uint8 inlikelike + { + get const { return realLink.inlikelike; } + set { realLink.inlikelike=value; } + } + + int shiftdir + { + get const { return realLink.shiftdir; } + set { realLink.shiftdir=value; } + } + + int sdir + { + get const { return realLink.sdir; } + set { realLink.sdir=value; } + } + + int hopdir + { + get const { return realLink.hopdir; } + set { realLink.hopdir=value; } + } + + int holddir + { + get const { return realLink.holddir; } + set { realLink.holddir=value; } + } + + int landswim + { + get const { return realLink.landswim; } + set { realLink.landswim=value; } + } + + bool ilswim + { + get const { return realLink.ilswim; } + set { realLink.ilswim=value; } + } + + bool walkable + { + get const { return realLink.walkable; } + set { realLink.walkable=value; } + } + + int action + { + get const { return realLink.action; } + set { realLink.action=value; } + } + + fix climb_cover_x + { + get const { return realLink.climb_cover_x; } + set { realLink.climb_cover_x=value; } + } + + fix climb_cover_y + { + get const { return realLink.climb_cover_y; } + set { realLink.climb_cover_y=value; } + } + + fix falling_oldy + { + get const { return realLink.falling_oldy; } + set { realLink.falling_oldy=value; } + } + + bool diagonalMovement + { + get const { return realLink.diagonalMovement; } + set { realLink.diagonalMovement=value; } + } + + // Methods ================================================================= + + // Temporary return values: + // 0: Keep going + // 1: Return true + // 2: Return false + int Update() + { + // Here we go... + + if(action!=climbcovertop&&action!=climbcoverbottom) + { + climb_cover_x=-1000; + climb_cover_y=-1000; + } + + if(stomping) + stomping = false; + + return 0; + } + + void hitlink(int hit2) + { + realLink.hitlink(hit2); + } + + // Find the attack power of the current melee weapon. + // The Whimsical Ring is applied on a target-by-target basis. + int weaponattackpower() + { + int power = directWpn>-1 ? + getItemProp(directWpn, ITEMPROP_POWER) : + (current_item_power(attack==wWand ? + itype_wand : + attack==wHammer ? + itype_hammer : + itype_sword)); + + // Multiply it by the power of the spin attack/quake hammer, if applicable. + power *= (spins>0 ? getItemProp(current_item_id(attack==wHammer ? itype_quakescroll : (spins>5 || current_item_id(itype_spinscroll) < 0) ? itype_spinscroll2 : itype_spinscroll), ITEMPROP_POWER) : 1); + return power; + } + + // Must only be called once per frame! + void positionSword(weapon@ w, int itemid) + { + itemid=vbound(itemid, 0, MAXITEMS-1); + // Place a sword weapon at the right spot. + int wy=1; + int wx=1; + int f=0,t,cs2; + + t = w.o_tile; + cs2 = w.o_cset; + slashxofs=0; + slashyofs=0; + + switch(dir) + { + case up: + wx=-1; + wy=-12; + + if(get_canslash() && w.id==wSword && (getItemProp(itemid, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0 && charging==0) + { + if(attackclk>10) //extended stab + { + slashyofs-=3; + wy-=2; + } + + if(attackclk>=14) //retracting stab + { + slashyofs+=3; + wy+=2; + } + } + else + { + if(attackclk==SWORDCHARGEFRAME) + { + wy+=4; + } + else if(attackclk==13) + { + wy+=4; + } + else if(attackclk==14) + { + wy+=8; + } + } + + break; + + case down: + f=questRuleEnabled(qr_SWORDWANDFLIPFIX)?3:2; + wy=11; + + if(get_canslash() && w.id==wSword && (getItemProp(itemid, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0 && charging==0) + { + if(attackclk>10) //extended stab + { + slashyofs+=3; + wy+=2; + } + + if(attackclk>=14) //retracting stab + { + slashyofs-=3; + wy-=2; + } + } + else + { + if(attackclk==SWORDCHARGEFRAME) + { + wy-=2; + } + else if(attackclk==13) + { + wy-=4; + } + else if(attackclk==14) + { + wy-=8; + } + } + + break; + + case left: + f=1; + wx=-11; + ++t; + + if(get_canslash() && w.id==wSword && (getItemProp(itemid, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0 && charging==0) + { + if(attackclk>10) //extended stab + { + slashxofs-=4; + wx-=7; + } + + if(attackclk>=14) //retracting stab + { + slashxofs+=3; + wx+=7; + } + } + else + { + if(attackclk==SWORDCHARGEFRAME) + { + wx+=2; + } + else if(attackclk==13) + { + wx+=4; + } + else if(attackclk==14) + { + wx+=8; + } + } + + break; + + case right: + wx=11; + ++t; + + if(get_canslash() && w.id==wSword && (getItemProp(itemid, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0 && charging==0) + { + if(attackclk>10) //extended stab + { + slashxofs+=4; + wx+=7; + } + + if(attackclk>=14) //retracting stab + { + slashxofs-=3; + wx-=7; + } + } + else + { + if(attackclk==SWORDCHARGEFRAME) + { + wx-=2; + } + else if(attackclk==13) + { + wx-=4; + } + else if(attackclk==14) + { + wx-=8; + } + } + + break; + } + + if(get_canslash() && (getItemProp(itemid, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0 && attackclk<11) + { + int wpn2=getItemProp(itemid, ITEMPROP_WPN2); + wpn2=vbound(wpn2, 0, MAXWPNS); + + //slashing tiles + switch(dir) + { + case up: + wx=15; + wy=-3; + ++t; + f=0; //starts pointing right + + if(attackclk>=7) + { + wy-=9; + wx-=3; + t = getWeaponProp(wpn2, WPNPROP_TILE); + cs2 = getWeaponProp(wpn2, WPNPROP_CSETS)&15; + f=0; + } + + break; + + case down: + wx=-13; + wy=-1; + ++t; + f=1; //starts pointing left + + if(attackclk>=7) + { + wy+=15; + wx+=2; + t = getWeaponProp(wpn2, WPNPROP_TILE); + cs2 = getWeaponProp(wpn2, WPNPROP_CSETS)&15; + ++t; + f=0; + } + + break; + + case left: + wx=3; + wy=-15; + --t; + f=0; //starts pointing up + + if(attackclk>=7) + { + wx-=15; + wy+=3; + slashxofs-=1; + t = getWeaponProp(wpn2, WPNPROP_TILE); + cs2 = getWeaponProp(wpn2, WPNPROP_CSETS)&15; + t+=2; + f=0; + } + + break; + + case right: + --t; + + if(spins>0 || questRuleEnabled(qr_SLASHFLIPFIX)) + { + wx=1; + wy=13; + f=2; + } + else + { + wx=3; + wy=-15; + f=0; + } + + if(attackclk>=7) + { + wx+=15; + slashxofs+=1; + t = getWeaponProp(wpn2, WPNPROP_TILE); + cs2 = getWeaponProp(wpn2, WPNPROP_CSETS)&15; + + if(spins>0 || questRuleEnabled(qr_SLASHFLIPFIX)) + { + wx-=1; + wy-=2; + } + else + { + t+=3; + f=0; + wy+=3; + } + } + + break; + } + } + + int itemid2 = current_item_id(itype_chargering); + + if(charging>(itemid2>=0 ? getItemProp(itemid2, ITEMPROP_MISC1) : 64)) + { + cs2=(BSZ ? (frame&3)+6 : ((frame>>2)&1)+7); + } + + w.x = x+wx; + w.y = y+wy-(54-(yofs+slashyofs)); + w.z = (z+zofs); + w.tile = t; + w.flip = f; + w.power = weaponattackpower(); + w.dir = dir; + } + + // separate case for sword/wand/hammer/slashed weapons only + // the main weapon checking is in the global function check_collisions() + void checkstab() + { + if(action!=attacking || (attack!=wSword && attack!=wWand && attack!=wHammer && attack!=wCByrna && attack!=wFire) + || (attackclk<=4)) + return; + + weapon@ w; + + int wx=0,wy=0,wz=0,wxsz=0,wysz=0; + bool found = false; + + for(int i=0; i=14 && charging==0) + return; + + if(!found) + return; + + if(attack==wCByrna||attack==wFire) + return; + + if(attack==wHammer) + { + if(attackclk<15) + { + switch(w.dir) + { + case up: + wx=x-1; + wy=y-4; + break; + + case down: + wx=x+8; + wy=y+28; + break; // This is consistent with 2.10 + + case left: + wx=x-13; + wy=y+14; + break; + + case right: + wx=x+21; + wy=y+14; + break; + } + + if(attackclk==12 && z==0 && sideviewhammerpound()) + { + addDecoration(dHAMMERSMACK, wx, wy); + } + + return; + } + else if(attackclk==15 && w.dir==up) + { + // Hammer's reach needs adjusted slightly for backward compatibility + w.hyofs-=1; + } + } + + // The return of Spaghetti Code Constants! + int itype = (attack==wWand ? itype_wand : itype_sword); + int itemid = (directWpn>-1 && getItemProp(directWpn, ITEMPROP_FAMILY)==itype) ? directWpn : current_item_id(itype); + itemid = vbound(itemid, 0, MAXITEMS-1); + + // The sword offsets aren't based on anything other than what felt about right + // compared to the NES game and what mostly kept it from hitting things that + // should clearly be out of range. They could probably still use more tweaking. + // Don't use 2.10 for reference; it's pretty far off. + // - Saf + + if(get_canslash() && (attack==wSword || attack==wWand) && (getItemProp(directWpn, ITEMPROP_FLAGS) & ITEM_FLAG4)!=0) + { + switch(w.dir) + { + case up: + if(attackclk<8) + { + wy-=4; + } + + break; + + case down: + //if(attackclk<8) + { + wy-=2; + } + break; + + case left: + + //if(attackclk<8) + { + wx+=2; + } + + break; + + case right: + + //if(attackclk<8) + { + wx-=3; + //wy+=((spins>0 || get_bit(quest_rules, qr_SLASHFLIPFIX)) ? -4 : 4); + } + + break; + } + } + + switch(w.dir) + { + case up: + wx+=2; + break; + + case down: + break; + + case left: + wy-=3; + break; + + case right: + wy-=3; + break; + } + + wx+=w.hxofs; + wy+=w.hyofs; + + for(int i=0; i0?16:8) && (attack!=wWand || !questRuleEnabled(qr_NOWANDMELEE))) + || (attack==wWand && getGuy(i).hit(wx,wy-8,z,16,24,z>0?16:8) && !questRuleEnabled(qr_NOWANDMELEE)) + || (attack==wHammer && getGuy(i).hit(wx,wy-8,z,16,24,z>0?16:8))) + { + // Checking the whimsical ring for every collision check causes + // an odd bug. It's much more likely to activate on a 0-damage + // weapon, since a 0-damage hit won't make the enemy invulnerable + // to damaging hits in the following frames. + + int whimsyid = current_item_id(itype_whimsicalring); + int whimsypower = 0; + + if(whimsyid>-1) + { + whimsypower = rand()%zc_max(getItemProp(current_item_id(itype_whimsicalring), ITEMPROP_MISC1), 1)!=0 ? + 0 : current_item_power(itype_whimsicalring); + } + + int h = hit_enemy(i,attack,(weaponattackpower() + whimsypower)*DAMAGE_MULTIPLIER,wx,wy,dir,directWpn); + + if(h<0 && whimsypower!=0) + { + sfx(getItemProp(whimsyid, ITEMPROP_SOUND)); + } + + if(h!=0 && charging>0) + { + attackclk = SWORDTAPFRAME; + spins=0; + } + + if(h!=0 && hclk==0 && inlikelike != 1) + { + if(GuyHit(i,x+7,y+7,z,2,2,hzsz)!=-1) + { + hitlink(i); + } + } + + if(h==2) + break; + } + } + + if(!questRuleEnabled(qr_NOITEMMELEE)) + { + for(int j=0; j= 32) + { + if(it.hit(wx,wy,z,wxsz,wysz,1) || (attack==wWand && it.hit(x,y-8,z,wxsz,wysz,1)) + || (attack==wHammer && it.hit(x,y-8,z,wxsz,wysz,1))) + { + int pickup = it.pickup; + + if((pickup&ipONETIME)!=0) // set mITEM for one-time-only items + setmapflag(mITEM); + else if((pickup&ipONETIME2)!=0) // set mBELOW flag for other one-time-only items + setmapflag(); + + if(getItemProp(it.id, ITEMPROP_PICKUP_SCRIPT)!=0) + { + runZScript(SCRIPT_ITEM, getItemProp(it.id, ITEMPROP_PICKUP_SCRIPT), it.id & 0xFFF); + } + + getitem(it.id); + deleteItem(j);//items.del(j); + + for(int i=0; i8 || attackclk==SWORDCHARGEFRAME // is not charging>0, as tapping a wall reduces attackclk but retains charging + || (attackclk>SWORDTAPFRAME && tapping)) + return; + + //keep things inside the screen boundaries + bx=vbound(bx, 0, 255); + by=vbound(by, 0, 176); + int fx=vbound(bx, 0, 255); + int fy=vbound(by, 0, 176); + + //find out which combo row/column the coordinates are in + bx &= 0xF0; + by &= 0xF0; + + int type = COMBOTYPE(bx,by); + int type2 = FFCOMBOTYPE(fx,fy); + int flag = MAPFLAG(bx,by); + int flag2 = MAPCOMBOFLAG(bx,by); + int flag3 = MAPFFCOMBOFLAG(fx,fy); + int i = (bx>>4) + by; + + if(i > 175) + return; + + bool ignorescreen=false; + bool ignoreffc=false; + + if(screengrid[i]) + { + ignorescreen = true; + } + + int current_ffcombo = getFFCAt(fx,fy); + + if(current_ffcombo == -1 || ffcgrid[current_ffcombo]) + { + ignoreffc = true; + } + + if(!isCuttableType(type) && + (flagmfXSWORD) && flag!=mfSTRIKE && (flag2mfXSWORD) && flag2!=mfSTRIKE) + { + ignorescreen = true; + } + + if(!isCuttableType(type2) && + (flag3mfXSWORD) && flag3!=mfSTRIKE) + { + ignoreffc = true; + } + + mapscr@ s = getTmpscr((currscr>=128) ? 1 : 0); + + int sworditem = (directWpn>-1 && getItemProp(directWpn, ITEMPROP_FAMILY)==itype_sword) ? getItemProp(directWpn, ITEMPROP_LEVEL) : current_item(itype_sword); + + if(!ignorescreen) + { + if((flag >= 16)&&(flag <= 31)) + { + s.data[i] = s.secretcombo[(s.sflag[i])-16+4]; + s.cset[i] = s.secretcset[(s.sflag[i])-16+4]; + s.sflag[i] = s.secretflag[(s.sflag[i])-16+4]; + } + else if(flag == mfARMOS_SECRET) + { + s.data[i] = s.secretcombo[sSTAIRS]; + s.cset[i] = s.secretcset[sSTAIRS]; + s.sflag[i] = s.secretflag[sSTAIRS]; + sfx(getTmpscr(0).secretsfx); + } + else if(((flag>=mfSWORD&&flag<=mfXSWORD)||(flag==mfSTRIKE))) + { + for(int i2=0; i2<=zc_min(sworditem-1,3); i2++) + { + findentrance(bx,by,mfSWORD+i2,true); + } + + findentrance(bx,by,mfSTRIKE,true); + } + else if(((flag2 >= 16)&&(flag2 <= 31))) + { + s.data[i] = s.secretcombo[(s.sflag[i])-16+4]; + s.cset[i] = s.secretcset[(s.sflag[i])-16+4]; + s.sflag[i] = s.secretflag[(s.sflag[i])-16+4]; + } + else if(flag2 == mfARMOS_SECRET) + { + s.data[i] = s.secretcombo[sSTAIRS]; + s.cset[i] = s.secretcset[sSTAIRS]; + s.sflag[i] = s.secretflag[sSTAIRS]; + sfx(getTmpscr(0).secretsfx); + } + else if(((flag2>=mfSWORD&&flag2<=mfXSWORD)||(flag2==mfSTRIKE))) + { + for(int i2=0; i2<=zc_min(sworditem-1,3); i2++) + { + findentrance(bx,by,mfSWORD+i2,true); + } + + findentrance(bx,by,mfSTRIKE,true); + } + else + { + if(isCuttableNextType(type)) + { + s.data[i]=s.data[i]+1; + } + else + { + s.data[i] = s.undercombo; + s.cset[i] = s.undercset; + s.sflag[i] = 0; + } + + //pausenow=true; + } + } + + if(((flag3>=mfSWORD&&flag3<=mfXSWORD)||(flag3==mfSTRIKE)) && !ignoreffc) + { + for(int i2=0; i2<=zc_min(sworditem-1,3); i2++) + { + findentrance(bx,by,mfSWORD+i2,true); + } + + findentrance(fx,fy,mfSTRIKE,true); + } + else if(!ignoreffc) + { + if(isCuttableNextType(type2)) + s.ffcs[current_ffcombo].modCombo(1); + else + { + s.ffcs[current_ffcombo].setCombo(s.undercombo); + s.ffcs[current_ffcombo].setCSet(s.undercset); + } + } + + if(!ignorescreen) + { + if(!isTouchyType(type)) screengrid[i]=true; + + if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && !getmapflag()) + { + placeitem(bx, by, getTmpscr(0).catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP); + sfx(getTmpscr(0).secretsfx); + } + else if(isCuttableItemType(type)) + { + int it = select_dropitem(12, bx, by); + + if(it!=-1) + { + placeitem(bx, by, it, ipBIGRANGE + ipTIMER); + } + } + + // WEIRDNESS + // This doesn't appear to do anything useful. + //putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]); + + if(isBushType(type) || isFlowersType(type) || isGrassType(type)) + { + if(questRuleEnabled(qr_MORESOUNDS)) + { + sfx(WAV_ZN1GRASSCUT, bx); + } + + if(isBushType(type)) + { + addDecoration(dBUSHLEAVES, fx, fy); + } + else if(isFlowersType(type)) + { + addDecoration(dFLOWERCLIPPINGS, fx, fy); + } + else if(isGrassType(type)) + { + addDecoration(dGRASSCLIPPINGS, fx, fy); + } + } + } + + if(!ignoreffc) + { + if(!isTouchyType(type)) ffcgrid[current_ffcombo]=true; + + if(isCuttableItemType(type2)) + { + int it=-1; + int r=rand()%100; + + if(r<15) + { + it=iHeart; // 15% + } + else if(r<35) + { + it=iRupy; // 20% + } + + if(it!=-1 && getItemProp(it, ITEMPROP_FAMILY) != itype_misc) // Don't drop non-gameplay items + { + placeitem(fx, fy, it, ipBIGRANGE + ipTIMER); + } + } + + if(isBushType(type2) || isFlowersType(type2) || isGrassType(type2)) + { + if(questRuleEnabled(qr_MORESOUNDS)) + { + sfx(WAV_ZN1GRASSCUT, bx); + } + + if(isBushType(type2)) + { + addDecoration(dBUSHLEAVES, fx, fy); + } + else if(isFlowersType(type2)) + { + addDecoration(dFLOWERCLIPPINGS, fx, fy); + } + else if(isGrassType(type2)) + { + addDecoration(dGRASSCLIPPINGS, fx, fy); + } + } + } + } + + void check_wand_block(int bx, int by) + { + //first things first + if(z>8) return; + + //keep things inside the screen boundaries + bx=vbound(bx, 0, 255); + by=vbound(by, 0, 176); + int fx=vbound(bx, 0, 255); + int fy=vbound(by, 0, 176); + + //find out which combo row/column the coordinates are in + bx &= 0xF0; + by &= 0xF0; + + int flag = MAPFLAG(bx,by); + int flag2 = MAPCOMBOFLAG(bx,by); + int flag3=0; + int flag31 = MAPFFCOMBOFLAG(fx,fy); + int flag32 = MAPFFCOMBOFLAG(fx,fy); + int flag33 = MAPFFCOMBOFLAG(fx,fy); + int flag34 = MAPFFCOMBOFLAG(fx,fy); + + if(flag31==mfWAND||flag32==mfWAND||flag33==mfWAND||flag34==mfWAND) + flag3=mfWAND; + + if(flag31==mfSTRIKE||flag32==mfSTRIKE||flag33==mfSTRIKE||flag34==mfSTRIKE) + flag3=mfSTRIKE; + + int i = (bx>>4) + by; + + if(flag!=mfWAND&&flag2!=mfWAND&&flag3!=mfWAND&&flag!=mfSTRIKE&&flag2!=mfSTRIKE&&flag3!=mfSTRIKE) + return; + + if(i > 175) + return; + + if(!(findentrance(bx,by,mfWAND,true))&&(!findentrance(bx,by,mfSTRIKE,true))) + { + if(flag3==mfWAND||flag3==mfSTRIKE) + { + findentrance(fx,fy,mfWAND,true); + findentrance(fx,fy,mfSTRIKE,true); + } + } + } + + void check_pound_block(int bx, int by) + { + //first things first + if(z>8) return; + + //keep things inside the screen boundaries + bx=vbound(bx, 0, 255); + by=vbound(by, 0, 176); + int fx=vbound(bx, 0, 255); + int fy=vbound(by, 0, 176); + + //find out which combo row/column the coordinates are in + bx &= 0xF0; + by &= 0xF0; + + int type = COMBOTYPE(bx,by); + int type2 = FFCOMBOTYPE(fx,fy); + int flag = MAPFLAG(bx,by); + int flag2 = MAPCOMBOFLAG(bx,by); + int flag3 = MAPFFCOMBOFLAG(fx,fy); + int i = (bx>>4) + by; + + if(i > 175) + return; + + bool ignorescreen=false; + bool ignoreffc=false; + bool pound=false; + + if(type!=cPOUND && flag!=mfHAMMER && flag!=mfSTRIKE && flag2!=mfHAMMER && flag2!=mfSTRIKE) + ignorescreen = true; // Affect only FFCs + + if(screengrid[i]) + ignorescreen = true; + + int current_ffcombo = getFFCAt(fx,fy); + + if(current_ffcombo == -1 || ffcgrid[current_ffcombo]) + ignoreffc = true; + + if(type2!=cPOUND && flag3!=mfSTRIKE && flag3!=mfHAMMER) + ignoreffc = true; + + if(ignorescreen && ignoreffc) // Nothing to do. + return; + + mapscr@ s= getTmpscr((currscr>=128) ? 1 : 0); + + if(!ignorescreen) + { + if(flag==mfHAMMER||flag==mfSTRIKE) // Takes precedence over Secret Tile and Armos->Secret + { + findentrance(bx,by,mfHAMMER,true); + findentrance(bx,by,mfSTRIKE,true); + } + else if(flag2==mfHAMMER||flag2==mfSTRIKE) + { + findentrance(bx,by,mfHAMMER,true); + findentrance(bx,by,mfSTRIKE,true); + } + else if((flag >= 16)&&(flag <= 31)) + { + s.data[i] = s.secretcombo[(s.sflag[i])-16+4]; + s.cset[i] = s.secretcset[(s.sflag[i])-16+4]; + s.sflag[i] = s.secretflag[(s.sflag[i])-16+4]; + } + else if(flag == mfARMOS_SECRET) + { + s.data[i] = s.secretcombo[sSTAIRS]; + s.cset[i] = s.secretcset[sSTAIRS]; + s.sflag[i] = s.secretflag[sSTAIRS]; + sfx(getTmpscr(0).secretsfx); + } + else if((flag2 >= 16)&&(flag2 <= 31)) + { + s.data[i] = s.secretcombo[(s.sflag[i])-16+4]; + s.cset[i] = s.secretcset[(s.sflag[i])-16+4]; + s.sflag[i] = s.secretflag[(s.sflag[i])-16+4]; + } + else if(flag2 == mfARMOS_SECRET) + { + s.data[i] = s.secretcombo[sSTAIRS]; + s.cset[i] = s.secretcset[sSTAIRS]; + s.sflag[i] = s.secretflag[sSTAIRS]; + sfx(getTmpscr(0).secretsfx); + } + else pound = true; + } + + if(!ignoreffc) + { + if(flag3==mfHAMMER||flag3==mfSTRIKE) + { + findentrance(fx,fy,mfHAMMER,true); + findentrance(fx,fy,mfSTRIKE,true); + } + else + { + s.ffcs[current_ffcombo].modCombo(1); + } + } + + if(!ignorescreen) + { + if(pound) + s.data[i]=s.data[i]+1; + + screengrid[i]=true; + + if((flag==mfARMOS_ITEM||flag2==mfARMOS_ITEM) && !getmapflag()) + { + placeitem(bx, by, getTmpscr(0).catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP); + sfx(getTmpscr(0).secretsfx); + } + + if(type==cPOUND && questRuleEnabled(qr_MORESOUNDS)) + sfx(WAV_ZN1HAMMERPOST,int(bx)); + + // WEIRDNESS + // This doesn't appear to do anything useful. + //putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]); + } + + if(!ignoreffc) + { + ffcgrid[current_ffcombo]=true; + + if(type2==cPOUND && questRuleEnabled(qr_MORESOUNDS)) + sfx(WAV_ZN1HAMMERPOST, bx); + } + } + + // Should swinging the hammer make the 'pound' sound? + // Or is Link just hitting air? + bool sideviewhammerpound() + { + int wx=0,wy=0; + + switch(dir) + { + case up: + wx=-1; + wy=-15; + + if(screenFlagSet(fSIDEVIEW)) wy+=8; + + break; + + case down: + wx=8; + wy=28; + + if(screenFlagSet(fSIDEVIEW)) wy-=8; + + break; + + case left: + wx=-8; + wy=14; + + if(screenFlagSet(fSIDEVIEW)) wy+=8; + + break; + + case right: + wx=21; + wy=14; + + if(screenFlagSet(fSIDEVIEW)) wy+=8; + + break; + } + + if(!screenFlagSet(fSIDEVIEW)) + { + return (COMBOTYPE(x+wx,y+wy)!=cSHALLOWWATER && !iswater(MAPCOMBO(x+wx,y+wy))); + } + + if(_walkflag(x+wx,y+wy,0)) return true; + + if(dir==left || dir==right) + { + wx+=16; + + if(_walkflag(x+wx,y+wy,0)) return true; + } + + return false; + } + + void Drown() + { + // Link should never drown if the ladder is out + if(ladderx!=0 || laddery!=0) + return; + + action=drowning; + attackclk=0; + attack=wNone; + attackid=-1; + reset_swordcharge(); + drownclk=64; + z=0; + fall=0; + } + + void execute(WalkflagInfo@ info) + { + int flags = info.getFlags(); + + if((flags & CLEARILSWIM)!=0) + ilswim =false; + else if((flags & SETILSWIM)!=0) + ilswim = true; + + if((flags & CLEARCHARGEATTACK)!=0) + { + charging = 0; + attackclk = 0; + } + + if((flags & SETDIR)!=0) + { + dir = info.getDir(); + } + + if((flags & SETHOPCLK)!=0) + { + hopclk = info.getHopClk(); + } + + if((flags & SETHOPDIR)!=0) + { + hopdir = info.getHopDir(); + } + + } + + void reset_swordcharge() + { + charging=0; + spins=0; + tapping=false; + } + + void setEaten(uint8 i) + { + inlikelike=i; + } + + int getEaten() + { + return inlikelike; + } + + int getAction() + { + if(spins > 0) + return isspinning; + else if(charging > 0) + return ischarging; + else if(diveclk > 0) + return isdiving; + + return action; + } + + bool isSwimming() + { + return ((action==swimming)||(action==swimhit)|| + (action==waterhold1)||(action==waterhold2)|| + (hopclk==0xFF)); + } + + bool drunk() + { + return ((0==(frame%((rand()%100)+1)))&&(rand()%500 0) + return; + + change_counter(-(getItemProp(itemid, ITEMPROP_MAGIC)*get_magicdrainrate()), 4); +} + +fix LinkX() +{ + return Link.x; +} + +fix LinkY() +{ + return Link.y; +} + +fix LinkZ() +{ + return Link.z; +} + +int LinkDir() +{ + return Link.dir; +} + diff --git a/output/common/angelscript/manhandla.as b/output/common/angelscript/manhandla.as new file mode 100644 index 0000000000..bd89d3da87 --- /dev/null +++ b/output/common/angelscript/manhandla.as @@ -0,0 +1,468 @@ +class Manhandla: enemy +{ + array headside; + int headcnt; + bool adjusted; + + Manhandla() + { + clk=0; + + superman=1; + dir=(rand()&7)+8; + headcnt=(dmisc2!=0)?8:4; + + for(int i=0; i=(frate>>1))?1:0); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + if(dmisc2==0) + { + switch(dir-8) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case l_up: //d + flip=0; + tile+=4; + break; + + case l_down: //l + flip=0; + tile+=8; + break; + + case left: //r + flip=0; + tile+=12; + break; + + case r_down: //ul + flip=0; + tile+=20; + break; + + case down: //ur + flip=0; + tile+=24; + break; + + case r_up: //dl + flip=0; + tile+=28; + break; + + case right: //dr + flip=0; + tile+=32; + break; + } + + tile+=f2; + enemy::draw(); + } //manhandla 2, big body + else + { + + switch(dir-8) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case l_up: //d + flip=0; + tile+=8; + break; + + case l_down: //l + flip=0; + tile+=40; + break; + + case left: //r + flip=0; + tile+=48; + break; + + case r_down: //ul + flip=0; + tile+=80; + break; + + case down: //ur + flip=0; + tile+=88; + break; + + case r_up: //dl + flip=0; + tile+=120; + break; + + case right: //dr + flip=0; + tile+=128; + break; + } + + tile+=(f2*2); + xofs-=8; + yofs-=8; + drawblock(); + xofs+=8; + yofs+=8; + } + } + else + { + if(dmisc2==0) + { + enemy::draw(); + } + else + { + xofs-=8; + yofs-=8; + enemy::draw(); + xofs+=16; + enemy::draw(); + yofs+=16; + enemy::draw(); + xofs-=16; + enemy::draw(); + xofs+=8; + yofs-=8; + } + } + } +} + +class ManhandlaHead: enemy // Head? Arm? Claw? Whatever... +{ + ManhandlaHead() + { + id=clk; + misc=clk; + + dir = clk & 3; + clk=0; + mainguy=false; + count_enemy=false; + dummy_bool0=false; + item_set=0; + bgsfx=-1; + flags &= ~guy_neverret; + } + + bool Update(int index) + + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + clk2-=1; + if(clk2<=0) + { + clk2=rand()%5+5; + clk3^=1; + } + + if((rand()&127)==0) + fireWeapon(); + + return enemy::animate(index); + } + + void Draw() + { + tile=o_tile; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + int f2=questRuleEnabled(qr_NEWENEMYTILES)? + efrate:((clk>=(frate>>1))?1:0); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + switch(misc&3) + { + case up: + break; + + case down: + tile+=4; + break; + + case left: + tile+=8; + break; + + case right: + tile+=12; + break; + } + + tile+=f2; + } + else + { + switch(misc&3) + { + case down: + flip=2; + + case up: + tile=(clk3!=0)?188:189; + break; + + case right: + flip=1; + + case left: + tile=(clk3!=0)?186:187; + break; + } + } + + enemy::draw(); + } +} diff --git a/output/common/angelscript/moldorm.as b/output/common/angelscript/moldorm.as new file mode 100644 index 0000000000..245a678482 --- /dev/null +++ b/output/common/angelscript/moldorm.as @@ -0,0 +1,272 @@ +class MoldormController: enemy +{ + int segcnt; + int segid; + + MoldormController() + { + x=128; + y=48; + dir=(rand()&7)+8; + superman=1; + fading=fade_invisible; + hxofs=1000; + segcnt=clk; + segid=id|0x1000; + clk=0; + id=numGuys(); + yofs=playing_field_offset; + tile=o_tile; + } + + bool Update(int index) + { + if(clk==0) + { + removearmos(x,y); + } + + if(clk2!=0) + { + clk2-=1; + if(clk2 == 0) + { + if((flags&guy_neverret)!=0) + never_return(index); + + if(dmisc2==0) + leave_item(); + + stopBGSFX(); + return true; + } + } + else + { + constant_walk_8(rate, homing, spw_floater); + misc=dir; + + // If any higher-numbered segments were killed, segcnt can be too high, + // leading to a crash + if(index+segcnt>=numGuys()) + segcnt=numGuys()-index-1; + + for(int i=index+1; i=0) + { + enemy@ en=getGuy(index-1); + hxofs=4; + step=en.step; + + if(parentclk == 0) + { + misc=dir; + dir=en.misc; + //do alignment, as in parent's animation :-/ -DD + x.vAND(0xFFFF0000); + y.vAND(0xFFFF0000); + } + + parentclk=(parentclk+1)%(int(8.0/step)); + + if(!watch) + { + sprite::move(step); + } + } + + return enemy::animate(index); + } + + int takehit(weapon@ w) + { + if(enemy::takehit(w)!=0) + return (w.id==wSBomb) ? 1 : 2; // force it to wait a frame before checking sword attacks again + + return 0; + } + + void Draw() + { + tile=o_tile; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + + int f2=questRuleEnabled(qr_NEWENEMYTILES)? + efrate:((clk>=(frate>>1))?1:0); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + tile+=dummy_int1*40; + + if(dir<8) + { + flip=0; + tile+=4*dir; + + if(dir>3) // Skip to the next row for diagonals + tile+=4; + } + else + { + switch(dir-8) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case l_up: //d + flip=0; + tile+=4; + break; + + case l_down: //l + flip=0; + tile+=8; + break; + + case left: //r + flip=0; + tile+=12; + break; + + case r_down: //ul + flip=0; + tile+=20; + break; + + case down: //ur + flip=0; + tile+=24; + break; + + case r_up: //dl + flip=0; + tile+=28; + break; + + case right: //dr + flip=0; + tile+=32; + break; + } + } + + tile+=f2; + } + + if(clk>=0) + enemy::draw(); + } +} diff --git a/output/common/angelscript/npc.as b/output/common/angelscript/npc.as new file mode 100644 index 0000000000..7a62e6d968 --- /dev/null +++ b/output/common/angelscript/npc.as @@ -0,0 +1,74 @@ +class NPC: enemy +{ + NPC() + { + o_tile+=getSpriteTile(iwNPCs); + count_enemy=false; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + switch(dmisc2) + { + case 0: + { + double ddir=atan2(y-Link.y, Link.x-x); + + if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4))) + { + dir=down; + } + + else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4))) + { + dir=right; + } + else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/8))) + { + dir=up; + } + else + { + dir=left; + } + } + break; + + case 1: + halting_walk(rate, homing, 0, hrate, 48); + + if(clk2==1 && (misc < dmisc1) && (rand()&15)==0) + { + newdir(rate, homing, 0); + clk2=48; + misc+=1; + } + + if(clk2==0) + misc=0; + + break; + } + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + int takehit(weapon@ w) + { + return 0; + } +} diff --git a/output/common/angelscript/other.as b/output/common/angelscript/other.as new file mode 100644 index 0000000000..4fe67985df --- /dev/null +++ b/output/common/angelscript/other.as @@ -0,0 +1,97 @@ +class Other: enemy +{ + int clk4; + bool shield; + + Other() + { + clk4=0; + shield=(flags&(inv_left | inv_right | inv_back |inv_front))!=0; + + // Spawn type + if((flags & guy_fadeflicker)!=0) + { + clk=0; + superman = 1; + fading=fade_flicker; + count_enemy=false; + dir=down; + + if(!canmove(down, 8, spw_none)) + clk3=int(13.0/step); + } + else if((flags & guy_fadeinstant)!=0) + { + clk=0; + } + } + + bool Update(int index) + { + if(fading!=0) + { + if(++clk4 > 60) + { + clk4=0; + superman=0; + fading=0; + + if((flags2&cmbflag_armos)!=0 && z==0) + removearmos(x,y); + + clk2=0; + + if(!canmove(down, 8, spw_none)) + { + dir=0; + y.vAND(0xF00000); + } + + return Dead(index); + } + else if((flags2&cmbflag_armos)!=0 && z==0 && clk==0) + removearmos(x, y); + } + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + int wpnDir = w.dir; + + if(wpnId==wHammer && shield && (flags & guy_bkshield)!=0 + && (((flags&inv_front)!=0 && wpnDir==(dir^down)) || ((flags&inv_back)!=0 && wpnDir==(dir^up)) + || ((flags&inv_left)!=0 && wpnDir==(dir^left)) || ((flags&inv_right)!=0 && wpnDir==(dir^right)))) + { + shield = false; + flags &= ~(inv_left|inv_right|inv_back|inv_front); + + if(questRuleEnabled(qr_BRKNSHLDTILES)) + o_tile=s_tile; + } + + int ret = enemy::takehit(w); + return ret; + } + + void break_shield() + { + if(!shield) + return; + + flags&=~(inv_front | inv_back | inv_left | inv_right); + shield=false; + + if(questRuleEnabled(qr_BRKNSHLDTILES)) + o_tile=s_tile; + } +} + diff --git a/output/common/angelscript/patra.as b/output/common/angelscript/patra.as new file mode 100644 index 0000000000..9962d4d658 --- /dev/null +++ b/output/common/angelscript/patra.as @@ -0,0 +1,436 @@ +class Patra: enemy +{ + int flycnt; + int flycnt2; + int loopcnt; + int lookat; + double circle_x; + double circle_y; + double temp_x; + double temp_y; + bool adjusted; + + Patra() + { + x=128; + y=48; + adjusted=false; + dir=(rand()&7)+8; + flycnt=dmisc1; + flycnt2=dmisc2; + loopcnt=0; + + if(dmisc6<1) + dmisc6=1; // ratio cannot be 0! + + if(flycnt!=0 || flycnt2!=0) + scriptFlags=asf_PATRADEFENSE; + } + + bool Update(int index) + { + if(dying) + { + for(int i=index+1; i84) + { + clk2=0; + + if(loopcnt!=0) + --loopcnt; + else + { + if((misc%dmisc6)==0) + loopcnt=dmisc7; + } + + misc+=1; + } + + double size=1; + + for(int i=index+1; i0) + { + orbiter.x = cos(a2+PI/2)*56*size - sin(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*28*size; + orbiter.y = -sin(a2+PI/2)*56*size + cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1))*28*size; + } + else + { + orbiter.x = cos(a2+PI/2)*28*size; + orbiter.y = -sin(a2+PI/2)*28*size; + } + + temp_x=orbiter.x; + temp_y=orbiter.y; + } + else + { + circle_x = cos(a2+PI/2)*42; + circle_y = -sin(a2+PI/2)*42; + + if(loopcnt>0) + { + orbiter.x = cos(a2+PI/2)*42; + orbiter.y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc1 == 0 ? 1 : dmisc1)))*21; + } + else + { + orbiter.x = circle_x; + orbiter.y = circle_y; + } + + temp_x=circle_x; + temp_y=circle_y; + } + + double ddir=atan2(temp_y, temp_x); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + orbiter.dir=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + orbiter.dir=left; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + orbiter.dir=l_up; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + orbiter.dir=up; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + orbiter.dir=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + orbiter.dir=right; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + orbiter.dir=r_down; + } + else + { + orbiter.dir=down; + } + + orbiter.x += x; + orbiter.y += y; + } + } + + if(dmisc5==1) + { + if((rand()&127)==0) + fireWeapon(); + } + + size=.5; + + if(flycnt2!=0) + { + for(int i=index+flycnt+1; i0) + { + orbiter.superman=1; + } + else + { + orbiter.superman=0; + } + + if(orbiter.hp <= 0) + { + for(int j=i; j0) + { + orbiter.x = cos(a2+PI/2)*56*size - sin(pos2*PI*2/(dmisc2==0? 1 : dmisc2))*28*size; + orbiter.y = -sin(a2+PI/2)*56*size + cos(pos2*PI*2/(dmisc2==0?1:dmisc2))*28*size; + } + else + { + orbiter.x = cos(a2+PI/2)*28*size; + orbiter.y = -sin(a2+PI/2)*28*size; + } + + temp_x=orbiter.x; + temp_y=orbiter.y; + } + else + { + circle_x = cos(a2+PI/2)*42*size; + circle_y = -sin(a2+PI/2)*42*size; + + if(loopcnt>0) + { + orbiter.x = cos(a2+PI/2)*42*size; + orbiter.y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc2 == 0 ? 1 : dmisc2)))*21*size; + } + else + { + orbiter.x = circle_x; + orbiter.y = circle_y; + } + + temp_x=circle_x; + temp_y=circle_y; + } + + double ddir=atan2(temp_y, temp_x); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + orbiter.dir=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + orbiter.dir=left; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + orbiter.dir=l_up; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + orbiter.dir=up; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + orbiter.dir=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + orbiter.dir=right; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + orbiter.dir=r_down; + } + else + { + orbiter.dir=down; + } + + orbiter.x += x; + orbiter.y = y-orbiter.y; + + } + } + } + + adjusted=true; + return enemy::animate(index); + } + + void Draw() + { + tile=o_tile; + update_enemy_frame(); + enemy::draw(); + } + + void checkOrbiters() + { + if(flycnt==0 && flycnt2==0) + // All orbiters are dead - no longer invincible + scriptFlags=0; + } +} + +class PatraOrbiter: enemy +{ + PatraOrbiter() + { + item_set=0; + misc=clk; + clk = -((misc*21)>>1)-1; + yofs=playing_field_offset; + hyofs=2; + hxsz=12; + hysz=12; + hxofs=2; + mainguy=false; + count_enemy=false; + bgsfx=-1; + flags &= (~guy_neverret); + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + return enemy::animate(index); + } + + void Draw() + { + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + tile = o_tile+(clk&3); + + switch(dir) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case down: //d + flip=0; + tile+=4; + break; + + case left: //l + flip=0; + tile+=8; + break; + + case right: //r + flip=0; + tile+=12; + break; + + case l_up: //ul + flip=0; + tile+=20; + break; + + case r_up: //ur + flip=0; + tile+=24; + break; + + case l_down: //dl + flip=0; + tile+=28; + break; + + case r_down: //dr + flip=0; + tile+=32; + break; + } + } + else + { + tile = o_tile+((clk&2)>>1); + } + + if(clk>=0) + enemy::draw(); + } +} + diff --git a/output/common/angelscript/patraBS.as b/output/common/angelscript/patraBS.as new file mode 100644 index 0000000000..1a86f63209 --- /dev/null +++ b/output/common/angelscript/patraBS.as @@ -0,0 +1,343 @@ +class PatraBS: enemy +{ + int flycnt; + int loopcnt; + int lookat; + double temp_x; + double temp_y; + bool adjusted; + + PatraBS() + { + x=128; + y=48; + + adjusted=false; + dir=(rand()&7)+8; + step=0.25; + flycnt=dmisc1; + loopcnt=0; + hxsz = 32; + hxofs=-8; + + if(dmisc6<1) + dmisc6=1; // ratio cannot be 0! + + if(flycnt!=0) + scriptFlags=asf_PATRADEFENSE; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + variable_walk_8(rate, homing, hrate, spw_floater); + + clk2+=1; + if(clk2>90) + { + clk2=0; + + if(loopcnt!=0) + --loopcnt; + else + { + if((misc%dmisc6)==0) + loopcnt=dmisc7; + } + + misc+=1; + } + + for(int i=index+1; i0) + { + orbiter.x = cos(a2+PI/2)*45; + orbiter.y = (-sin(a2+PI/2)-cos(pos2*PI*2/(dmisc1==0?1:dmisc1)))*22.5; + } + else + { + orbiter.x = temp_x; + orbiter.y = temp_y; + } + + double ddir=atan2(temp_y, temp_x); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + orbiter.dir=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + orbiter.dir=left; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + orbiter.dir=l_up; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + orbiter.dir=up; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + orbiter.dir=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + orbiter.dir=right; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + orbiter.dir=r_down; + } + else + { + orbiter.dir=down; + } + + orbiter.x += x; + orbiter.y += y; + } + } + + adjusted=true; + return enemy::animate(index); + } + + void Draw() + { + tile=o_tile; + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + double ddir=atan2(y-Link.y, Link.x-x); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + lookat=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + lookat=down; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + lookat=r_down; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + lookat=right; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + lookat=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + lookat=up; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + lookat=l_up; + } + else + { + lookat=left; + } + + switch(lookat) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case down: //d + flip=0; + tile+=8; + break; + + case left: //l + flip=0; + tile+=40; + break; + + case right: //r + flip=0; + tile+=48; + break; + + case l_up: //ul + flip=0; + tile+=80; + break; + + case r_up: //ur + flip=0; + tile+=88; + break; + + case l_down: //dl + flip=0; + tile+=120; + break; + + case r_down: //dr + flip=0; + tile+=128; + break; + } + + tile+=(2*(clk&3)); + xofs-=8; + yofs-=8; + drawblock(); + xofs+=8; + yofs+=8; + } + else + { + flip=(clk&1); + xofs-=8; + yofs-=8; + enemy::draw(); + xofs+=16; + enemy::draw(); + yofs+=16; + enemy::draw(); + xofs-=16; + enemy::draw(); + xofs+=8; + yofs-=8; + } + } +} + +class PatraOrbiterBS: enemy +{ + PatraOrbiterBS() + { + item_set=0; + misc=clk; + clk = -((misc*21)>>1)-1; + yofs=playing_field_offset; + hyofs=2; + hxsz=16; + hysz=16; + bgsfx=-1; + mainguy=false; + count_enemy=false; + flags &= ~guy_neverret; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + return enemy::animate(index); + } + + void Draw() + { + tile=o_tile; + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + switch(dir) //directions get screwed up after 8. *shrug* + { + case up: //u + flip=0; + break; + + case down: //d + flip=0; + tile+=4; + break; + + case left: //l + flip=0; + tile+=8; + break; + + case right: //r + flip=0; + tile+=12; + break; + + case l_up: //ul + flip=0; + tile+=20; + break; + + case r_up: //ur + flip=0; + tile+=24; + break; + + case l_down: //dl + flip=0; + tile+=28; + break; + + case r_down: //dr + flip=0; + tile+=32; + break; + } + + tile += ((clk&6)>>1); + } + else + { + tile += ((clk&4)!=0)?1:0; + } + + if(clk>=0) + enemy::draw(); + } +} + diff --git a/output/common/angelscript/peahat.as b/output/common/angelscript/peahat.as new file mode 100644 index 0000000000..fc503942a8 --- /dev/null +++ b/output/common/angelscript/peahat.as @@ -0,0 +1,104 @@ +class Peahat: enemy +{ + Peahat() + { + floater_walk((misc!=0) ? rate : 0, hrate, dstep/100.0, dstep/1000.0, 10, 80, 16); + dir=8; + movestatus=1; + clk=0; + step=0; + scriptFlags=asf_ALWAYSDIE; + } + + bool Update(int index) + { + if(slide()) + { + return false; + } + + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(stunclk==0 && clk>96) + misc=1; + + if(!watch) + floater_walk((misc!=0)?rate:0, hrate, dstep/100.0, dstep/1000.0, 10, 80, 16); + + if(questRuleEnabled(qr_ENEMIESZAXIS) && !screenFlagSet(fSIDEVIEW)) + { + z=int(step*1.1/fix((dstep/1000.0)*1.1)); + } + + if(watch && questRuleEnabled(qr_PEAHATCLOCKVULN)) + superman=0; + else + superman=(movestatus!=0 && !questRuleEnabled(qr_ENEMIESZAXIS)) ? 1 : 0; + stunclk=0; + + if(x<16) dir=right; //this is ugly, but so is moving or creating these guys with scripts. + + return enemy::animate(index); + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + int enemyHitWeapon = w.parentitem; + + if(dying || clk<0 || hclk>0) + return 0; + + if(superman!=0 && wpnId!=wSBomb // vulnerable to super bombs + // fire boomerang, for nailing peahats + && !(wpnId==wBrang && (enemyHitWeapon>-1 ? getItemProp(enemyHitWeapon, ITEMPROP_POWER) : current_item_power(itype_brang))>0)) + return 0; + + // Time for a kludge... + int s = superman; + superman = 0; + int ret = enemy::takehit(w); + superman = s; + + // Anyway... + if(stunclk == 160) + { + clk2=0; + movestatus=0; + misc=0; + clk=0; + step=0; + } + + return ret; + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + void DrawShadow() + { + int tempy=yofs; + flip = 0; + shadowtile = getSpriteTile(iwShadow)+posframe; + + if(!questRuleEnabled(qr_ENEMIESZAXIS)) + { + yofs+=8; + yofs+=step/(dstep/1000.0); + } + + enemy::drawshadow(); + yofs=tempy; + } +} + diff --git a/output/common/angelscript/projectileShooter.as b/output/common/angelscript/projectileShooter.as new file mode 100644 index 0000000000..071bc60ce8 --- /dev/null +++ b/output/common/angelscript/projectileShooter.as @@ -0,0 +1,92 @@ +class ProjectileShooter: enemy +{ + int minRange; + + ProjectileShooter() + { + mainguy=false; + count_enemy=false; + minRange=clk; // the "no fire" range + clk=0; + clk3=96; + + if(o_tile==0) + { + superman=1; + hxofs=1000; + } + } + + bool Update(int index) + { + if(clk==0) + { + removearmos(x,y); + } + + double ddir=atan2(y-Link.y, Link.x-x); + + if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4))) + { + dir=down; + } + else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4))) + { + dir=right; + } + else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4))) + { + dir=up; + } + else + { + dir=left; + } + + clk3+=1; + if(clk3>80) + { + if(dmisc1==9) // Breath type + { + if(isFiring()) + { + updateFiring(); + if(!isFiring()) + clk3=0; + } + else if((rand()&63)==0) + fireWeapon(); + } + + else // Not breath type + { + int r=rand(); + + if((r&63)==0 && !LinkInRange(minRange)) + { + fireWeapon(); + + if(wpn==ewFireball || wpn==ewFireball2) // Shouldn't it check that it's single-shot, too? + { + if((r&(15<<7))==0) // Is this right? Seems too frequent. + { + x-=4; + fireWeapon(); + x+=4; + } + } + clk3=0; + } + } + } + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } +} + diff --git a/output/common/angelscript/spinningTile.as b/output/common/angelscript/spinningTile.as new file mode 100644 index 0000000000..5c4166788a --- /dev/null +++ b/output/common/angelscript/spinningTile.as @@ -0,0 +1,109 @@ +class SpinningTile: enemy +{ + SpinningTile() + { + if(clk>0) // clk>0 when created by a Spinning Tile combo + { + o_tile=clk; + cs=id>>12; + } + + id=id&0xFFF; + clk=0; + step=0; + mainguy=false; + } + + void facelink() + { + if(Link.x-x==0) + { + dir=(Link.y+8(((-7)*PI)/8))) + { + dir=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + dir=down; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + dir=r_down; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + dir=right; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + dir=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + dir=up; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + dir=l_up; + } + else + { + dir=left; + } + } + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + misc+=1; + + if(misc==96) + { + facelink(); + double ddir=atan2(double((Link.y)-y),double(Link.x-x)); + angular=true; + angle=ddir; + step=(dstep/100.0); + } + + if(y>186 || y<=-16 || x>272 || x<=-16) + kickbucket(); + + sprite::move(step); + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + y-=(misc>>4); + yofs+=2; + enemy::draw(); + yofs-=2; + y+=(misc>>4); + } + + void DrawShadow() + { + flip = 0; + shadowtile = getSpriteTile(iwShadow)+(clk%4); + yofs+=4; + enemy::drawshadow(); + yofs-=4; + } +} diff --git a/output/common/angelscript/sprite.as b/output/common/angelscript/sprite.as new file mode 100644 index 0000000000..8618a29ceb --- /dev/null +++ b/output/common/angelscript/sprite.as @@ -0,0 +1,337 @@ +abstract class sprite: spriteIF +{ + __RealSprite@ realSprite; + + sprite() + { + @realSprite=__getRealSprite(); + } + + // Properties ============================================================== + + int uid + { + get const { return realSprite.uid; } + set { realSprite.uid=value; } + } + + fix x + { + get const { return realSprite.x; } + set { realSprite.x=value; } + } + + fix y + { + get const { return realSprite.y; } + set { realSprite.y=value; } + } + + fix z + { + get const { return realSprite.z; } + set { realSprite.z=value; } + } + + fix fall + { + get const { return realSprite.fall; } + set { realSprite.fall=value; } + } + + int tile + { + get const { return realSprite.tile; } + set { realSprite.tile=value; } + } + + int shadowtile + { + get const { return realSprite.shadowtile; } + set { realSprite.shadowtile=value; } + } + + int cs + { + get const { return realSprite.cs; } + set { realSprite.cs=value; } + } + + int flip + { + get const { return realSprite.flip; } + set { realSprite.flip=value; } + } + + int c_clk + { + get const { return realSprite.c_clk; } + set { realSprite.c_clk=value; } + } + + int clk + { + get const { return realSprite.clk; } + set { realSprite.clk=value; } + } + + int misc + { + get const { return realSprite.misc; } + set { realSprite.misc=value; } + } + + fix xofs + { + get const { return realSprite.xofs; } + set { realSprite.xofs=value; } + } + + fix yofs + { + get const { return realSprite.yofs; } + set { realSprite.yofs=value; } + } + + fix zofs // Both hit and draw, because why not + { + get const { return realSprite.zofs; } + set { realSprite.zofs=value; } + } + + int hxofs + { + get const { return realSprite.hxofs; } + set { realSprite.hxofs=value; } + } + + int hyofs + { + get const { return realSprite.hyofs; } + set { realSprite.hyofs=value; } + } + + int hxsz + { + get const { return realSprite.hxsz; } + set { realSprite.hxsz=value; } + } + + int hysz + { + get const { return realSprite.hysz; } + set { realSprite.hysz=value; } + } + + int hzsz + { + get const { return realSprite.hzsz; } + set { realSprite.hzsz=value; } + } + + int txsz + { + get const { return realSprite.txsz; } + set { realSprite.txsz=value; } + } + + int tysz + { + get const { return realSprite.tysz; } + set { realSprite.tysz=value; } + } + + int id + { + get const { return realSprite.id; } + set { realSprite.id=value; } + } + + int dir + { + get const { return realSprite.dir; } + set { realSprite.dir=value; } + } + + bool angular + { + get const { return realSprite.angular; } + set { realSprite.angular=value; } + } + + bool canfreeze + { + get const { return realSprite.canfreeze; } + set { realSprite.canfreeze=value; } + } + + double angle + { + get const { return realSprite.angle; } + set { realSprite.angle=value; } + } + + int lasthitclk + { + get const { return realSprite.lasthitclk; } + set { realSprite.lasthitclk=value; } + } + + int lasthit + { + get const { return realSprite.lasthit; } + set { realSprite.lasthit=value; } + } + + int drawstyle + { + get const { return realSprite.drawstyle; } + set { realSprite.drawstyle=value; } + } + + int extend + { + get const { return realSprite.extend; } + set { realSprite.extend=value; } + } + + uint8 scriptcoldet + { + get const { return realSprite.scriptcoldet; } + set { realSprite.scriptcoldet=value; } + } + + // Methods ================================================================= + + int real_x(fix fx) + { + int rx=fx.getV()>>16; + + switch(dir) + { + case 9: + case 13: + if((fx.getV()&0xFFFF)!=0) + ++rx; + + break; + } + + return rx; + } + + int real_y(fix fy) + { + return fy.getV()>>16; + } + + void draw() + { + realSprite.draw(); + } + + void drawcloaked() + { + realSprite.drawcloaked(); + } + + bool hit(sprite@ s) + { + if((scriptcoldet&1)==0) + return false; + + if(id<0 || s.id<0 || clk<0) + return false; + + return hit(s.x+s.hxofs, s.y+s.hyofs, s.z+s.zofs, s.hxsz, s.hysz, s.hzsz); + } + + bool hit(int tx,int ty,int tz,int txsz2,int tysz2,int tzsz2) + { + if((scriptcoldet&1)==0) + return false; + + if(id<0 || clk<0) + return false; + + return tx+txsz2>x+hxofs && + ty+tysz2>y+hyofs && + tz+tzsz2>z+zofs && + + tx=160 && currscr>=0x70 && !screenFlagSet(wfDOWN))); + } +} + diff --git a/output/common/angelscript/tektite.as b/output/common/angelscript/tektite.as new file mode 100644 index 0000000000..6fd761e489 --- /dev/null +++ b/output/common/angelscript/tektite.as @@ -0,0 +1,261 @@ +class Tektite: enemy +{ + private fix old_y; // a kludge used to check for ZScript modification of Y + private int c; + private int clk2start; + private int cstart; + + Tektite() + { + old_y=y; + dir=down; + misc=1; + clk=-15; + + if(!BSZ) + clk*=rand()%3+1; + + // avoid divide by 0 errors + if(dmisc1 == 0) + dmisc1 = 24; + + if(dmisc2 == 0) + dmisc2 = 3; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(questRuleEnabled(qr_ENEMIESZAXIS)) + { + y=floor_y; + } + + if(clk>=0 && stunclk==0 && (!watch || misc==0)) + { + int nb; + switch(misc) + { + case 0: // normal + if((rand()%dmisc1)==0) + { + misc=1; + clk2=32; + } + + break; + + case 1: // waiting to pounce + clk2-=1; + if(clk2<=0) + { + int r=rand(); + misc=2; + step=0-((dstep)/100.0); // initial speed + clk3=(r&1)+2; // left or right + clk2=(r&31)+10; // flight time + clk2start=clk2; + + if(y<32) clk2+=2; // make them come down from top of screen + + if(y>112) clk2-=2; // make them go back up + + cstart=c = 9-((r&31)>>3); // time before gravity kicks in + } + + break; + + case 2: // in flight + move(step); + + if(step>0) //going down + { + if(COMBOTYPE(x+8,y+16)==cNOJUMPZONE) + { + step=0-step; + } + else if(COMBOTYPE(x+8,y+16)==cNOENEMY) + { + step=0-step; + } + else if(MAPFLAG(x+8,y+16)==mfNOENEMY) + { + step=0-step; + } + else if(MAPCOMBOFLAG(x+8,y+16)==mfNOENEMY) + { + step=0-step; + } + } + else if(step<0) + { + if(COMBOTYPE(x+8,y)==cNOJUMPZONE) + { + step=0-step; + } + else if(COMBOTYPE(x+8,y)==cNOENEMY) + { + step=0-step; + } + else if(MAPFLAG(x+8,y)==mfNOENEMY) + { + step=0-step; + } + else if(MAPCOMBOFLAG(x+8,y)==mfNOENEMY) + { + step=0-step; + } + } + + if(clk3==left) + { + if(COMBOTYPE(x,y+8)==cNOJUMPZONE) + { + clk3^=1; + } + else if(COMBOTYPE(x,y+8)==cNOENEMY) + { + clk3^=1; + } + else if(MAPFLAG(x,y+8)==mfNOENEMY) + { + clk3^=1; + } + else if(MAPCOMBOFLAG(x,y+8)==mfNOENEMY) + { + clk3^=1; + } + } + else + { + if(COMBOTYPE(x+16,y+8)==cNOJUMPZONE) + { + clk3^=1; + } + else if(COMBOTYPE(x+16,y+8)==cNOENEMY) + { + clk3^=1; + } + else if(MAPFLAG(x+16,y+8)==mfNOENEMY) + { + clk3^=1; + } + else if(MAPCOMBOFLAG(x+16,y+8)==mfNOENEMY) + { + clk3^=1; + } + } + + --c; + + if(c<0 && step<(dstep/100.0)) + { + step+=(dmisc3/100.0); + } + + nb=questRuleEnabled(qr_NOBORDER) ? 16 : 0; + + if(x<=16-nb) clk3=right; + + if(x>=224+nb) clk3=left; + + x += (clk3==left) ? -1 : 1; + + clk2-=1; + if((clk2<=0 && y>=16-nb) || y>=144+nb) + { + if(y>=144+nb && questRuleEnabled(qr_ENEMIESZAXIS)) + { + step=0-step; + y--; + } + else if((rand()%dmisc2)!=0) //land and wait + { + clk=0; + misc=0; + } //land and jump again + else + { + misc=1; + clk2=0; + } + } + + break; + } // switch + } + + if(questRuleEnabled(qr_ENEMIESZAXIS) && misc==2) + { + int tempy = floor_y; + z=zc_max(0,zc_min(clk2start-clk2,clk2)); + floor_y = y; + y=tempy-z; + old_y = y; + } + + if(stunclk!=0 && (clk&31)==1) + clk=0; + + return enemy::animate(index); + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + void DrawShadow() + { + if(z<1 && questRuleEnabled(qr_ENEMIESZAXIS)) + return; + + int tempy=yofs; + int fdiv = frate/4; + int efrate = fdiv == 0 ? 0 : clk/fdiv; + int f2=questRuleEnabled(qr_NEWENEMYTILES)? + efrate:((clk>=(frate>>1))?1:0); + flip = 0; + shadowtile = getSpriteTile(iwShadow); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + if(misc==0) + { + shadowtile+=f2; + } + else if(misc!=1) + shadowtile+=2; + } + else + { + if(misc==0) + { + shadowtile += (f2!=0) ? 1 : 0; + } + else if(misc!=1) + { + shadowtile+=1; + } + } + + yofs+=8; + + if(!questRuleEnabled(qr_ENEMIESZAXIS) && misc==2) + { + yofs+=zc_max(0,zc_min(clk2start-clk2,clk2)); + } + + enemy::drawshadow(); + yofs=tempy; + } +} + diff --git a/output/common/angelscript/trapConstant.as b/output/common/angelscript/trapConstant.as new file mode 100644 index 0000000000..68da0b2780 --- /dev/null +++ b/output/common/angelscript/trapConstant.as @@ -0,0 +1,146 @@ +class TrapConstant: enemy +{ + TrapConstant() + { + lasthit=-1; + lasthitclk=0; + mainguy=false; + count_enemy=false; + step=2; + + if(dmisc1==1 || (dmisc1==0 && (rand()&2)!=0)) + { + dir=(x<=112)?right:left; + } + else + { + dir=(y<=72)?down:up; + } + + if(questRuleEnabled(qr_TRAPPOSFIX)) + { + yofs = playing_field_offset; + } + + dummy_int1=0; + } + + bool Update(int index) + { + if(clk<0) + return enemy::animate(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(!questRuleEnabled(qr_PHANTOMPLACEDTRAPS)) + { + if(lasthitclk>0) + { + lasthitclk-=1; + } + else + { + lasthit=-1; + } + + bool hitenemy=false; + + for(int j=0; j=160) + return true; + break; + + case left: + if(x<=0) + return true; + break; + + case right: + if(x>=240) + return true; + break; + } + + return false; + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + int takehit(weapon@ w) + { + return 0; + } +} + diff --git a/output/common/angelscript/trapLOS.as b/output/common/angelscript/trapLOS.as new file mode 100644 index 0000000000..08017435e1 --- /dev/null +++ b/output/common/angelscript/trapLOS.as @@ -0,0 +1,317 @@ +class TrapLOS: enemy +{ + int ox2; + int oy2; + + TrapLOS() + { + ox2=x; //original x + oy2=y; //original y + + if(questRuleEnabled(qr_TRAPPOSFIX)) + { + yofs = playing_field_offset; + } + + mainguy=false; + count_enemy=false; + dummy_int1=0; + } + + bool Update(int index) + { + if(clk<0) + return enemy::animate(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(misc==0) // waiting + { + ox2 = x; + oy2 = y; + double ddir=atan2(y-Link.y, Link.x-x); + + if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4))) + { + dir=down; + } + else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4))) + { + dir=right; + } + else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4))) + { + dir=up; + } + else + { + dir=left; + } + + int d2=lined_up(15,true); + + if(((d2 right) && (dmisc1==1)) || + ((d2>down) && (dmisc1==2)) || + ((d2>right) && (dmisc1==0)) || + ((d2=oy2) trap_rest=true; + else sprite::move(step); + + break; + + case right: + if(int(x)>=ox2) trap_rest=true; + else sprite::move(step); + + break; + + case l_up: + if(int(x)<=ox2 && int(y)<=oy2) trap_rest=true; + else sprite::move(step); + + break; + + case r_up: + if(int(x)>=ox2 && int(y)<=oy2) trap_rest=true; + else sprite::move(step); + + break; + + case l_down: + if(int(x)<=ox2 && int(y)>=oy2) trap_rest=true; + else sprite::move(step); + + break; + + case r_down: + if(int(x)>=ox2 && int(y)>=oy2) trap_rest=true; + else sprite::move(step); + + break; + } + + if(trap_rest) + { + x=ox2; + y=oy2; + misc=0; + } + } + + return enemy::animate(index); + } + + bool trapmove(int ndir) + { + if(questRuleEnabled(qr_MEANTRAPS)) + { + if(screenFlagSet(fFLOATTRAPS)) + return canmove(ndir, 1, spw_floater, 0, 0, 15, 15); + + return canmove(ndir, 1, spw_water, 0, 0, 15, 15); + } + + if(oy2==80 && !(ndir==left || ndir == right)) + return false; + + if(ox2==128 && !(ndir==up || ndir==down)) + return false; + + if(oy2<80 && ndir==up) + return false; + + if(oy2>80 && ndir==down) + return false; + + if(ox2<128 && ndir==left) + return false; + + if(ox2>128 && ndir==right) + return false; + + if(ox2<128 && oy2<80 && ndir==l_up) + return false; + + if(ox2<128 && oy2>80 && ndir==l_down) + return false; + + if(ox2>128 && oy2<80 && ndir==r_up) + return false; + + if(ox2>128 && oy2>80 && ndir==r_down) + return false; + + return true; + } + + bool clip() + { + if(questRuleEnabled(qr_MEANPLACEDTRAPS)) + { + switch(dir) + { + case up: + if(y<=0) return true; + + break; + + case down: + if(y>=160) return true; + + break; + + case left: + if(x<=0) return true; + + break; + + case right: + if(x>=240) return true; + + break; + + case l_up: + if(y<=0||x<=0) return true; + + break; + + case l_down: + if(y>=160||x<=0) return true; + + break; + + case r_up: + if(y<=0||x>=240) return true; + + break; + + case r_down: + if(y>=160||x>=240) return true; + + break; + } + + return false; + } + else + { + switch(dir) + { + case up: + if(oy2>80 && y<=86) return true; + + break; + + case down: + if(oy2<80 && y>=80) return true; + + break; + + case left: + if(ox2>128 && x<=124) return true; + + break; + + case right: + if(ox2<120 && x>=116) return true; + + break; + + case l_up: + if(oy2>80 && y<=86 && ox2>128 && x<=124) return true; + + break; + + case l_down: + if(oy2<80 && y>=80 && ox2>128 && x<=124) return true; + + break; + + case r_up: + if(oy2>80 && y<=86 && ox2<120 && x>=116) return true; + + break; + + case r_down: + if(oy2<80 && y>=80 && ox2<120 && x>=116) return true; + + break; + } + + return false; + } + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } + + int takehit(weapon@ w) + { + return 0; + } +} diff --git a/output/common/angelscript/trigger.as b/output/common/angelscript/trigger.as new file mode 100644 index 0000000000..687977d12e --- /dev/null +++ b/output/common/angelscript/trigger.as @@ -0,0 +1,14 @@ +class Trigger: enemy +{ + Trigger() + { + hxofs=1000; + } + + void Draw() + { + update_enemy_frame(); + enemy::draw(); + } +} + diff --git a/output/common/angelscript/walkingEnemy.as b/output/common/angelscript/walkingEnemy.as new file mode 100644 index 0000000000..c471f6e1f6 --- /dev/null +++ b/output/common/angelscript/walkingEnemy.as @@ -0,0 +1,730 @@ +class WalkingEnemy: enemy +{ + bool haslink // Like Like + { + get const { return realEnemy.haslink; } + set { realEnemy.haslink=value; } + } + + int clk4, //Tribble clock + clk5; // Like Like clock + bool fired; // Darknut5, Bombchu + bool shield; // Darknut + bool dashing; // Rope + int multishot; // Shoot twice/thrice/n times in one halt + fix fy, shadowdistance; // Pols Voice + int starting_hp; + + WalkingEnemy() + { + multishot = 0; + fired = false; + dashing = false; + haslink = false; + dummy_bool0=false; + shield=(flags&(inv_left | inv_right | inv_back |inv_front))==0; + starting_hp=hp; + + if(dmisc9==e9tARMOS && (rand()&1)!=0) + { + step=dmisc10/100.0; + + if(anim==aARMOS4) + o_tile+=20; + } + + if((flags & guy_fadeflicker)!=0) + { + clk=0; + superman = 1; + fading=fade_flicker; + count_enemy=false; + dir=down; + + if(!canmove(down, 8, spw_none)) + clk3=int(13.0/step); + } + else if((flags & guy_fadeinstant)!=0) + { + clk=0; + } + + shadowdistance = 0; + clk4 = 0; + clk5 = 0; + } + + bool Update(int index) + { + if(dying) + { + if(haslink) + { + Link.setEaten(0); + haslink=false; + } + + if(dmisc9==e9tROPE && dmisc2==e2tBOMBCHU && !fired && hp<=0 && hp>-1000 && wpn>wEnemyWeapons) + { + hp=-1000; + activateDeathAttack(); + } + else if(wpn!=0 && wpn!=ewBrang && dmisc2==e2tFIREOCTO) // Fire Octo + { + activateDeathAttack(); + } + + KillWeapon(); + return Dead(index); + } + else if((hp<=0 && dmisc2==e2tSPLIT) || (dmisc2==e2tSPLITHIT && hp>0 && hp 60) + { + clk4=0; + superman=0; + fading=0; + + if((flags2&cmbflag_armos)!=0 && z==0) + removearmos(x,y); + + clk2=0; + + newdir(); + } + else return enemy::animate(index); + } + else if((flags2&cmbflag_armos)!=0 && z==0 && clk==0) + removearmos(x,y); + + if(haslink) + { + Link.x=x; + Link.y=y; + clk2+=1; + + if(clk2==(dmisc8==0 ? 95 : dmisc8)) + { + switch(dmisc7) + { + case e7tEATITEMS: + { + for(int i=0; i=0) switch(id>>12) + { + case 0: // Normal movement + if(dmisc9==e9tVIRE || dmisc9==e9tPOLSVOICE) //Vire + { + vire_hop(); + break; + } + else if(dmisc9==e9tROPE) //Rope charge + { + if(!fired && dashing && stunclk==0 && !watch) + { + if(dmisc2==e2tBOMBCHU && LinkInRange(16) && wpn+dmisc3 > wEnemyWeapons) //Bombchu + { + hp=-1000; + activateDeathAttack(); + } + } + + charge_attack(); + break; + } + /* + * Boomerang-throwers have a halt count of 1 + * Zols have a halt count of (rand()&7)<<4 + * Gels have a halt count of ((rand()&7)<<3)+2 + * Everything else has 48 + */ + else + { + if(wpn==ewBrang) // Goriya + { + halting_walk(rate,homing,0,hrate, 1); + } + else if(dmisc9==e9tNORMAL && wpn==0) + { + if(dmisc2==e2tSPLITHIT) // Zol + { + halting_walk(rate,homing,0,hrate,(rand()&7)<<4); + } + else if(frate<=8 && starting_hp==1) // Gel + { + halting_walk(rate,homing,0,hrate,((rand()&7)<<3)+2); + } + else // Other + { + halting_walk(rate,homing,0,hrate, 48); + } + } + else // Other + { + halting_walk(rate,homing,0,hrate, 48); + } + } + break; + + // Following cases are for just after creation-by-splitting. + case 1: + if(misc==1) + { + dir=up; + step=8; + } + + if(misc<=2) + { + move(step); + + if(!canmove(dir,0,0)) + dir=down; + } + + if(misc==3) + { + if(canmove(right,16,0)) + x+=16; + } + + misc+=1; + break; + + case 2: + if(misc==1) + { + dir=down; + step=8; + } + + if(misc<=2) + { + move(step); + } + + if(misc==3) + { + if(canmove(left,16,0)) + x-=16; + } + + misc+=1; + break; + + default: + if(misc==1) + { + dir=(rand()%4); + step=8; + } + + if(misc<=2) + { + move(step); + + if(!canmove(dir,0,0)) + dir=dir^1; + } + + if(misc==3) + { + if(dir >= left && canmove(dir,16,0)) + x+=(dir==left ? -16 : 16); + } + + misc+=1; + break; + } + + if((id>>12)!=0 && misc>=4) //recently spawned by a split enemy + { + id&=0xFFF; + step = dstep/100.0; + + if(x<32) x=32; + + if(x>208) x=208; + + if(y<32) y=32; + + if(y>128) y=128; + + misc=3; + } + } + else + { + if(clk2>2) clk2-=1; + } + + // Fire Zol + if(wpn!=0 && dmisc1==e1tEACHTILE && clk2==1 && hclk==0) + { + fireWeapon(); + + int i=numEwpns()-1; + weapon@ ew = getEwpn(i); + + if(wpn==ewFIRETRAIL && getWeaponProp(ewFIRETRAIL, WPNPROP_FRAMES)>1) + { + ew.aframe=rand()%getWeaponProp(ewFIRETRAIL, WPNPROP_FRAMES); + ew.tile+=ew.aframe; + } + } + // Goriya + else if(wpn==ewBrang && clk2==1 && sclk==0 && stunclk==0 && !watch && wpn!=0 && !WeaponOut()) + { + misc=index+100; + fireWeapon(); + + if(dmisc1==2) + { + int ndir=dir; + + if(Link.x-x==0) + { + ndir=(Link.y+8(((-6)*PI)/8))) + { + ndir=down; + } + else if((ddir<=(((2)*PI)/8))&&(ddir>(((-2)*PI)/8))) + { + ndir=right; + } + else if((ddir<=(((6)*PI)/8))&&(ddir>(((2)*PI)/8))) + { + ndir=up; + } + else + { + ndir=left; + } + } + + getEwpn(numEwpns()-1).aimedBrang=true; + + if(canmove(ndir)) + { + dir=ndir; + } + } + } + else if((clk2==16 || dmisc1==e1tCONSTANT) && dmisc1!=e1tEACHTILE && wpn!=0 && wpn!=ewBrang && sclk==0 && stunclk==0 && !watch) + switch(dmisc1) + { + case e1tCONSTANT: //Deathnut + { + // Overloading clk5 (Like Like clock) to avoid making another clock just for this attack... + if(clk5>64) + { + clk5=0; + fired=false; + } + + clk5+=(rand()&3); + + if((clk5>24)&&(clk5<52)) + { + tile+=20; //firing + + if(!fired&&(clk5>=38)) + { + fireWeapon(); + fired=true; + } + } + + break; + } + + case e1tFIREOCTO: //Fire Octo + fireWeapon(); + break; + + default: + fireWeapon(); + break; + } + + /* Fire again if: + * - clk2 about to run out + * - not already double-firing (dmisc1 is 1) + * - not carrying Link + * - one in 0xF chance + */ + if(clk2==1 && (multishot < dmisc6) && dmisc1 != e1tEACHTILE && !haslink && (rand()&15)==0) + { + newdir(rate, homing, grumble); + clk2=28; + ++multishot; + } + + if(clk2==0) + { + multishot = 0; + } + + if(isFiring()) + { + clk2=15; //this keeps the octo in place until he's done firing + updateFiring(); + } + + if(dmisc2==e2tTRIBBLE) + ++clk4; + + if(clk4==((dmisc5!=0) ? dmisc5 : 256) && (dmisc2==e2tTRIBBLE) && dmisc3!=0 && dmisc4!=0) + { + int kids = numGuys(); + int id2=dmisc3; + + for(int i=0; i=(frate>>1))?1:0); + shadowtile = getWeaponProp(iwShadow, WPNPROP_TILE); + + if(questRuleEnabled(qr_NEWENEMYTILES)) + { + shadowtile+=f2; + } + else + { + shadowtile+=(f2!=0)?1:0; + } + + yofs+=shadowdistance; + yofs+=8; + } + + enemy::drawshadow(); + yofs=tempy; + } + + int takehit(weapon@ w) + { + int wpnId = w.id; + int wpnDir = w.dir; + + if(wpnId==wHammer && shield && (flags & guy_bkshield)!=0 + && (((flags&inv_front)!=0 && wpnDir==(dir^down)) || ((flags&inv_back)!=0 && wpnDir==(dir^up)) + || ((flags&inv_left)!=0 && wpnDir==(dir^left)) || ((flags&inv_right)!=0 && wpnDir==(dir^right)))) + { + shield = false; + flags &= ~(inv_left|inv_right|inv_back|inv_front); + + if(questRuleEnabled(qr_BRKNSHLDTILES)) + o_tile=s_tile; + } + + int ret = enemy::takehit(w); + + if(sclk!=0 && dmisc2==e2tSPLITHIT) + sclk+=128; + + return ret; + } + + void charge_attack() + { + if(slide()) + return; + + if(clk<0 || dir<0 || stunclk!=0 || watch || ceiling) + return; + + if(clk3<=0) + { + fix_coords(true); + + if(!dashing) + { + int ldir = lined_up(7,false); + + if(ldir!=-1 && canmove(ldir)) + { + dir=ldir; + dashing=true; + step=(dstep/100.0)+1; + } + else newdir(4,0,0); + } + + if(!canmove(dir)) + { + step=dstep/100.0; + newdir(); + dashing=false; + } + + fix div = step; + + if(div == 0) + div = 1; + + clk3=int(16.0/div); + return; + } + + move(step); + clk3-=1; + } + + void vire_hop() + { + if(dmisc9!=e9tPOLSVOICE) + { + if(sclk!=0) + return; + } + else sclk=0; + + if(clk<0 || dying || stunclk!=0 || watch || ceiling) + return; + + int jump_width; + int jump_height; + + if(dmisc9==e9tPOLSVOICE) + { + jump_width=2; + jump_height=27; + } + else + { + jump_width=1; + jump_height=16; + } + + y=floor_y; + + if(clk3<=0) + { + fix_coords(); + + //if we're not in the middle of a jump or if we can't complete the current jump in the current direction + if(clk2<=0 || !canmove(dir,1,spw_floater) || (screenFlagSet(fSIDEVIEW) && ON_SIDEPLATFORM())) + newdir(rate,homing,dmisc9==e9tPOLSVOICE ? spw_floater : spw_none); + + if(clk2<=0) + { + if(!canmove(dir,2,spw_none) || m_walkflag(x,y,spw_none) || (rand()&15)>=hrate) + clk2=wpn==ewBrang ? 1 : int(16*jump_width/step); + } + + if(dmisc9!=e9tPOLSVOICE && dir>=left) //if we're moving left or right + { + clk2=int(16*jump_width/step); + } + + clk3=int(16.0/step); + } + + clk3-=1; + + if(dmisc9==e9tPOLSVOICE || clk2>0) + move(step); + + floor_y=y; + clk2-=1; + + //if we're in the middle of a jump + if(clk2>0 && (dir>=left || dmisc9==e9tPOLSVOICE)) + { + // Casting to double and using regular sin() breaks this terribly. + // I have no idea why. + int h = int(fix(clk2*128*step/(16*jump_width)).sin()*jump_height); + + if(questRuleEnabled(qr_ENEMIESZAXIS) && !screenFlagSet(fSIDEVIEW)) + { + z=h; + } + else + { + y=floor_y-h; + shadowdistance=h; + } + } + else + shadowdistance = 0; + } + + void eatlink() + { + if(!haslink && Link.getEaten()==0 && Link.getAction() != hopping && Link.getAction() != swimming) + { + haslink=true; + y=floor_y; + z=0; + + if(Link.isSwimming()) + { + Link.x=x; + Link.y=y; + } + else + { + x=Link.x; + y=Link.y; + } + + clk2=0; + } + } + + bool WeaponOut() + { + for(int i=0; i80 && clk>=0) + { + int wall=link_on_wall(); + int wallm_cnt=0; + + for(int i=0; i0) + { + --wall; + misc=1; //emerging from the wall? + clk2=0; + clk3=wall^1; + wallm_load_clk=frame; + + if(wall<=down) + { + if(LinkDir()==left) + dir=right; + else + dir=left; + } + else + { + if(LinkDir()==up) + dir=down; + else + dir=up; + } + + switch(wall) + { + case up: + y=0; + break; + + case down: + y=160; + break; + + case left: + x=0; + break; + + case right: + x=240; + break; + } + + switch(dir) + { + case up: + y=LinkY()+48-(wallm_cnt&1)*12; + flip=wall&1; + break; + + case down: + y=LinkY()-48+(wallm_cnt&1)*12; + flip=((wall&1)^1)+2; + break; + + case left: + x=LinkX()+48-(wallm_cnt&1)*12; + flip=(wall==up?2:0)+1; + break; + + case right: + x=LinkX()-48+(wallm_cnt&1)*12; + flip=(wall==up?2:0); + break; + } + } + } + } + else + wallm_crawl(); + + return enemy::animate(index); + } + + void wallm_crawl() + { + bool w=watch; + hxofs=0; + + if(slide()) + { + return; + } + + // if(dying || watch || (!haslink && stunclk)) + if(dying || (!haslink && stunclk!=0)) + { + return; + } + + watch=false; + clk2+=1; + // Misc1: slightly different movement + misc=(clk2/(dmisc1==1?40:int((40.0/dstep)*40)))+1; + + if(w&&misc>=3&&misc<=5) + { + clk2-=1; + } + + switch(misc) + { + case 1: + case 2: + { + int temp=dir; + dir=clk3; + clk3=temp; + move(step); + temp=dir; + dir=clk3; + clk3=temp; + break; + } + case 3: + case 4: + case 5: + if(w) + { + watch=w; + return; + } + + move(step); + break; + + case 6: + case 7: + { + int temp=dir; + dir=clk3; + clk3=temp; + dir^=1; + move(step); + dir^=1; + temp=dir; + dir=clk3; + clk3=temp; + break; + } + + default: + misc=0; + break; + } + + // The transition to AngelScript seems to have affected the movement + // slightly, suggesting this was very fragile in the first place... + if(clk3==right && x<0) + x=0; + else if(clk3==left && x>240) + x=240; + else if(clk3==down && y<0) + y=0; + else if(clk3==up && y>160) + y=160; + + watch=w; + } + + // TODO: Currently unused - fix that. + // This was calle by GrabLink(), which was called by LinkClass::hitlink(). + void grablink() + { + haslink=true; + superman=1; + } + + void Draw() + { + dummy_bool1=haslink; + update_enemy_frame(); + + if(misc>0) + { + masked_draw(16,playing_field_offset+16,224,144); + } + } + + int link_on_wall() + { + int lx = Link.x; + int ly = Link.y; + + if(lx>=48 && lx<=192) + { + if(ly==32) return up+1; + + if(ly==128) return down+1; + } + + if(ly>=48 && ly<=112) + { + if(lx==32) return left+1; + + if(lx==208) return right+1; + } + + return 0; + } +} + diff --git a/output/common/angelscript/weapon.as b/output/common/angelscript/weapon.as new file mode 100644 index 0000000000..82643e9ddf --- /dev/null +++ b/output/common/angelscript/weapon.as @@ -0,0 +1,64 @@ +class weapon: sprite +{ + __RealWeapon@ realWeapon; + + weapon() + { + @realWeapon=__getRealWeapon(); + } + + int power + { + get const { return realWeapon.power; } + set { realWeapon.power=value; } + } + + int type + { + get const { return realWeapon.type; } + set { realWeapon.type=value; } + } + + int parentid + { + get const { return realWeapon.parentid; } + set { realWeapon.parentid=value; } + } + + int parentitem + { + get const { return realWeapon.parentitem; } + set { realWeapon.parentitem=value; } + } + + uint16 aframe + { + get const { return realWeapon.aframe; } + set { realWeapon.aframe=value; } + } + + int o_tile + { + get const { return realWeapon.o_tile; } + set { realWeapon.o_tile=value; } + } + + int o_cset + { + get const { return realWeapon.o_cset; } + set { realWeapon.o_cset=value; } + } + + bool aimedBrang + { + get const { return realWeapon.aimedBrang; } + set { realWeapon.aimedBrang=value; } + } + + + void adjustDraggedItem(int removed) + { + realWeapon.adjustDraggedItem(removed); + } +} + diff --git a/output/common/angelscript/wizzrobe.as b/output/common/angelscript/wizzrobe.as new file mode 100644 index 0000000000..878e6fcc29 --- /dev/null +++ b/output/common/angelscript/wizzrobe.as @@ -0,0 +1,351 @@ +class Wizzrobe: enemy +{ + bool charging; + bool firing; + int fclk; + + Wizzrobe() + { + switch(dmisc1) + { + case 0: + hxofs=1000; + fading=fade_invisible; + // Set clk to just before the 'reappear' threshold + clk=zc_min(clk+(146+zc_max(0,dmisc5))+14,(146+zc_max(0,dmisc5))-1); + break; + + default: + dir=(loadside==right)?right:left; + misc=-3; + break; + } + + charging=false; + firing=false; + fclk=0; + + if(dmisc1==0) frate=1200+146; //1200 = 20 seconds + } + + bool Update(int index) + { + if(dying) + { + return Dead(index); + } + + if(clk==0) + { + removearmos(x,y); + } + + if(dmisc1!=0) // Floating + { + wizzrobe_attack(); + } + else // Teleporting + { + if(watch) + { + fading=0; + hxofs=0; + } + else switch(clk) + { + case 0: + if(dmisc2!=0) + { + place_on_axis(true, dmisc4!=0); + } + else + { + int t=0; + bool placed=false; + + while(!placed && t<160) + { + if(isdungeon()) + { + x=((rand()%12)+2)*16; + y=((rand()%7)+2)*16; + } + else + { + x=((rand()%14)+1)*16; + y=((rand()%9)+1)*16; + } + + if(!m_walkflag(x,y,spw_door)&&((abs(x-Link.x)>=32)||(abs(y-Link.y)>=32))) + { + placed=true; + } + + ++t; + } + + if(abs(x-Link.x)=(146+zc_max(0,dmisc5))) + clk=-1; + + break; + } + } + + return enemy::animate(index); + } + + void wizzrobe_attack() + { + if(clk<0 || dying || stunclk!=0 || watch || ceiling) + return; + + if(clk3<=0 || ((clk3&31)==0 && !canmove(dir, 1, spw_door) && misc==0)) + { + fix_coords(); + + switch(misc) + { + case 1: //walking + if(!m_walkflag(x,y,spw_door)) + misc=0; + else + { + clk3=16; + + if(!canmove(dir, 1, spw_wizzrobe)) + { + wizzrobe_newdir(0); + } + } + + break; + + case 2: //phasing + { + int jx=x; + int jy=y; + int jdir=-1; + + switch(rand()&7) + { + case 0: + jx-=32; + jy-=32; + jdir=15; + break; + + case 1: + jx+=32; + jy-=32; + jdir=9; + break; + + case 2: + jx+=32; + jy+=32; + jdir=11; + break; + + case 3: + jx-=32; + jy+=32; + jdir=13; + break; + } + + if(jdir>0 && jx>=32 && jx<=208 && jy>=32 && jy<=128) + { + misc=3; + clk3=32; + dir=jdir; + break; + } + } + + case 3: + dir&=3; + misc=0; + + case 0: + wizzrobe_newdir(64); + + default: + if(!canmove(dir, 1, spw_door)) + { + if(canmove(dir, 15, spw_wizzrobe)) + { + misc=1; + clk3=16; + } + else + { + wizzrobe_newdir(64); + misc=0; + clk3=32; + } + } + else + { + clk3=32; + } + + break; + } + + if(misc<0) + misc==1; + } + + clk3-=1; + + switch(misc) + { + case 1: + case 3: + step=1.0; + break; + + case 2: + step=0; + break; + + default: + step=0.5; + break; + + } + + move(step); + + if(dmisc1!=0 && misc<=0 && clk3==28) + { + if(dmisc2 != 1) + { + if(lined_up(8,false) == dir) + { + fireWeapon(); + fclk=30; + } + } + else + { + if((rand()%500)>=400) + { + fireWeapon(); + fclk=30; + } + } + } + + if(misc==0 && (rand()&127)==0) + misc=2; + + if(misc==2 && clk3==4) + fix_coords(); + + if(!(charging||firing)) //should never be charging or firing for these wizzrobes + { + if(fclk>0) + { + --fclk; + } + } + + } + + void wizzrobe_newdir(int homing) + { + // Wizzrobes shouldn't move to the edge of the screen; + // if they're already there, they should move toward the center + if(x<32) + dir=right; + else if(x>=224) + dir=left; + else if(y<32) + dir=down; + else if(y>=144) + dir=up; + else + newdir(4, homing, spw_wizzrobe); + } + + void Draw() + { + if(dmisc1!=0 && (misc==1 || misc==3) && (clk3&1)!=0 && hp>0 && !watch && stunclk==0) // phasing + return; + + int tempint=dummy_int1; + bool tempbool1=dummy_bool1; + bool tempbool2=dummy_bool2; + dummy_int1=fclk; + dummy_bool1=charging; + dummy_bool2=firing; + update_enemy_frame(); + dummy_int1=tempint; + dummy_bool1=tempbool1; + dummy_bool2=tempbool2; + enemy::draw(); + } +} + diff --git a/output/common/angelscript/zora.as b/output/common/angelscript/zora.as new file mode 100644 index 0000000000..faaaa53eee --- /dev/null +++ b/output/common/angelscript/zora.as @@ -0,0 +1,143 @@ +class Zora: enemy +{ + private int maxHP; + + Zora() + { + mainguy=false; + count_enemy=false; + maxHP=hp; + } + + bool Update(int index) + { + if(dying) + return Dead(index); + + if(clk==0) + { + removearmos(x,y); + } + + if(watch) + { + // WEIRDNESS: This doesn't match the C++ implementation, + // but it seems to work. Better make sure, though... + clk=0; + return false; + } + + if(questRuleEnabled(qr_NEWENEMYTILES)) + facelink(); + + switch(clk) + { + case 0: // reposition him + { + int t=0; + int pos2=rand()%160 + 16; + bool placed=false; + + while(!placed && t<160) + { + if(iswater(pos2) && (pos2&15)>0 && (pos2&15)<15) + { + x=(pos2&15)<<4; + y=pos2&0xF0; + hp=maxHP; // refill life each time + hxofs=1000; // avoid hit detection + stunclk=0; + placed=true; + } + + pos2+=19; + + if(pos2>=176) + pos2-=160; + + ++t; + } + + if(!placed || whistleclk>=88) // can't place him, he's gone + return true; + + } + break; + + case 35: + if(!questRuleEnabled(qr_NEWENEMYTILES)) + dir=(Link.y+8(((-7)*PI)/8))) + { + dir=l_down; + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + dir=down; + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + dir=r_down; + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + dir=right; + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + dir=r_up; + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + dir=up; + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + dir=l_up; + } + else + { + dir=left; + } + } + } + + void Draw() + { + if(clk<3) + return; + + update_enemy_frame(); + enemy::draw(); + } +} + diff --git a/output/common/std.txt b/output/common/std.txt new file mode 100644 index 0000000000..9d9d7cab16 --- /dev/null +++ b/output/common/std.txt @@ -0,0 +1,657 @@ +================= +--- Constants --- +================= + +const float PI, PI2, E + * The mathematical constants pi, 2*pi and e. + +const int NULL + * Refers to an invalid array pointer, returned by ALLOCATEMEM when memory cannot be allocated + +const int MAX_CONSTANT, float MAX_VARIABLE +const int MAX_BITSPERVARIABLE +const int MAX_SCRIPTDRAWINGCOMMANDS +const int MAX_MESSAGES +const int MAX_MESSAGELENGTH +const int MAX_DMAPS +const int MAX_DMAPNAMELENGTH, MAX_DMAPTITLELENGTH, MAX_DMAPINTROLENGTH + * Information about some system constraints + +const float GRAVITY +const float TERMINAL_VELOCITY +const float JUMPING_LAYER_THRESHOLD + * Some defaults from Init. Data + +const int HP_PER_HEART, MP_PER_BLOCK + * Constants about how HP and MP work + +const int SFX_* + * Sound effects, can be used with Game->PlaySound. + +const int IC_* + * Itemclass IDs, can be compared against itemdata->Family + +const int I_* + * Item IDs, can be used with Link->Item, Link->Equipment, item->ID, Link->HeldItem, GetEquipmentA, + * GetEquipmentB, Screen->CreateItem, CreateItemAt, NumItemsOf + +const int LA_* + * Link's actions, can be used to set or compare against Link->Action + +const int NPCT_* + * NPC Types, can be used to compare against npc->Type + +const int NPC_* + * NPC IDs, can be used with npc->ID, Screen->CreateNPC, NumNPCsOf + +const int HP_SILENT + * NPC HP value, can be used to set npc->HP + +const int LW_* + * LWeapon IDs, can be used with lweapon->ID, Screen->CreateLWeapon, CreateLWeaponAt, NumLWeaponsOf + +const int EW_* + * EWeapon IDs, can be used with eweapon->ID, Screen->CreateEWeapon, CreateEWeaponAt, NumEWeaponsOf + +const int WDS_* + * Weapon DeadState Values, can be used to set or compare against *weapon->DeadState + +const int FFCF_* + * FFC Flags, can be used to set or compare against ffc->Flags[] + +const int DIR_* + * Directions, can be used with Link->Dir, npc->Dir, *weapon->Dir + +const int CF_* + * Combo Flags, can be used with Screen->ComboF[], Screen->ComboI[], Game->GetComboFlag, Game->SetComboFlag, + * Game->GetComboInherentFlag, Game->SetComboInherentFlag + +const int CT_* + * Combo Types, can be used with Screen->ComboT[], Game->GetComboType, Game->SetComboFlag + +const int IP_* + * Item Pickup Flags, can be used with item->Pickup, GetItemPickup, SetItemPickup + +const int SF_* + * Screen Flag Categories, can be used with Screen->Flags, GetScreenFlags + +const int SEF_* + * Screen Enemy Flag Categories, can be used with Screen->EFlags, GetScreenEFlags + +const int DMF_* + * DMap Flags, can be used with Game->DMapFlags[], GetDMapFlag, SetDMapFlag + +const int NPCA*_* + * NPC Attributes, can be used to compare against npc->Attributes[] + +const int NPCD_* + * NPC Defenses, can be used to compare against npc->Defense[] + +const int NPCDT_* + * NPC Defense types, can be used to compare against npc->Defense[] + +const int DS_* + * Draw Styles, can be used with item->DrawStyle + +const int WT_* + * Warp Types, can be used with Screen->SetSideWarp, Screen->SetTileWarp + +const int FONT_* + * Font Types, can be used with Screen->DrawCharacter, Screen->DrawString, Screen->DrawInteger + +const int TF_* + * Text Formats, can be used with Screen->DrawString + +const int PT_* + * Texture Mapping Rendering Modes, can be used with Screen->*3D + +const int OP_* + * Opacity options, can be used with all shape and tile drawing commands. + +const int RT_* + * Render targets, can be used with Screen->SetRenderTarget and Screen->DrawBitmap. + +const int EXT_* + * Sprite Extend Types, can be used with Link->Extend, npc->Extend, *weapon->Extend, item->Extend + +const int CR_* + * Counter types, can be used with itemclass->Counter, Game->Counter[], Game->MCounter[], Game->DCounter[] + +const int GEN_* + * Generic Data Types, can be used to set or compare against Game->Generic[] + +const int LI_* + * Level Item Flags, can be used with Game->LItems[], GetLevelItems, SetLevelItems + +cosnt int ST_* + * Screen States, can be used with Screen->State[], Game->GetScreenState, Game->SetScreenState + +const int D_* + * Door types, can be used with Screen->Door[] + +const int WPN_* + * Enemy Weapon Types, can be used with npc->Weapon + +const int AT_* + * Weapon aim types, to be used with AimEWeapon + +const int IS_* + * Item Drop Sets, can be used to set or compare against npc->ItemSet + +const int BPAL_* + * Boss Palletes, can be used to set or compare against npc->BossPal + +const int SL_* + * Sprite Lists, can be used with Screen->ClearSprites + +const int MB_* + * Mouse Buttons, can be used with Link->InputMouseB + + +================= +--- Functions --- +================= + +-- Mathematical Functions -- +============================ + +float LogToBase(float x, float base) + * Returns the logarithm of x to the given base + +int Floor(float x) + * Truncates x to an integer + +int Ceiling(float x) + * Raises x to the nearest integer + +int Round(float x) + * Rounds x to the nearest integer + +int VBound(int x, int high, int low) + * Bounds x between two values + +int Div(float x, float y) + * Modulo's complement; returns the quotient only of x divided by y + +int Rand(int min, int max) + * Overload to rand, returning a random integer in the bounds of min and max + +float Randf(float n) + * Returns a random floating point number up to n + +float Randf(float n1, float n2) + * Overloaded to take two boundaries as arguments + +float DegtoRad(float d) + * Converts 'd' in degrees to radians + +float RadtoDeg(float r) + * Converts 'r' in radians to degrees + +int Sign(int n) + * Returns the sign of n + +float Distance(int x1, int y1, int x2, int y2) + * Returns the distance between two sets of coordinates using Pythagoras' Theorem + +float Angle(int x1, int y1, int x2, int y2) + * Returns the direction of the vector from point 1 to point 2, in degrees from -180 to 180. (0 = right) + +float RadianAngle(int x1, int y1, int x2, int y2) + * The above, but in radians. + +float VectorX(int len, float angle) + * Returns the X component of a vector with a degree angle. + * A length of 3 and angle of 0 returns 3. + * A length of 3 and angle of 45 returns approx. 1.57. + * A length of 3 and angle of 90 returns 0. + +float VectorY(int len, float angle) + * Returns the Y component of a vector with a degree angle. + * A length of 3 and angle of 0 returns 0. + * A length of 3 and angle of 45 returns approx. 1.57. + * A length of 3 and angle of 90 returns 3. + +float Lerp(float p1, float p2, float t) + * Interpolates between p1 and p2 given 't' clamped within range 0,1. + +float DotProduct( float x1, float y1, float x2, float y2 ) + * Returns the dot product of two vectors. + +float CrossProduct( float x1, float y1, float x2, float y2 ) + * Returns the cross product of two vectors. + +float DistanceSquared( float x, float y ) + * Returns the squared distance of a vector. + +float Midpoint(float p1, float p2) + * Finds the center of p1 and p2. + +float SmoothStep(float p1, float p2, float t) + * Performs a "Smooth" Interpolation given 't' clamped within range 0,1. + +float WrapAngle( float radians ) + * Wraps radian value towards the range of -PI,PI. + +float WrapDegrees( float degrees ) + * Wraps degree value towards the range of -180,180. + +float TurnTowards( int X, int Y, int targetX, int targetY, float radian_angle, float t ) + * Returns an angle pointing (t)percentage more accurate to the target than the specified radian_angle. + +-- Direction Functions -- +========================= + * Make sure your angles are in the range -PI to PI (with WrapAngle) before using these functions + + +int AngleDir8(float angle) + * Converts a counterclockwise degree angle (from -180 to 180) into one of the eight + * standard directions (DIR_UP etc.) used by ZC. + +int RadianAngleDir8(float angle) + * The above, but for radian angles. + +int AngleDir4(float angle) + * Converts a counterclockwise degree angle (from -180 to 180) into one of the four + * standard directions (DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT) used by ZC. + +int RadianAngleDir4(float angle) + * The above, but for radian angles. + +int OppositeDir(int dir) + * Returns the opposite direction to 'dir' + +int SpinDir(int dir) + * Converts directions to go round in a circle rather than U, D, L, R + +-- Drawing Functions -- +======================= + +void DrawString(int layer, int x, int y, int font, int color, int background_color, int format, int opacity, + int string, int start) + * Overload to Screen->DrawString which includes a position to start drawing from in the string + * Does not check for overflow + +void DrawString(int layer, int x, int y, int font, int color, int background_color, int format, int opacity, + int string, int start, int end) + * Overload to Screen->DrawString which includes a start and end position to draw the string + * Does not check for overflow + +void DrawTileSimple(int x, int y, int tile, int color) + * A very simple layer 0 tile drawing routine. + +void DrawToLayer(T ptr, int layer, int opacity) + * Draws a pointer to given layer. Overloaded to take all pointers as arguments + + +-- Conditional Functions -- +=========================== + +T Cond(bool cond, T a, T b) + * Returns a if cond is true, else b. Overloaded to take all types as arguments + +float Choose(float a, float b) +float Choose(float a, float b, float c) +float Choose(float a, float b, float c, float d) +float Choose(float a, float b, float c, float d, float e) +float Choose(float a, float b, float c, float d, float e, float f) + * Chooses one of the options randomly and fairly. + + +-- Collision Detection Functions -- +=================================== + +bool RectCollision(int box1_x1, int box1_y1, int box1_x2, int box1_y2, int box2_x1, int box2_y1, int box2_x2, int box2_y2) + * Generalized and optimized rectangle collision checking function. + * Returns true if the bounding box of box1 and box2 overlap. + +bool SquareCollision(int c1x, int c1y, int side1, int c2x, int c2y, int side2) + * Check for collisions of two squares given upper-left coordinates and a side length for each. + +bool SquareCollision2(int c1x, int c1y, int radius1, int c2x, int c2y, int radius2) + * Check for collisions of two squares given center coordinates and a halved side length for each. + +bool CircleCollision(int c1x, int c1y, int radius1, int c2x, int c2y, int radius2) + * Returns true if the two circles c1 and c2 overlap. + +bool Collision(T a, S b) + * Returns true if there is a collision between the hitboxes of any two pointers + +bool LinkCollision(T ptr) + * Returns true if there is a collision between Link's hitbox and any pointer's + +int HitboxLeft(T ptr) + * Returns the X coordinate of the left edge of the hitbox for any pointer + +int HitboxTop(T ptr) + * Returns the Y coordinate of the top edge of the hitbox for any pointer + +int HitboxRight(T ptr) + * Returns the X coordinate of the right edge of the hitbox for any pointer + +int HitboxBottom(T ptr) + * Returns the Y coordinate of the bottom edge of the hitbox. + +bool CanWalk(int x, int y, int dir, int step, bool full_tile) + * This should allow any scripted object to easily mimic Link styled LOZ solidity collision + * checking, be it Link, FFCs, or enemies. + * Note - You should use full_tile=true if you don't want the upper eight pixels to overlap + * solid combos as per LOZ1 behavior. + +bool OnSidePlatform(int x, int y) +bool OnSidePlatform(int x, int y, int xOff, int yOff, int h) + * Returns true if the sprite at (x,y) is standing on a sideview platform on a sideview screen, as worked out + * by ZC's internal code. + + + +-- Functions for accessing data stored in binary format -- +========================================================== + +void SetScreenDBit(int dmap, int screen, int d, int bit, bool state) +void SetScreenDBit(int screen, int d, int bit, bool state) +void SetScreenDBit(int d, int bit, bool state) + * Sets bit 'bit' of Screen->D[] register 'd' to 'state', overloaded to set on other screens + +bool GetScreenDBit(int dmap, int screen, int d, int bit) +bool GetScreenDBit(int screen, int d, int bit) +bool GetScreenDBit(int d, int bit) + * Returns the state of bit 'bit' of Screen->D[] register 'd' + * Overloaded to get from other screens + +bool InputLeftClick() + * Returns true if the left mouse button is pressed + +bool InputRightClick() + * Returns true if the right mouse button is pressed + +int GetEquipmentA() + * Returns the item ID of the item equipped to Link's A button + +int GetEquipmentB() + * Returns the item ID of the item equipped to Link's B button + +bool UsingItem(int id) + * Returns true if Link is using item 'id' + +int ScreenFlag(int category, int flag) + * Returns 1 if Screen Flag 'flag' is set from category 'category', 0 if it's not and -1 if an invalid flag is passed + * Flags are numbered starting from 0 + +int ScreenEFlag(int category, int flag) + * Returns 1 if Screen Enemy Flag 'flag' is set from category 'category', 0 if it's not and -1 if an invalid flag is passed + * Flags are numbered starting from 0 + +bool GetDMapFlag(int dmap, int flag) + * Returns true if DMap Flag 'flag' is set on dmap 'dmap' + +void SetDMapFlag(int dmap, int flag, bool state) + * Sets a certain DMap flag to 'state' + +bool GetItemPickup(item i, int pickup) + * Returns true if an item's Pickup state is set + * Use the IP_ constants for the 'pickup' argument of this function + +void SetItemPickup(item i, int pickup, bool state) + * Sets an item's Pickup state to 'state' + +bool GetNPCMiscFlag(npc e, int flag) + * Returns true if an npc's Misc. flag is set. + +bool GetLevelItem(int level, int itm) +bool GetLevelItem(int itm) + * Returns true if Link has the level item 'itm' from level 'level' + * Overloaded to use the current level if no 'level' arg is entered + * Use the LI_ constants for the 'itm' argument + +void SetLevelItem(int level, int itm, bool state) +void SetLevelItem(int itm, bool state) + * Gives or removes a level item from Link's inventory + + +-- Functions to help handling in-built pointers -- +================================================== + +lweapon NextToLink(int id, int distx, int disty) +lweapon NextToLink(int id, int dist) + * Creates an lweapon at 'distx, disty' away from where Link is facing + +eweapon NextToNPC(npc n, int id, int distx, int disty) +eweapon NextToNPC(npc n, int id, int dist) + * Creates an eweapon at 'distx, disty' away from where npc 'n' is facing + +void AimEWeapon(eweapon e, int aimtype) + * Aims eweapon e according to the AT_* constant passed to aimtype + +void AimLWeapon(lweapon l, npc n, int aimtype) +void AimLWeapon(lweapon l, int aimtype) + * Aims lweapon l according to the AT_* constant passed to aimtype, overloaded to shoot + * at an npc or at random + +int WeaponTypeToID(int weapontype) + * Turns a WPN_* constant to an EW_* constant + +*weapon Duplicate(*weapon a) + * Creates and returns an exact copy of the passed weapon. Assumes that the passed pointer is valid. + +npc CreateNPCAt(int id, int x, int y) + * Create an NPC and set its X and Y position in one command + +item CreateItemAt(int id, int x, int y) + * Create an Item and set its X and Y position in one command + +lweapon CreateLWeaponAt(int id, int x, int y) + * Create an LWeapon and set its X and Y position in one command + +eweapon CreateEWeaponAt(int id, int x, int y) + * Create an EWeapon and set its X and Y position in one command + +void Remove(T n) + * Removes sprite 'n' from the screen. Overloaded. + +int NumLWeaponsOf(int type) + * Returns the number of lweapons of type 'type' currently on the screen + +int NumEWeaponsOf(int type) + * Returns the number of weapons of type 'type' currently on the screen + +int NumNPCsOf(int type) + * Returns the number of npcs of type 'type' currently on the screen + +int NumItemsOf(int type) + * Returns the number of items of type 'type' currently on the screen + +lweapon LoadLWeaponOf(int type) + * Returns the first LWeapon of the given type. Use the LW_ constants. + * If none exist, it returns an uninitialised pointer. + +eweapon LoadEWeaponOf(int type) + * Returns the first EWeapon of the given type. Use the EW_ constants. + * If none exist, it returns an uninitialised pointer. + +npc LoadNPCOfType(int type) + * Returns the first NPC of the given type. Use the NPCT_ constants. + * If none exist, it returns an uninitialised pointer. + +npc LoadNPCOf(int type) + * Returns the first NPC of the given ID. Use the NPC_ constants. + * If none exist, it returns an uninitialised pointer. + +item CreateTimeoutItem(int id, int x, int y) + * Creates a timeout item (such as a rupee or heart) with ID 'id' at '(x, y)' + +-- Position Functions -- +======================== + +int GridX(int x) + * Snaps 'x' to the combo grid + * Equivalent to calling ComboX(ComboAt(x, foo)); + +int GridY(int y) + * Snaps 'y' to the combo grid + * Equivalent to calling ComboY(ComboAt(foo, y)); + +int AtFrontX(int dir) +int AtFrontY(int dir) + * Returns the correct offset to be at the front of a sprite facing in + * the direction 'dir' + +int InFrontX(int dir, int dist) +int InFrontY(int dir, int dist) + * Returns the correct offset to be 'dist' pixels away from the front of + * a sprite facing in the direction 'dir' + +int CenterX(ffc anFFC) +int CenterY(ffc anFFC) +int CenterX(npc anNPC) +int CenterY(npc anNPC) +int CenterX(eweapon anEWeapon) +int CenterY(eweapon anEWeapon) +int CenterX(lweapon anLWeapon) +int CenterY(lweapon anLWeapon) +int CenterLinkX() +int CenterLinkY() + * Returns the X or Y coordinate at the center of the given sprite. + + +-- Combo Functions -- +===================== + +int ComboAt(int x, int y) + * Finds the location of a combo, given its (x,y) coordinates on the screen + +int ComboX(int loc) +int ComboY(int y) + * Return the coordinates of a combo on the screen + +bool ComboFI(int x, int y, int flag) +bool ComboFI(int loc, int flag) + * Returns true if the combo at '(x, y)' or 'loc' has either an + * inherent or placed flag of type 'flag' + +int GetLayerComboD(int layer, int pos) + * A shorthand way to get a combo on the current layer. + * Layer 0 is the screen itself. + +void SetLayerComboD(int layer, int pos, int combo) + * A shorthand way to set a combo on the current layer. + * Layer 0 is the screen itself. + +int GetLayerComboF(int layer, int pos) + * A shorthand way to get a combo flag on the current layer. + * Layer 0 is the screen itself. + +void SetLayerComboF(int layer, int pos, int flag) + * A shorthand way to set a combo flag on the current layer. + * Layer 0 is the screen itself. + +int GetLayerComboT(int layer, int pos) + * A shorthand way to get a combo type on the current layer. + * Layer 0 is the screen itself. + +void SetLayerComboT(int layer, int pos, int type) + * A shorthand way to set a combo type on the current layer. + * Layer 0 is the screen itself. + +int GetLayerComboS(int layer, int pos) + * A shorthand way to get a combo's solidity on the current layer. + * Layer 0 is the screen itself. + +void SetLayerComboS(int layer, int pos, int solidity) + * A shorthand way to set a combo's solidity on the current layer. + * Layer 0 is the screen itself. + +int FirstComboOf(int t, int layer) + * Returns the position of the first instance of the given combo, or -1. + +int LastComboOf(int t, int layer) + * Returns the position of the last instance of the given combo, or -1. + +int FirstComboTypeOf(int t, int layer) + * Returns the position of the first instance of the given combo, or -1. + +int LastComboTypeOf(int t, int layer) + * Returns the position of the last instance of the given combo, or -1. + +int FirstComboFlagOf(int t, int layer) + * Returns the position of the first instance of the given combo flag, or -1. + * Checks inherent flags too! + +int LastComboFlagOf(int t, int layer) + * Returns the position of the last instance of the given combo flag, or -1. + * Checks inherent flags too! + +bool IsWater(int position) + * Returns true if the combo at the given position is water or a swim or dive warp. Shallow water doesn't count. + +bool IsPit(int position) + * Returns true if the combo at the given position is a pit. + + +-- Tile Functions -- +==================== + +void SwapTileRow(int first, int second, int length) + * Swaps a row of tiles of length 'length' between positions 'first' and 'second' + +void CopyTileRow(int source, int dest, int length) + * Copies a row of tiles of length 'length' from 'source' onto 'dest' + +void ClearTileRow(int ref, int length) + * Clears a row of tiles of length 'length' starting from tile 'ref' + +void SwapTileBlock(int first, int last, int second) + * Swaps a block of tiles defined by diagonal corners 'first' and 'last' + * with the block starting with top left tile 'second' + +void CopyTileBlock(int sourcefirst, int sourcelast, int destfirst) + * Copies a block of tiles defined by diagonal corners 'sourcefirst' and 'sourcelast' + * onto the block starting with top left tile 'destfirst' + +void ClearTileBlock(int reffirst, int reflast) + * Clears a block of tiles defined by diagonal corners 'reffirst' and 'reflast' + + +-- Miscellaneous Functions -- +============================= + +void Waitframes(int n) + * Wait for 'n' frames + +void NoAction() + * Kills all of Link's inputs + +void WaitNoAction() +void WaitNoAction(int frames) + * NoAction, then Waitframe or (equivalent of) Waitframes + +void ScreenCopy(int destmap, int destscr, int srcmap, int srcscr) + * Copies the combos and csets from one screen to another. + * Only copies layer 0! + +int FFCNum(ffc f) + * Returns the number of an FFC, and -1 for a non-valid FFC (which should never happen) + +int NumTriforcePieces() + * Returns the number of Triforce Pieces Link currently has + +void GetNPCName(int ID, int string[]) + * Puts the name of an npc into a string + +void GetMessage(int ID, int string[]) + * Puts string 'ID' into 'string', removing the trailing spaces. + +itemdata GetItemData(item i) + * Returns an itemdata pointer from an item pointer + +int GetHighestLevelItem(int itemclass) +int GetHighestLevelItem(item i) + * Returns the highest level item of a given itemclass, or of the class 'i' belongs to + +bool IsSideview() + * Returns true if Link is on a sideview screen + +int DMapToMap(int screen, int dmap) +int MapToDMap(int screen, int dmap) + * Convert between map and DMap screen coordinates + diff --git a/output/common/std.zh b/output/common/std.zh new file mode 100644 index 0000000000..9bb85d1eec --- /dev/null +++ b/output/common/std.zh @@ -0,0 +1,9 @@ +// std.zh +// Standard header for ZScript. +// Please don't edit this file. Instead, create a new header file for your +// quests' scripts, add constants and procedures to that file, +// and import it separately. + +import "std_constants.zh" +import "std_functions.zh" + diff --git a/output/common/std_constants.zh b/output/common/std_constants.zh new file mode 100644 index 0000000000..ef871918c9 --- /dev/null +++ b/output/common/std_constants.zh @@ -0,0 +1,1267 @@ +// std_constants.zh +// Contains required constants for std.zh and ZScript functions. + + +const float PI = 3.1416; +const float PI2 = 6.2832; +const float E = 2.7183; + +const int NULL = 0; + +const float MAX_CONSTANT = 214747.9999; +//const float MAX_VARIABLE = 214748.3648; Obviously this is truncated as a constant. Equal to ((2^31)-1)/10000 +const int MAX_BITSPERVARIABLE = 18; +const int MAX_SCRIPTDRAWINGCOMMANDS = 1000; + +const int HP_PER_HEART = 16; +const int MP_PER_BLOCK = 32; + +const int MAX_MESSAGES = 65535; +const int MAX_MESSAGELENGTH = 145; //Pass an array of (at least) this size to Game->GetMessage + +const int MAX_DMAPS = 512; +const int MAX_DMAPNAMELENGTH = 21; //Size of arrays to pass to Game->GetDMapX +const int MAX_DMAPTITLELENGTH = 21; +const int MAX_DMAPINTROLENGTH = 73; + +//Defaults from Init Data +const float GRAVITY = 0.16; +const float TERMINAL_VELOCITY = 3.20; +const int JUMPING_LAYER_THRESHOLD = 16; + +//Sound effect IDs. To be used for PlaySound(). +const int SFX_ARROW = 1; // Arrow is fired. +const int SFX_BEAM = 2; // Sword beam is fired. +const int SFX_BOMB = 3; // Bomb explodes. +const int SFX_BRANG = 4; // Boomerang spinning. +const int SFX_CHARGE1 = 35; // Sword powering up. +const int SFX_CHARGE2 = 36; // Sword powering up again (Hurricane Spin). +const int SFX_CURSOR = 5; // Subscreen cursor. +const int SFX_CLINK = 6; // Shield is hit. +const int SFX_CLEARED = 7; // Chime when screen item appears. +const int SFX_DINSFIRE = 37; // Din's Fire blast. +const int SFX_DODONGO = 8; // Dodongo's roar. +const int SFX_SHUTTER = 9; // Shutter bang. +const int SFX_EDEAD = 10; // Enemy is killed. +const int SFX_EHIT = 11; // Enemy is hit. +const int SFX_LOWHP = 12; // Low hearts warning beep. +const int SFX_FALL = 38; // Enemy falls from ceiling (unused). +const int SFX_FARORESWIND = 39; // Farore's Wind spell. +const int SFX_FIRE = 13; // Flame roar. +const int SFX_FIREBALL = 40; // Enemy fireball. +const int SFX_GANON = 14; // Music when Ganon appears/dies. +const int SFX_GASP = 15; // Boss is hit. +const int SFX_GRASSCUT = 41; // Grass or bush slashed. +const int SFX_HAMMER = 16; // Hammer pound. +const int SFX_HAMMERPOST = 42; // Pounded a post. +const int SFX_HOOKSHOT = 17; // Hookshot chain rattle. +const int SFX_HOVER = 43; // Hover boots. +const int SFX_ICE = 44; // Unused. +const int SFX_JUMP = 45; // Jumping. +const int SFX_LENSOFF = 46; // Lens of Truth off. +const int SFX_LENSON = 47; // Lens of Truth on. +const int SFX_MSG = 18; // Message typing. +const int SFX_NAYRUSLOVE1 = 48; // Nayru's Love shield hum. +const int SFX_NAYRUSLOVE2 = 49; // Nayru's Love shield running out. +const int SFX_OUCH = 19; // Link is hit. +const int SFX_PICKUP = 20; // Chime when item is held above head. +const int SFX_PLACE = 21; // Bomb is placed. +const int SFX_PLINK = 22; // Heart/Rupee is collected. +const int SFX_PUSHBLOCK = 50; // Pushed a block. +const int SFX_REFILL = 23; // Hearts being refilled. +const int SFX_ROAR = 24; // Aquamentus, Gleeok and Ganon's roar. +const int SFX_ROCK = 51; // Octorok rock is fired. +const int SFX_ROCKETDOWN = 52; // Spell rocket descends. +const int SFX_ROCKETUP = 53; // Spell rocket launched. +const int SFX_SCALE = 25; // Chime when fairy appears/is picked up. +const int SFX_SEA = 26; // "Ocean SFX" ambience. +const int SFX_SECRET = 27; // Chime when secret is discovered. +const int SFX_SPINATTACK = 54; // Sword spin. +const int SFX_SPIRAL = 28; // Link dies. +const int SFX_SPLASH = 55; // Splashing in shallow water. +const int SFX_STAIRS = 29; // Link marches down stairs. +const int SFX_SUMMON = 56; // Summoner magic. +const int SFX_SWORD = 30; // Sword swipe. +const int SFX_TAP1 = 57; // Sword taps wall. +const int SFX_TAP2 = 58; // Sword taps bombable wall. +const int SFX_PATRA = 31; // Patra and Manhandla's shriek. +const int SFX_WAND = 32; // Magic is fired by Wizzrobes or Link. +const int SFX_WHIRLWIND = 59; // Whistle whirlwind. +const int SFX_WHISTLE = 33; // Whistle is played. +const int SFX_ZELDA = 34; // Music when ending sequence begins. + +//Item class ids. Use as comparisons with Itemdata->Family +const int IC_AMULET = 11; +const int IC_ARROW = 2; +const int IC_ARROWAMMO = 40; +const int IC_BAIT = 5; +const int IC_BOMB = 27; +const int IC_BOMBAMMO = 47; +const int IC_BOMBBAG = 48; +const int IC_BOOK = 16; +const int IC_BOOTS = 20; +const int IC_BOSSKEY = 35; +const int IC_BOW = 13; +const int IC_BOWANDARROW = 87; +const int IC_BRACELET = 18; +const int IC_BRANG = 1; +const int IC_CANDLE = 3; +const int IC_CBYRNA = 38; +const int IC_CHARGERING = 55; +const int IC_CLOCK = 29; +const int IC_COMPASS = 34; +const int IC_CROSSSCROLL = 52; +const int IC_DINSFIRE = 24; +const int IC_FAIRY = 41; +const int IC_FARORESWIND = 25; +const int IC_FLIPPERS = 19; +const int IC_HAMMER = 23; +const int IC_HEART = 43; +const int IC_HEARTCONTAINER = 44; +const int IC_HEARTPIECE = 45; +const int IC_HEARTRING = 58; +const int IC_HOOKSHOT = 21; +const int IC_HOVERBOOTS = 50; +const int IC_HURRICANESCROLL = 60; +const int IC_KEY = 30; +const int IC_KILLALL = 46; +const int IC_LADDER = 15; +const int IC_LENS = 22; +const int IC_LETTER = 6; +const int IC_LETTERPOTION = 88; +const int IC_LEVELKEY = 37; +const int IC_MAGIC = 42; +const int IC_MAGICCONTAINER = 31; +const int IC_MAGICKEY = 17; +const int IC_MAGICRING = 59; +const int IC_MAP = 33; +const int IC_MISC = 66; +const int IC_NAYRUSLOVE = 26; +const int IC_PERILRING = 65; +const int IC_PERILSCROLL = 56; +const int IC_POTION = 7; +const int IC_QUAKESCROLL = 53; +const int IC_QUIVER = 36; +const int IC_RAFT = 14; +const int IC_RING = 9; +const int IC_ROCS = 49; +const int IC_RUPEE = 39; +const int IC_SBOMB = 28; +const int IC_SHIELD = 12; +const int IC_SPINSCROLL = 51; +const int IC_SQUAKESCROLL = 61; +const int IC_STOMPBOOTS = 63; +const int IC_STONEAGONY = 62; +const int IC_SWORD = 0; +const int IC_TRIFORCE = 32; +const int IC_WALLET = 10; +const int IC_WAND = 8; +const int IC_WEALTHMEDAL = 57; +const int IC_WHIMSICALRING = 64; +const int IC_WHISPRING = 54; +const int IC_WHISTLE = 4; + +const int IC_CUSTOM1 = 67; +const int IC_CUSTOM2 = 68; +const int IC_CUSTOM3 = 69; +const int IC_CUSTOM4 = 70; +const int IC_CUSTOM5 = 71; +const int IC_CUSTOM6 = 72; +const int IC_CUSTOM7 = 73; +const int IC_CUSTOM8 = 74; +const int IC_CUSTOM9 = 75; +const int IC_CUSTOM10 = 76; +const int IC_CUSTOM11 = 77; +const int IC_CUSTOM12 = 78; +const int IC_CUSTOM13 = 79; +const int IC_CUSTOM14 = 80; +const int IC_CUSTOM15 = 81; +const int IC_CUSTOM16 = 82; +const int IC_CUSTOM17 = 83; +const int IC_CUSTOM18 = 84; +const int IC_CUSTOM19 = 85; +const int IC_CUSTOM20 = 86; + + +//Item IDs. Use with CreateItem() and Link->Item[]. +//These are DEFAULT values, and may not be correct for custom quests which +//have overridden item action data. +const int I_AMULET1 = 50; +const int I_AMULET2 = 63; +const int I_ARROW1 = 13; +const int I_ARROW2 = 14; +const int I_ARROW3 = 57; +const int I_ARROWAMMO1 = 70; +const int I_ARROWAMMO10 = 72; +const int I_ARROWAMMO30 = 73; +const int I_ARROWAMMO5 = 71; +const int I_BAIT = 16; +const int I_BOMB = 3; +const int I_BOMBAMMO1 = 77; +const int I_BOMBAMMO30 = 80; +const int I_BOMBAMMO4 = 78; +const int I_BOMBAMMO8 = 79; +const int I_BOMBBAG1 = 81; +const int I_BOMBBAG2 = 82; +const int I_BOMBBAG3 = 83; +const int I_BOMBBAG4 = 106; +const int I_BOOK = 32; +const int I_BOOTS = 55; +const int I_BOSSKEY = 67; +const int I_BOW1 = 15; +const int I_BOW2 = 68; +const int I_BRACELET1 = 107; +const int I_BRACELET2 = 19; +const int I_BRACELET3 = 56; +const int I_BRANG1 = 23; +const int I_BRANG2 = 24; +const int I_BRANG3 = 35; +const int I_CANDLE1 = 10; +const int I_CANDLE2 = 11; +const int I_CBYRNA = 88; +const int I_CHARGERING1 = 101; +const int I_CHARGERING2 = 102; +const int I_CLOCK = 4; +const int I_COMPASS = 22; +const int I_CROSSSCROLL = 95; +const int I_DINSFIRE = 64; +const int I_DUST_PILE = 43; +const int I_FAIRY = 34; +const int I_FAIRYSTILL = 69; +const int I_FARORESWIND = 65; +const int I_FLIPPERS = 51; +const int I_HAMMER = 54; +const int I_HCPIECE = 49; +const int I_HEART = 2; +const int I_HEARTCONTAINER = 28; +const int I_HEARTRING1 = 112; +const int I_HEARTRING2 = 113; +const int I_HEARTRING3 = 114; +const int I_HOOKSHOT1 = 52; +const int I_HOOKSHOT2 = 89; +const int I_HOVERBOOTS = 92; +const int I_KEY = 9; +const int I_KILLALL = 62; +const int I_LADDER1 = 27; +const int I_LADDER2 = 108; +const int I_LENS = 53; +const int I_LETTER = 12; +const int I_LETTERUSED = 90; +const int I_LEVELKEY = 84; +const int I_MAGICCONTAINER = 58; +const int I_MAGICJAR1 = 59; +const int I_MAGICJAR2 = 60; +const int I_MAGICKEY = 33; +const int I_MAGICRING1 = 115; +const int I_MAGICRING2 = 116; +const int I_MAGICRING3 = 117; +const int I_MAGICRING4 = 118; +const int I_MAP = 21; +const int I_MISC1 = 46; +const int I_MISC2 = 47; +const int I_NAYRUSLOVE = 66; +const int I_PERILRING = 121; +const int I_PERILSCROLL = 103; +const int I_POTION1 = 29; +const int I_POTION2 = 30; +const int I_QUAKESCROLL1 = 96; +const int I_QUAKESCROLL2 = 97; +const int I_QUIVER1 = 74; +const int I_QUIVER2 = 75; +const int I_QUIVER3 = 76; +const int I_QUIVER4 = 105; +const int I_RAFT = 26; +const int I_RING1 = 17; +const int I_RING2 = 18; +const int I_RING3 = 61; +const int I_ROCSFEATHER = 91; +const int I_RUPEE1 = 0; +const int I_RUPEE10 = 86; +const int I_RUPEE100 = 87; +const int I_RUPEE20 = 38; +const int I_RUPEE200 = 40; +const int I_RUPEE5 = 1; +const int I_RUPEE50 = 39; +const int I_SBOMB = 48; +const int I_SELECTA = 45; +const int I_SELECTB = 85; +const int I_SHIELD1 = 93; +const int I_SHIELD2 = 8; +const int I_SHIELD3 = 37; +const int I_SPINSCROLL1 = 94; +const int I_SPINSCROLL2 = 98; +const int I_STOMPBOOTS = 120; +const int I_STONEAGONY = 119; +const int I_SWORD1 = 5; +const int I_SWORD2 = 6; +const int I_SWORD3 = 7; +const int I_SWORD4 = 36; +const int I_TRIFORCE = 20; +const int I_TRIFORCEBIG = 44; +const int I_WALLET500 = 41; +const int I_WALLET999 = 42; +const int I_WALLETA = 104; +const int I_WAND = 25; +const int I_WEALTHMEDAL = 109; +const int I_WEALTHMEDAL2 = 110; +const int I_WEALTHMEDAL3 = 111; +const int I_WHIMSICALRING = 122; +const int I_WHISPRING1 = 99; +const int I_WHISPRING2 = 100; +const int I_WHISTLE = 31; + +//Link actions +const int LA_NONE = 0; +const int LA_WALKING = 1; +const int LA_ATTACKING = 2; +const int LA_FROZEN = 3; +const int LA_HOLD1LAND = 4; // One hand. +const int LA_HOLD2LAND = 5; // Both hands. +const int LA_RAFTING = 6; +const int LA_GOTHURTLAND = 7; +const int LA_INWIND = 8; +const int LA_SCROLLING = 9; +const int LA_WINNING = 10; +const int LA_SWIMMING = 11; +const int LA_HOPPING = 12; // Leaving water. +const int LA_GOTHURTWATER = 13; +const int LA_HOLD1WATER = 14; +const int LA_HOLD2WATER = 15; +const int LA_CASTING = 16; // Casting a spell. +const int LA_CAVEWALKUP = 17; +const int LA_CAVEWALKDOWN = 18; +const int LA_DYING = 19; +const int LA_DROWNING = 20; +const int LA_CHARGING = 22; // Charging the sword. +const int LA_SPINNING = 23; // Spin attack. +const int LA_DIVING = 24; + +//NPC Types. Compare against npc->Type. +const int NPCT_GUY = 0; +const int NPCT_WALK = 1; +const int NPCT_TEKTITE = 3; +const int NPCT_LEEVER = 4; +const int NPCT_PEAHAT = 5; +const int NPCT_ZORA = 6; +const int NPCT_ROCK = 7; +const int NPCT_GHINI = 8; +const int NPCT_ARMOS = 9; +const int NPCT_KEESE = 10; +const int NPCT_TRAP = 15; +const int NPCT_WALLMASTER = 16; +const int NPCT_WIZZROBE = 21; +const int NPCT_AQUAMENTUS = 22; +const int NPCT_MOLDORM = 23; +const int NPCT_DODONGO = 24; +const int NPCT_MANHANDLA = 25; +const int NPCT_GLEEOK = 26; +const int NPCT_DIGDOGGER = 27; +const int NPCT_GOHMA = 28; +const int NPCT_LANMOLA = 29; +const int NPCT_PATRA = 30; +const int NPCT_GANON = 31; +const int NPCT_PROJECTILE = 32; +const int NPCT_SPINTILE = 37; +const int NPCT_NONE = 38; +const int NPCT_FAIRY = 39; +const int NPCT_OTHERFLOAT = 40; +const int NPCT_OTHER = 41; + +//Guy IDs. Use with CreateNPC(). +const int NPC_ABEI = 1; +const int NPC_AMA = 2; +const int NPC_MERCHANT = 3; +const int NPC_MOBLIN = 4; +const int NPC_FIRE = 5; +const int NPC_FAIRY = 6; +const int NPC_GORIYA = 7; +const int NPC_ZELDA = 8; +const int NPC_ABEI2 = 9; + +//Default enemy IDs. Use with CreateNPC(). +const int NPC_AQUAMENTUSL = 93; +const int NPC_AQUAMENTUSR = 58; +const int NPC_ARMOS = 37; +const int NPC_BAT = 106; +const int NPC_BOMBCHU = 160; +const int NPC_BOULDER = 135; +const int NPC_BUBBLEITEMP = 118; // Permanently jinxes +const int NPC_BUBBLEITEMR = 119; // Restores item usage +const int NPC_BUBBLEITEMT = 117; +const int NPC_BUBBLESWORDP = 81; // Permanently jinxes +const int NPC_BUBBLESWORDR = 82; // Restores sword usage +const int NPC_BUBBLESWORDT = 51; +const int NPC_CEILINGMASTER = 101; // This enemy isn't implemented +const int NPC_DARKNUT1 = 49; +const int NPC_DARKNUT2 = 50; +const int NPC_DARKNUT3 = 92; // Splits when killed. +const int NPC_DARKNUT4 = 172; // This enemy isn't implemented +const int NPC_DARKNUT5 = 87; // Sword beams. +const int NPC_DIGDOGGER1 = 66; // Splits into 1 +const int NPC_DIGDOGGER3 = 67; // Splits into 3 +const int NPC_DIGKID1 = 68; // Spawned by NPC_DIGDOGGER1 +const int NPC_DIGKID2 = 69; // Spawned by NPC_DIGDOGGER3 +const int NPC_DIGKID3 = 70; // Spawned by NPC_DIGDOGGER3 +const int NPC_DIGKID4 = 71; // Spawned by NPC_DIGDOGGER3 +const int NPC_DODONGO = 60; // Uses one tile when walking vertically +const int NPC_DODONGOBS = 114; // Uses two tiles when walking vertically +const int NPC_DODONGOFIRE = 115; // This enemy isn't implemented +const int NPC_ENEMYFIRE = 85; // The Fire enemy in Princess Zelda's screen +const int NPC_FLOORMASTER = 102; // This enemy isn't implemented +const int NPC_GANON = 78; +const int NPC_GEL = 42; +const int NPC_GELFIRE = 161; +const int NPC_GELFIRETRIB = 163; +const int NPC_GELTRIB = 88; +const int NPC_GHINI1 = 35; +const int NPC_GHINI2 = 36; +const int NPC_GHINIMGC = 173; // This enemy isn't implemented +const int NPC_GIBDO = 54; +const int NPC_GLEEOK1 = 62; +const int NPC_GLEEOK1FIRE = 109; +const int NPC_GLEEOK2 = 63; +const int NPC_GLEEOK2FIRE = 110; +const int NPC_GLEEOK3 = 64; +const int NPC_GLEEOK3FIRE = 111; +const int NPC_GLEEOK4 = 65; +const int NPC_GLEEOK4FIRE = 112; +const int NPC_GOHMA1 = 72; +const int NPC_GOHMA2 = 73; +const int NPC_GOHMA3 = 121; +const int NPC_GOHMAFIRE = 122; +const int NPC_GORIYA1 = 45; +const int NPC_GORIYA2 = 46; +const int NPC_GORIYA3 = 136; +const int NPC_GRAPBUGHP = 174; // This enemy isn't implemented +const int NPC_GRAPBUGMP = 175; // This enemy isn't implemented +const int NPC_ITEMFAIRY = 84; +const int NPC_KEESE1 = 38; +const int NPC_KEESE2 = 39; +const int NPC_KEESE3 = 40; +const int NPC_KEESETRIB = 90; +const int NPC_LANMOLA1 = 74; +const int NPC_LANMOLA2 = 75; +const int NPC_LEEVER1 = 26; +const int NPC_LEEVER2 = 27; +const int NPC_LEEVER3 = 137; +const int NPC_LIKELIKE = 53; +const int NPC_LYNEL1 = 30; +const int NPC_LYNEL2 = 31; +const int NPC_LYNEL3 = 168; +const int NPC_MANHANDLA = 61; +const int NPC_MANHANDLA2 = 94; +const int NPC_MOBLIN1 = 28; +const int NPC_MOBLIN2 = 29; +const int NPC_MOLDORM = 59; +const int NPC_OCTOROCK1F = 22; +const int NPC_OCTOROCK1S = 20; +const int NPC_OCTOROCK2F = 23; +const int NPC_OCTOROCK2S = 21; +const int NPC_OCTOROCKBOMBF = 141; +const int NPC_OCTOROCKBOMBS = 140; +const int NPC_OCTOROCKFIREF = 139; +const int NPC_OCTOROCKFIRES = 138; +const int NPC_OCTOROCKMGC = 86; +const int NPC_PATRA1 = 76; +const int NPC_PATRA2 = 104; +const int NPC_PATRA3 = 105; +const int NPC_PATRABS = 103; +const int NPC_PATRAOVAL = 77; +const int NPC_PEAHAT = 32; +const int NPC_PEAHATFIRE = 169; // This enemy isn't implemented +const int NPC_POLSVOICE = 55; +const int NPC_POLSVOICEBS = 171; // This enemy isn't implemented +const int NPC_POLSVOICEMGC = 170; +const int NPC_ROCK = 34; +const int NPC_ROPE1 = 44; +const int NPC_ROPE2 = 80; +const int NPC_SHOOTFBALL = 83; +const int NPC_SHOOTFLAME = 158; +const int NPC_SHOOTFLAME2 = 159; +const int NPC_SHOOTMAGIC = 154; +const int NPC_SHOOTROCK = 155; +const int NPC_SHOOTSPEAR = 156; +const int NPC_SHOOTSWORD = 157; +const int NPC_SPINTILE = 166; +const int NPC_SPINTILERND = 167; // Random spin tile +const int NPC_STALFOS1 = 41; +const int NPC_STALFOS2 = 79; +const int NPC_STALFOS3 = 120; +const int NPC_TEKTITE1 = 24; +const int NPC_TEKTITE2 = 25; +const int NPC_TEKTITE3 = 165; // This enemy isn't implemented +const int NPC_TRAP = 47; +const int NPC_TRAP8WAY = 142; // This enemy isn't implemented +const int NPC_TRAPBACKSLASHC = 146; // This enemy isn't implemented +const int NPC_TRAPBACKSLASHLOS = 147; // This enemy isn't implemented +const int NPC_TRAPCCLOCKWISEC = 150; // This enemy isn't implemented +const int NPC_TRAPCCLOCKWISELOS = 151; // This enemy isn't implemented +const int NPC_TRAPCLOCKWISEC = 148; // This enemy isn't implemented +const int NPC_TRAPCLOCKWISELOS = 149; // This enemy isn't implemented +const int NPC_TRAPDIAG = 143; // This enemy isn't implemented +const int NPC_TRAPHORIZC = 97; +const int NPC_TRAPHORIZLOS = 95; +const int NPC_TRAPSLASHC = 144; // This enemy isn't implemented +const int NPC_TRAPSLASHLOS = 145; +const int NPC_TRAPVERTC = 98; +const int NPC_TRAPVERTLOS = 96; +const int NPC_TRIGGER = 116; +const int NPC_VIRE = 52; +const int NPC_VIRETRIB = 91; +const int NPC_WALLMASTER = 48; +const int NPC_WIZZROBE1 = 56; // Teleports +const int NPC_WIZZROBE2 = 57; // Phases through blocks +const int NPC_WIZZROBEBAT = 107; +const int NPC_WIZZROBEBAT2 = 108; // This enemy isn't implemented +const int NPC_WIZZROBEFIRE = 99; +const int NPC_WIZZROBEICE = 153; // This enemy isn't implemented +const int NPC_WIZZROBEMIRR = 113; +const int NPC_WIZZROBESUMM = 152; +const int NPC_WIZZROBEWIND = 100; +const int NPC_ZOL = 43; +const int NPC_ZOLFIRE = 162; +const int NPC_ZOLFIRETRIB = 164; +const int NPC_ZOLTRIB = 89; +const int NPC_ZORA = 33; + +//NPC hit point values. Use with npc->HP to make the enemy die in a special manner. +const int HP_SILENT = -1000; // The enemy will die without their Death Sound playing. + +//LWeapon types. Use with Screen->CreateLWeapon() and Screen->LoadLWeapon(). +const int LW_SWORD = 1; // This cannot be created +const int LW_WAND = 12; // This cannot be created +const int LW_CANDLE = 12; // This cannot be created +const int LW_HAMMER = 19; // This cannot be created +const int LW_HOOKSHOT = 20; // This cannot be created +const int LW_CANEOFBYRNA = 27; // This cannot be created +const int LW_ARROW = 8; +const int LW_BEAM = 2; // Sword beam +const int LW_BRANG = 3; +const int LW_BOMB = 6; +const int LW_BOMBBLAST = 4; // Bomb explosion +const int LW_SBOMB = 7; +const int LW_SBOMBBLAST = 5; // Super Bomb explosion +const int LW_FIRE = 9; +const int LW_WHISTLE = 10; // Whistle music - kills Digdogger +const int LW_BAIT = 11; +const int LW_MAGIC = 13; // Wand magic +const int LW_WIND = 15; // Whistle whirlwind +const int LW_REFMAGIC = 16; // Reflected wand magic +const int LW_REFFIREBALL = 17; // Reflected fireball +const int LW_REFROCK = 18; // Reflected rock +const int LW_REFBEAM = 28; // Reflected sword beam +const int LW_SPARKLE = 23; +const int LW_FIRESPARKLE = 24; // Damages enemies +// Dummy weapons, for use with scripts. +const int LW_SCRIPT1 = 31; +const int LW_SCRIPT2 = 32; +const int LW_SCRIPT3 = 33; +const int LW_SCRIPT4 = 34; +const int LW_SCRIPT5 = 35; +const int LW_SCRIPT6 = 36; +const int LW_SCRIPT7 = 37; +const int LW_SCRIPT8 = 38; +const int LW_SCRIPT9 = 39; +const int LW_SCRIPT10 = 40; + +//EWeapon types. Use with Screen->CreateEWeapon() and Screen->LoadEWeapon(). +const int EW_ARROW = 130; +const int EW_BRANG = 131; +const int EW_BEAM = 132; // Sword beam +const int EW_ROCK = 133; +const int EW_MAGIC = 134; +const int EW_FIREBALL = 129; +const int EW_FIREBALL2 = 145; // Arcing boss fireball +const int EW_BOMB = 137; // Projectile bomb +const int EW_BOMBBLAST = 135; // Bomb explosion +const int EW_SBOMB = 138; // Projectile super bomb +const int EW_SBOMBBLAST = 136; // Super bomb explosion +const int EW_FIRETRAIL = 139; +const int EW_FIRE = 140; +const int EW_WIND = 141; // Wind wizzrobe magic +const int EW_FIRE2 = 142; +// Dummy weapons, for use with scripts. +const int EW_SCRIPT1 = 31; +const int EW_SCRIPT2 = 32; +const int EW_SCRIPT3 = 33; +const int EW_SCRIPT4 = 34; +const int EW_SCRIPT5 = 35; +const int EW_SCRIPT6 = 36; +const int EW_SCRIPT7 = 37; +const int EW_SCRIPT8 = 38; +const int EW_SCRIPT9 = 39; +const int EW_SCRIPT10 = 40; + +//Weapon DeadState values. Use with Weapon->DeadState. +const int WDS_NOHIT = -10; // This value switches collision detection off. Deprecated by weapon->CollDetection. +const int WDS_ALIVE = -1; // Weapon is currently 'alive'. +const int WDS_DEAD = 0; // Use to dispose of most weapons. +const int WDS_BEAMSHARDS = 23; // Use with LW_BEAMs to shatter it into shards. +const int WDS_ARROW = 4; // Use with LW_ARROWs to make them 'wink out' using tile 54. +const int WDS_BOUNCE = 1; // Use with LW_BRANGs or LW_HOOKSHOTs to + // make it 'bounce off' and start returning to Link. + +//FFC Flags. To be used as indices into ffc->Flags[]. +const int FFCF_OVERLAY = 0; // Draw Over (draw between layers 4 and 5) +const int FFCF_TRANS = 1; // Translucent +const int FFCF_SOLID = 2; // Unused +const int FFCF_CARRYOVER = 3; // Carry Over +const int FFCF_STATIONARY = 4; // Stationary +const int FFCF_CHANGER = 5; // Is A Changer +const int FFCF_PRELOAD = 6; // Run Script On Screen Init +const int FFCF_LENSVIS = 7; // Only Visible to Lens of Truth +const int FFCF_RESET = 8; // Script Resets When Carried Over +const int FFCF_ETHEREAL = 9; // The FFC's Combo Type is ignored. +const int FFCF_IGNOREHOLDUP = 10; // The FFC is updated while Link is holding up an item + +//Directions. Use with Link->Dir, etc. +const int DIR_UP = 0; //000b +const int DIR_DOWN = 1; //001b +const int DIR_LEFT = 2; //010b +const int DIR_RIGHT = 3; //011b +const int DIR_LEFTUP = 4; //100b +const int DIR_RIGHTUP = 5; //101b +const int DIR_LEFTDOWN = 6; //110b +const int DIR_RIGHTDOWN = 7; //111b + +//Combo flags. Use with Screen->ComboF[] +const int CF_NONE = 0; +const int CF_PUSHUPDOWN = 1; +const int CF_PUSH4WAY = 2; +const int CF_WHISTLE = 3; +const int CF_CANDLE1 = 4; +const int CF_ARROW = 5; +const int CF_BOMB = 6; +const int CF_FAIRY = 7; +const int CF_RAFT = 8; +const int CF_ARMOSSECRET = 9; +const int CF_ARMOSITEM = 10; +const int CF_SBOMB = 11; +const int CF_RAFTBRANCH = 12; +const int CF_DIVEITEM = 13; +const int CF_ZELDA = 15; +const int CF_SECRETS01 = 16; +const int CF_SECRETS02 = 17; +const int CF_SECRETS03 = 18; +const int CF_SECRETS04 = 19; +const int CF_SECRETS05 = 20; +const int CF_SECRETS06 = 21; +const int CF_SECRETS07 = 22; +const int CF_SECRETS08 = 23; +const int CF_SECRETS09 = 24; +const int CF_SECRETS10 = 25; +const int CF_SECRETS11 = 26; +const int CF_SECRETS12 = 27; +const int CF_SECRETS13 = 28; +const int CF_SECRETS14 = 29; +const int CF_SECRETS15 = 30; +const int CF_SECRETS16 = 31; +const int CF_TRAPH = 32; +const int CF_TRAPV = 33; +const int CF_TRAP4WAY = 34; +const int CF_TRAPLR = 35; +const int CF_TRAPUD = 36; +const int CF_ENEMY0 = 37; +const int CF_ENEMY1 = 38; +const int CF_ENEMY2 = 39; +const int CF_ENEMY3 = 40; +const int CF_ENEMY4 = 41; +const int CF_ENEMY5 = 42; +const int CF_ENEMY6 = 43; +const int CF_ENEMY7 = 44; +const int CF_ENEMY8 = 45; +const int CF_ENEMY9 = 46; +const int CF_PUSHLR = 47; +const int CF_PUSHUP = 48; +const int CF_PUSHDOWN = 49; +const int CF_PUSHLEFT = 50; +const int CF_PUSHRIGHT = 51; +const int CF_PUSHUPDOWNNS = 52; +const int CF_PUSHLEFTRIGHTNS = 53; +const int CF_PUSH4WAYNS = 54; +const int CF_PUSHUPNS = 55; +const int CF_PUSHDOWNNS = 56; +const int CF_PUSHLEFTNS = 57; +const int CF_PUSHRIGHTNS = 58; +const int CF_PUSHUPDOWNINS = 59; +const int CF_PUSHLEFTRIGHTINS = 60; +const int CF_PUSH4WAYINS = 61; +const int CF_PUSHUPINS = 62; +const int CF_PUSHDOWNINS = 63; +const int CF_PUSHLEFTINS = 64; +const int CF_PUSHRIGHTINS = 65; +const int CF_BLOCKTRIGGER = 66; +const int CF_NOBLOCKS = 67; +const int CF_BRANG1 = 68; +const int CF_BRANG2 = 69; +const int CF_BRANG3 = 70; +const int CF_ARROW2 = 71; +const int CF_ARROW3 = 72; +const int CF_CANDLE2 = 73; +const int CF_WANDFIRE = 74; +const int CF_DINSFIRE = 75; +const int CF_WANDMAGIC = 76; +const int CF_REFMAGIC = 77; +const int CF_REFFIREBALL = 78; +const int CF_SWORD1 = 79; +const int CF_SWORD2 = 80; +const int CF_SWORD3 = 81; +const int CF_SWORD4 = 82; +const int CF_SWORD1BEAM = 83; +const int CF_SWORD2BEAM = 84; +const int CF_SWORD3BEAM = 85; +const int CF_SWORD4BEAM = 86; +const int CF_HOOKSHOT = 87; +const int CF_WAND = 88; +const int CF_HAMMER = 89; +const int CF_STRIKE = 90; +const int CF_BLOCKHOLE = 91; +const int CF_MAGICFAIRY = 92; +const int CF_ALLFAIRY = 93; +const int CF_SINGLE = 94; +const int CF_SINGLE16 = 95; +const int CF_NOENEMY = 96; +const int CF_NOGROUNDENEMY = 97; +const int CF_SCRIPT1 = 98; +const int CF_SCRIPT2 = 99; +const int CF_SCRIPT3 = 100; +const int CF_SCRIPT4 = 101; +const int CF_SCRIPT5 = 102; + +//Combo types. Use with Screen->ComboT[] +const int CT_ARMOS = 4; +const int CT_AWARPA = 94; +const int CT_AWARPB = 95; +const int CT_AWARPC = 96; +const int CT_AWARPD = 97; +const int CT_AWARPR = 98; +const int CT_BLOCKALL = 118; +const int CT_BLOCKARROW1 = 111; +const int CT_BLOCKARROW2 = 112; +const int CT_BLOCKARROW3 = 113; +const int CT_BLOCKBRANG1 = 114; +const int CT_BLOCKBRANG2 = 115; +const int CT_BLOCKBRANG3 = 116; +const int CT_BLOCKFIREBALL = 119; +const int CT_BLOCKMAGIC = 50; +const int CT_BLOCKSWORDBEAM = 117; +const int CT_BOSSCHEST = 69; +const int CT_BOSSCHEST2 = 70; +const int CT_BOSSLOCKBLOCK = 61; +const int CT_BOSSLOCKBLOCK2 = 62; +const int CT_BSGRAVE = 64; +const int CT_BUSH = 55; +const int CT_BUSHC = 134; +const int CT_BUSHNEXT = 131; +const int CT_BUSHNEXTC = 139; +const int CT_CAVE = 2; +const int CT_CAVE2 = 51; +const int CT_CAVE2B = 83; +const int CT_CAVE2C = 84; +const int CT_CAVE2D = 85; +const int CT_CAVEB = 74; +const int CT_CAVEC = 75; +const int CT_CAVED = 76; +const int CT_CENTERSTATUE = 35; +const int CT_CHEST = 65; +const int CT_CHEST2 = 66; +const int CT_CVDOWN = 15; +const int CT_CVLEFT = 16; +const int CT_CVRIGHT = 17; +const int CT_CVUP = 14; +const int CT_DAMAGE1 = 31; +const int CT_DAMAGE2 = 32; +const int CT_DAMAGE3 = 33; +const int CT_DAMAGE4 = 34; +const int CT_DAMAGE5 = 120; +const int CT_DAMAGE6 = 121; +const int CT_DAMAGE7 = 122; +const int CT_DIVEWARP = 19; +const int CT_DIVEWARPB = 89; +const int CT_DIVEWARPC = 90; +const int CT_DIVEWARPD = 91; +const int CT_DOCK = 6; +const int CT_EYEBALL4WAY = 140; +const int CT_EYEBALLA = 52; +const int CT_EYEBALLB = 53; +const int CT_FLOWERS = 56; +const int CT_FLOWERSC = 135; +const int CT_GRAVE = 5; +const int CT_HOOKSHOTONLY = 42; +const int CT_HSBRIDGE = 30; +const int CT_HSGRAB = 29; +const int CT_LADDERHOOKSHOT = 20; +const int CT_LADDERONLY = 63; +const int CT_LEFTSTATUE = 11; +const int CT_LOCKBLOCK = 59; +const int CT_LOCKBLOCK2 = 60; +const int CT_LOCKEDCHEST = 67; +const int CT_LOCKEDCHEST2 = 68; +const int CT_MAGICPRISM = 48; +const int CT_MAGICPRISM4WAY = 49; +const int CT_MIRROR = 45; +const int CT_MIRRORBACKSLASH = 47; +const int CT_MIRRORSLASH = 46; +const int CT_NOENEMY = 110; +const int CT_NOFLYZONE = 44; +const int CT_NOGROUNDENEMY = 128; +const int CT_NOJUMPZONE = 54; +const int CT_NONE = 0; +const int CT_OVERHEAD = 43; +const int CT_PIT = 41; +const int CT_PITB = 80; +const int CT_PITC = 81; +const int CT_PITD = 82; +const int CT_PITR = 93; +const int CT_POUND = 28; +const int CT_PUSHHEAVY = 9; +const int CT_PUSHHEAVY2 = 26; +const int CT_PUSHHEAVY2WAIT = 27; +const int CT_PUSHHEAVYWAIT = 10; +const int CT_PUSHWAIT = 8; +const int CT_RESET = 71; +const int CT_RIGHTSTATUE = 12; +const int CT_SAVE = 72; +const int CT_SAVE2 = 73; +const int CT_SCREENFREEZE = 126; +const int CT_SCREENFREEZEFF = 127; +const int CT_SCRIPT1 = 142; +const int CT_SCRIPT2 = 143; +const int CT_SCRIPT3 = 144; +const int CT_SCRIPT4 = 145; +const int CT_SCRIPT5 = 146; +const int CT_SHALLOWWATER = 58; +const int CT_SLASH = 24; +const int CT_SLASHC = 132; +const int CT_SLASHITEM = 25; +const int CT_SLASHITEMC = 133; +const int CT_SLASHNEXT = 129; +const int CT_SLASHNEXTC = 137; +const int CT_SLASHNEXTITEM = 130; +const int CT_SLASHNEXTITEMC = 138; +const int CT_SPINTILE1 = 124; +const int CT_SPINTILE2 = 125; +const int CT_STAIR = 1; +const int CT_STAIRB = 77; +const int CT_STAIRC = 78; +const int CT_STAIRD = 79; +const int CT_STAIRR = 92; +const int CT_STEP = 106; +const int CT_STEPALL = 108; +const int CT_STEPCOPY = 109; +const int CT_STEPSAME = 107; +const int CT_STRIGFLAG = 105; +const int CT_STRIGNOFLAG = 104; +const int CT_SWARPA = 99; +const int CT_SWARPB = 100; +const int CT_SWARPC = 101; +const int CT_SWARPD = 102; +const int CT_SWARPR = 103; +const int CT_SWIMWARP = 18; +const int CT_SWIMWARPB = 86; +const int CT_SWIMWARPC = 87; +const int CT_SWIMWARPD = 88; +const int CT_TALLGRASS = 57; +const int CT_TALLGRASSC = 136; +const int CT_TALLGRASSNEXT = 141; +const int CT_TRAP4WAY = 38; +const int CT_TRAPH = 36; +const int CT_TRAPLEFTRIGHT = 39; +const int CT_TRAPUPDOWN = 40; +const int CT_TRAPV = 37; +const int CT_TRIGFLAG = 22; +const int CT_TRIGNOFLAG = 21; +const int CT_WALKSLOW = 13; +const int CT_WATER = 3; +const int CT_ZELDA = 23; + + +//Item pickup flags. OR (|) these together to use with item->Pickup +//Other values are reserved for internal usage, and have no effect +const int IP_HOLDUP = 0x002; //Link holds it up when collecting it. +const int IP_ST_ITEM = 0x004; //Sets the screen state "Item" when collected. +const int IP_DUMMY = 0x008; //A 'dummy' item, such as rupee markers in shops. Can't be collected and ignores gravity. +const int IP_ENEMYCARRIED = 0x080; //The item-carrying NPC carries it. If no NPC has an item, the most recently created NPC carries it. +const int IP_TIMEOUT = 0x100; //Disappears after 512 frames. Can be collected by melee weapons if the related quest rule is not set. +const int IP_ST_SPECIALITEM = 0x800; //Sets the screen state "Special Item" when collected. + +//Screen Flag categories. Flags from each category are ORed together, starting with the first flag +//See Screen Data dialog for what flags are contained in each category. Use in Screen->Flags +const int SF_ROOMTYPE = 0; +const int SF_VIEW = 1; +const int SF_SECRETS = 2; +const int SF_WARP = 3; +const int SF_ITEMS = 4; +const int SF_COMBOS = 5; +const int SF_SAVE = 6; +const int SF_FFC = 7; +const int SF_WHISTLE = 8; +const int SF_MISC = 9; + +//Screen Enemy Flag categories, handled in the same way as the SF_ constants. +//Use in Screen->EFlags +const int SEF_SPAWN = 0; +const int SEF_LIST1 = 1; //left-hand list +const int SEF_LIST2 = 2; //right-hand list + +//Room types (Screen => Room Type) +//Use with Screen->RoomType +const int RT_DOORREPAIR = 5; +const int RT_FEEDTHEGORIYA = 7; +const int RT_GAMBLE = 4; +const int RT_GANON = 15; +const int RT_ITEMPOND = 17; //doesn't work +const int RT_LEARNSLASH = 19; +const int RT_LEVEL9ENTRANCE = 8; +const int RT_MAGICUPGRADE = 18; +const int RT_MONEYORLIFE = 12; +const int RT_MOREARROWS = 20; +const int RT_MOREBOMBS = 11; +const int RT_NONE = 0; +const int RT_PAYFORINFO = 2; +const int RT_POTIONORHEART = 6; +const int RT_POTIONSHOP = 9; +const int RT_SECRETMONEY = 3; +const int RT_SHOP = 10; +const int RT_SPECIALITEM = 1; +const int RT_STAIRWARP = 14; +const int RT_TAKEONEITEM = 21; +const int RT_TENRUPEES = 13; +const int RT_ZELDA = 16; + +//DMap Flag constants. Use with Game->DMapFlags. +const int DMF_CAVESNOTCELLARS = 0x0001; //Use caves instead of item cellars +const int DMF_3STAIRWARPS = 0x0002; //Allow 3-stair warps +const int DMF_WWIND = 0x0004; //Allow whistle whirlwinds +const int DMF_GUYCAVES = 0x0008; //Special rooms and guys are in caves only +const int DMF_NOCOMPASS = 0x0010; //Don't display compass marker in minimap +const int DMF_WAVY = 0x0020; //Underwater wave effect +const int DMF_WWINDRET = 0x0040; //Whistle whirlwind returns Link to start +const int DMF_ALWAYSINTROMSG = 0x0080; //Always display intro string +const int DMF_VIEWMAP = 0x0100; //View overworld map by pressing 'Map' +const int DMF_DMAPMAP = 0x0200; //...But only show screens marked in minimap +const int DMF_MINIMAPCOLORFIX = 0x0400; //Use minimap foreground colour 2 +const int DMF_SCRIPT1 = 0x0800; +const int DMF_SCRIPT2 = 0x1000; +const int DMF_SCRIPT3 = 0x2000; +const int DMF_SCRIPT4 = 0x4000; +const int DMF_SCRIPT5 = 0x8000; + +//NPC Attribute 1 constants. Use with npc->Attributes. +const int NPCA1_1SHOT = 0; +const int NPCA1_ENDHALT = 1; +const int NPCA1_RAPIDFIRE = 2; +const int NPCA1_1FAST = 3; +const int NPCA1_1SLANT = 4; +const int NPCA1_3SHOTS = 5; +const int NPCA1_4SHOTS = 6; +const int NPCA1_5SHOTS = 7; +const int NPCA1_3FAST = 8; +const int NPCA1_BREATH = 9; +const int NPCA1_8SHOTS = 10; +const int NPCA1_SUMMON = 11; +const int NPCA1_SUMMONLAYER = 12; + +//NPC Attribute 2 constants. Use with npc->Attributes. +const int NPCA2_NORMAL = 0; +const int NPCA2_SPLITHIT = 1; +const int NPCA2_SPLIT = 2; +const int NPCA2_8SHOTS = 3; +const int NPCA2_EXPLODE = 4; +const int NPCA2_TRIBBLE = 5; + +//NPC Attribute 7 constants. Use with npc->Attributes. +const int NPCA7_NORMAL = 0; +const int NPCA7_TEMPJINX = 1; +const int NPCA7_PERMJINX = 2; +const int NPCA7_CUREJINX = 3; +const int NPCA7_LOSEMAGIC = 4; +const int NPCA7_LOSERUPEES = 5; +const int NPCA7_DRUNK = 6; +const int NPCA7_EATITEMS = 7; +const int NPCA7_EATMAGIC = 8; +const int NPCA7_EATRUPEES = 9; + +//NPC Attribute 9 constants. Use with npc->Attributes. +const int NPCA9_NORMAL = 0; +const int NPCA9_ROPE = 1; +const int NPCA9_VIRE = 2; +const int NPCA9_POLSVOICE = 3; + +//NPC Defenses. Use as indices to npc->Defense[]. +const int NPCD_ARROW = 3; +const int NPCD_BEAM = 10; +const int NPCD_BRANG = 0; +const int NPCD_BOMB = 1; +const int NPCD_BYRNA = 16; +const int NPCD_FIRE = 4; +const int NPCD_HAMMER = 8; +const int NPCD_HOOKSHOT = 7; +const int NPCD_MAGIC = 6; +const int NPCD_REFBEAM = 11; +const int NPCD_REFMAGIC = 12; +const int NPCD_REFFIREBALL = 13; +const int NPCD_REFROCK = 14; +const int NPCD_SBOMB = 2; +const int NPCD_SCRIPT = 17; +const int NPCD_STOMP = 15; +const int NPCD_SWORD = 9; +const int NPCD_WAND = 5; + +//NPC Defense types. Use with npc->Defense[]. +const int NPCDT_NONE = 0; +const int NPCDT_HALFDAMAGE = 1; +const int NPCDT_QUARTERDAMAGE = 2; +const int NPCDT_STUN = 3; +const int NPCDT_STUNORBLOCK = 4; +const int NPCDT_STUNORIGNORE = 5; +const int NPCDT_BLOCK1 = 6; +const int NPCDT_BLOCK2 = 7; +const int NPCDT_BLOCK4 = 8; +const int NPCDT_BLOCK6 = 9; +const int NPCDT_BLOCK8 = 10; +const int NPCDT_BLOCK = 11; +const int NPCDT_IGNORE1 = 12; +const int NPCDT_IGNORE = 13; +const int NPCDT_ONEHITKILL = 14; + +//Draw styles. Use with item->DrawStyle +const int DS_NORMAL = 0; +const int DS_PHANTOM = 1; +const int DS_CLOAKED = 2; +const int DS_LINK = 3; + +//Warp types. Use with Screen->SetSideWarp +const int WT_CAVE = 0; +const int WT_PASSAGE = 1; +const int WT_ENTRANCEEXIT = 2; +const int WT_SCROLLING = 3; +const int WT_IAWARP = 4; +const int WT_IWARPBLACKOUT = 5; +const int WT_IWARPOPENWIPE = 6; +const int WT_IWARPZAP = 7; +const int WT_IWARPWAVE = 8; +const int WT_NOWARP = 9; + +// Font types. Use with Screen->DrawCharacter *note -some of these fonts may not represent normal ascii characters, +//and all of these are completely undocumented. Use at your own peril +const int FONT_Z1 = 0; +const int FONT_Z3 = 1; +const int FONT_Z3SMALL = 2; +const int FONT_DEF = 3; +const int FONT_L = 4; +const int FONT_L2 = 5; +const int FONT_P = 6; +const int FONT_MATRIX = 7; +const int FONT_ZTIME = 8; +const int FONT_S = 9; +const int FONT_S2 = 10; +const int FONT_SP = 11; +const int FONT_SUBSCREEN1 = 12; +const int FONT_SUBSCREEN2 = 13; +const int FONT_SUBSCREEN3 = 14; +const int FONT_SUBSCREEN4 = 15; +const int FONT_GBLA = 16; +const int FONT_GORON = 17; +const int FONT_ZORAN = 18; +const int FONT_HYLIAN1 = 19; +const int FONT_HYLIAN2 = 20; +const int FONT_HYLIAN3 = 21; +const int FONT_HYLIAN4 = 22; +const int FONT_GBORACLE = 23; +const int FONT_GBORACLEP = 24; +const int FONT_DSPHANTOM = 25; +const int FONT_DSPHANTOMP = 26; + +// PrintString Text Formats. Use with Screen->DrawString. +const int TF_NORMAL = 0; // treats the left-most char as (x) +const int TF_CENTERED = 1; // prints the string centered on (x) +const int TF_RIGHT = 2; // treats the right-most char as (x) + +// Texture mapping rendering modes. Use with Screen->"Psuedo 3D" or "*3D" drawing routines. ie; Polygon, Quad, or Triangle +const int PT_FLAT = 0; // single color shading +const int PT_FLATSHADED = 1; // "" with flat shading (*3D only) +const int PT_COLSHADED = 2; // "" with color shading (*3D only) +const int PT_TEXTURE = 3; // texture mapped polygon using 2d linear interpolation +const int PT_PTEXTURE = 4; // "" +const int PT_MASKTEXTURE = 5; // transparent texture mapped polygon using 2d linear interpolation +const int PT_MASKPTEXTURE = 6; // "" +const int PT_LITTEXTURE = 7; // "" with lighting (*3D only) +const int PT_LITPTEXTURE = 8; // "" (*3D only) +const int PT_MASKLITTEXTURE = 9; // "" with transparency +const int PT_MASKLITPTEXTURE = 10; // "" +const int PT_TRANSTEXTURE = 11; // translucent texture mapped polygon using 2d linear interpolation +const int PT_TRANSPTEXTURE = 12; // "" +const int PT_MASKTRANSTEXTURE = 13; // translucent and transparent texture mapped polygon using 2d linear interpolation +const int PT_MASKTRANSPTEXTURE = 14; // "" + +// Opacity options. Use with drawing commands. +const int OP_TRANS = 64; +const int OP_OPAQUE = 128; + +// Render Targets. Use with Screen->"*RenderTarget" and Screen->"Bitmap" drawing routines. +const int RT_SCREEN = -1; // draws to screen +const int RT_BITMAP0 = 0; // draws to off-screen bitmap 0 +const int RT_BITMAP1 = 1; // draws to off-screen bitmap 1 +const int RT_BITMAP2 = 2; // draws to off-screen bitmap 2 +const int RT_BITMAP3 = 3; // draws to off-screen bitmap 3 +const int RT_BITMAP4 = 4; // draws to off-screen bitmap 4 +const int RT_BITMAP5 = 5; // draws to off-screen bitmap 5 +const int RT_BITMAP6 = 6; // draws to off-screen bitmap 6 + +//Sprite extending methods. Use with Link->Extend, item->Extend, +//npc->Extend, eweapon->Extend and lweapon->Extend. +const int EXT_NONE = 0; // Not extended +const int EXT_NORMAL = 3; // Extended +const int EXT_NOSHADOW = 4; // Extended; NPC has no shadow. + +//Generic counters. Use with itemclass->Counter, Game->Counter[], Game->MCounter[] and Game->DCounter[] +const int CR_LIFE = 0; +const int CR_RUPEES = 1; +const int CR_BOMBS = 2; +const int CR_ARROWS = 3; +const int CR_MAGIC = 4; +const int CR_KEYS = 5; +const int CR_SBOMBS = 6; +const int CR_SCRIPT1 = 7; +const int CR_SCRIPT2 = 8; +const int CR_SCRIPT3 = 9; +const int CR_SCRIPT4 = 10; +const int CR_SCRIPT5 = 11; +const int CR_SCRIPT6 = 12; +const int CR_SCRIPT7 = 13; +const int CR_SCRIPT8 = 14; +const int CR_SCRIPT9 = 15; +const int CR_SCRIPT10 = 16; +const int CR_SCRIPT11 = 17; +const int CR_SCRIPT12 = 18; +const int CR_SCRIPT13 = 19; +const int CR_SCRIPT14 = 20; +const int CR_SCRIPT15 = 21; +const int CR_SCRIPT16 = 22; +const int CR_SCRIPT17 = 23; +const int CR_SCRIPT18 = 24; +const int CR_SCRIPT19 = 25; +const int CR_SCRIPT20 = 26; +const int CR_SCRIPT21 = 27; +const int CR_SCRIPT22 = 28; +const int CR_SCRIPT23 = 29; +const int CR_SCRIPT24 = 30; +const int CR_SCRIPT25 = 31; + + +//Generic data indices. Use this with Game->Generic[] +const int GEN_HEARTPIECES = 0; // Heart Pieces currently possessed +const int GEN_MAGICDRAINRATE = 1; // Link's magic usage equals n / 2. +const int GEN_CANSLASH = 2; // Link can slash with the sword. +const int GEN_WARPLEVEL = 3; // Warp Ring number that a Whirlwind warp will send Link to. + // It is set every time that Link uses the Whistle. +const int GEN_HCPPERHC = 4; // How many Pieces of Heart form a complete Heart Container? +const int GEN_CONTINUEHEARTS = 5; // Amount of life that Link continues with +const int GEN_CONTINUEISPERCENT = 6; // ...Or a percentage of his total life + +//Level item flags. Or (|) these together and use with Game->LItems[] +const int LI_TRIFORCE = 0x01; // The Triforce of this Level has been obtained +const int LI_MAP = 0x02; // The Dungeon Map of this Level has been obtained +const int LI_COMPASS = 0x04; // The Compass of this Level has been obtained +const int LI_BOSS = 0x08; // A "Dungeon Boss" enemy has been slain +const int LI_BOSSKEY = 0x10; // The Boss Key of this Level has been obtained + +//Screen states. Use these with Screen->State[], etc. + +const int ST_DOORUP = 0; // The locked/bomb door has been permanently unlocked/bombed +const int ST_DOORDOWN = 1; // The locked/bomb door has been permanently unlocked/bombed +const int ST_DOORLEFT = 2; // The locked/bomb door has been permanently unlocked/bombed +const int ST_DOORRIGHT = 3; // The locked/bomb door has been permanently unlocked/bombed +const int ST_SECRET = 13; // Screen Secrets have been made permanent +const int ST_ITEM = 4; // If set, the item is gone +const int ST_SPECIALITEM = 5; // If set, the Cave/Item Cellar/Dive For Item/Armos item is gone +const int ST_ENEMYNORETURN = 6; // If set, enemies won't return +const int ST_TEMPNORETURN = 7; // If set, enemies won't return. This is automatically unset when you leave the DMap +const int ST_LOCKBLOCK = 8; // The lock block on the screen has been triggered +const int ST_BOSSLOCKBLOCK = 9; // The boss lock block on the screen has been triggered +const int ST_CHEST = 10; // The unlocked chest on this screen has been opened +const int ST_LOCKEDCHEST = 11; // The locked chest on this screen has been opened +const int ST_BOSSCHEST = 12; // The boss chest on this screen has been opened +const int ST_VISITED = 14; // If set, this screen will appear on the Overworld Map + +//Door types. Use with Screen->Door[] +const int D_WALL = 0; +const int D_OPEN = 1; +const int D_LOCKED = 2; +const int D_UNLOCKED = 3; // A locked door that has been opened +const int D_SHUTTER = 4; // Defeat enemies to unlock this door +const int D_BOMB = 6; // A door that changes when bombed +const int D_BOMBED = 7; // A door that has been bombed +const int D_WALKTHRU = 8; // Push against the wall to pass through +const int D_BOSSLOCKED = 10; +const int D_BOSSUNLOCKED = 11; // A boss door that has been opened +const int D_OPENSHUTTER = 12; // A shutter that has been opened +const int D_1WAYSHUTTER = 14; // A shutter that locks behind you and never opens + +//Enemy projectile weapon selections. Use with npc->Weapon. +//Note: Don't use these with Screen->CreateEWeapon! Use the EW_ constants instead. +const int WPN_NONE = 0; +const int WPN_ENEMYFLAME = 140; +const int WPN_ENEMYWIND = 141; +const int WPN_ENEMYFIREBALL = 129; +const int WPN_ENEMYARROW = 130; +const int WPN_ENEMYBRANG = 131; +const int WPN_ENEMYSWORD = 132; +const int WPN_ENEMYROCK = 133; +const int WPN_ENEMYMAGIC = 134; +const int WPN_ENEMYBOMB = 135; +const int WPN_ENEMYSBOMB = 136; +const int WPN_ENEMYLITBOMB = 137; +const int WPN_ENEMYLITSBOMB = 138; +const int WPN_ENEMYFIRETRAIL = 139; +const int WPN_ENEMYFLAME2 = 142; +const int WPN_ENEMYFLAME2TRAIL = 143; // Not implemented +const int WPN_ENEMYICE = 144; // Not implemented +const int WPN_ENEMYFIREBALL2 = 145; // A fireball that doesn't fly toward Link + +//Default item drop sets. Use with npc->ItemSet +const int IS_NONE = 0; +const int IS_DEFAULT = 1; +const int IS_BOMBS = 2; +const int IS_MONEY = 3; +const int IS_LIFE = 4; +const int IS_BOMB100 = 5; // Used by Dodongos +const int IS_SBOMB100 = 6; // Used by Dodongos +const int IS_MAGIC = 7; +const int IS_MAGICBOMBS = 8; +const int IS_MAGICMONEY = 9; +const int IS_MAGICLIFE = 10; +const int IS_MAGIC2 = 11; +const int IS_COMBOS = 12; // Used by Tall Grass / Bush / Slash combos. + +//Boss palettes. Use with npc->BossPal +const int BPAL_AQUA = 0; +const int BPAL_GLEEOK = 1; +const int BPAL_DODONGO = 2; +const int BPAL_GANON = 3; +const int BPAL_BROWN = 4; +const int BPAL_PILE = 5; // Used for the Dust Pile. +const int BPAL_BLUE = 6; +const int BPAL_RED = 7; +const int BPAL_GOLD = 8; +const int BPAL_ICON1 = 9; // Used for Quest Icon 1. +const int BPAL_ICON2 = 10; // Used for Quest Icon 2. +const int BPAL_ICON3 = 11; // Used for Quest Icon 3. +const int BPAL_ICON4 = 12; // Used for Quest Icon 4. +const int BPAL_GLEEOKF = 13; +const int BPAL_FROZEN = 14; // Unused + +//Sprite lists. Use with Screen->ClearSprites() +const int SL_GUYS = 0; // Enemies +const int SL_ITEMS = 1; // Items +const int SL_EWPNS = 2; // Enemy weapons +const int SL_LWPNS = 3; // Link's weapons +const int SL_DECORATIONS = 4; // Grass clippings, Hover boots glow, etc. +const int SL_PARTICLES = 5; // Farore's Wind particles + +//Mouse buttons +const int MB_LEFTCLICK = 0x1; //AND (&) these with Link->InputMouseB to get the current button state of the mouse +const int MB_RIGHTCLICK = 0x2; +const int MB_MIDDLECLICK = 0x4; //Keep in in mind that not all mice/touchpads have a middle mouse button + diff --git a/output/common/std_functions.zh b/output/common/std_functions.zh new file mode 100644 index 0000000000..775fa2ab93 --- /dev/null +++ b/output/common/std_functions.zh @@ -0,0 +1,1750 @@ +//std_functions.zh +// + + +// +// Some utility routines +// + +//Wait for n frames +void Waitframes(int n) { + while(n-- > 0) Waitframe(); +} + +//Returns a if cond is true, else b. Overloaded. +float Cond(bool cond, float a, float b) { + if (cond) return a; + else return b; +} +bool Cond(bool cond, bool a, bool b) { + if (cond) return a; + else return b; +} +npc Cond(bool cond, npc a, npc b) { + if (cond) return a; + else return b; +} +item Cond(bool cond, item a, item b) { + if (cond) return a; + else return b; +} +lweapon Cond(bool cond, lweapon a, lweapon b) { + if (cond) return a; + else return b; +} +eweapon Cond(bool cond, eweapon a, eweapon b) { + if (cond) return a; + else return b; +} +ffc Cond(bool cond, ffc a, ffc b) { + if (cond) return a; + else return b; +} +itemdata Cond(bool cond, itemdata a, itemdata b) { + if (cond) return a; + else return b; +} + +// Chooses one of the options randomly and fairly. +float Choose(float a, float b) { + if (Rand(2)==0) return a; + else return b; +} + +float Choose(float a, float b, float c) { + int r = Rand(3); + if (r==0) return a; + else if (r==1) return b; + else return c; +} + +float Choose(float a, float b, float c, float d) { + int r = Rand(4); + if (r==0) return a; + else if (r==1) return b; + else if (r==2) return c; + else return d; +} + +float Choose(float a, float b, float c, float d, float e) { + int r = Rand(5); + if (r==0) return a; + else if (r==1) return b; + else if (r==2) return c; + else if (r==3) return d; + else return e; +} + +float Choose(float a, float b, float c, float d, float e, float f) { + int r = Rand(6); + if (r==0) return a; + else if (r==1) return b; + else if (r==2) return c; + else if (r==3) return d; + else if (r==4) return e; + else return f; +} + +//Returns the logarithm of x to the given base +float LogToBase(float x, float base){ + return Ln(x)/Ln(base); +} + +//Truncates x to an integer +int Floor(float x) { + if(x < 0) + return (x-.9999)<<0; + return x<<0; +} + +//Raises x to the nearest integer +int Ceiling(float x) { + if(x < 0) + return x<<0; + return (x+.9999)<<0; +} + +//Rounds x to the nearest integer +float Round(float x) { + if(x < 0) + return (x-.5)<<0; + return (x+.5)<<0; +} + +//Returns true if the integer is odd (or even in IsEven) +bool IsOdd(int x) +{ + return ((x & 1) == 1); +} + +bool IsEven(int x) +{ + return ((x & 1) == 0); +} + +//Clamps x to the range of low, high. +int Clamp(int x, int low, int high) { + if(xhigh) x=high; + return x; +} + +//same as Clamp, but with reversed values. +int VBound(int x, int high, int low) { + if(xhigh) x=high; + return x; +} + +//Returns the Quotient only of x divided by y +int Div(float x, float y) { + return (x/y)<<0; +} + +//Returns a random integer in the bounds of min and max +int Rand(int min, int max) { + return min+(Rand((1+max)-min)); +} + +//Returns a random floating point number up to n +float Randf(float n) { + return (Rand(0x7fff)/0x7fff)*n; +} + +//Returns a random floating point number between min and max +float Randf(float n1, float n2) { + return n1 + (Rand(0x7fff)/(0x7fff))*(n2-n1); +} + +//Converts 'd' in degrees to radians +float DegtoRad(float d) { + return d*0.0174; +} + +//Converts 'r' in radians to degrees +float RadtoDeg(float r) { + return r*57.2958; +} + +//Returns the sign of n +int Sign(int n) { + if (n > 0) return 1; + else if (n < 0) return -1; + else return 0; +} + +//Finds the location of a combo, given its (x,y) coordinates on the screen +int ComboAt(int x, int y) { + x = VBound(x,255,0); + y = VBound(y,175,0); + return (y & 240)+(x>>4); +} + +//Snaps 'x' to the combo grid +//Equivalent to calling ComboX(ComboAt(x,foo)); +int GridX(int x) { + return (x >> 4) << 4; +} + +//Snaps 'y' to the combo grid +//Equivalent to calling ComboY(ComboAt(foo,y)); +int GridY(int y) { + return (y >> 4) << 4; +} + + +//Returns the correct offset to be at the front of a sprite facing in the direction 'dir' +int AtFrontX(int dir) { + + int x = 0; + if(dir == DIR_UP || dir == DIR_DOWN) x = 8; + else if(dir == DIR_RIGHT) x = 16; + return x; +} + +int AtFrontY(int dir) { + + int y = 0; + if(dir == DIR_DOWN) y = 16; + else if(dir == DIR_LEFT || dir == DIR_RIGHT) y = 8; + return y; +} + +//Returns the correct offset to be 'dist' pixels away from the front of a sprite facing in the direction 'dir' +int InFrontX(int dir, int dist) { + int x = 0; + if(dir == DIR_LEFT) x = -16+dist; + else if(dir == DIR_RIGHT) x = 16-dist; + return x; +} + +int InFrontY(int dir, int dist){ + int y = 0; + if(dir == DIR_UP) y = -16+dist; + else if(dir == DIR_DOWN) y = 16-dist; + return y; +} + +// Get the X and Y coordinates at the center of a sprite +int CenterX(ffc anFFC) { return anFFC->X+8*anFFC->TileWidth; } +int CenterY(ffc anFFC) { return anFFC->Y+8*anFFC->TileHeight; } +int CenterX(npc anNPC) { return anNPC->X+8*anNPC->TileWidth; } +int CenterY(npc anNPC) { return anNPC->Y+8*anNPC->TileHeight; } +int CenterX(eweapon anEWeapon) { return anEWeapon->X+8*anEWeapon->TileWidth; } +int CenterY(eweapon anEWeapon) { return anEWeapon->Y+8*anEWeapon->TileHeight; } +int CenterX(lweapon anLWeapon) { return anLWeapon->X+8*anLWeapon->TileWidth; } +int CenterY(lweapon anLWeapon) { return anLWeapon->Y+8*anLWeapon->TileHeight; } +int CenterLinkX() { return Link->X+8; } +int CenterLinkY() { return Link->Y+8; } + +//Return the coordinates of a combo on the screen +int ComboX(int loc) { + return loc%16*16; +} +int ComboY(int loc) { + return loc&0xF0; +} + +//Returns true if the combo at '(x, y)' has either an inherent or place flag of type 'flag' +bool ComboFI(int x, int y, int flag){ + + int loc = ComboAt(x,y); + + return Screen->ComboF[loc] == flag || Screen->ComboI[loc] == flag; +} + +//Returns true if the combo at 'loc' has either an inherent or place flag of type 'flag' +bool ComboFI(int loc, int flag){ + + return Screen->ComboF[loc] == flag || Screen->ComboI[loc] == flag; +} + +//Sets bit 'bit' of Screen->D[] register 'd' to 'state' +void SetScreenDBit(int dmap, int screen, int d, int bit, bool state){ + int curstate = Game->GetDMapScreenD(dmap, screen, d); + if(state) Game->SetDMapScreenD(dmap, screen, d, curstate | (1 << bit)); + else Game->SetDMapScreenD(dmap, screen, d, curstate & ~(1 << bit)); +} +void SetScreenDBit(int screen, int d, int bit, bool state){ + int curstate = Game->GetScreenD(screen, d); + if(state) Game->SetScreenD(screen, d, curstate | (1 << bit)); + else Game->SetScreenD(screen, d, curstate & ~(1 << bit)); +} +void SetScreenDBit(int d, int bit, bool state){ + if(state) Screen->D[d] |= (1 << bit); + else Screen->D[d] &= ~(1 << bit); +} + +//Returns the state of bit 'bit' of Screen->D[] register 'd' +bool GetScreenDBit(int dmap, int screen, int d, int bit){ + return ( Game->GetDMapScreenD(dmap, screen, d) & (1 << bit) ) != 0; +} +bool GetScreenDBit(int screen, int d, int bit){ + return ( Game->GetScreenD(screen, d) & (1 << bit) ) != 0; +} +bool GetScreenDBit(int d, int bit){ + return (Screen->D[d] & (1 << bit)) != 0; +} + +//A shorthand way to get a combo on the current layer. +//Layer 0 is the screen itself. +int GetLayerComboD(int layer, int pos) { + if (layer==0) + return Screen->ComboD[pos]; + else + return Game->GetComboData(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos); +} + +//A shorthand way to set a combo on the current layer. +//Layer 0 is the screen itself. +void SetLayerComboD(int layer, int pos, int combo) { + if (layer == 0) + Screen->ComboD[pos] = combo; + else + Game->SetComboData(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos, combo); +} + +//A shorthand way to get a combo flag on the current layer. +//Layer 0 is the screen itself. +int GetLayerComboF(int layer, int pos) { + if (layer==0) + return Screen->ComboF[pos]; + else + return Game->GetComboFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos); +} + +//A shorthand way to set a combo flag on the current layer. +//Layer 0 is the screen itself. +void SetLayerComboF(int layer, int pos, int flag) { + if (layer == 0) + Screen->ComboF[pos] = flag; + else + Game->SetComboFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos, flag); +} + +//A shorthand way to get a combo type on the current layer. +//Layer 0 is the screen itself. +int GetLayerComboT(int layer, int pos) { + if (layer==0) + return Screen->ComboT[pos]; + else + return Game->GetComboType(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos); +} + +//A shorthand way to set a combo type on the current layer. +//Layer 0 is the screen itself. +void SetLayerComboT(int layer, int pos, int type) { + if (layer == 0) + Screen->ComboT[pos] = type; + else + Game->SetComboType(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos, type); +} + +//A shorthand way to get a combo's solidity on the current layer. +//Layer 0 is the screen itself. +int GetLayerComboS(int layer, int pos) { + if (layer==0) + return Screen->ComboS[pos]; + else + return Game->GetComboSolid(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos); +} + +//A shorthand way to set a combo's solidity on the current layer. +//Layer 0 is the screen itself. +void SetLayerComboS(int layer, int pos, int solidity) { + if (layer == 0) + Screen->ComboS[pos] = solidity; + else + Game->SetComboSolid(Screen->LayerMap(layer), Screen->LayerScreen(layer), pos, solidity); +} + +//Copies the combos and csets from one screen to another. +//Only copies layer 0! +void ScreenCopy(int destmap, int destscr, int srcmap, int srcscr) { + for (int i = 0; i < 176; i++) { + Game->SetComboData(destmap,destscr, i, Game->GetComboData(srcmap,srcscr,i)); + Game->SetComboCSet(destmap,destscr, i, Game->GetComboCSet(srcmap,srcscr,i)); + } +} + +//Swaps a row of tiles of length 'length' between positions 'first' and 'second' +void SwapTileRow(int first, int second, int length){ + for(int i=0;iDrawString which includes a position to start drawing from in the string +//Does not check for overflow +void DrawString(int layer, int x, int y, int font, int color, int background_color, int format, int opacity, + int string, int start){ + int buffer[256]; + for(int i=start;string[i]!=0;i++) buffer[i-start] = string[i]; + Screen->DrawString(layer,x,y,font,color,background_color,format,opacity,buffer); +} + +//Overload to Screen->DrawString which includes a start and end position to draw the string +//Does not check for overflow +void DrawString(int layer, int x, int y, int font, int color, int background_color, int format, int opacity, + int string, int start, int end){ + int buffer[256]; + for(int i=start;iDrawString(layer,x,y,font,color,background_color,format,opacity,buffer); +} + + +// A very simple layer 0 tile drawing routine. +void DrawTileSimple(int x, int y, int tile, int color) +{ + + Screen->FastTile(0, x, y, tile, color, 128); +} + + +//Returns the distance between two sets of coordinates using Pythagoras' Theorem +float Distance(int x1, int y1, int x2, int y2) { + int x = (x1-x2); + int y = (y1-y2); + return Sqrt(x*x+y*y); +} + +//Returns the direction of the vector from point 1 to point 2, in degrees from -180 to 180. (0 = right) +float Angle(int x1, int y1, int x2, int y2) { + return ArcTan(x2-x1, y2-y1)*57.2958; +} + +//The above, but in radians. +float RadianAngle(int x1, int y1, int x2, int y2) { + return ArcTan(x2-x1, y2-y1); +} + +// Returns the X component of a vector with a degree angle. +// A length of 3 and angle of 0 returns 3. +// A length of 3 and angle of 45 returns approx. 1.57. +// A length of 3 and angle of 90 returns 0. +float VectorX(int len, float angle) { + return Cos(angle)*len; +} + +// Returns the Y component of a vector with a degree angle. +// A length of 3 and angle of 0 returns 0. +// A length of 3 and angle of 45 returns approx. 1.57. +// A length of 3 and angle of 90 returns 3. +float VectorY(int len, float angle) { + return Sin(angle)*len; +} + +//rotates X about a center point by an amount of degrees +float RotatePointX(float x, float y, float centerX, float centerY, float degrees) { + float dx = x - centerX; + float dy = y - centerY; + return (Cos(degrees) * dx) - (Sin(degrees) * dy) + centerX; +} + +//rotates Y about a center point by an amount of degrees +float RotatePointY(float x, float y, float centerX, float centerY, float degrees) { + float dx = x - centerX; + float dy = y - centerY; + return (Sin(degrees) * dx) - (Cos(degrees) * dy) + centerY; +} + +//scales X to centerX by a given scale +float ScalePointX(float x, float centerX, float scale) { + return (scale * (x - centerX)) + centerX; +} + +//scales Y to centerY by a given scale +float ScalePointY(float y, float centerY, float scale) { + return (scale * (y - centerY)) + centerY; +} + +//rotates and scales X about a center point by an amount of degrees +float RotateScalePointX(float x, float y, float centerX, float centerY, float degrees, float scaleX, float scaleY) { + float dx = (x - centerX) * scaleX; + float dy = (y - centerY) * scaleY; + return (Cos(degrees) * dx) - (Sin(degrees) * dy) + centerX; +} + +//rotates and scales Y about a center point by an amount of degrees +float RotateScalePointY(float x, float y, float centerX, float centerY, float degrees, float scaleX, float scaleY) { + float dx = (x - centerX) * scaleX; + float dy = (y - centerY) * scaleY; + return (Sin(degrees) * dx) - (Cos(degrees) * dy) + centerY; +} + + +// Interpolates between p1 and p2 given 't' clamped within range 0,1. +float Lerp(float p1, float p2, float t) { + return (p1 + (p2 - p1) * t); +} + +// Returns the dot product of two vectors. +float DotProduct( float x1, float y1, float x2, float y2 ) { + return (x1 * x2 + y1 * y2); +} + +// Returns the cross product of two vectors. +float CrossProduct( float x1, float y1, float x2, float y2 ) { + return (x1 * y2 - y1 * x2); +} + +// Returns the squared distance of a vector. +float DistanceSquared( float x, float y ) { + return (x * x + y * y); +} + +// Finds the center of p1 and p2. +float Midpoint(float p1, float p2) { + return Lerp(p1, p2, 0.5); +} + +// Performs a "Smooth" Interpolation given 't' clamped within range 0,1. +float SmoothStep(float p1, float p2, float t) { + t = (t * t) * (3.0 - (2.0 * t)); + return Lerp(p1, p2, t); +} + +// Returns an angle pointing (t)percentage more accurate to the target than the specified radian_angle. +float TurnTowards( int X, int Y, int targetX, int targetY, float radian_angle, float t ) { + float a = ArcTan( targetX - X, targetY - Y ); + float d = WrapAngle(a - radian_angle); + if ( d > PI ) + d =-( PI2 - d ); + else if ( d < -PI ) + d = PI2 + d; + return WrapAngle(radian_angle + d * t); +} + +// Wraps radian value towards the range of -PI,PI. +float WrapAngle( float radians ) { + while (radians <= -PI) radians += PI2; + while (radians > PI) radians -= PI2; + return radians; +} + +// Wraps degree value towards the range of -180,180. +float WrapDegrees( float degrees ) { + while (degrees <= -180) degrees += 360; + while (degrees > 180) degrees -= 360; + return degrees; +} + +// Converts a counterclockwise degree angle (from -180 to 180) into one of the eight +// standard directions (DIR_UP etc.) used by ZC. +int AngleDir8(float angle) { + if (angle <= 157.5 && angle > 112.5) + return DIR_LEFTDOWN; + else if (angle <= 112.5 && angle > 67.5) + return DIR_DOWN; + else if (angle <= 67.5 && angle > 22.5) + return DIR_RIGHTDOWN; + else if (angle <= 22.5 && angle > -22.5) + return DIR_RIGHT; + else if (angle <= -22.5 && angle > -67.5) + return DIR_RIGHTUP; + else if (angle <= -67.5 && angle > -112.5) + return DIR_UP; + else if (angle <= -112.5 && angle > -157.5) + return DIR_LEFTUP; + else + return DIR_LEFT; +} + +//The above, but for radian angles. +int RadianAngleDir8(float angle) { + return AngleDir8(angle*57.2958); +} + +// Converts a counterclockwise degree angle (from -180 to 180) into one of the four +// standard directions (DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT) used by ZC. +int AngleDir4(float angle) { + if (angle <= 135 && angle > 45) + return DIR_DOWN; + else if (angle <= 45 && angle > -45) + return DIR_RIGHT; + else if (angle <= -45 && angle > -135) + return DIR_UP; + else + return DIR_LEFT; +} + +//The above, but for radian angles. +int RadianAngleDir4(float angle) { + return AngleDir4(angle*57.2958); +} + +//Returns the opposite direction to angle 'dir' +int OppositeDir(int dir) { + return Cond(dir < 4, dir^1b, dir^11b); +} + +//Converts directions to go round in a circle rather than U, D, L, R +int SpinDir(int dir) { + if(dir==0) + return DIR_UP; + else if(dir==1) + return DIR_RIGHT; + else if(dir==2) + return DIR_DOWN; + else if(dir==3) + return DIR_LEFT; + return -1; +} + +//Draws an ffc to a given layer. If the ffc is larger than 1x1 its graphics must all be comboed +void DrawToLayer(ffc f, int layer, int opacity){ + Screen->DrawCombo(layer,f->X,f->Y,f->Data,f->TileWidth,f->TileHeight,f->CSet,-1,-1,0,0,0,-1,0,true,opacity); +} + +//Draws an npc to a given layer +void DrawToLayer(npc n, int layer, int opacity){ + Screen->DrawTile(layer,n->X,n->Y,n->Tile,n->TileWidth,n->TileHeight,n->CSet,-1,-1,0,0,0,0,true,opacity); +} + +//Draws an lweapon to a given layer +void DrawToLayer(lweapon l, int layer, int opacity){ + Screen->DrawTile(layer,l->X,l->Y,l->Tile,l->TileWidth,l->TileHeight,l->CSet,-1,-1,0,0,0,0,true,opacity); +} + +//Draws an eweapon to a given layer +void DrawToLayer(eweapon e, int layer, int opacity){ + Screen->DrawTile(layer,e->X,e->Y,e->Tile,e->TileWidth,e->TileHeight,e->CSet,-1,-1,0,0,0,0,true,opacity); +} + +//Draws an item to a given layer +void DrawToLayer(item i, int layer, int opacity){ + Screen->DrawTile(layer,i->X,i->Y,i->Tile,i->TileWidth,i->TileHeight,i->CSet,-1,-1,0,0,0,0,true,opacity); +} + +//Generalized and optimized rectangle collision checking function. +//Returns true if the bounding box of box1 and box2 overlap. +bool RectCollision(int box1_x1, int box1_y1, int box1_x2, int box1_y2, int box2_x1, int box2_y1, int box2_x2, int box2_y2) { + if( box1_y2 < box2_y1 ) return false; + else if( box1_y1 > box2_y2 ) return false; + else if( box1_x2 < box2_x1 ) return false; + else if( box1_x1 > box2_x2 ) return false; + return true; +} + +//Check for collisions of two squares given upper-left coordinates and a side length for each. +bool SquareCollision(int c1x, int c1y, int side1, int c2x, int c2y, int side2) { + return RectCollision(c1x, c1y, c1x+side1, c1y+side1, c2x, c2y, c2x+side1, c2y+side1); +} + +//Check for collisions of two squares given center coordinates and a halved side length for each. +bool SquareCollision2(int c1x, int c1y, int radius1, int c2x, int c2y, int radius2) { + if( c1y + radius1 < c2y - radius2 ) return false; + else if( c1y - radius1 > c2y + radius2 ) return false; + else if( c1x + radius1 < c2x - radius2 ) return false; + else if( c1x - radius1 > c2x + radius2 ) return false; + return true; +} + +//Returns true if the two circles c1 and c2 overlap. +bool CircleCollision(int c1x, int c1y, int radius1, int c2x, int c2y, int radius2) { + return (Distance(c1x,c1y,c2x,c2y) <= (radius1+radius2)); +} + +//Returns true if there is a collision between the hitboxes of an lweapon and an eweapon. +bool Collision(lweapon a, eweapon b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an lweapon and an lweapon. +bool Collision(lweapon a, lweapon b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an eweapon and an eweapon. +bool Collision(eweapon a, eweapon b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an lweapon and an npc. +bool Collision(lweapon a, npc b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an eweapon and an npc. +bool Collision(eweapon a, npc b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an npc and an npc. +bool Collision(npc a, npc b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an item and an lweapon. +bool Collision(item a, lweapon b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an item and an eweapon. +bool Collision(item a, eweapon b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an item and an npc. +bool Collision(item a, npc b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an item and an item. +bool Collision(item a, item b) { + int ax = a->X + a->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = a->Y + a->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+a->HitWidth, ay+a->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (a->Z + a->HitZHeight >= b->Z) && (a->Z <= b->Z + b->HitZHeight); +} + +//A collision between an ffc and an lweapon. Uses TileWidth and TileHeight for the FFC's bounding box. Ignores the Z axis. +bool Collision(ffc f, lweapon b) { + int bx = b->X + b->HitXOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), bx, by, bx+b->HitWidth, by+b->HitHeight); +} + +//A collision between an ffc and an eweapon. Uses TileWidth and TileHeight for the FFC's bounding box. Ignores the Z axis. +bool Collision(ffc f, eweapon b) { + int bx = b->X + b->HitXOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), bx, by, bx+b->HitWidth, by+b->HitHeight); +} + +//A collision between an ffc and an npc. Uses TileWidth and TileHeight for the FFC's bounding box. Ignores the Z axis. +bool Collision(ffc f, npc b) { + int bx = b->X + b->HitXOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), bx, by, bx+b->HitWidth, by+b->HitHeight); +} + +//A collision between an ffc and an item. Uses TileWidth and TileHeight for the FFC's bounding box. Ignores the Z axis. +bool Collision(ffc f, item b) { + int bx = b->X + b->HitXOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), bx, by, bx+b->HitWidth, by+b->HitHeight); +} + +//A collision between an ffc and an ffc. Uses TileWidth and TileHeight for the FFCs' bounding boxes. +bool Collision(ffc f, ffc f2) { + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), f2->X, f2->Y, f2->X+f2->TileWidth*16, f2->Y+f2->TileHeight*16); +} + +//A circular collision between an ffc and an ffc. Uses TileWidth and TileHeight to find the centre of the FFCs. +bool Collision(ffc f, int radius1, ffc f2, int radius2) { + return CircleCollision(f->X+f->TileWidth/2, f->Y+f->TileHeight/2, radius1,f2->X+f2->TileWidth/2, f2->Y+f2->TileHeight/2, radius2); +} + +// So that you don't have to remember the ordering of the args +bool Collision(eweapon a, lweapon b) { + return Collision(b, a); +} + +bool Collision(npc a, lweapon b) { + return Collision(b, a); +} + +bool Collision(npc a, eweapon b) { + return Collision(b, a); +} + +bool Collision(lweapon a, item b) { + return Collision(b, a); +} + +bool Collision(eweapon a, item b) { + return Collision(b, a); +} + +bool Collision(npc a, item b) { + return Collision(b, a); +} + +bool Collision(lweapon a, ffc b) { + return Collision(b, a); +} + +bool Collision(eweapon a, ffc b) { + return Collision(b, a); +} + +bool Collision(npc a, ffc b) { + return Collision(b, a); +} + +bool Collision(item a, ffc b) { + return Collision(b, a); +} + +// Returns true if there is a collision between Link's hitbox and the eweapon's. +// This only checks hitboxes. +bool LinkCollision(eweapon b) { + int ax = Link->X + Link->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = Link->Y + Link->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+Link->HitWidth, ay+Link->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (Link->Z + Link->HitZHeight >= b->Z) && (Link->Z <= b->Z + b->HitZHeight); +} + +// Returns true if there is a collision between Link's hitbox and the lweapon's. +// This only checks hitboxes. +bool LinkCollision(lweapon b) { + int ax = Link->X + Link->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = Link->Y + Link->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+Link->HitWidth, ay+Link->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (Link->Z + Link->HitZHeight >= b->Z) && (Link->Z <= b->Z + b->HitZHeight); +} + +// Returns true if there is a collision between Link's hitbox and the item's. +// This only checks hitboxes. +bool LinkCollision(item b) { + int ax = Link->X + Link->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = Link->Y + Link->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+Link->HitWidth, ay+Link->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (Link->Z + Link->HitZHeight >= b->Z) && (Link->Z <= b->Z + b->HitZHeight); +} + +// Returns true if there is a collision between Link's hitbox and the npc's. +// This only checks hitboxes. Uses TileWidth and TileHeight to find the centre of the FFCs. +bool LinkCollision(npc b) { + int ax = Link->X + Link->HitXOffset; + int bx = b->X + b->HitXOffset; + int ay = Link->Y + Link->HitYOffset; + int by = b->Y + b->HitYOffset; + return RectCollision(ax, ay, ax+Link->HitWidth, ay+Link->HitHeight, bx, by, bx+b->HitWidth, by+b->HitHeight) && (Link->Z + Link->HitZHeight >= b->Z) && (Link->Z <= b->Z + b->HitZHeight); +} + +// Returns true if there is a collision between Link's hitbox and the FFC's. +// This only checks hitboxes. +bool LinkCollision(ffc f) { + int ax = Link->X + Link->HitXOffset; + int ay = Link->Y + Link->HitYOffset; + return RectCollision(f->X, f->Y, f->X+(f->TileWidth*16), f->Y+(f->TileHeight*16), ax, ay, ax+Link->HitWidth, ay+Link->HitHeight); +} + +// Returns the X coordinate of the left edge of the hitbox. +int HitboxLeft(eweapon a) { + return (a->X + a->HitXOffset); +} + +int HitboxLeft(lweapon a) { + return (a->X + a->HitXOffset); +} + +int HitboxLeft(item a) { + return (a->X + a->HitXOffset); +} + +int HitboxLeft(npc a) { + return (a->X + a->HitXOffset); +} + +int HitboxLeft(ffc a) { + return a->X; +} + +// Returns the X coordinate of the right edge of the hitbox. +int HitboxRight(eweapon a) { + return (a->X + a->HitXOffset + a->HitWidth - 1); +} + +int HitboxRight(lweapon a) { + return (a->X + a->HitXOffset + a->HitWidth - 1); +} + +int HitboxRight(item a) { + return (a->X + a->HitXOffset + a->HitWidth - 1); +} + +int HitboxRight(npc a) { + return (a->X + a->HitXOffset + a->HitWidth - 1); +} + +int HitboxRight(ffc a) { + return a->X + a->TileWidth*16 - 1; +} + +// Returns the Y coordinate of the top edge of the hitbox. +int HitboxTop(eweapon a) { + return (a->Y + a->HitYOffset); +} + +int HitboxTop(lweapon a) { + return (a->Y + a->HitYOffset); +} + +int HitboxTop(item a) { + return (a->Y + a->HitYOffset); +} + +int HitboxTop(npc a) { + return (a->Y + a->HitYOffset); +} + +int HitboxTop(ffc a) { + return a->Y; +} + +// Returns the Y coordinate of the bottom edge of the hitbox. +int HitboxBottom(eweapon a) { + return (a->Y + a->HitYOffset + a->HitHeight - 1); +} + +int HitboxBottom(lweapon a) { + return (a->Y + a->HitYOffset + a->HitHeight - 1); +} + +int HitboxBottom(item a) { + return (a->Y + a->HitYOffset + a->HitHeight - 1); +} + +int HitboxBottom(npc a) { + return (a->Y + a->HitYOffset + a->HitHeight - 1); +} + +//Uses TileWidth and TileHeight for the FFC's bounding box. +int HitboxBottom(ffc a) { + return a->Y + (a->TileHeight*16) - 1; +} + +//Returns the number of an FFC, and -1 for a non-valid FFC (which should never happen) +int FFCNum(ffc f) { + for(int i=1; i<=32; i++) + if(f == Screen->LoadFFC(i)) + return i; + return -1; +} + +//Functions for those who are not comfortable with binary +//Returns true if the left mouse button is pressed +bool InputLeftClick() { + return (Link->InputMouseB&MB_LEFTCLICK) != 0; +} + +//Returns true if the right mouse button is pressed +bool InputRightClick() { + return (Link->InputMouseB&MB_RIGHTCLICK) != 0; +} + +//Returns the item ID of the item equipped to Link's A button +int GetEquipmentA() { + return (Link->Equipment&0xFF); +} + + + +//Returns the item ID of the item equipped to Link's B button +int GetEquipmentB() { + return ((Link->Equipment&0xFF00)>>8); +} + +//Returns true if Link is using item 'id' +bool UsingItem(int id){ + return (GetEquipmentA() == id && Link->InputA) || (GetEquipmentB() == id && Link->InputB); +} + +//Returns the number of Triforce Pieces Link currently has +int NumTriforcePieces(){ + int ret = 0; + for(int i=1;i<=8;i++) + if(Game->LItems[i]&LI_TRIFORCE) ret++; + return ret; +} + +//Returns 1 if Screen Flag 'flag' is set from category 'category', 0 if it's not and -1 if an invalid flag is passed +//Flags are numbered starting from 0 +int ScreenFlag(int category, int flag) { + int catsizes[] = {3,7,5,3,2,4,4,2,3,7}; + if(flag < 0 || flag >= catsizes[category]) return -1; + return Screen->Flags[category]&(1<= catsizes[category]) return -1; + return Screen->EFlags[category]&(1<DMapFlags[dmap]&flag)!=0; +} + +//Sets a certain DMap flag to 'state' +void SetDMapFlag(int dmap, int flag, bool state){ + if(state) Game->DMapFlags[dmap] |= flag; + else Game->DMapFlags[dmap] &= ~flag; +} + +//Returns true if an item's Pickup state is set +//Use the IP_ constants for the 'pickup' argument of this function +bool GetItemPickup(item i, int pickup) { + return (i->Pickup&pickup) != 0; +} + +//Sets an item's Pickup state to 'state' +void SetItemPickup(item i, int pickup, bool state) { + if(state) i->Pickup |= pickup; + else i->Pickup &= ~pickup; +} + +//Returns true if an npc's Misc. flag is set. +bool GetNPCMiscFlag(npc e, int flag) { + return (e->MiscFlags&flag) != 0; +} + +//Returns true if Link has the level item 'itm' from level 'level' +//Overloaded to use the current level if no 'level' arg is entered +//Use the LI_ constants for the 'itm' argument +bool GetLevelItem(int level, int itm) { + return (Game->LItems[level]&itm) != 0; +} +bool GetLevelItem(int itm) { + return (Game->LItems[Game->GetCurLevel()]&itm) != 0; +} +//Gives or removes a level item from Link's inventory +void SetLevelItem(int level, int itm, bool state) { + if(state) Game->LItems[level] |= itm; + else Game->LItems[level] &= ~itm; +} +void SetLevelItem(int itm, bool state) { + if(state) Game->LItems[Game->GetCurLevel()] |= itm; + else Game->LItems[Game->GetCurLevel()] &= ~itm; +} + +//Create an NPC and set its X and Y position in one command +npc CreateNPCAt(int id, int x, int y) { + npc nme = Screen->CreateNPC(id); + if(nme->isValid()) { + nme->X = x; + nme->Y = y; + } + return nme; +} + +//Create an Item and set its X and Y position in one command +item CreateItemAt(int id, int x, int y) { + item it = Screen->CreateItem(id); + if(it->isValid()) { + it->X = x; + it->Y = y; + } + return it; +} + +//Create an LWeapon and set its X and Y position in one command +lweapon CreateLWeaponAt(int id, int x, int y) { + lweapon lw = Screen->CreateLWeapon(id); + if(lw->isValid()) { + lw->X = x; + lw->Y = y; + } + return lw; +} + +//Create an EWeapon and set its X and Y position in one command +eweapon CreateEWeaponAt(int id, int x, int y) { + eweapon ew = Screen->CreateEWeapon(id); + if(ew->isValid()) { + ew->X = x; + ew->Y = y; + } + return ew; +} + + +//Creates an lweapon at 'distx,disty' away from where Link is facing +lweapon NextToLink(int id, int distx, int disty) { + lweapon l = CreateLWeaponAt(id, Link->X+InFrontX(Link->Dir, distx), Link->Y+InFrontY(Link->Dir, disty)); + if(l->isValid()) { + l->Dir = Link->Dir; + } + return l; +} + +//Creates an lweapon 'dist' pixels away from the front of Link +lweapon NextToLink(int id, int dist) { + return NextToLink(id, dist, dist); +} + +eweapon NextToNPC(npc n, int id, int distx, int disty) { + eweapon e = CreateEWeaponAt(id, n->X+InFrontX(n->Dir, distx), n->Y+InFrontY(n->Dir, disty)); + if(e->isValid()) { + e->Dir = n->Dir; + } + return e; +} +eweapon NextToNPC(npc n, int id, int dist) { + return NextToNPC(n, id, dist, dist); +} + + +//Aim-type constants, for use with AimEWeapon +const int AT_NONE = 0; +const int AT_4DIR = 1; +const int AT_8DIR = 2; +const int AT_ANGULAR = 3; +const int AT_RAND4DIR = 4; +const int AT_RAND8DIR = 5; +const int AT_RANDANGULAR = 6; + +//Various methods for shooting at Link and at random +void AimEWeapon(eweapon e, int aimtype) +{ + int angle = RadianAngle(e->X, e->Y, Link->X, Link->Y); + if(aimtype == AT_4DIR) + { + e->Dir = RadianAngleDir4(angle); + } + else if(aimtype == AT_8DIR) + { + e->Dir = RadianAngleDir8(angle); + } + else if(aimtype == AT_ANGULAR) + { + e->Angular = true; + e->Angle = angle; + e->Dir = RadianAngleDir8(angle); + } + else if(aimtype == AT_RAND4DIR) + { + e->Dir = Rand(4); + } + else if(aimtype == AT_RAND8DIR) + { + e->Dir = Rand(8); + } + else if(aimtype == AT_RANDANGULAR) + { + e->Angular = true; + e->Angle = Randf(PI2); + e->Dir = RadianAngleDir8(e->Angle); + } +} + +//Aiming at enemies and at random +void AimLWeapon(lweapon l, npc n, int aimtype) +{ + int angle = RadianAngle(l->X, l->Y, n->X, n->Y); + if(aimtype == AT_4DIR) + { + l->Dir = RadianAngleDir4(angle); + } + else if(aimtype == AT_8DIR) + { + l->Dir = RadianAngleDir8(angle); + } + else if(aimtype == AT_ANGULAR) + { + l->Angular = true; + l->Angle = angle; + l->Dir = RadianAngleDir8(angle); + } + else + AimLWeapon(l, aimtype); +} +void AimLWeapon(lweapon l, int aimtype) +{ + if(aimtype == AT_RAND4DIR) + { + l->Dir = Rand(4); + } + else if(aimtype == AT_RAND8DIR) + { + l->Dir = Rand(8); + } + else if(aimtype == AT_RANDANGULAR) + { + l->Angular = true; + l->Angle = Randf(PI2); + l->Dir = RadianAngleDir8(l->Angle); + } +} + +//Turns a WPN_ constant to an EW_ constant +int WeaponTypeToID(int wpnt) +{ + if(wpnt == WPN_ENEMYFLAME) return EW_FIRE; + else if(wpnt == WPN_ENEMYWIND) return EW_WIND; + else if(wpnt == WPN_ENEMYFIREBALL) return EW_FIREBALL; + else if(wpnt == WPN_ENEMYARROW) return EW_ARROW; + else if(wpnt == WPN_ENEMYBRANG) return EW_BRANG; + else if(wpnt == WPN_ENEMYSWORD) return EW_BEAM; + else if(wpnt == WPN_ENEMYROCK) return EW_ROCK; + else if(wpnt == WPN_ENEMYMAGIC) return EW_MAGIC; + else if(wpnt == WPN_ENEMYBOMB) return EW_BOMB; + else if(wpnt == WPN_ENEMYSBOMB) return EW_SBOMB; + else if(wpnt == WPN_ENEMYLITBOMB) return EW_BOMBBLAST; + else if(wpnt == WPN_ENEMYLITSBOMB) return EW_SBOMBBLAST; + else if(wpnt == WPN_ENEMYFIRETRAIL) return EW_FIRETRAIL; + else if(wpnt == WPN_ENEMYFLAME2) return EW_FIRE2; + else if(wpnt == WPN_ENEMYFIREBALL2) return EW_FIREBALL2; + return -1; +} + + +//Removes LWeapon 'l' from the screen +void Remove(lweapon l){ + if(!l->isValid()) return; + l->DeadState = WDS_DEAD; + l->X = 32768; +} + +//Removes EWeapon 'e' from the screen +void Remove(eweapon e){ + if(!e->isValid()) return; + e->DeadState = WDS_DEAD; + e->X = 32768; +} + +//Removes Item 'i' from the screen +void Remove(item i){ + if(!i->isValid()) return; + i->X = 32768; +} + +//Removes NPC 'n' from the screen +void Remove(npc n){ + if(!n->isValid()) return; + n->X = 32768; + n->HP = -1000; +} + +//Creates a timeout item (like a rupee or heart) +item CreateTimeoutItem(int id, int x, int y) { + item Spawn = Screen->CreateItem(id); + SetItemPickup(Spawn, IP_TIMEOUT, true); + Spawn->HitWidth = 16; Spawn->HitHeight = 16; + Spawn->X = x; Spawn->Y = y; +} + +// Use the I_ constants. +// Warning: these iterate over every onscreen item. +// Iterating over every onscreen lweapon multiple times per frame may +// cause slowdown in Zelda Classic. +int NumItemsOf(int type) { + int ret = 0; + item it; + for (int i = Screen->NumItems(); i >0 ; i--) { + it = Screen->LoadItem(i); + if (it->ID == type) + ret++; + } + return ret; +} + + +// Use the LW_ constants. +// Warning: these iterate over every onscreen lweapon. +// Iterating over every onscreen lweapon multiple times per frame may +// cause slowdown in Zelda Classic. +int NumLWeaponsOf(int type) { + int ret = 0; + lweapon w; + for (int i = Screen->NumLWeapons(); i > 0; i--) { + w = Screen->LoadLWeapon(i); + if (w->ID == type) + ret++; + } + return ret; +} + +int NumEWeaponsOf(int type) { + int ret = 0; + eweapon w; + for (int i = Screen->NumEWeapons(); i > 0; i--) { + w = Screen->LoadEWeapon(i); + if (w->ID == type) + ret++; + } + return ret; +} + +int NumNPCsOf(int type) { + int ret = 0; + npc n; + for (int i = Screen->NumNPCs(); i > 0 ; i--) { + n = Screen->LoadNPC(i); + if (n->ID == type) + ret++; + } + return ret; +} + +// Returns the first LWeapon of the given type. Use the LW_ constants. +// If none exist, it returns an uninitialised pointer. +lweapon LoadLWeaponOf(int type) { + lweapon w; + for (int i=1; i <= Screen->NumLWeapons(); i++) { + w = Screen->LoadLWeapon(i); + if (w->ID == type) return w; + } + lweapon w2; + return w2; +} + +// Returns the first EWeapon of the given type. Use the EW_ constants. +// If none exist, it returns an uninitialised pointer. +eweapon LoadEWeaponOf(int type) { + eweapon w; + for (int i=1; i <= Screen->NumEWeapons(); i++) { + w = Screen->LoadEWeapon(i); + if (w->ID == type) return w; + } + eweapon w2; + return w2; +} + +// Returns the first NPC of the given type. Use the NPCT_ constants. +// If none exist, it returns an uninitialised pointer. +npc LoadNPCOfType(int type) { + npc n; + for (int i=1; i <= Screen->NumNPCs(); i++) { + n = Screen->LoadNPC(i); + if (n->Type == type) return n; + } + npc n2; + return n2; +} + +// Returns the first NPC of the given ID. Use the NPC_ constants. +// If none exist, it returns an uninitialised pointer. +npc LoadNPCOf(int type) { + npc n; + for (int i=1; i <= Screen->NumNPCs(); i++) { + n = Screen->LoadNPC(i); + if (n->ID == type) return n; + } + npc n2; + return n2; +} + +//Returns the position of the first instance of the given combo, or -1. +int FirstComboOf(int t, int layer) { + for (int i = 0; i < 176; i++) { + if (layer == 0) { + if (Screen->ComboD[i] == t) + return i; + } + else { + if (GetLayerComboD(layer,i) == t) + return i; + } + } + return -1; +} + +//Returns the position of the last instance of the given combo, or -1. +int LastComboOf(int t, int layer) { + for (int i = 175; i >= 0; i--) { + if (layer == 0) { + if (Screen->ComboD[i] == t) + return i; + } + else { + if (GetLayerComboD(layer,i) == t) + return i; + } + } + return -1; +} + +//Returns the position of the first instance of the given combo, or -1. +int FirstComboTypeOf(int t, int layer) { + for (int i = 0; i < 176; i++) { + if (layer == 0) { + if (Screen->ComboT[i] == t) + return i; + } + else { + if (GetLayerComboT(layer,i) == t) + return i; + } + } + return -1; +} + +//Returns the position of the last instance of the given combo, or -1. +int LastComboTypeOf(int t, int layer) { + for (int i = 175; i >= 0; i--) { + if (layer == 0) { + if (Screen->ComboT[i] == t) + return i; + } + else { + if (GetLayerComboT(layer,i) == t) + return i; + } + } + return -1; +} + +//Returns the position of the first instance of the given combo flag, or -1. +//Checks inherent flags too! +int FirstComboFlagOf(int t, int layer) { + for (int i = 0; i < 176; i++) { + if (layer == 0) { + if (Screen->ComboF[i] == t || Screen->ComboI[i] == t) return i; + } + else { + if (Game->GetComboFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer),i) == t + || Game->GetComboInherentFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer),i) == t) + return i; + } + } + return -1; +} + +//Returns the position of the last instance of the given combo flag, or -1. +//Checks inherent flags too! +int LastComboFlagOf(int t, int layer) { + for (int i = 175; i >= 0; i--) { + if (layer == 0) { + if (Screen->ComboF[i] == t || Screen->ComboI[i] == t) return i; + } + else { + if (Game->GetComboFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer),i) == t + || Game->GetComboInherentFlag(Screen->LayerMap(layer), Screen->LayerScreen(layer),i) == t) + return i; + } + } + return -1; +} + +// Returns true if the combo at the given position is water. +bool IsWater(int position) +{ + int combo=Screen->ComboT[position]; + if(combo==CT_WATER || combo==CT_SWIMWARP || combo==CT_DIVEWARP || (combo>=CT_SWIMWARPB && combo<=CT_DIVEWARPD)) + return true; + else + return false; +} + +// Returns true if the combo at the given position is a pit. +bool IsPit(int position) +{ + int combo=Screen->ComboT[position]; + if(combo==CT_PIT || combo==CT_PITR || (combo>=CT_PITB && combo<=CT_PITD)) + return true; + else + return false; +} + +//Creates and returns an exact copy of the passed LWeapon. Assumes that the passed pointer is valid. +lweapon Duplicate(lweapon a) { + lweapon b = Screen->CreateLWeapon(a->ID); + b->X = a->X; + b->Y = a->Y; + b->Z = a->Z; + b->Jump = a->Jump; + b->Extend = a->Extend; + b->TileWidth = a->TileWidth; + b->TileHeight = a->TileHeight; + b->HitWidth = a->HitWidth; + b->HitHeight = a->HitHeight; + b->HitZHeight = a->HitZHeight; + b->HitXOffset = a->HitXOffset; + b->HitYOffset = a->HitYOffset; + b->DrawXOffset = a->DrawXOffset; + b->DrawYOffset = a->DrawYOffset; + b->DrawZOffset = a->DrawZOffset; + b->Tile = a->Tile; + b->CSet = a->CSet; + b->DrawStyle = a->DrawStyle; + b->Dir = a->Dir; + b->OriginalTile = a->OriginalTile; + b->OriginalCSet = a->OriginalCSet; + b->FlashCSet = a->FlashCSet; + b->NumFrames = a->NumFrames; + b->Frame = a->Frame; + b->ASpeed = a->ASpeed; + b->Damage = a->Damage; + b->Step = a->Step; + b->Angle = a->Angle; + b->Angular = a->Angular; + b->CollDetection = a->CollDetection; + b->DeadState = a->DeadState; + b->Flash = a->Flash; + b->Flip = a->Flip; + for (int i = 0; i < 16; i++) + b->Misc[i] = a->Misc[i]; + return b; +} + +//Creates and returns an exact copy of the passed EWeapon. Assumes that the passed pointer is valid. +eweapon Duplicate(eweapon a) { + eweapon b = Screen->CreateEWeapon(a->ID); + b->X = a->X; + b->Y = a->Y; + b->Z = a->Z; + b->Jump = a->Jump; + b->Extend = a->Extend; + b->TileWidth = a->TileWidth; + b->TileHeight = a->TileHeight; + b->HitWidth = a->HitWidth; + b->HitHeight = a->HitHeight; + b->HitZHeight = a->HitZHeight; + b->HitXOffset = a->HitXOffset; + b->HitYOffset = a->HitYOffset; + b->DrawXOffset = a->DrawXOffset; + b->DrawYOffset = a->DrawYOffset; + b->DrawZOffset = a->DrawZOffset; + b->Tile = a->Tile; + b->CSet = a->CSet; + b->DrawStyle = a->DrawStyle; + b->Dir = a->Dir; + b->OriginalTile = a->OriginalTile; + b->OriginalCSet = a->OriginalCSet; + b->FlashCSet = a->FlashCSet; + b->NumFrames = a->NumFrames; + b->Frame = a->Frame; + b->ASpeed = a->ASpeed; + b->Damage = a->Damage; + b->Step = a->Step; + b->Angle = a->Angle; + b->Angular = a->Angular; + b->CollDetection = a->CollDetection; + b->DeadState = a->DeadState; + b->Flash = a->Flash; + b->Flip = a->Flip; + for (int i = 0; i < 16; i++) + b->Misc[i] = a->Misc[i]; + return b; +} + +//This should allow any scripted object to easily mimic Link styled LOZ solidity collision +//checking, be it Link, FFCs, or enemies. +//Note - You should use full_tile=true if you don't want the upper eight pixels to overlap +//solid combos as per LOZ1 behavior. +bool CanWalk(int x, int y, int dir, int step, bool full_tile) { + int c=8; + int xx = x+15; + int yy = y+15; + if(full_tile) c=0; + if(dir==0) return !(y-step<0||Screen->isSolid(x,y+c-step)||Screen->isSolid(x+8,y+c-step)||Screen->isSolid(xx,y+c-step)); + else if(dir==1) return !(yy+step>=176||Screen->isSolid(x,yy+step)||Screen->isSolid(x+8,yy+step)||Screen->isSolid(xx,yy+step)); + else if(dir==2) return !(x-step<0||Screen->isSolid(x-step,y+c)||Screen->isSolid(x-step,y+c+7)||Screen->isSolid(x-step,yy)); + else if(dir==3) return !(xx+step>=256||Screen->isSolid(xx+step,y+c)||Screen->isSolid(xx+step,y+c+7)||Screen->isSolid(xx+step,yy)); + return false; //invalid direction +} + +//Returns true if Link is on a sideview screen +bool IsSideview() { + return Screen->Flags[SF_ROOMTYPE] & 4; +} + +//Returns true if the sprite at (x,y) is standing on a sideview platform on a sideview screen, as worked out +//by ZC's internal code. +//For 16 pixel high sprites only. +bool OnSidePlatform(int x, int y) { + return (Screen->isSolid(x+4,y+16) && Screen->isSolid(x+12,y+16) && Screen->Flags[SF_ROOMTYPE]&4); +} + +//Returns true if a sprite of height 'h' at position (x,y) with an offset of (xOff,yOff) is standing +//on a sideview platform on a sideview screen. +bool OnSidePlatform(int x, int y, int xOff, int yOff, int h) { + return (Screen->isSolid((x+xOff)+4,(y+yOff)+h) && Screen->isSolid((x+xOff)+12,(y+yOff)+h) && Screen->Flags[SF_ROOMTYPE]&4); +} + +//Kills all of Link's inputs +void NoAction() +{ + Link->InputUp = false; Link->PressUp = false; + Link->InputDown = false; Link->PressDown = false; + Link->InputLeft = false; Link->PressLeft = false; + Link->InputRight = false; Link->PressRight = false; + Link->InputR = false; Link->PressR = false; + Link->InputL = false; Link->PressL = false; + Link->InputA = false; Link->PressA = false; + Link->InputB = false; Link->PressB = false; + Link->InputEx1 = false; Link->PressEx1 = false; + Link->InputEx2 = false; Link->PressEx2 = false; + Link->InputEx3 = false; Link->PressEx3 = false; + Link->InputEx4 = false; Link->PressEx4 = false; +} + +//NoAction, then Waitframe or (equivalent of) Waitframes +void WaitNoAction() +{ + NoAction(); + Waitframe(); +} +void WaitNoAction(int frames) +{ + for(int i = 0; i < frames; i++) + WaitNoAction(); +} + +//Get an NPC's name from an ID +void GetNPCName(int ID, int string) +{ + npc n = Screen->CreateNPC(ID); + n->GetName(string); + Remove(n); +} + +void GetMessage(int ID, int string) +{ + Game->GetMessage(ID, string); + int i; + for(i = MAX_MESSAGELENGTH-2; string[i] == ' '; i--); + string[i+1] = 0; +} + +itemdata GetItemData(item i) +{ + return Game->LoadItemData(i->ID); +} + +int GetHighestLevelItem(int itemclass) +{ + itemdata id; + int ret = -1; + int curlevel = -1000; + //143 is default max items, increase if you add lots of your own + for(int i = 0; i < 143; i++) + { + id = Game->LoadItemData(i); + if(id->Family != itemclass) + continue; + if(id->Level > curlevel) + { + curlevel = id->Level; + ret = i; + } + } + return ret; +} + +int GetHighestLevelItem(item i) +{ + itemdata argid = GetItemData(i); + int ret = i->ID; + int curlevel = argid->Level; + itemdata id; + //143 is max items, decrease to improve speed if you need to + for(int i = 0; i < 256; i++) + { + id = Game->LoadItemData(i); + if(id->Family != argid->Family) + continue; + if(id->Level > curlevel) + { + curlevel = id->Level; + ret = i; + } + } + return ret; +} + +// Convert between map and DMap screens +int DMapToMap(int screen, int dmap) { + return screen+Game->DMapOffset[dmap]; +} + +int MapToDMap(int screen, int dmap) { + return screen-Game->DMapOffset[dmap]; +} + diff --git a/output/common/string.txt b/output/common/string.txt new file mode 100644 index 0000000000..5b7f56c70c --- /dev/null +++ b/output/common/string.txt @@ -0,0 +1,234 @@ +========================================================== +--- String.zh: string-handling constants and functions --- +========================================================== + +=============== +-- Constants -- +=============== + + * Message ASCII Code +const int MSGC_LINEFEED = 10 + * The ASCII value for '\n' + + * Message Format +const int MF_NONE = 0 +const int MF_STRING = 1 +const int MF_INT = 2 +const int MF_FLOAT = 3 +const int MF_NUM = 4 +const int MF_PTR = 5 +const int MF_CHAR = 6 + * Entered directly into 'strcatf' and 'strncatf' as the format type for the + * argument + * Converted (respectively) from the '%n', '%s', '%i', '%f', '%d', '%p' and '%c' + * format arguments in sprintf and printf (via the sprintf_MFCodeToInt function) + +================================ +-- Single Character Functions -- +================================ + +bool isControlCode(int chr) + * Returns true if 'chr' is in the control code range of ascii characters + +bool isNumber(int chr) + * Returns true if 'chr' is in the range of ascii characters '0' to '9' + +bool isAlphabetic(int chr) + * Returns true if 'chr' is an alphabetic character + +bool isAlphaNumeric(int chr) + * Returns true if 'chr' is an alphanumeric character + +bool isHex(int chr) + * Returns true if 'chr' is in the set { '0'-'9', 'A'-'F' , 'a'-'f' } + +bool isUpperCase(int chr) + * Returns true if 'chr' is an upper-case character + +bool isLowerCase(int chr) + * Returns true if 'chr' is a lower-case character + +int UpperToLower(int chr) + * Converts all upper case characters to lower case, leaving non-alphabetic + * characters unchanged + +int LowerToUpper(int chr) + * Converts all lower case characters to upper case, leaving non-alphabetic + * characters unchanged + +int ConvertCase(int chr) + * Converts lower case to upper case and upper case to lower case + +========================= +-- Memory Manipulation -- +========================= + + * Memory Set +void memset(int ptr[], int value, int n) + * Sets block of memory of size 'n' pointed by 'ptr' to 'value' + + * Memory Copy +int memcpy(int dest[], int src[], int n) + * Copys block of memory pointed by 'src' of size 'n' to 'dest' and returns + * 'dest' + + * Memory Move +int memmove(int dest[], int src[], int n) + * As memcpy, but uses a buffer so memory space can overlap + + * Array Set +void arrayset(int a[], int a0, int a1, int a2,...) + * Assign all elements of array 'a'. Overloaded for up to 16 elements + +========================= +-- String Manipulation -- +========================= + + * String Copy +void strcpy(int dest[], int src[]) + * Copys string 'src' into string 'dest' without checking for overflow in 'dest' +void strncpy(int dest[], int src[], int n) + * As strcpy, but only takes the first 'n' characters from src + + * Remove Characters +void remchr(int string[]) + * Remove all characters starting from pointer 'string' +void remnchr(int string[], int n) + * Remove 'n' characters and shift the rest of the string back to pointer 'string' + + * String Length +int strlen(int string[]) + * Returns the length of string 'string' + + * String Concatenate +int strcat(int dest[], int src[]) + * Appends string 'src' onto string 'dest' (assuming dest has enough extra memory + * allocated to allow the operation) +int strncat(int dest, int src, int n) + * strcat for the first 'n' characters in src + + +-- String Searching -- +====================== + + * String Character +int strchr(int string[], int character) + * Returns the position of the first occurence of 'character' in 'string', + * or -1 if none are found + + * String Reverse Character +int strrchr(int string[], int character) + * Returns the position of the last occurence of 'character' in 'string' + * starting from the end, or -1 if none are found + + * String Sub-String +int strstr(int string[], int sub[]) + * Returns the position of the first occurence of sub-string 'sub' in 'string, + * or -1 if sub is not found + + * String Span +int strspn(int str[], int keys[]) + * Returns the length of characters in 'str' before a character not contained in + * 'keys' is found + + * String Complement Span +int strcspn(int str[], int keys[]) + * Returns the length of characters in 'str' before a character contained in + * 'keys' is found + + +-- String Comparison -- +======================= + + * String Compare +int strcmp(int str1[], int str2[]) + * Iterates through str1 and str2 until a character is found which is not the same in + * both strings, and then returns > 0 if the character is larger in str1, and < 0 if it is + * larger in str2. Returns 0 if the strings are equal +int strncmp(int str1[], int str2[], int n) + * strcmp up to 'n' characters + + +-- Converting between variables and strings -- +============================================== + + * ASCII to Integer +int atoi(int string[]) + * Returns the decimal integer pointed by 'string' + + * Integer Length +int ilen(int string[]) + * Returns the length of characters of the decimal integer pointed by 'string' + + * Hexadecimal ASCII to Integer +int xtoi(int string[]) + * Returns the (positive) hexadecimal integer pointed by 'string' + + * Hexadecimal Length +int xlen(int string[]) + * Returns the length of characters of the (positive) hexadecimal integer pointed by 'string' + + * ASCII to Float +float atof(int string[]) + * Returns the floating point number pointed by 'string' + + * Float Length +int flen(int string[]) + * Returns the length of characters of the floating point number pointed by 'string' + + * ASCII to Number +float aton(int string[]) + * Returns the number pointed by 'string', calling either atoi or atof depending on context + + * Number Length +int nlen(int string[]) + * Returns the length of characters of the number pointed by 'string', calling either + * ilen or flen depending on context + + * Integer to ASCII +int itoa(int string[], int num) + * Places integer 'num' into string 'string' without checking for overflow, + * and returns the number of characters used + + * Float to ASCII +int ftoa(int string[], float num, bool printall) + * Places float 'num' into string 'string' without checking for overflow, + * and returns the number of characters used. If 'printall' is true, it will add 4 decimal places + * regardless of the most significant digit + + * Number to ASCII +int ntoa(int string[], float num) + * Checks whether 'num' is an integer or not, and calls the appropriate function + + +-- String Formatting -- +======================= + + * String Concatenate Format +int strcatf(int dest[], int arg, int format) + * Appends 'arg' onto 'dest' as the MF_ constant passed into 'format' +int strncatf(int dest[], int arg, int format, int n) + * As strcatf, using only 'n' characters of 'arg' + + * String Print Format +void sprintf(int ret[], int formatstr[], int a0, int a1, int a2,...) + * Prints string 'formatstr' into 'ret' according to the arguments inputted (see C function for reference), + * returning the number of characters used. Does not check for overflow in 'ret' + * Overloaded up to a maximum of 16 arguments. Enter the right number of arguments for your format string; + * there is (currently) no way to check how many arguments have been entered or of what type they are + * Currently supported arguments: + * '%s' - String + * '%i' - Integer + * '%f' - Float + * '%d' - Number (Integer/Float depending on context) + * '%n' - Nothing + * '%p' - Pointer Address + * '%c' - Single character + * '%x' - Hexadecimal Integer (lower case) + * '%X' - Hexadecimal Integer (upper case) + * '\n' places a line feed ASCII character into the string + + * Print Format +void printf(int formatstr[], int a0, int a1, int a2,...) + * Uses a buffer to print the results of sprintf(formatstr,...) straight to allegro.log + * Overloaded up to a maximum of 16 arguments diff --git a/output/common/string.zh b/output/common/string.zh new file mode 100644 index 0000000000..23487621be --- /dev/null +++ b/output/common/string.zh @@ -0,0 +1,1011 @@ +//string.zh +//ZScript string handling functions, akin to those found in C + +//Constants +//printf, sprintf and strcatf arguments +const int MSGC_LINEFEED = 10; // '\n' + +const int MF_NONE = 0; // '%n' +const int MF_STRING = 1; // '%s' +const int MF_INT = 2; // '%i' +const int MF_FLOAT = 3; // '%f' +const int MF_NUM = 4; // '%d' +const int MF_PTR = 5; // '%p' +const int MF_CHAR = 6; // '%c' +const int MF_HEXLOWER = 7; // '%x' +const int MF_HEXUPPER = 8; // '%X' + + +//Single character functions +//Returns true if 'chr' is in the control code range of ascii characters +bool isControlCode(int chr) +{ + return (chr >= 0 && chr < ' '); +} + +//Returns true if 'chr' is in the range of ascii characters '0' to '9' +bool isNumber(int chr) +{ + return (chr >= '0' && chr <= '9'); +} + +//Returns true if 'chr' is an alphabetic character +bool isAlphabetic(int chr) +{ + return (chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z'); +} + +//Returns true if 'chr' is an alphanumeric character +bool isAlphaNumeric(int chr) +{ + return isNumber(chr) || isAlphabetic(chr); +} + +//Returns true if 'chr' is in the set { '0'-'9', 'A'-'F' , 'a'-'f' } +bool isHex(int chr) +{ + return isNumber(chr) || (chr >= 'A' && chr <= 'F') || (chr >= 'a' && chr <= 'f'); +} + +//Returns true if 'chr' is an upper-case character +bool isUpperCase(int chr) +{ + return (chr >= 'A' && chr <= 'Z'); +} + +//Returns true if 'chr' is a lower-case character +bool isLowerCase(int chr) +{ + return (chr >= 'a' && chr <= 'z'); +} + +//Converts all upper case characters to lower case, leaving non-alphabetic +//characters unchanged +int UpperToLower(int chr) +{ + if(!isAlphabetic(chr)) + return chr; + return Cond(isLowerCase(chr), chr, chr + ('a' - 'A')); +} + +//Converts all lower case characters to upper case, leaving non-alphabetic +//characters unchanged +int LowerToUpper(int chr) +{ + if(!isAlphabetic(chr)) + return chr; + return Cond(isLowerCase(chr), chr - ('a' - 'A'), chr); +} + +//Converts lower case to upper case and upper case to lower case +int ConvertCase(int chr) +{ + if(!isAlphabetic(chr)) + return chr; + return chr + Cond(isLowerCase(chr), 'A' - 'a', 'a' - 'A'); +} + + +//Memory Manipulation +//Memory Set +//Sets block of memory of size 'n' pointed by 'ptr' to 'value' +void memset(int ptr, int pos, int value, int n) +{ + for(int i = 0; i < n; i++) + ptr[pos + i] = value; +} +void memset(int ptr, int value, int n) +{ + memset(ptr, 0, value, n); +} + +//Memory Copy +//Copys block of memory pointed by 'src' of size 'n' to 'dest' +void memcpy(int dest, int dpos, int src, int spos, int n) +{ + for(int i = 0; i < n; i++) + dest[dpos + i] = src[spos + i]; +} +void memcpy(int dest, int src, int n) +{ + memcpy(dest, 0, src, 0, n); +} + +//Memory Move +//As memcpy, but uses a buffer so memory space can overlap +int memmove(int dest, int dpos, int src, int spos, int n) +{ + int buffer[0x100]; + for(int i = 0; i < n; i++) + buffer[i] = src[spos + i]; + for(int i = 0; i < n; i++) + dest[dpos + i] = buffer[i]; + return dest; +} + + +//Array Set +//Assign all elements of array. Overloaded. +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad,int ae,int af){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; a[0xb] = ab; a[0xc] = ac; a[0xd] = ad; a[0xe] = ae; a[0xf] = af; +} + + +//String Manipulation +//String Copy +//Copys string 'src' into string 'dest' without checking for overflow in 'dest' +void strcpy(int dest, int dpos, int src, int spos) +{ + for(int i = 0; src[spos + i] != 0; i++) + dest[dpos + i] = src[spos + i]; +} +void strcpy(int dest, int src) +{ + strcpy(dest, 0, src, 0); +} + +//As strcpy, but only takes the first 'n' characters from src +void strncpy(int dest, int dpos, int src, int spos, int n) +{ + for(int i = 0; src[spos + i] != 0 && i < n; i++) + dest[dpos + i] = src[spos + i]; +} +void strncpy(int dest, int src, int n) +{ + strncpy(dest, 0, src, 0, n); +} + +//Remove Characters +//Remove all characters starting from pointer 'string' +void remchr(int string, int pos) +{ + for(int i = 0; string[pos + i] != 0; i++) + string[pos + i] = 0; +} + +//Remove 'n' characters and shift string back to pointer 'string' +void remnchr(int string, int pos, int n) +{ + int l = strlen(string); + int temp = n + pos; + for(int i = 0; string[pos + i] != 0; i++) + string[pos + i] = Cond(temp + i < l, string[temp + i] ,0); +} + +//String Length +//Returns the length of string 'string' +int strlen(int string) +{ + int l; + for(l = 0; string[l] != 0; l++); + return l; +} + +//String Concatenate +//Appends string 'src' onto string 'dest' (assuming dest has enough extra memory +//allocated to allow the operation) +void strcat(int dest, int src, int spos) +{ + int i; + int l = strlen(dest); + for(i = 0; src[spos + i] != 0; i++) + dest[l + i] = src[spos + i]; + dest[l + i] = 0; +} +void strcat(int dest, int src) +{ + strcat(dest, src, 0); +} + +//strcat up to 'n' characters in src +void strncat(int dest, int src, int spos, int n) +{ + int i; + int l = strlen(dest); + for(i = 0; src[spos + i] != 0 && i < n; i++) + dest[l + i] = src[spos + i]; + dest[l + i] = 0; +} +void strncat(int dest, int src, int n) +{ + strncat(dest, src, 0, n); +} + + +//String Searching +//String Character +//Returns the position of the first occurence of 'character' in 'string', +//or -1 if none are found +int strchr(int string, int pos, int chr) +{ + for(int i = 0; string[pos + i] != 0; i++) + if(string[pos + i] == chr) + return pos + i; + return -1; +} +int strchr(int string, int chr) +{ + return strchr(string, 0, chr); +} + +//String Reverse Character +//Returns the position of the last occurence of 'character' in 'string' +//starting from the end, or -1 if none are found +int strrchr(int string, int pos, int chr) +{ + for(int i = strlen(string) - pos; i > 0; i--) + if(string[i] == chr) + return i; + return -1; +} +int strrchr(int string, int chr) +{ + return strrchr(string, 0, chr); +} + + +//String Sub-String +//Returns the position of the first occurence of sub-string 'sub' in 'string', +//or -1 if sub is not found +int strstr(int string, int pos, int sub) +{ + int l = strlen(sub) - 1; + for(int i = 0; string[pos + i] != 0; i++) + for(int j = 0; sub[j] != 0 && string[pos + i + j] != 0 && string[pos + i + j] == sub[j]; j++) + if(j == l) + return pos + i; + return -1; +} +int strstr(int string, int sub) +{ + return strstr(string, 0, sub); +} + +//String Span +//Returns the length of characters in 'str' before a character not contained in +//'keys' is found +int strspn(int str, int pos, int keys) +{ + int i; + bool found; + for(i = 0; str[pos + i] != 0; i++) + { + found = false; + for(int j = 0; keys[j] != 0;j ++) + if(str[pos + i] == keys[j]) + found = true; + if(!found) + return pos + i; + } + return pos + i; +} +int strspn(int str, int keys) +{ + return strspn(str, 0, keys); +} + +//String Complement Span +//Returns the length of characters in 'str' before a character contained in +//'keys' is found +int strcspn(int str, int pos, int keys) +{ + int i; + for(i = 0; str[pos + i] != 0; i++) + for(int j = 0; keys[j] != 0; j++) + if(str[pos + i] == keys[j]) + return pos + i; + return pos + i; +} +int strcspn(int str, int keys) +{ + return strcspn(str, 0, keys); +} + +//String Comparison +//String Compare +//Iterates through str1 and str2 until a character is found which is not the same in +//both strings, and then returns > 0 if the character is larger in str1, and < 0 if it is +//larger in str2. Returns 0 if the strings are equal +int strcmp(int str1, int pos1, int str2, int pos2) +{ + int i; + for(i = 0; str1[pos1 + i] != 0 && str2[pos2 + i] != 0 && str1[pos1 + i] == str2[pos2 + i]; i++); + return str1[pos1 + i] - str2[pos2 + i]; +} +int strcmp(int str1, int str2) +{ + return strcmp(str1, 0, str2, 0); +} + +//strcmp up to 'n' characters +int strncmp(int str1, int pos1, int str2, int pos2, int n) +{ + int i; + for(i = 0; str1[pos1 + i] != 0 && str2[pos2 + i] != 0 && str1[pos1 + i] == str2[pos2 + i] && i < n; i++); + if(i == n) + i--; + return str1[pos1 + i] - str2[pos2 + i]; +} +int strncmp(int str1, int str2, int n) +{ + return strncmp(str1, 0, str2, 0 , n); +} + + +//Converting between variables and strings +//ASCII to Integer +//Returns the decimal integer pointed by 'string' +int atoi(int string, int pos) +{ + int i=0; + bool neg = false; + if(string[pos + i] == '-'){ + i++; + neg = true; + } + int ret; + for(ret = 0; isNumber(string[pos + i]); i++) + ret = ret*10 + (string[pos + i] - '0'); + return ret*Cond(neg, -1, 1); +} +int atoi(int string) +{ + return atoi(string, 0); +} + +//Integer Length +//Returns the length of characters of the decimal integer pointed by 'string' +int ilen(int string, int pos) +{ + int ret = 0; + if(string[pos] == '-') + ret++; + for(; isNumber(string[pos + ret]); ret++); + return ret; +} +int ilen(int string) +{ + return ilen(string, 0); +} + +//Hexadecimal ASCII to Integer +//Returns the (positive) hexadecimal integer pointed by 'string' +int xtoi(int string, int pos) +{ + int ret = 0; + for(int i = 0; isHex(string[pos + i]); i++) + ret = ret*0x10 + Cond(isNumber(string[pos + i]), string[pos + i] - '0', LowerToUpper(string[pos + i]) - ('A' + 0xA)); + return ret; +} +int xtoi(int string) +{ + return xtoi(string, 0); +} + +//Hexadecimal Length +//Returns the length of characters of the (positive) hexadecimal integer pointed by 'string' +int xlen(int string, int pos) +{ + int ret = 0; + for(; isHex(string[pos + ret]); ret++); + return ret; +} +int xlen(int string) +{ + return xlen(string, 0); +} + +//ASCII to Float +//Returns the floating point number pointed by 'string' +float atof(int string, int pos) +{ + int i = 0; + bool neg = false; + if(string[pos + i] == '-') + { + i++; + neg = true; + } + + int ret = 0; + for(; isNumber(string[pos + i]); i++) + ret = ret*10 + (string[pos + i]-'0'); + + if(string[pos + i] != '.') + return ret; + i++; + + int decimal = 0; + for(int j = 0; j < 4; j++) + decimal = decimal*10 + Cond(isNumber(string[pos + i + j]), (string[pos + i + j] - '0'), 0); + + return (ret + decimal / 10000) * Cond(neg, -1, 1); +} +float atof(int string) +{ + return atof(string, 0); +} + +//Float Length +//Returns the length of characters of the floating point number pointed by 'string' +int flen(int string, int pos) +{ + int ret = ilen(string, pos); + + if(string[pos + ret] != '.') + return ret; + ret++; + + return ret + ilen(string, pos + ret); +} +int flen(int string) +{ + return flen(string, 0); +} + +//ASCII to Number +//Calls either atoi or atof depending on context +int aton(int string, int pos) +{ + int i = 0; + if(string[pos + i] == '-') + i++; + for(; isNumber(string[pos + i]); i++); + + if(string[pos + i] == '.') + return atof(string, pos); + else + return atoi(string, pos); +} +int aton(int string) +{ + return aton(string, 0); +} + +//Number Length +//Calls either flen or ilen depending on context +int nlen(int string, int pos) +{ + int i = 0; + if(string[pos + i] == '-') + i++; + for(; isNumber(string[pos + i]); i++); + + if(string[i] == '.') + return flen(string, pos); + else + return ilen(string, pos); +} +int nlen(int string) +{ + return nlen(string, 0); +} + +//Integer to ASCII +//Places integer 'num' into string 'string' without checking for overflow, +//and returns the number of characters used +int itoa(int string, int pos, int num) +{ + int ret = 0; + if(num < 0) + { + string[pos] = '-'; + ret++; + num = -num; + } + else if(num == 0) + { + string[pos] = '0'; + return 1; + } + + int digits = Floor(Log10(num) + 1); + for(int i = 0; i < digits; i++) + string[pos + ret + i] = (Floor(num / Pow(10, digits - i - 1)) % 10) + '0'; + return ret + digits; +} +int itoa(int string, int num) +{ + return itoa(string, 0, num); +} + +//Hexadecimal Integer to ASCII +//Places integer 'num' into string 'string' in base 16 without checking for overflow, +//and returns the number of characters used +int xtoa(int string, int pos, int num, bool upper) +{ + num = Floor(Abs(num)); + string[pos] = '0'; + string[pos+1] = 'x'; + int ret = 2; + + if(num == 0) + { + string[pos+2] = '0'; + return 3; + } + + int digits = Floor(LogToBase(num, 16) + 1); + int alphaoffset = Cond(upper, 'A' - 0xA, 'a' - 0xa); + for(int i = 0; i < digits; i++) + { + int coeff = (Floor(num / Pow(0x10, digits - i - 1)) % 0x10); + string[pos + ret + i] = Cond(coeff < 0xA, coeff + '0', coeff + alphaoffset); + } + return ret + digits; +} +int xtoa(int string, int num, bool upper) +{ + return xtoa(string, 0, num, upper); +} +int xtoa(int string, int num) +{ + return xtoa(string, 0, num, true); +} + +//Float to ASCII +//Places float 'num' into string 'string' without checking for overflow, +//and returns the number of characters used. If 'printall' is true, it will add 4 decimal places +//regardless of the most significant digit +int ftoa(int string, int pos, float num, bool printall) +{ + int oldPos=pos; + int place=100000; + int digit; + bool printZero=false; + int storedZeroes=0; + + if(num<0) + { + string[pos]='-'; + pos++; + num=-num; + } + + + for(int i=0; i<10; i++) + { + digit=((num/place)<<0)%10; + + // If the fractional part hasn't been reached yet, or + // if all four of its digits are to be printed, this is easy. + if(place>=1 || printall) + { + if(digit>0 || printZero) + { + string[pos]=digit+'0'; + pos++; + + // Start printing 0 at the first non-zero digit. + printZero=true; + } + } + + // Otherwise, it's trickier. + else + { + // A zero isn't printed unless there's something else after it. + // Don't print it, just keep count. + if(digit==0) + storedZeroes++; + + // Any other digit flushes the zeroes and then is printed. + else + { + for(; storedZeroes>0; storedZeroes--) + { + string[pos]='0'; + pos++; + } + + string[pos]=digit+'0'; + pos++; + } + } + + num%=place; // To make sure num/place doesn't overflow when place<1 + place/=10; + + if(place==1) // Last digit before the decimal point + printZero=true; + + else if(place==0.1) // Reached the fractional part + { + string[pos]='.'; + pos++; + } + } + + if(storedZeroes==4) + { + // printall is false and the number is an integer; + // just add one zero to the end. + string[pos]='0'; + pos++; + } + + return pos-oldPos; +} +int ftoa(int string, float num, bool printall) +{ + return ftoa(string, 0, num, printall); +} +int ftoa(int string, int pos, float num) +{ + return ftoa(string, pos, num, false); +} +int ftoa(int string, float num) +{ + return ftoa(string, 0, num, false); +} + +//Number to ASCII +//Checks whether 'num' is an integer or not, and calls the appropriate function +int ntoa(int string, int pos, float num) +{ + if(num == Floor(num)) + return itoa(string, pos, num); + else + return ftoa(string, pos, num, false); +} +int ntoa(int string, float num) +{ + return ntoa(string, 0, num); +} + + +//String Formating +//String Concatenate Format +//Appends 'arg' onto 'dest' as the MF_ constant passed into 'format' +void strcatf(int dest, int arg, int format) +{ + if(format == MF_INT) + { + int buffer[0x20]; + itoa(buffer, arg); + strcat(dest, buffer); + } + else if(format == MF_HEXLOWER) + { + int buffer[0x20]; + xtoa(buffer, arg, false); + strcat(dest, buffer); + } + else if(format == MF_HEXUPPER) + { + int buffer[0x20]; + xtoa(buffer, arg, true); + strcat(dest, buffer); + } + else if(format == MF_FLOAT) + { + int buffer[0x20]; + ftoa(buffer, arg, false); + strcat(dest, buffer); + } + else if(format == MF_FLOAT) + { + int buffer[0x20]; + ftoa(buffer, arg, false); + strcat(dest, buffer); + } + else if(format == MF_NUM) + { + int buffer[0x20]; + ntoa(buffer, arg); + strcat(dest, buffer); + } + else if(format == MF_PTR) + { + int buffer[0x20]; + itoa(buffer, arg); + strcat(dest, buffer); + } + else if(format == MF_CHAR) + { + int buffer[0x2]; + arrayset(buffer, arg, 0); + strcat(dest, buffer); + } + else if(format == MF_STRING && arg != 0) + strcat(dest, arg); + +} + +//As strcatf, using only 'n' characters of 'arg' +void strncatf(int dest, int arg, int format, int n) +{ + if(format == MF_INT) + { + int buffer[0x20]; + itoa(buffer, arg); + strncat(dest, buffer, n); + } + else if(format == MF_HEXLOWER) + { + int buffer[0x20]; + xtoa(buffer, arg, false); + strncat(dest, buffer, n); + } + else if(format == MF_HEXUPPER) + { + int buffer[0x20]; + xtoa(buffer, arg, true); + strncat(dest, buffer, n); + } + else if(format == MF_FLOAT) + { + int buffer[0x20]; + ftoa(buffer, arg, false); + strncat(dest, buffer, n); + } + else if(format == MF_NUM) + { + int buffer[0x20]; + ntoa(buffer, arg); + strncat(dest, buffer, n); + } + else if(format == MF_PTR) + { + int buffer[0x20]; + itoa(buffer, arg); + strncat(dest, buffer, n); + } + else if(format == MF_CHAR) + { + int buffer[0x2]; + arrayset(buffer, arg, 0); + strncat(dest, buffer, n); + } + else if(format == MF_STRING && arg != 0) + strncat(dest, arg, n); + +} + +//String Print Format +//Prints string 'formatstr' into 'ret' according to the arguments inputted (see C function for reference) +//Maximum 16 arguments +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad,int ae,int af) +{ + int pos = 0; + int currentarg = 0; + int a[0x10]; + arrayset(a,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af); + + for(int i = 0; formatstr[i] != 0; i++) + { + int chr = formatstr[i]; + if(chr == '\') //Control code + { + int nextchr = formatstr[i + 1]; + if(nextchr == 'n') + { + ret[pos] = MSGC_LINEFEED; + pos++; + i++; + continue; + } + } + else if(chr == '%') //Format argument + { + int nextchr = formatstr[i + 1]; + if(sprintf_isMFCode(nextchr)) + { + strcatf(ret, a[currentarg], sprintf_MFCodeToInt(nextchr)); + for(; ret[pos] != 0; pos++); + currentarg++; + i++; + continue; + } + } + + ret[pos] = chr; + pos++; + } + + return pos; +} + +//Print Format +//Uses a buffer to print the results of sprintf(formatstr,...) straight to allegro.log +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad,int ae,int af) +{ + int buffer[0x200]; //Max TraceS length is 512 + sprintf(buffer,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,af); + TraceS(buffer); +} + +//Used by sprintf +bool sprintf_isMFCode(int chr) +{ + return (chr == 'n' || chr == 's' || chr == 'i' || chr == 'f' || chr == 'd' || + chr == 'p' || chr == 'c' || chr == 'x' || chr == 'X'); +} +int sprintf_MFCodeToInt(int chr) +{ + if(chr == 'n') return MF_NONE; + else if(chr == 'i') return MF_INT; + else if(chr == 'f') return MF_FLOAT; + else if(chr == 'd') return MF_NUM; + else if(chr == 's') return MF_STRING; + else if(chr == 'p') return MF_PTR; + else if(chr == 'c') return MF_CHAR; + else if(chr == 'x') return MF_HEXLOWER; + else if(chr == 'X') return MF_HEXUPPER; + return -1; +} + + +//Function overloads +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad,int ae){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,a7,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,a6,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4,int a5){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,a5,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3,int a4){ + return sprintf(ret,formatstr,a0,a1,a2,a3,a4,0,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2,int a3){ + return sprintf(ret,formatstr,a0,a1,a2,a3,0,0,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1,int a2){ + return sprintf(ret,formatstr,a0,a1,a2,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0,int a1){ + return sprintf(ret,formatstr,a0,a1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr,int a0){ + return sprintf(ret,formatstr,a0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +int sprintf(int ret,int formatstr){ + return sprintf(ret,formatstr,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} + +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad,int ae){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,ae,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac,int ad){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,ad,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab,int ac){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,ac,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,ab,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,aa,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,a8,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,a7,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5,int a6){ + printf(formatstr,a0,a1,a2,a3,a4,a5,a6,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4,int a5){ + printf(formatstr,a0,a1,a2,a3,a4,a5,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3,int a4){ + printf(formatstr,a0,a1,a2,a3,a4,0,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2,int a3){ + printf(formatstr,a0,a1,a2,a3,0,0,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1,int a2){ + printf(formatstr,a0,a1,a2,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0,int a1){ + printf(formatstr,a0,a1,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr,int a0){ + printf(formatstr,a0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} +void printf(int formatstr){ + printf(formatstr,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +} + +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab, int ac, int ad, int ae){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; a[0xb] = ab; a[0xc] = ac; a[0xd] = ad; a[0xe] = ae; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab, int ac, int ad){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; a[0xb] = ab; a[0xc] = ac; a[0xd] = ad; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab, int ac){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; a[0xb] = ab; a[0xc] = ac; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa,int ab){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; a[0xb] = ab; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9,int aa){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; a[0xa] = aa; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8,int a9){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; a[0x9] = a9; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7, + int a8){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; + a[0x8] = a8; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6,int a7){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; a[0x7] = a7; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5,int a6){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; a[0x6] = a6; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4,int a5){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; a[0x5] = a5; +} +void arrayset(int a,int a0,int a1,int a2,int a3,int a4){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; a[0x4] = a4; +} +void arrayset(int a,int a0,int a1,int a2,int a3){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; a[0x3] = a3; +} +void arrayset(int a,int a0,int a1,int a2){ + a[0x0] = a0; a[0x1] = a1; a[0x2] = a2; +} +void arrayset(int a,int a0,int a1){ + a[0x0] = a0; a[0x1] = a1; +} +void arrayset(int a,int a0){ + a[0x0] = a0; +} + diff --git a/output/common/zquest.txt b/output/common/zquest.txt new file mode 100644 index 0000000000..b5b0c4c846 --- /dev/null +++ b/output/common/zquest.txt @@ -0,0 +1,2930 @@ ++--------------------------------+ +| /\ ZQuest v2.50 /\ | +| /__\ User Reference /__\ | +| http://www.zeldaclassic.com | ++--------------------------------+ + ++-----------------------------+ +| 1. INTRODUCTION | ++-----------------------------+ + + "The first thing you should know is that Zelda Classic does have its limitations. It started out as a clone of Zelda 1, which is also very limited. Although it has grown and will continue to grow, it can't do everything you might have in mind. + "That said, you'll find that there is a lot that can be done within ZC's limitations. It allows for multiple overworlds, huge dungeons, and caves and dungeons that aren't "levels". It also allows you to customize the graphics, colors, MIDIs, and more. Some features are still in development." + The above was written by Phantom Menace referring to the 1.84 version in mid 2000. It still holds true, though its limitations are fewer with each new version. It is now possible to make quests that bear very little resemblance to The Legend of Zelda. + + This is not an exhaustive manual, but a summary of the numerous features of ZQuest. There is a documentation wiki which explains each feature in detail. It is available at http://www.shardstorm.com/ZCwiki/. It is also considerably easier to navigate than this text file. + ++-----------------------------+ +| 2.1 FUNDAMENTAL CONCEPTS | ++-----------------------------+ + +Here is a list of terms and concepts for various defining features of Zelda Classic quests. + + - The Header lists the name of the quest, its author, and contains the password required to edit it (if any). + + - Quest Rules alter the behaviour and features of Zelda Classic's game engine. + + - Cheats are special passwords that the player can enter to enable certain cheat functions. + + - Items are the numerous objects that Link collects and uses during play, such as Rupees, Clocks, Boomerangs or Rings. + + - Enemies (also known as NPCs) are the foes that Link encounters, including bosses. + + - Weapons are projectile sprites that are created by enemies or Link's items, such as fireballs, arrows or magic. In the game engine, they are divided into LWeapons ("Link Weapons", weapons that affect enemies) and EWeapons ("Enemy Weapons", weapons that affect Link). + + - Guys are the non-player characters who speak to Link in The Legend of Zelda. + + - Strings are the messages that the Guys say to Link. They can also appear by other means, such as by scripts. + + - Init Data determines Link's starting inventory, his starting DMap, and some miscellaneous physics constants. + + - Palettes are grids of colours used by sprites and combos in the game. They are divided into sets of 16 colours called CSets. + + - Tiles are raw graphics. They are typically divided into 16x16 pixel squares. In accordance with NES limitations, they are initially 4-bit, which means they are limited to 16 colours. However, 4-bit tiles can be drawn with different CSets, and thus it is very easy to 'palette-swap' tiles. Individual tiles can also be converted to 8-bit colour, letting them use all 256 colours of a palette, but preventing them from being palette-swapped. + + - Combos are terrain squares. They are a 'combination' of a tile, collision data, and various options. Combos are 'painted' onto screens to make environments. + + - Combo Flags are placed on screens to indicate secret triggers (such as bombable squares) as well as pushable blocks and specific enemy spawn locations. + + - DMaps (Dungeon Maps) define the 'dungeons' in the quest and their characteristics - their music, palette, subscreen map and such. + + - Screens are the environments that Link explores. They are grids of combos, 16 wide and 11 high (thus making them 256x176 pixel rectangles). Screens are stored in 16x8 grids +known as Maps. In addition to combos, they each have an Enemy List, Layers, Screen Flags, Freeform Combos, Warps, Secret Combos, and more. + + - Freeform Combos are miscellaneous sprites used for a variety of purposes - primarily, as combos that aren't adhered to the grid, and secondarily, as slots for scripts. Each screen has 32 Freeform Combos. + + - Subscreens are the game displays that show Link's current status, as well as the pause screens where Link equips his equipment items. + + - Item Drop Sets determine the odds that a certain item will appear when an enemy is defeated. + + - Door Combo Sets are templates for the doors used in NES Dungeons - shutters, locked doors, bombable walls, and such. + + - MIDIs are the music tracks in your quest. (It is also possible for your quest's DMaps to use external music files in much richer formats, though.) + + - Scripts are programming code that you can attach to screens (via their Freeform Combos), items, or the game engine itself, and give you tremendous power to modify or build upon the game engine of Zelda Classic. Scripts can be written in a high-level C-like language called ZScript, or in an assembly-like language called ZASM. + ++-----------------------------+ +| 2.2 BASIC COMMANDS | ++-----------------------------+ + + ZQuest is loaded with "hot keys". Once you become familiar with them, you will be able to work faster. Many hot keys are listed in the main menus. Here are some important ones: + +Main Editor View: + - u: undo + - w: toggle 'Show Walkability', highlighting solid areas of the screen + - f: toggle 'Show Flags', showing where Combo Flags are placed + - arrow keys: change the current screen + - control + arrow keys: activate the current screen's Side Warp in the given direction + - comma,period: dec/inc the current map + - +,-: inc/dec the current CSet + - *,/: inc/dec the current combo flag value + - d: toggles the "dark room" screen flag + - l: turn out the lights (waits for keypress) + - q: toggles 'show csets', then 'show types' + - 0-9: set the screen palette to this level palette (this is only for convenience in editing; the game ignores this setting). + - shift + 0-9: same as above but adds 10 to the level number + - shift + up,down: scroll combo selector one line + - shift + pgup,pgdn: scroll combo selector one screen of a combo page + - control + pgup,pgdn: scroll combo selector one combo page + - p: scroll combo selector to the specified combo page + - shift + h: flip the screen horizontally, rearranging its combos + - shift + v: flip the screen vertically + - control + h: flip the map horizontally, rearranging its screens + - control + v: flip the map vertically + - shift + X: Preview mode, a mode in which screen secrets and freeform combo movement can be previewed. + +Other Editors and Dialogs may use: + - u: undo + - F1: show this help file + - c,v: copy/cut, paste + - del: delete + - h,v: flip tiles horizontally, vertically. This works in almost every editor that lets you select a tile for an entity. + - n: normalize (used in the tile editor after flipping a tile, to make it stay flipped.) + - o: overlap + - r: rotate (used in the tile editor to rotate a tile clockwise. Shift/r will rotate the tile counter-clockwise.) + - m: move (in tile or combo editors). + - s: swap (in combo editor; more convenient than "move"). + ++-----------------------------+ +| 2.3 MAIN SCREEN | ++-----------------------------+ + + The main screen is where you edit the screens of your quest. Select combos from the selector or selectors to the right, and paint them onto the screen. The gray shaded bar indicates part of the screen that, in accordance with The Legend of Zelda, isn't visible unless the screen is scrolling vertically. Additionally, there may be four dark-shaded strips surrounding the main screen, conveniently showing the combos of the adjoining screens. + + If Freeform Combos have been placed on a screen, you can click on a Freeform Combo and drag it to a new location. + +Main Screen Right-Click Menu: + - Select Combo: Makes the combo you right-clicked on the selected combo. + - Scroll to Combo: Scrolls the currently active combo selector to the current combo. Useful if your quest has many pages of combos. + - Edit Combo: Brings up the Edit Combo window for the combo you right-clicked on. + - Draw Block commands: The first number is width and the second height. Example: to draw the large tree (2x2) select the upper left combo of the tree, right-click where you want the upper left combo to be on the screen, then click on Draw Block -> 2x2. The entire tree will be drawn. + - Brush Width/Height: They allow you to draw with more than one combo at once. So, if you need to place a lot of something down and that thing takes up a 4-combo square, you'd set the brush height and brush witdh both to 2. Then, you start drawing with it. + - Set Fill Type: control + click to fill an area with one combo. + 1) Flood fills the whole screen with the selected combo. + 2) Fill is basically like the fill command in a paint program. It changes the CTRL+Click'ed on combo to the selected combo, so long as the fill can reach it without crossing over another combo type. The 4-way version can only travel up, down, left, or right from any combo. The 8-way version can go diagonally as well. + 3) Fill2 command is useful for making lakes. Draw an outline and then use fill2 inside it. Anything that's not your current combo gets changed. There's also a 4-way and 8-way version for that. + - Replace All: Replaces all instnces of the combo you right-clicked on with the selected combo. + - Properties: Gives the position, combo, cset, flag (if any), and combo type of the tile you right-clicked on. + - Place + Edit FFC: Places the first unused Freeform Combo at this location and edits it. + - Paste FFC as FFC: Pastes a copied FFC into this FFC slot. + +Additionally, right-clicking an FFC brings up a menu with these items: + - Copy FFC: Copies the FFC. + - Paste FFC: Replaces the FFC with the copied FFC. + - Edit FFC: Edits the FFC. + - Clear FFC: Removes the FFC, rendering that slot unused. + ++-----------------------------+ +| 2.4 MAIN PANEL | ++-----------------------------+ + + If you are in Large Mode (the default ZQuest mode), then below the main screen will be 9 buttons. These are Screen Tabs, and function much like the tabs in a web browser. You can use them to edit multiple screens in a convenient fashion. + + Furthermore, below the Screen Tabs is the Layers Toolbar. You can use this to toggle or switch the layers of a screen. See the summary of the Screen menu for more information on Layers. + + At the bottom-left corner is a pane showing the current map. Click or use the arrow keys to change to different screens on the map. Push the comma or period keys to change the current map. + + Next to the map pane there may be several placement squares. These are used to edit the location of various spots where Link or other things appear. Click on a square, and then click and drag on the screen to place it. + +- The rupee/item square affects the location of the screen's item. +- The stairs square affects the location of the screen's stairs secret, if it exists. +- The green square affects where Link appears when he continues or starts the game if the 'Use Warp Return Points Only' rule is NOT set. Otherwise, it does nothing and its functionality is handled by warp return A. +- The flag lets you place a combo flag in addition to using the Combo Flag menu item in the Tools menu. Press / or * to increment/decrement the combo flag. +- The blue squares let you place the screen's Warp Returns. Warp Returns are the locations Link appears at when he is warped to this screen from other places. If placed directly on top of Cave combos, Link will climb out of the combo when he appears. (And, for compatability with Whistle Warps, they will also do this if placed 16 pixels below the Cave combo.) +- The large black pane visually lists all of the enemies in the Enemy List for this screen. + + If you are in Large Mode, there are two more panes: Commands and Favorites. Commands allows you to allocate commonly used menu items (such as 'Tiles' or 'Compile ZScript') to a convenient button. Click a button labelled '(None)' to edit the command, or control-click a button to remove its command. + + Favourites allows you to 'bookmark' commonly used combos. Click to place combos in the favourites pane. Right-click and select 'Remove Combo' to remove them. + ++----------------------------+ +| 2.5 SMALL MODE MAIN PANEL | ++----------------------------+ + + The old ZQuest interface prior to 2.50 can be toggled in the ZQuest options, where it is called Small Mode. It is 320x240 resolution and lacks several recent ZQuest features. + + In Small Mode, the ZQuest main panel is divided into 8 pages which can be navigated with Page Up and Page Down. + + - Page 1 shows the title of the quest file you are editing and the combo type of the tile you currently have selected, which will be placed on the screen if you click on the screen. +The two squares show the tile you have selected, the first square showing in red the parts of the tile that are unwalkable. The number to the right of the squares is the current cset, toggled by pressing + or - on the numeric keyboard. The numbers below the squares are the combo page and tile number of the selected tile. + - Page 2 features the first four placement squares, which are described in the previous section. + - Page 3 shows at a glance a few of the screen and enemy flags for the current screen. +(Screen) Flags: D (Dodongo roar), H (Hold up item), E (Enemies->secret), T (Floating traps), G (Roar=gasp style), S (Secret SFX), O (Ocean surf SFX), M (Maze path), L (Use ladder), W (Whistle->Stairs), R (Boss roar SFX), D (Dark room), I (Enemies->Item), B (Block->Shutters), I (Invisible enemies). +Enemy (Flags): B (Dungeon boss), I (Enemy carries item), L (Has ringleader), F (Statues shoot fire), R (Falling rocks), 2 (Center traps), 4 (Corner traps), Z (Zora). P (Pattern): random or enter from sides. + - Page 4 shows the Guy, String, and Room type assigned to the current screen. If the Room Type requires additional information of the kind that usually appears in the 'Screen -> Catch All' menu item, this information will be shown too. + - Page 5 shows Tile Warp A and Side Warp A of the current screen along with the warps destination (DMap : Screen) and type. + - Page 6 shows triggers for side warps: Right, Left, Bottom, Top, Maze Path for the current screen and the Exit direction of the maze. + - Page 7 features a Layers selector. Check the layers you want to show on the base (Layer 0) screen in ZQuest. If any layers besides 0 are used (assigned in Data/Layers), a circle will appear under that layer. By clicking on that circle, you can edit that layer from the base screen instead of having to go to the map/screen where that layer actually is. To see what layer you are editting without going to this page, press the letter B. + - Page 8 shows the four blue squares, which are described in the previous section. + ++-----------------------------+ +| 3. FILE MENU | ++-----------------------------+ + + - New: Start a new quest with the current quest template (which by default is New Default). You can choose a set of quest rules for the new quest. + - Open (F3): Used to load existing quests or quests-in-progress into the editor. If a quest is passworded, you must have the password to open the quest. + - Save (F2): Used to save changes to an already named quest. + - Save As: Used to save changes to a quest without eliminating the current version. For instance, is you open one of the example quests to use as the basis of your quest, use Save As so that the example quest will still be there unchanged to use again. With Save As you must give a name and location for your new quest. + - Quest Templates: Lets you edit the list of quest templates to use when you create a new quest. Quest templates are quest files that are used as a starting point for a quest. The default template is New Default. + - Import: This is used to import files with the extensions given below to a quest you are working on. Remember that the imported file will replace the one already in the quest, e.g. importing a .zpl file will replace your current palettes with the new palettes. +Exceptions: +1) When importing tiles and combos you can specify which page of your current tile or combo sheet to start the import on, so that you can avoid erasing current tiles and combos. +2) When importing a map, ZQ bring up a Map Import Bias window. The options are: +--Total Copy: Use this option if you want to erase the original map you are importing to. With the next 2 options, blank screens are not imported. +--Prefer Original: If the map you are importing has unblank screens where the original does, the original screens will be used and the conflicting screen will not be imported. +--Prefer Import: Like the above except that conflicting screens on the import map will be imported, erasing those screens on the original map. + + - Export: Used to make a file (extensions below) of a part of your quest. Exporting does not erase that segment of your quest. +[Map (.map file); DMaps (.dmp); Tiles (.til), a ZQuest-specific tile format; Palettes (.zpl); String Table (.zqs); Text Dump (.txt): a formatted string table; Combo Table (.cmb); Graphics Pack (.zgp): consists of tiles, palettes, and combos; Quest Template (.zqt): a compressed graphics pack; Unencoded Quest (.qsu)] + +- Exit (ESC): Closes ZQuest. You will be prompted to save if you have unsaved changes. + ++-----------------------------+ +| 4. QUEST MENU | ++-----------------------------+ + + This menu contains most all of the significant data and asset editors in ZQuest. + + - Header: Lets you password-protect your quest. Also contains quest metadata that is displayed when you first load a quest. + - Rules: Lets you choose among the various Quest Rules. + - Map Count: Lets you add or remove maps from your quest. + - Cheats: Lets you add cheat passwords. + - Items: Lets you edit the item varieties that will appear in your quest. + - Enemies: Lets you edit the enemy varieties that will appear in your quest. + - Strings: Lets you edit the basic strings in your quest. + - DMaps: Lets you edit the quest's DMaps. + - Init Data: Lets you edit Link's starting DMap and inventory/ + - Misc. Data: Lets you edit Subscreens and various miscellaneous data sets. + - Graphics: Lets you edit palettes, tile settings for various sprites, and combo structures such as Combo Aliases and Door Combo Sets. + - Audio: Lets you load MIDIs and sound effects. + - Scripts: Lets you load and compile ZScript and ZASM scripts. + - Template: Lets you load a quest template. + - Defaults: Lets you restore default settings for certain data types. + + The full details of these functions and editors are given below. + ++----------------------------+ +| 4.1 HEADER | ++----------------------------+ + +Quest Version: The version number of your quest. + +Minimum Version: If a player's saved game was from a version less than the minimum version (using a string comparison) they have to restart from the beginning. This is useful if you make major changes to your quest. + +Quest Number: This is only editable if you hold down Shift while selecting Header from the menu. Custom quests should always use the default, 0. Other numbers are reserved for built-in quests. + +Password: Use a password to lock your quest. If the quest has a password, it can't be loaded in ZQuest without entering the password. You should know that for testing or debugging purposes, the ZC developers can open any quest file without knowing the password. + +Title and Author: You get about 60 characters for each. + ++----------------------------+ +| 4.2 QUEST RULES | ++----------------------------+ + + Leave all rules unchecked for normal NES-style game play. + Note: in addition to these rules, there is also a rule that enables Link to move diagonally. This can be toggled in Quest -> Graphics -> Sprites -> Link. + ++----------------------------+ +| 4.2a ANIMATION RULES | ++----------------------------+ + + - BS-Zelda Animation +Changes the number of Link's frames to three, redefining his tile positions, and also alters the animation of some other items, like the boomerang. + + - Interpolated Fading +Dark rooms no longer refer to the level palette to determine the colors in between their light state and dark state. The colors are instead automatically generated. The freed up space in the level palettes can now be used to implement palette cycling. A second CSet 2 row will also appear in the palette editor. Colors filled in here determine what colors in CSet 2 appear slightly when the room is completely dark. + + - Fade CSet 5 +Dark rooms, fading between DMaps with different palettes, and other actions that darken the normal level csets will also affect CSet 5 with this rule. + + - Fast Dungeon Scrolling +Scrolling between screens in Dungeon DMaps is sped up approximately 5 times. + + - Cool Opening/Closing Wipes +Instead of the left and right sides of the screen closing inward when warping, a circle with center at the point of the warp rapidly shrinks until the screen is black. + + - No Screen Scrolling +When Link enters a different screen, Zelda Classic jump-cuts to the destination screen instead of smoothly scrolling between them. The advantage of this is that the designer is less obliged to make the adjacent combos of each screen transition into each other. + + - Expanded Link Tile Modifiers +If this rule is checked, when Link picks up an item with a Link Tile Modifier, all of his sprites will be moved down the tile page by the specified amount, rather than just his walking animation tiles. + + - Invincible Link Flickers +Getting a Clock, or taking damage, made Link flash through different CSets. With this checked, he instead flickers. + + - Items Held Above Link's Head Continue to Animate +Fixed the bug where items would stop animating when holding them in the air. + + - Bomb Explosions Don't Flash Palette +The entire screen will not flash when a Bomb explodes. + + - Layers 1 And 2 Are Drawn Under Caves +"Caves" refers to "Cave (Walk Down)" and "Cave (Walk Up)" combos. If this rule is checked, Link will be drawn above layers 1 and 2 when he walks down or up a Cave combo. + + - FFCs are Visible While The Screen Is Scrolling +FFCs will scroll with other sprites when Link transitions between two screens. + + - Smooth Vertical Scrolling +The screen scrolls smoothly vertically instead of half-tile by half-tile as the original did due to NES limitations. + ++----------------------------+ +| 4.2b COMBO RULES | ++----------------------------+ + + - Push Blocks Don't Move When Bumped/Hesitant Push Blocks +Link must push blocks for 1 second before they will move. This is designed to prevent accidental pushing of blocks. + + - Link Drowns in Walkable Water +Just like in the Oracle games, if Link lacks the flippers, he will sink, take damage, and respawn at the exact location where he entered the screen. This requires that Water combos are not solid or unwalkable. + + - Smart Screen Scrolling +Prevents Link from walking into an unwalkable combo from another screen. Can be a bit buggy. + + - Can't Push Blocks Onto Unwalkable Tiles/Solid Blocks +Pushable blocks cannot be pushed onto combos that are unwalkable. + + - Burn Flags Are Triggered Instantly +Rather than wait for a flame to animate and disappear before the flag is triggered, the flag is triggered as soon as the Flame touches the combo. This also allows fiery Wand magic to trigger "Burn 3 (Wand)" flags without having to burst into flame first. + + - Magic Mirror/Prism Combos Reflect Sword Beams +The Magic Mirrors and Prisms do the same to Sword Beams that they do to Magic. + + - Magic Mirrors Reflect Whistle Whirlwinds +With this rule checked, any Magic Mirror combos will reflect the Whistle's Whirlwind as well as Magic cast with the Wand and by Wizzrobes. + + - Combo Cycling On Layers +Allows combo cycling to function on layers other than Layer 0. You will most surely want this checked. + + - Full Priority Damage Combos + In the case of Link colliding with overlapping damage combos, the most damaging damage combo takes priority. + + - Warps Ignore Arrival X/Y Position +This rule affects whether Scrolling Warps or Entrance/Exit warps set Link's continue point if the warp return is in the upper-left corner of the screen, and exists primarily for backwards-compatability with older versions of ZC. You will most probably want this off. + + - Use Warp Return Points Only +If this rule is enabled, Zelda Classic will ignore the green continue square and use the blue Warp Returns when warping. In this case, the Warp A square also acts as the continue square (for instance, when you specify the continue here point in a DMap). If this rule is disabled, Zelda Classic uses the green continue square to determine where Link appears on a screen when he warps to it; the blue warp markers are ignored. + + - Use Old-Style Warp Detection (NES Movement Only) +This rule affects how Link collides with warp combos using NES movement, and exists solely for backwards-compatability with older versions of ZC. You will most probably want it to be off. + + - Damage Combos Work on Layers 1 and 2 +With this rule checked, damage combos that are placed on layers 1 and 2 will hurt Link. You will most surely want this checked. + + - Hookshot Grab Combos Work on Layers 1 and 2 +With this rule checked, Link can use the hookshot to grapple onto Hookshot Grab combos that are placed on layers 1 and 2. You will most surely want this checked. + + - Scrolling Warps Don't Set The Continue Point +In older versions of Zelda Classic, when Link passed through a scrolling warp, the continue point was set to the screen he arrived on. This was an intended feature, but a little known one that many people mistook for a bug. This rule disables it. + ++----------------------------+ +| 4.2c ITEMS RULES | ++----------------------------+ + + - Link's Bombs Hurt Link +Causes bombs to hurt Link, much like in later Zelda games. By default, Bombs will deal 2 hearts of damage to Link and Super Bombs will deal 8 hearts of damage to Link. + + - Enable Magic +Items with magic costs, such as the Lens of Truth, will expend that much magic (or rupees) when used. + + - Medicine Doesn't Remove Sword Jinxes +Using a blue potion or red potion will not restore the player's use of the A or B button if they were taken away by a red bubble or red item bubble. + + - Fairies Don't Remove Sword Jinxes +Grabbing a fairy will not restore the player's use of the A or B button if they were taken away by a red bubble or red item bubble. + + - New Boomerang/Hookshot +The Boomerang and Hookshot physically drag items they hit towards Link, as in later Zelda games, and can also be used to block enemy projectiles. Note that arrows cannot grab items with this rule turned on. + + - True Arrows +Enables the Quivers and causes the number of arrows to be stored in a separate counter. + + - No Diving +Link can't dive underwater. This rule's status can be reversed by a screen flag, so specific screens can (dis)allow diving at their whim. + + - Dark Rooms Stay Lit Only While Fire Is On Screen +Self explanatory. Rooms will revert to the state they were in before Link used a Fire-generating item in the room. + + - Link Isn't Hurt By Own Fire Weapons/Own Fire Doesn't Hurt +The flames created from the Blue Candle, Red Candle, or Wand and Magic Book will not hurt Link, like in ALttP. + + - Rings Affect Damage Combos +This rule will cause the strength of a damage combo to be lessened by the damage factor of the ring, in effect making it like the damage taken from an enemy. With it off, damage combos will always remove the specified number of hearts, regardless of the ring. + + - Quick Sword +The sword can be swung again before its animation is finished. Also works with the wand. + + - Flip Right-Facing Slash +With this checked, Link can slash in all 4 Diagonal Directions. + + - Wand Can't Be Used As Melee Weapon +You can not use the Wand itself to damage enemies. + + - Melee Weapons Can't Pick Up Items +Items such as the sword will not grab rupees or hearts dropped by enemies that they touch. + + - Boomerang/Hookshot Grabs All Items +The Boomerang and Hookshot can grab screen items and special items, not just enemy item drops. + + - 'Hearts Required' Affects Non-Special Items +With this rule checked, items not in special guy rooms that require a certain number of hearts cannot be picked up unless Link has the required number of hearts. + + - Big Triforce Pieces +The number of Triforce pieces needed is halved. See Level 9 Entrance. + + - 3 or 6 Triforce Total +The number of Triforce pieces needed is reduced from 8 to 6. If Big Triforce Pieces is also turned on, it is reduced from 4 to 3. See Level 9 Entrance. + + - Slow Walk While Charging +Link walks slowly while charging his sword for a spin attack. + + - Show Secret Combo Hints When Using the Lens/Show Lens Hints +The sprite for the item that can activate a secret combo shown by the Lens of Truth will be displayed, instead of just the combos themselves. + + - Lens Shows Raft Paths +The Lens of Truth reveals rafting routes. + + - Lens Reveals Invisible Enemies +Normally the Amulet reveals invisible enemies. With this checked, you can use the Lens of Truth to do the same, regardless of the amulet. + + - Triforce Doesn't Remove Sword Jinxes/Non-Bubble Triforce +Getting a Triforce piece will not restore the player's use of the A or B button if they were taken away by a red bubble or red item bubble. + + - Things That Remove Sword Jinxes Also Remove Item Jinxes +With this rule turned on, any item that removes a jinx from a sword bubble also removes a jinx from an item bubble. + ++----------------------------+ +| 4.2d ENEMIES RULES | ++----------------------------+ + + - Use New Enemy Tiles +Enemies use their New Tiles and E. Anims for animation instead of their Old Tiles and O. Anims. The Old Tiles are, by default, concise two-frame or one-frame sets of tiles on tile page 0, whereas the New Tiles are four-frame sets starting on page 6. A larger number of tiles can be defined for each enemy, opening up more graphical possibilities. + + - Show Shadows +Some enemies, such as Tektites, Peahats, or Keese, will have shadows underneath of them. The graphic of the shadow can be defined in the Sprites/Misc. menu item. + + - Translucent Shadows +The shadows shown under enemies will be partially transparent. See Show Shadows. + + - Shadows Flicker +The shadows shown under enemies will blink. See Show Shadows. + + - Enemies Jump/Fly Through Z-Axis +With the implementation of the Roc's Feather, a Z-axis or height parameter was added to the engine. With this rule checked, jumping and flying enemies will move through the Z-axis instead of the Y-axis. Peahats are slightly easier to defeatt, and Pols Voice enemies in the air won't collide with Link on the ground. + + - Hide Enemy-Carried Items +Hides items carried by enemies, and fixes the bug where getting hit by an enemy would give you their item. + + - Enemies Always Return +Enemies now return much faster. Killing all but one will not cause only one to appear on that screen, and all the enemies may reappear after exiting and immediately reentering the screen. + + - Temporary No Return Disabled +Fixes a bug in The Legend of Zelda where some enemies would not return when they were supposed to. In the NES game, Lanmolas stay dead until you exit the dungeon. Also, if you defeat every enemy in a room that has traps, they stay dead until you exit the dungeon. This rule disables this behavior. + + - Must Kill All Bosses To Set 'No Return' Screen State +Fixes the bug where killing one enemy on a screen where the boss flag is set and then continuing will kill all enemies on that screen. + + - Multi-Directional Traps +Center traps may now strike in other directions, not just toward the center of the screen. + + - Line-Of-Sight Traps Can Move Across Entire Screen +Line-of-Sight Traps placed by flags can move across the entire screen if unobstructed. If left unchecked, they will only move about the distance covered by 4 combos. Note that Line-Of-Sight Traps will ignore walkability and the invisible border unless the 'Multi-Directional Traps' rule is also turned on. + + - Constant Traps Can Pass Through Enemies +Constant Traps placed by flags will not bounce if they hit each other or an enemy. + + - Flying Enemies Can Appear on Unwalkable Combos +Flying enemies, such as Peahats or Keese, can appear on unwalkable combos. + + - Broken Enemy Shield Tiles/Broken Darknut Shield Tiles +New sprites will be substituted for the normal shielded enemy tiles when its shield is broken (requires New Enemy Tiles). + + - Enemies Don't Flash When Dying/No Flashing Enemy Death +The death sprite used by enemies does not flash different csets. + ++----------------------------+ +| 4.2e NES FIXES RULES | ++----------------------------+ + +- Freeform Dungeons +Removes the overhead border around screens in NES Dungeon DMaps and the restriction of not being able to walk parallel to an edge of the screen you're close to. This should probably always be on. Note that this doesn't remove the automatic walking of 2 combo lengths into each screen. + + - Can Safely Trigger Armos/Grave From The South +Link can touch a Grave or Armos from the south end, without taking damage. + + - Can Use Items/Weapons on Edge of Screen +Unchecked, Link cannot use any items if he is less than 2 combos away from the edge of the screen. + + - Fix Link's Position in Dungeons +In The Legend of Zelda, Link's screen position in NES Dungeons was slightly higher than in the overworld. Checking this rule fixes that. + + - Raft/Ladder Fix +The raft and ladder will have their sprites rotated 90 degrees when used in a horizontal motion. + + - No Palette 3 CSet 6 Fix/No Level 3 CSet Fix +When entering a DMap with a Level number of 3, no changes occur to CSet 6. This fixes the simulation of a bug in The Legend of Zelda. + + - Holding Up Items Doesn't Restart Music +In The Legend of Zelda, holding up an item causes the music to stop, and then start again. This rule disables this behavior. + + - Leaving Item Cellar/Passageway Doesn't Restart Music +In The Legend of Zelda, when Link left a screen 80 or 81 item or passage room, the music would be reset. This rule stops the reset from happening. + + - Tunic Color Can Change On Overworld +When Link is given a ring, his color will change immediately rather than only after changing screens. + + - Sword/Wand Flip Fix +Makes the weapon sprites flip when you swing them the opposite way so you can line them up with Link's hand. + + - Weapon Animation Fix +With this rule checked, weapons can be fully animated in all 4 directions instead of only being able to be 1 frame. + + - Push Block CSet Fix +In the Legend Of Zelda, moving push blocks in NES Dungeons are visible even in darkness. Presumably, this is because they are set to CSet 9. This rule fixes that. + + - Trap Position Fix +Fixes the position of Trap enemies. + + - No Invisible Border On Non-Dungeon DMaps +With this rule checked, enemies and enemy projectiles can step onto the edges of the screen on Non-Dungeon DMaps, where Link would be safe with this rule turned off. + + - Items Disappear During Hold-Up +When Link holds up an item, all other items on the screen disappear. Keep this checked for NES behaviour. + + - Subscreen Appears Above Sprites +In The Legend of Zelda, it is possible for Tektites and other creatures to momentarily jump into the passive subscreen region, where their sprites were drawn above it. This rule gives the passive subscreen priority over enemies. + + - Correct Bomb/Darknut Interaction +Normally, a shielded walking enemy will 'block' a bomb's explosion if the bomb's placement direction (that is, the direction Link was facing when he placed the bomb) is counter to the enemy's shield. This rule fixes this behavior. + + - Correct Offset Enemy Weapon Collision Detection +Enemy weapons' collision boxes are correctly offset. + + - Special Items Don't Appear In Passageways +This rule fixes a bug in the Zelda 1 Hack 'Zelda Challenge- The Outlands', in which a special item appears on the screen used for passageway warps if a screen with a passageway warp set has the special item room type set. + + - No NES Sprite Flicker/No Sprite Flicker +Fixes the bug where sprites on the same row would flicker to overcome an NES limitation. + + - Invincible Link Isn't Hurt By Own Fire Weapons +The flames created from the Blue Candle, Red Candle, or Wand and Magic Book will not hurt Link while he is invincible. + + - Link Holds Special Bombs Over His Head/Bomb Hold Fix +In The Legend of Zelda, Link will never hold the Bomb item over his head. This rule fixes that. + + - No Position Offset For Screen Items +In The Legend of Zelda, screen items are placed a few pixels lower than normal. This rule fixes that. + + - Allow Ladder Anywhere +Normally, the ladder cannot be used on non-Dungeon DMaps. This rule fixes that. This rule's status can be reversed by a screen flag. + ++----------------------------+ +| 4.2f OTHER RULES | ++----------------------------+ + + - More Sound Effects +When this rule is checked, the following events will be accompanied with certain sound effects: + - Octoroks shooting Magic weapons + - Constant-moving Traps reversing direction + - Summoners summoning enemies (note: if rule is off, this will play SFX_FIRE instead) + - Pounding shallow water combos with the Hammer + - Slashing Tall Grass, Flowers or Bush combos. + - Pounding a Pound combo + - Spell rockets rising and falling + - Din's Fire flame ring expanding + - Using the Nayru's Love shield + - Using the Lens of Truth + - Using Farore's Wind + - Pushing a "Push" combo + - Whistle whirlwinds moving across the screen + - Enemy fireballs being shot + - Enemy rocks being shot + - Enemy boomerangs flying + + - Can Select A Button Weapon on Subscreen +The sword is no longer the permanent A-Button Item, and you can select items, as in Link's Awakening. All items on the subscreen will remain in their same positions, so the subscreen must be edited to include the sword if this rule is checked. + + - Fast Heart Refill +When a fairy flag is touched, or when a Triforce piece is obtained, the refilling of hearts is about 3 times faster than it was in The Legend of Zelda. + + - Enable 1/4 Heart Life Bar +Enables the life bear to display quarter-heart quantities of life, not just halves. + + - Messages Can Be Sped Up With The A Button/Allow Fast Messages +Messages display at triple speed when you hold A. + + - Messages Can Be Bypassed With The B Button +When a string appears on the screen, if the player presses the 'B' button, it will then dissapear. + + - Messages Freeze All Action +While a message string appears, ALL action is frozen, including animations. + + - Messages Disappear +The Text from a Message String Disappears after it has finished by pressing the A button. This DOES remove the invisible 5 combo tall wall that prevents Link from accessing the upper half of the room. + + - Show Time on Subscreen +The time spent playing the quest will be displayed on the subscreen. + + - Healing Fairy Heart Circle Is Centered Around Link +The heart circle that is displayed when a fairy flag is touched will be centered around Link's position, instead of the center of the screen. + + - No Healing Fairy Heart Circle +The heart circle that is displayed when a fairy flag is touched will not appear. + + - No Saving When Continuing +With this ruled checked, the save option will not be available on the continue screen. + + - Skip Continue Screen +When Link dies, and the game is over, or the player uses F6 to quit the game, Zelda Classic will return to the file select screen without offering the player the ability to continue. + + - No Fires in Special Rooms/No Guy Room Fires +The fire graphics in rooms with guys will not be displayed. + + - Special Room Guys Don't Create A Puff When Appearing +Guys in the room type "Special Item" don't puff into existence. + + - Log Game Events To Allegro.log +All of the special event logging is tied to this rule. It's a helpful rule for debugging, but it should be turned off if you don't want players to be able to peek behind the curtain, so to speak. + ++-----------------------------+ +| 4.3 MAPS / MAP COUNT | ++-----------------------------+ + +Maps are just 16x8 (+4) collections of screens. The limit is 255 maps to a quest, but you can have more than one DMap per map. + +The last four screens in a map have specific uses: + - 0x80: Cave or Item Cellar + - 0x81: 3-Stair Warp Cave, or Passageway + - 0x82: Reserved for future use + - 0x83: NES Dungeon Template (see Template section) + - 0x84-0x87: Reserved for future use + +To create a new map, increase the Map Count number by one. + ++----------------------------+ +| 4.4 CHEATS | ++----------------------------+ + +There are four levels of cheats, each with a separate code (a 40 character string) that enables them. You can disable cheats altogether, or disable certain ones by leaving the code empty (be sure there are no spaces). It's helpful to use the cheats when designing a quest. You can also choose to give out the cheat codes. It's up to you. + + - Level 1: Refill life, bombs, arrows, or rupees any time you want. + - Level 2: Lets you to set your number of heart containers, your maximum bombs, and make Link invincible. + - Level 3: Allows you to choose what items, equipment, and triforce pieces Link has. + - Level 4: Quest debugging. Allows Link to walk through walls, display sprite hitboxes, warp directly to specific screens and DMaps, hide or show specific layers, and toggle darkness. + ++-----------------------------+ +| 4.5 ITEM EDITOR | ++-----------------------------+ + +This editor allows you to define new items and modify the existing ones. A certain number of items are defined by default; to create a new one, a quest builder can select an unused item slot ("zz###") towards the bottom of the list and continue to name it and set its attributes. There is a limit of 256 distinct items per quest. + +The options within the editor are explained below. + ++-----------------------------+ +| 4.5a ITEM EDITOR -> DATA | ++-----------------------------+ + + - Name +Give your item a name. The name of the item appears in the Subscreen's 'Selected Item Name' element whenever this item is selected. + + - Level +This determines if the item is 'better' than another item of the same class. When Link possesses multiple items of the same class, in the subscreen only the highest-leveled item will be displayed and selectable. (Though subscreen elements can optionally override this and access specific items in particular.) + + - Class +Select the type of item. This determines most of the item's built-in abilities and functions. See the official wiki for detailed information about classes' behaviour. Note that the 'zz###' classes are reserved for future Zelda Classic expansion. Use the 'Custom Itemclass' classes instead, if you intend to use a new item class. + + - Power +Determines the 'strength' of the item. What this means depends on the item's class. In the case of damaging items, the Power is the amount of HP damage to do to enemies. An item with a power of 1 does 2HP damage to enemies. + + - Equipment Item (checkbox) +Set this for items Link can hold in his inventory, like Boomerangs, Rings or Bomb Bags. Note that this cannot be set for Hearts, Arrow Ammo, etc. If a Triforce Piece has this checkbox set and you are in a DMap whose level is between 1 and 8, collecting it will set the appropriate Triforce Piece # as collected. + + - Misc. Attributes +These checkboxes and values allow behaviour specific to the item class to be edited. For a complete description of every class's attributes, see the wiki. + ++-----------------------------+ +| 4.5b ITEM EDITOR -> GFX | ++-----------------------------+ + +This tab concerns the graphics of the item in the subscreen and in the game. Click on the tile box to bring up the tile page. Find the tile you wish to assign to this item and click on it. Use + and - to change the CSet until the tile is the color you want it, than press Enter. (Keep in mind that items using CSets 2, 3, 4, and 9 will change color if the player enters a level.) Unlike in other editors, you can't give the item's tile a Flip setting by pressing H and V. + +For animated items, enter the number of animation frames and the animation speed on the proper lines. The speed determines how long to delay before proceeding to the next tile (smaller = faster). + +Other options: + - Flash (checkbox): Check if you want the item to "flash" between its CSet and the Flash CSet. + - 2-Hand (checkbox): When checked, Link uses two hands to hold up the item. + - Test: Preview the animation of the item. + - Initial Delay: The delay before running or rerunning the animation sequence. The Number entered is a multiple (2=2x, etc.). + - Link Tile Modification: If this is an Equipment Item and Link possesses this item, Link's sprite tiles are offset in the tile page by an amount equal to this number. If this number were set to 20, then Link's sprites would be drawn with the tiles that are 20 tiles right of their original positions in the tile pages. If it were -20, then all Link tiles would shift left 20 tiles. Be careful: Link Tile Modification is cumulative - Link's tile is offset by the sum of all possessed equipment items' Link Tile Modifiers. + +Link Tile Modification is used, for instance, by the Shield items to change the shield that Link's sprite wears. Also, using a script to give Link a 'dummy' invisible equipment item with a Link Tile Modification is one of the easiest ways to alter Link's sprite for specific purposes. + ++-----------------------------+ +| 4.5c ITEM EDITOR -> PICKUP | ++-----------------------------+ + +The Pickup tab concerns what happens when Link gets the item. ZC has several internal counters for things like Link's hearts, rupees, arrows etc. and these can be changed when Link picks up items. + + - Increase Amount +For items like bombs, rupees or keys this tells you how much you gain. For instance, the 100-rupee item has this set to 100. Set to 0 if you don't use a counter. + + - Counter Reference +Which counter this item uses. Set to -1 for none. The counters are listed below. + - 0: Life. + - 1: Rupees. Uses DCounter. + - 2: Bombs. + - 3: Arrows. + - 4: Magic. Uses DCounter. + - 5: Keys. This is different to Level-Specific Keys. + - 6: Super Bombs. + + - DCounter (checkbox) +If this is set, then the counter rolls upward or downward rather than immediately being set to the new value. Only some counters use this. + + - Full Max +The highest your maximum can get when you collect the item. The only time when you would want this higher than +Max would be with items which you would collect more than once, like Heart Containers. Set to 0 if you don't need to change the maximum. This setting is for items like quivers, wallets or bomb bags which don't change the number of items (arrows) you have, but the maximum you can carry. + + - +Max +How much the maximum actually increases. For instance, if this is a wallet and you set Full Max to 500 and +Max to 500, you can carry up to 500 rupees in total. If you instead set this to 50, you can carry 50 more than you could before. + + - Script +Run the item script in this numbered slot when the item is picked up. Note: it runs before everything else (such as counter increments) does. See compiling scripts and assigning scripts (ZScript) for details on how to compile and use scripts with items. + + - Sound +Which sound slot plays when you pick up this item. + +- Hearts Required +Refuse pickup if Link doesn't have enough hearts. In The Legend of Zelda, for instance, you needed a certain number of hearts to get the White Sword. Leave blank or as 0 to disable. + + - Keep Lower Level Items +If Link had previously collected lower-level items of the same class, then the lower-level items are not removed from his inventory when this item is collected. This is useful if, for instance, this item can be eaten + + - Gain All Lower Level Items +When Link collects this item, all lower-level items of the same class are added to his inventory. This means that if this item is destroyed or eaten, Link will revert to the next highest item of the same class. + + - Can be eaten by Enemies +If Link is engulfed by any enemy that can eat items (such as Like Likes), this item will be removed from his inventory if he doesn't escape quickly enough. + + - Upgrade Item When Collected Twice +Getting two of this item gives one of the same class but a higher level. In The Legend of Zelda, collecting a Blue Potion while already possessing a Blue Potion would cause Link to obtain a Red Potion. Note that if the higher-leveled item has the 'Keep Lover Level Items' checkbox set, then this lower-level item is retained. + ++-----------------------------+ +| 4.5d ITEM EDITOR -> ACTION | ++-----------------------------+ + +If this is an equipment item, this tab controls what happens when this item is assigned to an in-game button and Link presses that button. + + - Script +The slot number of the item script to be run when Link uses the item. If this value is 0, then no script will run. See compiling scripts and assigning scripts (ZScript) for details on how to compile and use scripts with items. + + - Magic +If the 'Enable Magic' quest rule is set, depletes the magic counter by this value whenever the item is used. If Link does not have enough magic, the item will not do anything. If this value is set to 0, then no magic is used by this item. + + - Sound +Notes the sound slot that plays when this item is used. If this value is set to 0, then no sound will play. Sound slots can be assigned with the SFX Editor. At the current version of ZQuest, some items' sounds are defined, and others are not. + + - Remove Item When Used (checkbox) +When this box is checked, the item is removed from Link's inventory when he uses it. This checkbox is mainly used for Potions. + + - Uses Rupees Instead of Magic (checkbox) +When checked, this item consumes rupees instead of magic. + + - Weapon 1-10 +The weapon/misc sprite graphics that this item displays when used. For instance, they determine the sword's stab, slash and beam sprites. Unused weapon sprites are disabled. + ++-------------------------------+ +| 4.5e ITEM EDITOR -> ARGUMENTS | ++-------------------------------+ + +These are the arguments for the item's Pickup and Action scripts. If you have no scripts assigned, ignore this tab. A1 and A2 are only used for ZASM scripts. + ++-----------------------------+ +| 4.6 ENEMY EDITOR | ++-----------------------------+ + +This editor allows you to define new enemies and modify the existing ones. Only a limited number of items are defined by default; to create a new one, a quest builder can select an unused enemy slot ("zz###") towards the bottom of the list and name it and set its attributes. There is a limit of 256 distinct enemies per quest. + +The options within the editor are explained below. + ++------------------------------+ +| 4.6a ENEMY EDITOR -> DATA 1 | ++------------------------------+ + + - Name +Give the enemy a name. + + - Old, Special, New +Select the tiles your enemy uses. If the 'Use New Enemy Tiles' quest rule is enabled (that is, the O. Anim dropdown menu is disabled), the New tile is used for the enemy, otherwise the Old tile is used. Special is used for certain specific enemies such as Pols Voice, or walkers with breakable shields. + + - Type +What type of enemy it is. Determines most of its movement and actions. You should avoid using (None)-type enemies in the game. Ganon-type enemies can't be instantiated in-game outside of being spawned by the Ganon room type. + + - HP +How many hit points this enemy has. It should be noted that a weapon with a Power of 1 will remove two points per hit. This is because, in The Legend of Zelda, an enemy having 1 HP meant that it could be killed by the boomerang. This is not the case for Zelda Classic, however, and the ratio of enemy HP to weapon Power is reluctantly maintained for historical reasons. + + - Damage +How many quarter-hearts Link loses if it touches him. + + - W. Damage +How much damage, in quarter-hearts, Link takes if this enemy's weapon hits him. + + - Hunger +Determines how attracted this enemy is to the Bait weapon. The range of values is 0 (no response) to 4 (extremely attracted). This is only applicable to the following enemy types: Walking Enemy, Armos, Ghini (except phantoms), Dodongo, Ganon, Lanmola. + + - Weapon +Which weapon, if any, this enemy fires. This is only applicable to the following enemy types: Walking Enemy, Projectile, Zora, Wizzrobe, Aquamentus, Manhandla, Gleeok, Gohma, Patra, Ganon. Weapons are typically only fired when the enemy halts - that is, when its Halt Rate is greater than 0. + + - O. Anim, E. Anim +What animation sequence to use. The 'n-Frame m-Dir' options refer to how many directions the enemy can face, and the number of animation frames it uses. A '4-Frame 4-Dir' animation makes use of four up-facing tiles, four down-facing tiles, four left-facing tiles, and four right-facing tiles, in that order. 'Firing' means that it uses an additional set of n-by-m tiles when it pauses to fire its weapon, and a third set of n-by-m tiles as it fires. 'Tracking' means that it faces toward Link regardless of its actual movement direction. Also, '3-Frame' animations actually has four animation frames, but repeats the second frame for the fourth frame, and thus only uses 3 tiles per direction. + + - F. Rate +Determines how long to delay before proceeding to the next tile (smaller = faster). + + - Item Set +What items this enemy may drop when killed. For exact information, see Item Drop Sets in Misc. Data. + + - Random Rate +How often this enemy considers changing direction after stepping upon a new combo, ranging from 0 (never) to 16 (always). + + - Halt Rate +How often this enemy considers stopping after moving to a new combo, ranging from 0 (never) to 16 (always). Zols by default use 16, and Bubbles by default use 0. + + - Homing Factor +How often this enemy changes to a direction that points toward Link. + + - Step Speed +Movement speed. 150 step speed is about as fast as Link's walking speed. Note that only certain enemy types use this. + + - Use Pal CSet +If checked, the enemy will use a CSet from the Extra Sprite Palettes instead of a standard CSet. + + - Pal CSet +The number of the CSet in the Extra Sprite Palettes to use. Does nothing unless Use Pal CSet is checked. + ++------------------------------+ +| 4.6b ENEMY EDITOR -> DATA 2 | ++------------------------------+ + + - Misc. Attributes +These dropdown boxes and values allow behaviour specific to the enemy type to be edited. For a complete description of every class's attributes, see the wiki. Since the Walking Enemy type has the most options, they shall be briefly discussed here. + - Shot Type: How the enemy fires its weapon. If the weapon is a Fire Trail or a Boomerang, most of these will be ignored. + - Death Type: What happens when the enemy is attacked/killed. + - Extra Shots: When the enemy has halted and fired a shot, it has a chance of remaining halted and firing additional shots. This number determines the number of additional shots. + - Touch Effects: What happens to Link when the enemy touches. + - Walk Style: How the enemy moves. + + - BG Sound +In The Legend of Zelda, certain enemies (i.e bosses) repeatedly roared until they were slain. This option lets you specify a sound that loops until the enemy is removed. + + - Hit Sound +In The Legend of Zelda, certain enemies (i.e bosses) screeched when you damaged them. This option lets you specify a sound that plays when you damage the enemy. + + - Death Sound +This option lets you specify a sound that plays when you slay the enemy. + ++-----------------------------------+ +| 4.6c ENEMY EDITOR -> MISC. FLAGS | ++-----------------------------------+ + + - Damaged by Power 0 Weapons +If these weapons have a Power of 0, they will deal damage to the enemy instead of stunning them. The amount of damage dealt depends on the weapon's level, so a power 0 weapon with a level of 1 deals 1 point of damage, a level 2 power 0 weapon deals 2 points of damage, and so on. + + - Is Invisible +This enemy is invisible, but if you look closely you can see a slight shimmer at its location. If you have an Amulet equipment item, the enemy becomes visible. + + - Never Returns After Death (Boss) +Once killed, this enemy does not return even if you leave the screen and return. + + - Doesn't Count as Beatable Enemy +This enemy does not affect push blocks, Enemies->Secret screen flags, or shutters, and is not affected by the Kill All Enemies Item or the death of the Ringleader. Projectile shooters and spinning tiles are not counted as beatable enemies regardless of this flag. + + - Can Only Be Seen By Lens of Truth +Is invisible, even with the Amulet, and does not shimmer. The quest rule 'Lens Reveals Invisible Enemies' must be turned on in order for the Lens of Truth to reveal this enemy. + + - Is Flashing +This enemy's sprite will flash between its CSet and another CSet. + + - Is Flickering +This enemy's sprite will flicker. + + - Is Transparent +This enemy's sprite is drawn translucent. + + - Shielded In Front (Walker) +This walking enemy is invulnerable on the front side. Only has an effect for Walking Enemies. + + - Shielded On Left (Walker) +This walking enemy is invulnerable on the left side. Only has an effect for Walking Enemies. + + - Shielded On Right (Walker) +This walking enemy is invulnerable on the right side. Only has an effect for Walking Enemies. + + - Shielded In Back (Walker) +This walking enemy is invulnerable on the back side. Only has an effect for Walking Enemies. + + - Hammer Can Break Shield +This walking enemy's shield can be broken by the hammer. Only has an effect for Walking Enemies. + ++--------------------------------+ +| 4.6d ENEMY EDITOR -> DEFENSES | ++--------------------------------+ + +Defenses determine how the enemy reacts to Link's weapons. Currently, these defenses do not apply to Traps, Rocks, Dodongos, Big Digdoggers, Ganon, Projectile Shooters, or (None)-Type Enemies. + +Each type of reaction is described below. To make an enemy invincible, set all of its Defenses to either 'Block' or 'Ignore'. + + - (None) +The enemy takes damage, or is stunned if the weapon's damage is 0. + + - Block +The enemy blocks the weapon. The weapon is destroyed or returns to Link, and the Shield sound effect is played. + + - Ignore +The weapon passes harmlessly through the enemy. + + - 1/2 Damage +The damage of the weapon is reduced by half. It cannot be reduced below 1/2 power. + + - 1/4 Damage +The damage of the weapon is reduced even further. It cannot be reduced below 1/4 power. + + - Stun +The enemy is stunned, even if the weapon normally does damage. + + - Stun or Block +If the weapon's damage is 1 or more, the enemy is stunned. Otherwise, the enemy blocks the weapon. + + - Stun or Ignore +If the weapon's damage is 1 or more, the enemy is stunned. Otherwise, the enemy ignores the weapon. + + - Block if < 1 +If the weapon's damage is less than 1, the enemy blocks the weapon. Otherwise, normal damage is dealt. + + - Block if < 2 +If the weapon's damage is less than 2, the enemy blocks the weapon. Otherwise, normal damage is dealt. + + - Block if < 4 +If the weapon's damage is less than 4, the enemy blocks the weapon. Otherwise, normal damage is dealt. + + - Block if < 6 +If the weapon's damage is less than 6, the enemy blocks the weapon. Otherwise, normal damage is dealt. + + - Block if < 8 +If the weapon's damage is less than 8, the enemy blocks the weapon. Otherwise, normal damage is dealt. + + - Ignore If < 1 +If the weapon's damage is less than 1, the enemy ignores the weapon. + + - One-Hit-Kill +The enemy dies, and the weapon continues on. + ++-----------------------------------+ +| 4.6e ENEMY EDITOR -> SPAWN FLAGS | ++-----------------------------------+ + +These determine where and how the enemy spawns. + + - Spawned by ... +When the enemy flag/combo type/combo flag/Ganon room type is on the screen, one of these enemies appears. + - Spawn Animation (Walker) +The manner in which the enemy appears. Only has an effect for Walking Enemies. + - Poof: Enemy uses the 'MISC: Spawn' Sprite when it appears. Used by most NES enemies. + - Flicker: Enemy fades in when it appears. Used by Armos. + - Instant: Enemy appears instantly with no spawn animation. Used by several bosses. + ++----------------------------+ +| 4.7a STRINGS | ++----------------------------+ + +Strings are lines of text which can be displayed by a screen's Guy, but can also be displayed with scripts. + +In the string list, double-click a string to edit it, double click "New String" to begin creating a new one. You can also use the "Duplicate" button to duplicate a string and all of its font, tile, position, sound and spacing options. This is a fast and convenient way to create many strings with similar options. + +You can reorder your strings by using the arrow buttons on the right. The top and bottom arrows move a string upward or downward 12 positions in the list, and the middle arrows move it up or down once in the list. + +If a string is linked to by the previous string in the list, it will be indented in the string list. This makes it easy to see long chains of linked strings. + +At the bottom, you may set the position of "Message More", which is a sprite prompting the player to press the "A" button to continue. The Y is Offset checkbox indicates that the Message More prompt's Y position should be added to that of the current string's Y position. + ++----------------------------+ +| 4.7b STRING EDITOR | ++----------------------------+ + +Here you are presented with a white box near the top, for text. The preview pane displays your text as it would appear in the game. Only the first three lines of text will be displayed, though. + +You can select a string that will be displayed immediately after this string. Click the 'Next in List' button to set it to the string that follows this one in the list. + +On the Attributes tab you can also select a tile to serve as the border of the string, in the form of a 2x2 frame. + +Also on the Attributes tab are a number of options. + + - X, Y +The onscreen position that the text will appear at. + + - Width, Height +The width and height of the string bounding box, in pixels. + + - H. Spacing, V. Spacing +You can manually set additional spacing between characters and lines. Leave at 0 to use the default values. + + - SFX +The sound effect to play when each of the string's characters appears. + + - Is continuation of previous string +If set, this string's contents will be printed after that of the previous string's, without clearing the previous string from the screen. + + - Text wraps around bounding box +If this is set, the string's text will wrap around automatically. In previous versions it was necessary to manually position the string text with spaces. + ++-----------------------------+ +| 4.7c STRING CONTROL CODES | ++-----------------------------+ + +Enter these control codes into a message string for special formatting, effects, basic dialog branching, or modification. (Henceforth, "X" denotes a number from 0 to 9999.) + +(Note: If you switch to a string that hasn't been created yet, then ZC will act as if you switched to a string with no characters in it. ) + + - Formatting Codes + +\1\X\X - Text Colour. Changes the following text to a certain colour. Argument 1 is the CSet, and argument 2 is the colour within that CSet. The text in the Preview Pane changes to reflect the addition and modification of this Control Code. + +\2\X - Text Speed. Changes the length of the delay between text characters appearing. If 0, text appears instantaneously. Argument 1 is the speed. + +\25 - New Line. Equivalent to pressing Enter in a document. Best used when text wrapping is enabled. + +\32 through \126 - ASCII Character. Prints a character based on its ASCII code. For example, \91 allows you to display a backslash. + + - Switch Codes + +\3\X\X\X - Goto If Screen Variable. If one of the Screen->D[] variables of the current screen is at or above a certain value, then ZC switches to another string. Argument 1 is the index into the screen's D array, argument 2 is the value, and argument 3 is the string to switch to. + +\4\X\X - Goto If Random. There is a one-in-(argument 1) chance that ZC switches to another string (argument 2). + +\5\X\X - Goto If Item. If Link has a certain item, then ZC switches to another string. Argument 1 is the item ID, and argument 2 is the string to switch to. + +\6\X\X\X - Goto If Counter. If a counter is at or above a certain value, then ZC switches to another string. Argument 1 is the counter, argument 2 is the value, and argument 3 is the string to switch to. + +\7\X\X\X - Goto If Counter %. If a counter is at or above a certain percentage of its maximum, then ZC switches to another string. + +\8\X\X - Goto If Triforce. If Link has acquired the Triforce from a certain level, then ZC switches to another string. Argument 1 is the level, and argument 2 is the string to switch to. + +\9\X\X - Goto If Triforce Count. If Link has acquired a certain number of Triforce pieces, then ZC switches to another string. Argument 1 is the quantity, and argument 2 is the string to switch to. + + - Counter Up/Down Codes + +\10\X\X - Counter Up. Increases a counter by a certain value. Argument 1 is the counter, and argument 2 is the value. + +\11\X\X - Counter Down. Reduces a counter by a certain value. Argument 1 is the counter, and argument 2 is the value. + +\12\X\X - Counter Set. Sets a counter to a certain value. Argument 1 is the counter, and argument 2 is the value. + +\13\X\X - Counter Up %. Increases a counter by a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\14\X\X - Counter Down %. Reduces a counter by a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\15\X\X - Counter Set %. Sets a counter to a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\16\X - Give Item. An item is silently added to Link's inventory. Link does not hold up the item, and the item's Pickup Script does not run - though the item's counter modifications will still take effect. Argument 1 is the item ID. + +\17\X - Take Item. An item is removed from Link's inventory. The item's counter modifications will be undone when this occurs. Argument 1 is the item ID. + + - Audio Effect Codes + +\20\X - Sound Effect. Argument 1 is the sound effect number. + +\21\X - Play MIDI. Argument 1 is the quest MIDI number. You cannot play the built-in MIDIs using this. + ++----------------------------+ +| 4.8 DMAPS | ++----------------------------+ + +DMaps are a way of dividing up Maps into "Dungeon Maps" with different characteristics. + +It is constructive to think of DMaps as being the data that tells Zelda Classic how to interpret the information put on Maps in the editor. When Zelda Classic plays your quest, it needs to know more information that just what Combos to draw on a Screen. It must also know what Music to play, what Palette to display the screen in, whether the Whistle works on that screen, what the minimap looks like on the subscreen, and other details. Most of these details come from the DMap. + +A single DMap is usually smaller than a whole Map. DMaps are typically horizontally offset from the actual edge of the Map. Whenever you are moving the player using a Warp, you specify the Warp location using the coordinates of the screen within the DMap, not the Map. + ++----------------------------+ +| 4.8 DMAPS -> MECHANICS | ++----------------------------+ + + - Map +This is the number of the map that the DMap's traits apply to. + + - Type +This determines the main traits of the DMap. A number of quest rules, screen flags and + - NES Dungeon - These DMaps are 8 screens by 8 screens in area. Door Combo Sets only function in this type of DMap. Secrets are always temporary. + - Overworld - These DMaps are 8 screens tall and 16 screens wide - thus, they are the only type of DMap which covers the entire area of a Map. + - Interior - These DMaps are 8 screens by 8 screens in area. + - BS-Overworld - These DMaps are 8 screens by 8 screens in area. They simulate the overworld of BS-Zelda. Unlike other DMap types, the passive subscreen map is a grid of screens. + + - Level +This number is used for continuity between different DMaps. DMaps with equal levels will use the same level-specific items and variables, such as Dungeon Maps, Compasses, Boss Keys, etc. For example, say you want to make a cavern with 8 floors using 8 DMaps, and want the Boss Key found in one floor to work on all others. Give them all the same level number (say 12) and this will be possible. + + - Minimap Grid +Use this grid to edit what the classic NES-style minimap looks like. + + - Slider +If the map is 8x8, this is used to position the DMap over certain screens on the Map. + + - Continue Here +If checked, Link starts on this map upon dying and having "Continue" selected. + + - Compass +This is the screen that the red compass icon indicates on the mini-map. + + - Continue +This is the screen that Link starts on after continuing from a Game Over, and also the screen that Link returns to when he is nabbed by a Wall Master, hit by an enemy's Wind weapon, uses a Farore's Wind item, or uses a whistle whirlwind when the 'Whistle Whirlwind Returns Link To Start' + ++----------------------------+ +| 4.8 DMAPS -> APPEARANCE | ++----------------------------+ + + - Color +This is the palette that the DMap uses. + + - DMap Title +This is the title that displays above the subscreen's minimap. If the first letter of the first word is in the top-left corner, and the last letter of the last word is in the bottom-right corner, the full title will be drawn centered. + + - DMap Intro +This is a basic message that displays upon the first entry of the DMap. Leave blank to disable. + + - Subscreens +The Active subscreen is the main item-selection subscreen that displays when you hit "Start." The Passive subscreen is the subscreen that occupies the top of the main screen. + ++-------------------------+ +| 4.8 DMAPS -> MUSIC | ++-------------------------+ + +Choose the MIDI that you want to play in this DMap. If you transition between two DMaps with identical MIDIs, then the music will not be interrupted. + +DMaps can optionally call upon external music files for music, falling back on the MIDI if it cannot find the file. Currently, this is the only way to play non-MIDI music. Zelda Classic understands the following formats: OGG, MP3, IT, XM, S3M, MOD, SPC, GYM, NSF, GBS, and VGM. The music file must be included in the same folder/directory as the quest file for Zelda Classic to play it. + ++-------------------------+ +| 4.8 DMAPS -> MAPS | ++-------------------------+ + +This allows you to change the appearance of the mini-map in the Passive Subscreen and the Large Map in the Active Subscreen, before and after Link finds the Map item for this DMap. Click on the map you want to change, the tiles screen will come up, then click on the upper-left tile of the map you want and press Enter. Note that setting the 'With Map' Minimap will disable the classic NES-style minimap. + ++-------------------------+ +| 4.8 DMAPS -> FLAGS | ++-------------------------+ + + - Use Caves Instead Of Item Cellars +The 'Cave/Item Cellar' warp behaves like Overworld-style caves rather than Dungeon-style item cellars. This flag entails, among other things, that warps to screen 80 will enter and exit at the center of the bottom instead of the upper left. + + - Allow 3-Stair Warp Rooms +Unless this is checked, the Room Type "3-Stair Warp" does nothing on this DMap. + + - Allow Whistle Whirlwinds +Unless this is checked, the Whistle cannot summon whirlwinds. + + - Whistle Whirlwind Returns Link To Start +Using the Whistle returns Link to the DMap's Start Screen instead of using the whistle warps. + + - Special Rooms And Guys Are In Caves Only +If this is checked, Guys, Message Strings and Room Types will not appear in ordinary screens, but only in screens 0x80 and 0x81. The exception to this rule is the 'Fairy' Guy. + + - Don't Display Compass Marker In Minimap +Even if you have the Compass, its marker won't appear in the passive subscreen. Useful if you're making a multi-floor dungeon with multiple DMaps of the same Level. + + - Underwater Wave Effect +Causes the screen to shift and warp, creating an 'underwater' effect, as seen in The Legend of Zelda: Oracle of Ages. + + - Always Display Intro String +The intro string displays every time Link enters the DMap, instead of just the first. + + - View Overworld Map By Pressing 'Map' +If the player presses the "Map" key, they can consult a large, detailed map of the screens that have been visited. + + - Use Minimap Foreground Color 2 +In Misc. Colors, an alternative Minimap Foreground Color can be set and used. In previous versions Foreground Color 2 was used exclusively for Interior DMaps. + + - Script 1-5 +These have no built-in purpose, but can be used by scripts to check if some scripted feature should occur in this DMap. + ++-------------------------+ +| 4.8 DMAPS -> DISABLE | ++-------------------------+ + +This is a new feature that lets certain specific equipment items be temporarily excluded from Link's inventory, preventing him from using them. Has no effect for non-equipment items, obviously. + ++-------------------------+ +| 4.9 INIT DATA | ++-------------------------+ + +This is where you set the equipment items that Link starts the quest with, as well as his initial Bombs, Arrows, Keys, Super Bombs, Magic, and maximums of each. + +In previous versions of Zelda Classic, the number of Super Bombs Link could carry was dependant on his maximum Bombs. Due to this, you can't directly change Link's maximum Super Bombs. You must adjust the Super Bomb ratio, which is the number of maximum Bombs per Super Bomb. + +The Level Items tab lets you set the Map, Compass, Boss Key or Level-Specific Keys that Link starts the game with, if any. As a DMap can have a level from 0 to 512, there are thus 512 possibilities. + +Under the Misc tab and Constants tabs, further options are available. + + - Starting DMap +You can set Link's starting DMap. Link will begin the quest in the Continue screen for that DMap. + + - Heart Containers, Pieces +The amount of Heart Containers and Pieces of Heart Link starts the quest with. + + - Per HC +The number of Heart Container Pieces that make up a Heart Container. When Link obtains this many Pieces, he also picks up item #20 (which is the Heart Container by default). + + - Starting HP, Continue HP +The amount of hearts that Link starts the game with. Continue HP can be expressed as a percentage of Link's maximum hearts. + + - Slash +If checked, Link begins the game with the ability to slash with melee weapons, such as Swords. + + - Magic +The amount of magic Link starts with. One Magic Container is equal to 32 units. + + - Double +If checked, Link begins the game with the '1/2 Magic Upgrade', which cuts his items' magic costs in half (as long as they use magic). + + - Triforce +Link can begin the game with specific Triforce pieces. + + - Gravity +The acceleration of sprites falling through the Z axis (and the Y axis in Sideview screens). This cannot be changed in-game. + + - Terminal Velocity +The maximum speed at which things can fall. This cannot be changed in-game. + + - Jumping Sprite Layer Threshold +If Link's Z height is greater than this, he is drawn above Layer 3 (but not Layer 4). This cannot be changed in-game. + ++-----------------------------+ +| 4.10 MISC. DATA | ++-----------------------------+ + + - Master Subscreen Type +If you want to edit your subscreens, this must be set to 'Custom'. Otherwise, changing it will replace all of your subscreens with built-in Zelda Classic subscreens, and change the subscreen settings for all of your DMaps. + + - Shop Types +This is used to set up shops for your quest. Shop Types are used for both the Shop room type and the Take One Item room type. To create a new shop type, click on a number you haven't used yet and Edit. +This brings up a Shop Data dialog box with spaces for three items. Choose an item from the drop-down menu and enter the price for it above that item. You can have a shop with just one item by using only the first item listed, or 2 items by using only the first 2, but don't leave one blank and enter something in the next one. + + - Info Types +This is for the Pay For Info room type. It works just like Shop Data: set the prices and choose the message strings from the drop-down menu. To create new strings go to Quest->Strings first. + + - Warp Rings +The Warp Rings are used for both Whistle Warps and the rooms with 3 staircases that warp you to different parts of your quest. Ring 8 is used by the default Whistle item. +When you click on Warp Rings, a dialog box will popup with the numbers 0-8. To create a warp ring, click on a number you haven't used yet and Edit. +This brings up the dialog box for that particular warp ring. Count (3-8) is where you enter how many locations you want for that warp ring. You then edit each site number, entering the dmap and screen number you want to warp to for each one. Then click OK, or (to test the warp) Go will take you to the screen you just entered. + + - Triforce pieces +For changing the placement of the triforce pieces in the Triforce Frame subscreen object. + + - End String +For making custom end-game messages. Without an End String, Zelda Classic just displays "THANKS LINK, YOU'RE THE HERO OF HYRULE" and "FINALLY, PEACE RETURNS TO HYRULE. THIS ENDS THE STORY." when you save Zelda. Note that Zelda Classic uses two strings: the selected string, and the string whose number is one more than the selected string. ZC currently ignores the Next String setting of the string, as well as all control codes in the string. + + - Item Drop Sets +Item Drop Sets are lists of items which are used to decide whether an enemy should drop an item when it is defeated, and if so, which. The Enemy Editor can change the drop set used by a certain enemy. One Item Drop Set, "Tall Grass Combos", is also used for Slash->Item, Tall Grass, Flowers and Bush combo types. Also, the "Bombs 100%" and "Super Bombs 100%" sets are used whenever you slay a Dodongo by slashing it, or using a Super Bomb, respectively. + ++-----------------------------+ +| 4.11 PALETTES | ++-----------------------------+ + +PALETTES: + +The ZC palette is divided up into 15 blocks of 16 colors each. These blocks are called "CSets" (color sets). The first color in each cset is transparent. + +Main: CSets 0-5 are background colors and 6-14 are typically used by sprites. Below is an explanation of each: + +Background colors: + - 0,1: used for subscreen colors and map colors + - 2-4: loaded with different "level colors" * + - 5: extra bkg CSet, independent of level + +Sprite colors: + - 6: Link's colors + - 7-8: constant sprite colors + - 9: level-defined sprite colors * + - 10-13: extra constant sprite color CSets + - 14: used for boss colors, which are loaded as needed + +* These CSets will change color according to the level the player is in. + +Levels: + - 00: Overworld dmap csets that change according to level + - 01-09: Palettes for Levels 1-9 dmaps + - 0A: Palettes for cave dmaps + - 0B: Palettes for passageways and item rooms in dungeons. + - 0C-FF: Extra level dmap palettes + +Note: The white numbers on the left in the level palette editor are the regular colors for the dungeon csets. +The black numbers show what that csets turns to when the room is dark. +The 2 shades of gray numbers are the in-between colors that csets go through when fading from light to dark or vice versa. + +Sprites: + +Extra Sprite Palette 1: + - 0: Aquamentus cset + - 1: Gleeok cset + - 2: Digdogger and its kids cset + - 3: Ganon cset + - 4: Ganon stunned cset + - 5: Ganon dying cset + - 6: Link with blue ring cset (used by the default Ring 1 item) + - 7: Link with red ring cset (used by the default Ring 2 item) + - 8: Link with gold ring cset (used by the default Ring 3 item) + - 9-12: Game Icon csets: 0, 1, 2, 3+ + - 13: Gleeok 2 cset + - 14: Unused + +Extra Sprite Palette 2: If you need extra sprite c-sets in making custom quests, load them here. + - 15: Patra BS cset + +Palette Edit Window: +In the palette windows, you can copy an entire Cset over to a different Cset. Highlight the Cset you wish to copy and press 'C', then highlight the any other Cset and press 'V'. Presto, you have copied the Cset. This can save a lot of time if you want to copy animated palettes, like the water and fire in dungeons, over to different levels. +When editing a palette, you can copy a single color to one of the other 16 colors in the palette. + +Also you can use the numeric keys to manually edit individual colors. 1, 2, 3, to move RGB values down (respectively), 7,8,9 to move RGB values up (respectively), and 4 to move the cursor left, 6 to move it right. This is easier than adjusting with the cross on the color spectrum and Inserting. + +In the level palettes there is a name field where you can name the palette for easy identification. + ++-----------------------------+ +| 4.12 WEAPONS/MISC SPRITES | ++-----------------------------+ + + These are the sprites for the weapons in the game. As seen in the Item Editor, various items use these data entries to determine the graphics of their projectiles. Enemies also use specific sprites for their weapons. + +This also includes sprites used for various special effects that occur in-game. Some of these are: + + - MISC: More: If you use string linking and assign a tile or set of tiles to this, it will be shown on the screen (position is adjustable in the Init Data dialog) to let you know there is more text available. + - MISC: Death: This is the flash created when enemies are killed. + - MISC: Spawn: Enemies with the 'Puff' spawn animation use these tiles when they appear. + - MISC: Ripples: These are drawn under Link when he walks on Shallow Water tiles. They use halves of tiles - only the top or bottom of the tile is drawn in a particular animation frame. + - MISC: Tall Grass: Much like Ripples, but are drawn when Link walks on Tall Grass tiles. + - MISC: Hover Boots Glow: Much like Ripples, but are drawn when Link uses the Hover Boots item. + - MISC: Shadow (Small): This is drawn under Link when he is in midair (usually by using the Roc's Feather item) or underneath enemies if they are moving through the Z axis, or the appropriate Quest Rule is set. + - MISC: Shadow (Large): Currently used exclusively by Boulder enemies. + - MISC: Bush Leaves: Drawn when Link slashes a Bush combo. Uses quarters of tiles - each of the four corners of the tile is treated as an individual animation frame. + - MISC: Flower Clippings: Drawn when Link slashes a Flowers combo. Uses quarters of tiles. + - MISC: Grass Clippings: Drawn when Link slashes a Tall Grass combo. Uses quarters of tiles. + - MISC: Quarter Hearts: Set this to allow the Life Gauges in the subscreen to draw quarter-hearts correctly. + ++-----------------------------+ +| 4.13 COMBOS | ++-----------------------------+ + + Combos are the building blocks of the many maps and terrain of your quest. They are a combination of a graphics tile and a type that determines how Link is affected when he steps on it. Various types include Damage, Lock Block, Water, Treasure Chest, Shallow Water, and many more. Combos also feature solidity flags that can be set for each corner, and prevent Link or certain enemies from walking on them. + ++-----------------------------+ +| 4.13a COMBO LIST | ++-----------------------------+ + + The combo list is used to organize your quest's combos. Combos are arranged in 254 pages of 255 combos each. Change pages by clicking the arrows near the page number, or by using the hotkeys (see below). + + As with the tile pages, you can select large groups of combos at once. Click on one combo, then click on a second combo while holding Shift. The combos between the two will be selected. You can then copy and paste the combos as a group, or perform some other action on them. + +The right-click menu contains: + + - Copy: Copies the combo to the 'clipboard' + - Paste: Pastes the clipboard combo to this location, overwriting the combo. + - Swap: Swaps the data of the clicked combo with the clipboard combo, thus making them switch places. + - Delete: Erases the data of the selected combo. + - Edit: Edits the combo. + - Insert New: Moves all of the subsequent combos to the right by one position, and edits an empty combo at this location. + - Remove: Moves all of the subsequent combos to the left by one position, overwriting this combo. + - Locations: Shows you whether this combo is actually used in the quest's maps, and where. + +Hot keys are: + + - space: toggle horizontal and vertical views. Horizontal view lists all of the combos horizontally and vertically. Vertical view arranges the combos in a series of + - +,-: change CSet + - e: edit current combo + - c: copy (select) a combo. + - o: overwrite the destination combo with the source combo. + - s: swap source and destination combos. + - v: paste. This will copy the source combo to the destination. + - p: go to a specific page. + - page up, page down: changes the combo page + + Note: To copy and paste a whole combo page (or part of one), click on the first combo, hold shift and click on the last combo. Press c. Go to the combo page you want to copy to. Click on the first space and hit v. This method can also be used to delete a number of combos by pressing delete after selecting the combos. + ++-----------------------------+ +| 4.13b COMBO EDITOR | ++-----------------------------+ + + Click on the tile to edit the tile and/or flip status. Within the tile selector, click on "Old" or press Esc to cancel, or "New" to use the new one. + + The square next to the tile shows the solidity - the places where Link can't walk. Click corners to toggle gray for walkable and red for unwalkable. + + The second square is used if you want to use more than one cset on the tile. Click the corners to toggle gray (regular cset) and blue (2nd cset). Enter the difference between the cset and thenumber of the 2nd cset on the CSet 2 line. With this, you can also make combos that use Cset 6, 7, 8, 9, 10, or 11 by making the entire square blue. + +Options include the following. + - Cycle: If the combo is animated, it will change into this combo as soon as its animation finishes. A very useful tool for a variety of purposes, including making combos that only animate once (such as doors swinging open), or timed traps and mechanisms (such as spikes that rise and fall repeatedly). + - A. Frames: Number of frames for the animated combo. + - A. Speed: Speed delay of animation. Lower numbers = faster animation. + - A. Skip X: Normally, the next 'frame' in a combo's animation is the tile directly after the combo's current tile. With this option, the animation will 'skip forward' and choose a further tile on the tile page for the next frame. For instance, an A. Skip X of 1 will make its animation use every other tile after its default tile. + - A. Skip Y: Similar to A. Skip X, but the animation will skip entire rows of the tile page. You could thus lay out a combo's animation tiles vertically in the page if you wish. + - Type: The combo's type. This defines what kind of combo this is. See below for a list of types. + - Flag: The combo's inherent flag. Use this for combos which should always have a certain combo flag on them. For instance, a cracked rock combo which should always have the 'Bomb Trigger' combo flag. See the Combo Flags section later in this document for more details. + - Refresh Animation on Room Entry: When Link enters the screen, this combo starts its animation from the beginning. + - Restart Animation when Cycled To: If a combo cycles into this combo, then it will start its animation from the beginning. + + Combo Types can be grouped into Weapon Types, Enemy Placement Types, Warp Types, Visual Types, Walk Effect Types, Destructible Types, Screen State Types, Push Block Types, Screen-Wide Effect Types, Save Types, Obsolete Types and Script Specific Combo Types. + ++-----------------------------+ +| 4.13b.1 WEAPON COMBO TYPES | ++-----------------------------+ + + - Block All +All projectile weapons that would usually pass through unwalkable combos will be stopped by Block All combos. + + - Block Arrow (All) +All Arrows that would usually pass through unwalkable combos will be stopped by Block Arrow (All) combos. + + - Block Arrow (L1, L2) +Arrows with a Level of 1 or 2 that would usually pass through unwalkable combos will be stopped by these combos, whereas higher-leveledArrows will still pass through this combotype. + + - Block Arrow (L1) +Arrows with a Level of 1 that would usually pass through unwalkable combos will be stopped by these combos, whereas higher-leveled Arrows will still pass through this combotype. + + - Block Brang (All) +All Boomerangs that would usually pass through unwalkable combos will be stopped by Block Brang (All) combos. + + - Block Brang (L1, L2) +Boomerangs with a Level of 1 or 2 that would usually pass through unwalkable combos will be stopped by these combos, whereas higher-leveled Boomerangs will still pass through this combo type. + + - Block Brang (L1) +Boomerangs with a Level of 1 that would usually pass through unwalkable combos will be stopped by these combos, whereas higher-leveled Boomerang swill still pass through this combo type. + + - Block Fireball +Enemy Fireball projectiles that would usually pass through unwalkable combos will be stopped by Block Fireball combos. + + - Block Magic +Wand magic or enemy magic that hits this combo is destroyed. + + - Block Sword Beam +Sword Beams, that would usually pass through unwalkable combos will be stopped by Block Sword Beam combos. + + - Hookshot Grab +If this combo is struck by the hookshot, Link is pulled towards the combo. + + - Hookshot Only +The hookshot's chain can pass through this combo, as can other ranged items that cannot normally pass through unwalkable combos. + + - Ladder Only +The ladder will be placed on this combo, and other ranged items that cannot normally pass through unwalkable combos. Note that the hookshot cannot pass through this combo. + + - Ladder or Hookshot +The ladder will be placed on this combo, and other ranged items including the hookshot that cannot normally pass through unwalkable combos will pass through it. + + - Magic Mirror (4-Way) +Wand magic or enemy magic that hits this combo is reflected 180 degrees. + + - Magic Mirror (Up-Left, Down-Right) +Wand magic or enemy magic that hits this combo is reflected 90 degrees as if the mirror were shaped like the following slash: \ + + - Magic Mirror (Up-Right, Down-Left) +Wand magic or enemy magic that hits this combo is reflected 90 degrees as if the mirror were shaped like the following slash: / + + - Magic Prism (3-Way) +Wand magic or enemy magic that hits this combo is duplicated twice. The two duplicate shots are fired perpendicular to the direction of the original shot. + + - Magic Prism (4-Way) +Wand magic or enemy magic that hits this combo is duplicated three times. The three magic shots are fired from all 4 directions. + ++--------------------------------+ +| 4.13b.2 ENEMY PLACEMENT TYPES | ++--------------------------------+ + + - Armos +When touched, the combo produces an Armos enemy. The Armos combo can be safely activated from the East, North or West sides of the combo, but if activated from the south the player will take damage (but this NES behaviour can be removed with a quest rule). When activated, the Armos combo changes to the screen's Under Combo. The Armos combo can also be set to work with flags 'Armos->Secret' and 'Armos->Item'. The 'Armos->Secret' flag will display the corresponding secret combo set in the screen's secret combo editor when the Armos is activated, and the 'Armos->Item' flag will put the screen's Secret Item beneath the Armos when it is activated. + + - BS Grave +BS Grave combos act exactly the same as Grave combos, but will change to the next combo on the list when activated. + + - Center Statue +If the 'Statues Shoot Fire' Screen Data flag is checked, a "Shooter (Fireball)" enemy is created on this combo. + + - Grave +When touched, a "Ghini (L1, Phantom)" appears from the combo. Graves can be safetly activated from the East, North and West sides, but if Link activates a grave from the South, he will take damage (but this NES behaviour can be removed with a quest rule). + + - Left Statue +If the 'Statues Shoot Fire' Screen Data flag is checked, a "Shooter (Fireball)" enemy is created on the left side of this combo. + + - No Enemies +Enemies cannot walk onto a No Enemies combo. + + - No Flying Enemies +Enemies such as peahats or keese, which normally ignore walkability, cannot fly here. + + - No Jumping Enemies +Tektites and Pols Voices, which normally ignore walkability, cannot jump here. + + - Right Statue +If the 'Statues Shoot Fire' Screen Data flag is checked, a "Shooter (Fireball)" enemy is created on the right side of this combo. + + - Spinning Tile (Immediate) +This combo spawns a 'Spinning Tile (Combo)' enemy as soon as it appears on the screen. The Spinning Tile will take its graphics from the tile page tiles preceding this combo's tile - thus, you can have different-looking Spinning Tiles spawn from different-looking combos. + ++-----------------------------+ +| 4.13b.3 WARP TYPES | ++-----------------------------+ + +These combos transport Link to a different screen in a certain manner when he steps on them. + + - Cave (Walk Down) [A-D] +Link appears to walk down on the combo when stepped on, warping him to the specified letter warp. Any pixels filled with a color other than transparent will appear about Link while the walking down animation plays. + + - Cave (Walk Up) [A-D] +Link appears to walk up on the combo when stepped on, warping him to the specified letter warp. Any pixels filled with a color other than transparent will appear about Link while the walking up animation plays. + + - Direct Warp [A-D] +Specified letter warp in which the exit point on the destination screen is ignored, instead using Link's position when the warp was touched. This warp is triggered even if Link walks on the top half of the combo. + + - Direct Warp [Random] +A direct warp that sends Link to any of the defined letter warps on that screen randomly. + + - Dive Warp [A-D] +Acts as a water combo, but if Link dives here, he is warped via the lettered tile warp. + + - Sensitive Warp [A-D] +Sensitive Warp [A-D] combos act exactly the same as Stairs [A-D] combos, but will be activated as soon as Link touches one pixel of the tile. These combos can be made to work exactly the same as Direct Warp [A-D] combos by checking the screen flag 'Auto-Warps Are Direct'. + + - Sensitive Warp [Random] +Sensitive Warp [Random] combos act exactly the same as Stairs [Random] combos, but will be activated as soon as Link touches one pixel of the tile. This combo can be made to work exactly the same as the Direct Warp [Random] combo by checking the screen flag 'Auto-Warps Are Direct'. + + - Stairs [A-D] +Basic Warp tile. This warp is triggered only if Link walks on the bottom half of the combo. Link will be warped via the corresponding lettered warp, and appear at the blue warp return point on the screen to be warped to. + + - Stairs [Random] +When Link steps onto a Stairs [Random] combo, there is a random chance of him warping to any of the screen's four Tile-Warps. + + - Swim Warp [A-D] +Acts as a combination between a water combo and a stairs combo. If Link swims here, he is warped to the corresponding lettered warp. + ++-----------------------------+ +| 4.13b.4 VISUAL TYPES | ++-----------------------------+ + + - Eyeball (8-way, A) +The tile changes depending on the position of Link relative to this combo. The directions are N, NE, E, SE, S, SW, W, and NW. + + - Eyeball (8-way, B) +The tile changes depending on the position of Link relative to this combo. The directions are NNE, ENE, ESE, SSE, SSW, WSW, WNW, and NNW. + + - Eyeball (4-way) +The tile changes depending on the position of Link relative to this combo. The directions are N, S, E, W. + + - Overhead +Non-flying sprites, like Link and most enemies, appear under this combo except for the transparent portions of the tile. If an Overhead combo is placed on layer 0 that contains some transparent pixels, tiles places on layers 1 and 2 will appear in place of the transparent pixels. + ++-----------------------------+ +| 4.13b.5 WALK EFFECT TYPES | ++-----------------------------+ + +These combos produce a certain effect if Link is stepping on them. + + - Conveyor D/L/R/U +Link will be shifted in the designated direction when he steps here, although the movement is not so strong that he cannot walk against it. Conveyors can be a little bit bugged. On a 'Sideview Gravity' screen, solid left and right conveyors will shift Link in the designated direction when he stands on top of them. + + - Damage (X Heart(s)) +When this combo is stepped on without the boots, Link loses the designated amount of hearts. Rings will not affect the damage taken unless the particular quest rule is checked. Damage amounts include 1/2 heart, 1 heart, 2 hearts, 4 hearts, 8 hearts, 16 hearts, and 32 hearts. + + - Dock +Link must begin a Raft Path on a dock combo. + + - Shallow Water +A small 16x8 pixel effect appears on Link while walking here. The graphic is set in Sprites/Misc. + + - Slow Walk +Link's walking speed is reduced on this combo. Enemy speed will not be. + + - Step->Next +When Link steps on a Step->Next combo, it will change to the next combo in the list. + + - Step->Next (All) +When Link steps on a Step->Next (All) combo, all Step->Next combos including Step->Next (Copycat) and Step->Next (Same) will change to the next combo on the list. + + - Step->Next (Copycat) +When a Step->Next (All) combo is activated on a screen with a Step->Next (Copycat) Combo, it will also change to the next combo on the list, but it cannot be triggered itself. + + - Step->Next (Same) +When Link steps on a Step->Next (Same) combo, all tiles of the same combo number will change to the next combo on the list. + + - Step->Secrets (Permanent) +This triggers Screen Secrets when the bottom half of this combo is stepped on. + + - Step->Secrets (Sens. Perm) +Trigger (Sens. Perm) combos act exactly the same as Trigger (Permanent) Combos, but will be activated as soon as Link touches one pixel of the tile. + + - Step->Secrets (Sens. Temp) +Trigger (Sens. Temp) combos act exactly the same as Trigger (Temporary) Combos, but will be activated as soon as Link touches one pixel of the tile. + + - Step->Secrets (Temporary) +This triggers Screen Secrets when the bottom half of this combo is stepped on, but it does not set the screen's "Secret" Screen State - that is, the Screen Secrets are temporary. + + - Reset Room +When Link steps on this combo, all of the current Screen's States are reset to 0 (except for those that have been labeled "No Reset" in Screen Data), and Link is instantly warped to the very same screen - effectively leaving Link unmoved, but resetting all of the enemies and combos. + + - Water +Water has the following properties: + -- Zora-type enemies can appear on this combo. + -- Ranged weapons that are normally stopped by unwalkable combos, like the Hookshot, fire freely over this combo regardless of its walkability. + -- The Ladder can be used to cross over this combo if it is unwalkable. + -- If Link has the flippers, and this combo is unwalkable, then he can swim on this combo. His tiles will be changed to the Link Swimming tiles set in the Link Sprites box. + -- If the "Whistle->Dry Lake" Screen Flag is set, then it loses its combo type and unwalkable flags when the Whistle is played. This effect is temporary, and vanishes if the screen is reentered. +If the "Link Drowns in Walkable Water" Rule is set, then the following changes to the above behaviour occur: + -- If Link is standing on this combo without the Flippers, and his Z-axis position is 0, he will drown. His sprite tiles will change to the "Diving" Link tiles, he will not be able to move, and after 60 frames he will lose 1/4 of a heart and reappear at the exact location where he entered the screen, flashing. + -- The Stepladder can be used to cross over this combo regardless of its walkability. + -- Other walking enemies will not walk on it, regardless of its walkability. + ++-----------------------------+ +| 4.13b.6 DESTRUCTIBLE TYPES | ++-----------------------------+ + +These can be destroyed with Link's items. + + - Bush +Acts as a Slash->Item combo. Small graphics will fly out from it when slashed, usually leaves, and the bush will change to the screen's under combo. These graphics are set in Sprites/Misc. A sound effect is also played when the bush is slashed. It will also create an item in the "Bush/Grass Combos" Item Drop Set. + + - Bush (Continuous) +Same as the Bush Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Bush->Next (Item) +The Bush->Next (Item) combo works in exactly the same way as the Bush combo, but instead of changing to the screen's under combo, it will change to the next combo in the list. It will also create an item in the "Bush/Grass Combos" Item Drop Set. + + - Bush->Next (Item, Continuous) +Same as the Bush->Next (Item) Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Flowers +Acts as a Slash->Item combo. Small graphics will fly out from it when slashed, usually leaves, and the flowers will change to the screen's under combo. These graphics are set in Sprites/Misc. A sound effect is also played when the flowers are slashed. It will also create an item in the "Bush/Grass Combos" Item Drop Set. + + - Flowers (Continuous) +Same as the Flowers Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Pound +When this combo is hit with the hammer, it changes to the next one in the combo list. + + - Slash +When hit with a sword, this combo becomes the screen's under combo. + + - Slash (Continuous) +Same as the Slash Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Slash (Item) +When hit with a sword, this combo becomes the under combo. It will also create an item in the "Bush/Grass Combos" Item Drop Set. + + - Slash (Item, Continuous) +Same as the Slash (Item) Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Slash->Next +This combo is the same as the Slash combo, but instead of changing to the screen's undercombo when touched with a sword, it will change to the next combo in the list. + + - Slash->Next (Continuous) +Same as the Slash->Next Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Slash->Next (Item) +This combo is the same as the Slash (->Item) combo, but instead of changing to the screen's undercombo when touched with a sword, it will change to the next combo in the list. + + - Slash->Next (Item, Continuous) +Same as the Slash->Next (Item) Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Tall Grass +Acts as a Slash->Item combo and Shallow Water combo combined. A 16x8 pixel effect appears on Link when walking here. Small graphics will fly out from it when slashed, usually leaves. Both of these graphics are set in Sprites/Misc (note that Tall Grass uses a different graphic to Shallow Water). It will also create an item in the "Bush/Grass Combos" Item Drop Set. + + - Tall Grass (Continuous) +Same as the Tall Grass Combo, but if it has a secret combo flag and the secret combo is a slashable combo, the slash's influence continues from this combo and affects the resultant slashable combo. + + - Tall Grass->Next +Same as the Tall Grass Combo, but it changes to the next combo on the list instead of the screen's under combo. + ++-----------------------------+ +| 4.13b.7 SCREEN STATE TYPES | ++-----------------------------+ + +These combos affect and are affected by Screen States. + + - Lock Block (Boss) +If pressed against while the player possesses the boss key, this combo and all others of its type, including the copycats, change into the next one on the list. + + - Lock Block (Boss, Copycat) +If a Boss Lock Block on the screen is pressed against while the player possesses the boss key, this combo changes into the next one on the list. + + - Lock Block (Normal) +If pressed against while the player possesses a key, this combo and all others of its type, including the copycats, changes into the next one on the list. A key will also be used. + + - Lock Block (Normal, Copycat) +If a Lock Block on the screen is pressed against while the player possesses a key, this combo changes into the next one on the list. + + - Treasure Chest (Boss) +Identical to "Treasure Chest (Normal)", but opening it requires the level Boss Key, and the "Treasure Chest (Boss)" Screen State is set. This combo is automatically opened if the screen's "Treasure Chest (Boss)" Screen State is already set. + + - Treasure Chest (Boss, Copycat) +When a Treasure Chest (Boss) combo is activated on a screen with a Treasure Chest (Boss, Copycat) combo, it will also change to the next combo on the list, but it cannot be triggered itself. + + - Treasure Chest (Locked) +Identical to "Treasure Chest (Normal)", but opening it requires and expends one Key, and the "Treasure Chest (Locked)" Screen State is set. This combo is automatically opened if the screen's "Treasure Chest (Locked)" Screen State is already set. + + - Treasure Chest (Locked, Copycat) +When a Treasure Chest (Locked) combo is activated on a screen with a Treasure Chest (Locked, Copycat) combo, it will also change to the next combo on the list, but it cannot be triggered itself. + + - Treasure Chest (Normal) +When Link walks upwards against the bottom of a Treasure Chest (Normal) combo, the combo will change to the next combo in the list, and the "Treasure Chest" Screen State is set. If the Treasure Chest (Normal) combo has flag 10, Armos->Item set to it, Link will recieve the screen's Secret Item when the combo changes. This flag placement is a throwback to when Treasure Chests were simulated with "Slash(->Item)" combos older versions of ZC. This combo is automatically opened if the screen's "Treasure Chest" Screen State is already set. + + - Treasure Chest (Normal, Copycat) +When a Treasure Chest (Normal) combo is activated on a screen with a Treasure Chest (Normal, Copycat) combo, it will also change to the next combo on the list, but it cannot be triggered itself. + ++-----------------------------+ +| 4.13b.8 PUSH BLOCK TYPES | ++-----------------------------+ + +Note: none of these combos can be pushed unless a Push Combo Flag is placed on them! + + - Push (Heavy) +The Bracelet is required to move this combo. + + - Push (Heavy, Wait) +The Bracelet is required to move this combo, but it cannot be moved until all enemies have been rid from the screen and will play the screen's Secret Sound effect. It will always hesitate before moving. + + - Push (Very Heavy) +The Bracelet 3 item is required to move this combo. + + - Push (Very Heavy, Wait) +The Bracelet 3 item is required to move this combo, but it cannot be moved until all enemies have been rid from the screen and will play the screen's Secret Sound effect. It will always hesitate before moving. + + - Push (Wait) +No Bracelet is needed to move this combo, but it will hesitate (if the correct Quest Rule is checked), trigger secrets or stairs, and not be able to move until the enemies are cleared from the screen. + ++----------------------------------+ +| 4.13b.9 SCREEN-WIDE EFFECT TYPES | ++----------------------------------+ + +These affect the entire screen instantly, regardless of where they are placed. + + - Auto Side Warp [A-D] +The Auto-Warp combo will warp Link to the given co-ordinates as soon as one is displayed on the screen. A-D is the reference to which warp will be used. Interestingly, the Auto-Warp combo will use the screen's corresponding Side-Warp, rather than the Tile-Warp. + + - Auto Side Warp [Random] +As soon an Auto-Warp [Random] combo is displayed on the screen, it will select at random one of the screen's Side-Warps, and send Link to its destination. + + - Screen Freeze +While this combo is on the screen, the screen is frozen as if the "Messages Freeze All Action" rule was in effect. + + - Screen Freeze (FFCs Animate) +Identical to the above, except that FFCs will continue to move. + ++----------------------------+ +| 4.13b.10 SAVE TYPES | ++----------------------------+ + + These combos allow Link to save his game without having to die or use F6 to quit. Note that these combos are the only way for Link to save his game if 1) the Save option on the Continue screen has been disabled by the Quest Rule 'No Saving When Continuing' or 2) the Continue screen has been disabled by the Quest Rule 'Skip Continue Screen'. + + - Save Point +Press the "Start" button when Link is standing on this combo, and the Save menu appears. This combo is used for saving and continuing. + + - Save-Quit Point +Press the "Start" button when Link is standing on this combo, and the Save menu appears. This combo is used for saving and quitting. + ++----------------------------+ +| 4.13b.11 OBSOLETE TYPES | ++----------------------------+ + + - Trap (4-way, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by '4-Way Trap' Combo Type/Flag" enemy data flag on this combo. Obsoleted by Combo Flag 34. + + - Trap (Horizontal, Constant) +Generates the lowest-numbered enemy with the "Spawned by 'LR Trap' Combo Type/Flag" enemy data flag on this combo. Obsoleted by Combo Flag 35. + + - Trap (Horizontal, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by 'Horz Trap' Combo Type/Flag" enemy data flag on this combo. Obsoleted by Combo Flag 32. + + - Trap (Vertical, Constant) +Generates the lowest-numbered enemy with the "Spawned by 'UD Trap' Combo Type/Flag" enemy data flag on this combo. Obsoleted by Combo Flag 36. + + - Trap (Vertical, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by 'Vert Trap' Combo Type/Flag" enemy data flag on this combo. Obsoleted by Combo Flag 33. + + - Win Game +Obsoleted by Flag 15 (Zelda). + ++-----------------------------+ +| 4.14 TILES | ++-----------------------------+ + + Tiles are the basic graphical "units" in ZQuest. All of the graphics in a Zelda Classic quest (apart from primitive graphics drawn by scripts) are made from tiles, including the combos, enemies, subscreens, and Link. + + All of your quest's tiles are stored in 252 'pages' of 260 tiles each. The Select Tile editor is where you organize your quest's tiles, by moving, rotating, and adjusting large groups of tiles. In the dialog, You can see one page at a time, and can change pages by clicking the arrows above and below the page number, or using the hotkeys (see below). + + As mentioned earlier, tiles can be either 8-bit or 4-bit. 8-bit tiles are signified by a flashing '8' in the lower-right corner, and by their inability to change color when you change the CSet. + + An important tile editing feature is the ability to select multiple tiles at once. Click on a tile, and then click on a second tile while holding Shift. All of the tiles between the first and second tile will be selected. You can then perform tile adjustment functions on the entire selected area, such as pixel-increment shifting, flipping horizontally or verically, or copying and pasting. However, you can currently only edit or rotate one tile at a time. The third box on the bottom panel changes the selection method. + + The second box on the bottom panel shows the first tile you have selected. The first box will show what tile(s) you have copied, ready to paste elsewhere. The number of the tile(s) will be under the box. + + In version 2.50, a new feature called Tile Protection was added. If you attempt to copy or paste into a tile, ZQuest will attempt to see if the tile is being used by a resource, and, if it thinks so, it asks for confirmation before performing the action. This only takes combos, enemies and items into account, and, currently, might not take into account the animation setting of each enemy. + +Buttons: + - Export: saves the current tile page in BMP format. + - Grab: opens the Tile Grabber to write grabbed tiles at the current position. + - Edit: edits the selected tile. + - Done: exits the tile list. + +Right click menu: + - Copy: copies the selected tile(s) to the 'clipboard' (the leftmost box on the lower panel). + - Paste: pastes the copied tile(s), replacing any tiles at the destination position(s). + - Move: pastes the copied tile(s) and erases its original position(s). + - Clear: erases the tile(s). + - Edit: edits the first selected tile. + - Grab: opens the Tile Grabber to load graphics from external files and place the results at the current tile position. + - Color Depth: changes the color depth (bit depth) of the currently selected tiles. 4-bit tiles can be drawn with different CSets, and thus it is very easy to 'palette-swap' tiles by changing the CSet. 8-bit tiles, conversely, can use all 256 colours of a palette. + - Blank?: tells you if the tile is blank. + - View: changes the view options of the tile selector. Hidden tiles have a static effect drawn in their place. By default, blank tiles are hidden. You can also hide used tiles to find unused sections of the tile pages, so that you don't accidentally overwrite a used block of tiles. + +Hot keys: + - Page up: go to the previous page. + - Page down: go to the next page. + - p: go to a specific page number. + - c: copies the selected tile(s) to the 'clipboard'. + - m (tile copied): moves the selected tile(s) from their current position to that of the destination tile(s), replacing the destination tile(s) in the process. + - v (tile copied): pastes the selected tile(s), replacing the destination tile(s) with the copied tile(s). + - o: overlays the copied tile on the destination tile, such that blank pixels in the copied tile(s) are replaced with those from the destination tile(s). A useful tool! + - h,v: flip all selected tiles horizontally, vertically. This does not change the position of tiles, but merely flips each of them individually. + - r: rotate the first selected tile clockwise. + - shift+r: rotate the first selected tile counterclockwise. + - option+arrows: shift the selected tiles by one-pixel increments. A very useful tool! Shifted tiles will 'wrap around' through the entire selection area. Use a larger selection if you want to reposition entire blocks of tiles. + - shift+arrows: increase or decrease the selection area. + - control+arrows: move the cursor to the corners of the page. + - d: create Relational or Dungeon Carving variants of the selected tile. Useful only if you use the Relational or Dungeon Carving combo drawing modes. + - control+u: toggles the hiding of unused and used tiles. + - b: changes bit depth of tile(s) to 8-bit. + - control+b: changes bit depth of tile(s) to 4-bit. + - m (no tile copied): opens the Combo Editor to let you create a new combo using this tile. + ++-----------------------------+ +| 4.14a TILE EDITOR | ++-----------------------------+ + +A simple paint editor that lets you edit individual tiles. Your paint tool has a primary and secondary color, assigned to the left and right mouse buttons. + +The tool boxes on the left are: + - Draw (sword): Changes color of only the pixel the cursor is on. Left-click to use the primary color, and right-click to use the secondary color. If a selected area exists, this will not affect any pixels outside of the selection. + - Shift (gauntlet): Shift the pixels in the drawing area. If a selected area exists, this will not affect any pixels outside of the selection. + - Fill Area (spilling potion): Changes the color of the colored area the cursor is on to the selected color. + - Replace (jeweled wand): Changes the color of all pixels the same color as the pixel the cursor is on to the selected color. + - Select (hookshot): select a rectangle of pixels. You can only draw, or use the Fill and Replace tools, within the selected area. + - Select Color (gnarled wand): select all pixels of a certain color. + - Eyedropper (lens of truth): left click to change the primary color to that of the clicked pixel. Right click to change the secondary color. + +The four boxes on the right are: + - Upper left: Original tile. + - Upper right: Original tile with transparent pixels transparent. + - Lower left:Changed tile. + - Lower right:Changed tile with transparent pixels transparent. + +Edit: Lets you edit the game's palettes quickly. + +Palette Square: Left-click on a color to assign it to the left mouse button. Right-click on a color to assign it to a right mouse button. Selected colors are shown in the 2 small squares to the right. A special note about 8-bit tile editing: since you can use colors from any CSet, you should be careful about using colors from CSets that are palette-dependant - i.e. CSets that change when the palette is changed. You should also be careful about using colors from Link's CSet - these colors are likely to change when Link acquires a Ring item. + +Hot keys: + - up, down, left, right: shift the tile by one-pixel increments in the given direction. + - +/-: change cset. Does nothing if the tile is 8-bit. + - r: rotate entire tile. + - h: flip entire tile horizontally. + - v: flip entire tile vertically. + - d: deselect, removing the selection. + - i: invert the selection, causing the outside to become selected instead of the inside. + - s: swap primary and secondary colors (assigned to the mouse buttons). + - control+s: replaces all instances of the primary colour in the tile with the secondary color (and vice versa). + + ++-----------------------------+ +| 4.14b TILE GRABBER | ++-----------------------------+ + +This is how you import graphics from image files, game ROMs or other files into your quest. File extensions that are "grabbable": .qst, .til, .zgp, .bmp, .gif, .jpg, .smc, .nes, .gb, .gba + +On the left, a group of status counters are shown: + - sel: shows how many pixels from the upper left corner of the image that the upper left corner of the tile you have selected is. + - pos: This show the postion in pixels that the top left corner of your current view is on the file you are viewing. + - cset: The current CSet used to view the grabbed tiles. Change this by pressing + or -. + - step: Shows how many pixel increments the selector will move in. Toggle this from 16 to 1 to 8 by pressing S. + - file: Shows information about the file you have selected. Image size and beneath that the image's postion on your hard drive. Choose the image by clicking on File and Browse. + + - Leech: the leech option window. It will allow you to take any graphic and cut it up into tiles and import those tiles into your quest. It has the following options: + +1. Update Status Every: (default) 500. --causes the counters on the next window to update every time this many tiles have been examined. +2. Check only new tiles: With this option checked, the program will only check the new tiles you have imported for duplicates. With this option off, it will check every tile up to the current tile, starting from tile 0. +3. Normal: If "Ignore" is selected, program won't check for exact duplicates at all. If "Check" is selected, it will check for exact duplicates and keep a count of them. If "Discard" is selected, it will check for exact duplicates and discard them. +4. H-Flip: If "Ignore" is selected, program won't check for horizontally-flipped duplicates at all. If "Check" is selected, it will check for h-flipped duplicates and keep a count of them. If "Discard" is selected, it will check for h-flipped duplicates and discard them. +5. V-Flip: Same as above, but with vertically flipped duplicates. +6. HV-Flip: Same as above but with horizontally and vertically flipped (rotated 180 degrees) duplicates. + +*Note: When you build a combo, you can flip a tile horizontally or vertically, so, these options can come in handy in saving space, since you only need one version of a tile to have 4 different combos. + + - The 1st box: You can choose not to grab any of the 4 8X8 pixel corners of the tile you have selected by toggling that portion of this box red. + - The next 2 boxes show the tile you have selected in the image, normal view and with transparencies. + - The 2 boxes under these show the tile you will be replacing when you Grab a tile from the image. +* To grab multiple tiles, click on the first tile you want to grab and shift-click on the last one. You can grab up to a 20 x 10 rectangle of tiles this way. + ++---------------------------+ +| 4.15 GAME ICONS | ++---------------------------+ + + This is where you choose the tile for your game icon (the picture that shows in the ZC Select box when you start or continue a game). The saved game icon changes when Link acquires a Ring item. Click on the first black square to choose the tile for Link with no rings, the 2nd for Link with the blue ring, the 3rd for Link with the red ring, and 4th for Link with a higher ring. In most cases this is the same tile. The colors will be determined by Extra Sprite Palette 1 CSets 9-12. + ++---------------------------+ +| 4.16 MISC. COLORS | ++---------------------------+ + +This pane lets you adjust colours for a variety of miscellaneous game features. Choose a color by entering the hexadecimal coordinates for its location in the square to the left. + - Text: the default text colour for subscreen text. + - Caption: Caption color on the subscreen. + - Overworld Minimap: the color of the NES minimap for Overworld DMaps. + - Minimap Background: the Interior or Dungeon minimaps' background color. In The Legend of Zelda, this is black. + - Minimap Foreground 1 and 2: the color used to draw the minimaps' rooms. DMaps can use either of these colours. + - BS Dark and Goal: Used for BS overworld maps. + - Compass Light and Dark: Light when the Triforce is still in the DMap, Dark when it is gone. + - Subscreen Background: the default color for subscreens. In The Legend of Zelda, this is black. + - Subscreen Shadow: in The Legend of Zelda, this is black. + - Triforce Frame color: the color for Triforce Frame objects in the subscreens. + - Big Map Background: color for the background of Big Map subscreen objects. + - Big Map Foreground: color for the background of Big Map subscreen objects. + - Link's Position: By default, ues Cset 6, color 1 (0x61) so that the indicator will change colors according to Link's ring. + - Message Text: the default message string color. + ++---------------------------+ +| 4.17 MAP STYLES | ++---------------------------+ + + Used for customizing the default tiles of some subscreen elements: Minimap (5x3), 2x2 Frame, Triforce Frame (which can be 6x3 or 6x6 depending on the quest rules), Triforce Fragments to fit into the frame (1x1 or 2x3), and Heart Container Pieces (1x1 - enter the first of the set of 5 tiles: empty, 1/4, 1/2, 3/4, and full). In earlier versions of ZC, this was the only way to customize a quest's subscreen. + ++---------------------------+ +| 4.18 DOOR COMBO SETS | ++---------------------------+ + + Door Combo Sets are used by NES Dungeon DMaps to perform the function of dungeon doors in The Legend of Zelda. + + In the Door Combo Set list, you can copy, paste and replace entire sets. Click on a set, then hit 'c'. Move to another, then hit 'v' (for paste) to make a duplicate. Hit 'r' to make all references to the other set change to this one (if you select set 1, hit 'c', select 2, then hit 'r', all screens that use set 1 will now use set 2). + +Here is an explanation of each type of Door Combo: + - Wall: Used for walls, and walls which can be bombed. + - Open: Used for open door. + - Locked / Unlocked: Used for locked doors. + - Shuttered / Open Shuttered: Used for shutters. + - Boss / Open Boss: Used for Boss doors. + - Bomb: Used for holes opened by bombs. The bottom two combos are for 'rubble' that appears above the screen's floor combos. + - Walk-Through: A marker that only appears in ZQuest, which signifies the presence of walk-through walls. + + The Overlay Walkthrough checkbox inside the editor sets whether or not the ZQuest walkthrough marker (used to indicate a walk-through wall) is transparent or not. It has no in-game effect. + + The Auto button takes the combos you've already assigned and tries to fill in what the other combos will be. For instance, If you have the left side of something, it will put in the right side automatically. It will copy the Open setting to any other blank Unlocked or Open sets. This is useful to quickly creating door sets. + + A brief note: Lock Block combos' functionality are suppressed if they are used as part of a Door Combo Set. This is to ensure that the door's trigger takes precedence over the Lock Block. The same applies to Boss Lock Blocks and Boss Doors. + ++---------------------------+ +| 4.19 SFX DATA | ++---------------------------+ + + This editor lets you change your quest's sound effects. Much like the Enemy and Item editors, you have 256 'slots' for sound effects. Sound effects are in WAV format. + + It should be noted that, while many items' and enemies' sound effects can be adjusted in their respective editors, some sound effect slots have hard-coded uses by ZQuest. Some of these are: + - 3 (Bomb blast): Used for the impact of the Quake Hammer and Super Quake. + - 5 (Subscreen cursor): Used by the subscreen cursor. + - 6 (Shield is hit): Used by the cursor on the Save / Continue / Retry screen, and when a weapon is blocked by an enemy's defenses. + - 7 (Item chime): Used when the 'Enemies->Item' screen flag causes an item to appear. + - 9 (Shutter): Used when a Lock Block is unlocked, when a locked door is unlocked, and when a shutter closes or opens. + - 12 (Low hearts warning): Used when Link is dangerously low on hearts. + - 13 (Fire): Used by various enemies' attacks. + - 14 (Ganon's fanfare): Used in Ganon rooms. + - 18 (Message): Used when Link is being healed. + - 19 (Link is hit): Used when Link takes damage. + - 21 (Bomb placed): Used when an item is selected in the subscreen if the 'Can Select A-Button Weapon On Subscreen' rule is set. + - 23 (Refill): Used when Link is being healed. + - 28 (Link dies): Used when Link dies. + - 29 (Stairs): Used when Link enters and exits Cave (Walk Down) and Cave (Walk Up) combos. + - 34 (Zelda's fanfare): Used for the ending cutscene. + - 35 (Charging weapon): Used when charging power for the Spin Attack or Quake Hammer. + - 36 (Charging weapon 2): Used for the Hurricane Spin and Super Quake. + - 56 (Summon magic): Used when an enemy with the 'Summon (Layer)' shot type summons enemies. + - 57 (Sword tapping): Used when Link taps a solid combo with a sword while charging the Spin Attack. + - 58 (Sword tapping (secret)): Used when Link taps a solid combo with a Bomb or Super Bomb flag, or taps a Bombable Door. +The following sounds are used if the 'More Sound Effects' quest rule is set. + - 38 (Enemy falls from ceiling): Used when enemies fall from the ceiling. + - 40 (Fireball): Used when enemies shoot a Fireball or Fireball (Rising) type weapon. + - 41 (Tall Grass slashed): Used when a Tall Grass, Bush or Flowers type combo is slashed. + - 42 (Pound pounded): Used when a Pound combo is pounded. + - 49 (Nayru's Love shield 2): Used when the Nayru's Love shield is running out. + - 50 (Push block): Used when a push block combo is pushed. + - 51 (Rock): Used when enemies shoot a Rock type weapon. + - 52 (Spell rocket down): Used when a Din's Fire or Nayru's Love rocket descends. + - 53 (Spell rocket up): Used when a Din's Fire or Nayru's Love rocket ascends. + - 55 (Splash): Used when Link jumps on a Water or Shallow Water combo, or uses the Hammer to hit a Water or Shallow Water combo. + - 59 (Whistle whirlwind): Used when a whistle whirlwind is moving. + +A brief note: while you could load an entire music file (in WAV format) into a sound effect slot to play higher-quality music in your quest, this is likely to greatly increase your quest's file size, and is not highly recommended. + ++----------------------------+ +| 4.20 MIDIs | ++----------------------------+ + + This loads MIDI files into your quest. These are currently the only music files (apart from WAVs) that can be stored internally in the quest file. Click on it to bring up the Select MIDI dialog box. + + Click on a number that has no MIDI file loaded, then Edit. This brings up the MIDI Specs dialog box. Click on Load to browse for a MIDI file on your hard drive. The one you select will be loaded and take you back to the Specs box. The Time, Length, and Name of the MIDI will be entered in the Specs...you can rename the file if you like. + - Volume: change the volume of the MIDI file if necessary. + - Start: Start position in MIDI file. + - Loop: Check this box if you want the MIDI to loop instead of playing through once and stopping. + - L.Strt: Starting point in looping MIDI. If a MIDI is looping, it will return to this point once it reached the L.End point. + - L.End: Ending point in looping MIDI. + ++----------------------------+ +| 4.21 TEMPLATE & DEFAULTS | ++----------------------------+ + + Template lets you set or change the quest template used for the current quest. It won't change your current information, but if you use the Quest->Default menu, it will use whatever quest template you have selected for the default you pick. + + Defaults is used to reset the chosen item (palettes, tiles, combos, sounds, items, enemies, weapon sprites, or map styles) to original settings based on your currently selected quest template. + ++----------------------------+ +| 5. EDIT MENU | ++----------------------------+ + + This menu contains standard copy and paste options for editing screens. + + - Undo (U): Undoes your last action. Will not undo multiple actions. + - Copy (C): Copies the screen. + - Paste (V): Pastes the screen. This only pastes combos, and leaves the more advanced screen options alone. + - Paste All: will paste all information about the screen you have copied to the new screen, including enemies, screen flags, warps, etc. + - Adv. Paste: Paste the current screen onto + -- Paste to All: Pastes the copied screen's combos to all screen on the map. + -- Paste All to All: Performs the Paste All operation from the copied screen to all screens on the map. + - Paste Spec.: Lets you only paste certain kinds of screen attributes. For instance, choosing 'Warps' only pastes the warp data from the copied screen onto the destination screen. A very useful feature. + - Delete (Del): deletes the current screen. + - Delete Map: deletes every screen on the entire map. + - Goto Map: go to a specific map. + ++----------------------------+ +| 6. VIEW MENU | ++----------------------------+ + + This menu lets you show and hide information pertaining to the current screen. + + - View Map: Shows the current overall map with your choice of 3 different resolutions, and lets you save it to a file. Note: in the Mac OS X version, the map will be saved to a location inside the ZQuest app bundle. +The options allow you to view walkable area, flags used, dark areas, and item placement. + - View Palette: This shows you the colours in the current palette being used for displaying the current screen. + - Show Walkability: If set, highlights all solid areas of the screen with a red colour. Useful for seeing at a glance where Link can or cannot travel. Can be toggled with the W hotkey. + - Show Flags: If set, shows the placed Combo Flags. Placed flags' numbers occupy the top-left corner of combos, whereas Inherent Flags' numbers occupy the bottom-left corner of combos. + - Show CSets: If set, displays each combo position's csets as numerals in the bottom-right corner of combos. + - Show Types: If set, displays each combo's csets as numerals in the bottom-right corner of combos. + - Show Screen Info: If set, then the bottom-right corner important information related to the mechanics of the current screen. This includes the presence of: Screen State Carryover, Timed Warp, Maze Path, the 'Sideview Gravity', 'Invisible Link', 'Save Screen', 'Continue Here' and 'Treat As..' Screen Flags, the String, every Room Type and Catch All, and all relevant Tile and Side Warps. Can be toggled with the N hotkey. + - Show Squares: If set, Warp Returns, Green Squares and Stairs Square locations are highlighted. + - Show Script Names: If set, shows the names of the scripts attached to this screen's Freeform Combos in the upper-left corner. + - Show Grid: If set, shows the grid boundaries of the combos. Can be toggled with the ~ hotkey. + ++----------------------------+ +| 7. TOOLS MENU | ++----------------------------+ + + This menu contains several miscellaneous tools for editing screens. + ++----------------------------+ +| 7.1 COMBO FLAGS | ++----------------------------+ + + A combo flag is a special property that can be applied to one or more combos. Combo flags are used to implement various screen-specific game features, such as making some combos pushable, changing a screen's combos when an action is performed, and defining areas where enemies can or cannot go. + + Combo flags should not be confused with Combo Types, although they are very similar. Combo Types, accessible by editing a combo, generally affect the characteristics of the terrain that combo is used for. Flags, meanwhile, usually define miscellaneous properties and can be selected using the Tools->Flags menu, then placed over other combos. In this way, a combo may have both a Combo Type and a Combo Flag simultaneously. Flags that are included with a combo and not manually placed are called Inherent Flags. + + Combo Flags can be grouped into Trigger Flags, Screen Secrets-Related Flags, Stair Based Flags, Special Item-Based Flags, Walk Effect Flags, Enemy Placement Flags, Push Block Flags, Visual Flags and Script-Specific Flags. + ++----------------------------+ +| 7.1a TRIGGER FLAGS | ++----------------------------+ + +A type of Combo Flag that can trigger Screen Secrets if a certain weapon touches it or a certain condition is met. When Screen Secrets are triggered, these flags are replaced with Secret Combos. The following flags are Trigger Combo Flags: + + - 1 Push Block (Vertical, Trigger) +Allows Link to push the combo up or down once, triggering Screen Secrets (or just the "Stairs" secret combo). + + - 2 Push Block (4-Way, Trigger) +Allows Link to push the combo in any direction once, triggering Screen Secrets (or just the "Stairs" secret combo). + + - 3 Whistle Trigger +Trigger secret tile 16-31 when Link plays the Whistle on this combo. + +- 4 Burn Trigger (Any) +Makes the combo trigger when Link touches it with fire from any source (candles, wand, Din's Fire, etc.) When Screen Secrets are triggered, this is replaced with the "Blue Candle" Secret Combo. + + - 5 Arrow Trigger (Any) +Will be triggered with level 1 (Wooden) arrows or higher. When Screen Secrets are triggered, this is replaced with the "Wooden Arrow" Secret Combo. + + - 6 Bomb Trigger (Any) +Makes the combo trigger when a bomb explodes in range of it. When Screen Secrets are triggered, this is replaced with the "Bomb" Secret Combo. + + - 11 Bomb (Super) +Makes the combo trigger when a Super bomb explodes in range of it. When Screen Secrets are triggered, this is replaced with the "Super Bomb" Secret Combo. + +- 47 Push Block(Horiz, Once, Trigger) +Allows Link to push the combo left or right once, triggering Screen Secrets (or just the "Stairs" secret combo). + +- 48 Push Block (Up, Once, Trigger), 49 (Down, Once, Trigger), 50 (Left, Once, Trigger), 51 (Right, Once, Trigger) +Ditto, but in specific other directions. + +- 66 Block Trigger +Pushing blocks (any, but typically flags 59-65) onto ALL Block Triggers will trigger Screen Secrets (or just the "Stairs" secret combo). + +- 68 Boomerang Trigger (Any) +Will be triggered by the level 1 (Wooden) boomerang or higher. When Screen Secrets are triggered, this is replaced with the "Wooden Boomerang" Secret Combo. + +- 69 Boomerang Trigger (Magic +) +Will be triggered by the level 2 (Magic) boomerang or higher. When Screen Secrets are triggered, this is replaced with the "Magic Boomerang" Secret Combo. + +- 70 Boomerang Trigger (Fire) +Will be triggered by the level 3 (Fire) boomerang or higher. When Screen Secrets are triggered, this is replaced with the "Fire Boomerang" Secret Combo. + +- 71 Arrow Trigger (Silver +) +Will be triggered by the level 2 (Silver) arrows or higher. When Screen Secrets are triggered, this is replaced with the "Silver Arrow" Secret Combo. + +- 72 Arrow Trigger (Golden) +Will be triggered by the level 3 (Golden) arrows or higher. When Screen Secrets are triggered, this is replaced with the "Golden Arrow" Secret Combo. + +- 73 Burn Trigger (Red Candle +) +Will be triggered by fire from the level 2 Candle, the Magic Wand (fire only, not magic) or Din's Fire. When Screen Secrets are triggered, this is replaced with the "Red Candle" Secret Combo. + +- 74 Burn Trigger (Wand Fire) +Will be triggered by fire from the Magic Wand (fire only, not magic) or Din's Fire. When Screen Secrets are triggered, this is replaced with the "Wand Fire" Secret Combo. + +- 75 Burn Trigger (Din's Fire) +Will only be triggered by fire from Din's Fire, nothing less. When Screen Secrets are triggered, this is replaced with the "Din's Fire" Secret Combo. + +- 76 Magic Trigger (Wand) +Will be triggered by any magic from the Magic Wand. When Screen Secrets are triggered, this is replaced with the "Wand Magic" Secret Combo. + +- 77 Magic Trigger (Reflected) +Will be triggered by magic that has been reflected (by Mirrors, Prisms or the Mirror Shield) from any source. When Screen Secrets are triggered, this is replaced with the "Reflected Magic" Secret Combo. + +- 78 Fireball Trigger (Reflected) +Will be triggered by an enemy fireball that has been reflected by the Mirror Shield. When Screen Secrets are triggered, this is replaced with the "Reflected Fireball" Secret Combo. + +- 79 Sword Trigger (Any) +Will be triggered by the level 1 (Wooden) sword or higher. When Screen Secrets are triggered, this is replaced with the "Sword" Secret Combo. + +- 80 Sword Trigger (White +) +Will be triggered by the level 2 (White) sword or higher. When Screen Secrets are triggered, this is replaced with the "White Sword" Secret Combo. + +- 81 Sword Trigger (Magic +) +Will be triggered by the level 3 (Magic) sword or higher. When Screen Secrets are triggered, this is replaced with the "Magic Sword" Secret Combo. + +- 82 Sword Trigger (Master) +Will only be triggered by the level 4 (Master) sword or higher. When Screen Secrets are triggered, this is replaced with the "Master Sword" Secret Combo. + +- 83 Sword Beam Trigger (Any) +Will be triggered by beams from the level 1 (Wooden) sword or higher. When Screen Secrets are triggered, this is replaced with the "Sword Beam" Secret Combo. + +- 84 Sword Beam Trigger (White +) +Will be triggered by beams from the level 2 (White) sword or higher. When Screen Secrets are triggered, this is replaced with the "White Sword Beam" Secret Combo. + +- 85 Sword Beam Trigger (Magic +) +Will be triggered by beams from the level 3 (Magic) sword or higher. When Screen Secrets are triggered, this is replaced with the "Magic Sword Beam" Secret Combo. + +- 86 Sword Beam Trigger (Master) +Will only be triggered beams from by the level 4 (Master) sword or higher. When Screen Secrets are triggered, this is replaced with the "Master Sword Beam" Secret Combo. + +- 87 Hookshot Trigger +Will be triggered by shooting it with the Hookshot. When Screen Secrets are triggered, this is replaced with the "Hookshot" Secret Combo. + +- 88 Wand Trigger +Will be triggered by whacking it with the Magic Wand itself (NOT its magic!) When Screen Secrets are triggered, this is replaced with the "Wand" Secret Combo. + +- 89 Hammer Trigger +Will be triggered by pounding it with the Hammer. When Screen Secrets are triggered, this is replaced with the "Hammer" Secret Combo. + +- 90 Strike Trigger +Will be triggered by just about any weapon or projectile Link could throw at it. When Screen Secrets are triggered, this is replaced with the "Any Weapon" Secret Combo. The following weapons cannot trigger this flag: Sword Beam, Flame, Stomp Boots, Cane of Byrna. + ++------------------------------------+ +| 7.1b SCREEN SECRETS-RELATED FLAGS | ++------------------------------------+ + +These flags affect exactly what conditions will trigger Screen Secrets. + +- 16-31 Secret Tile 0-15 +When placed on a combo, causes that combo to change to the appropriate Secret Combo when the secret combos are triggered on that screen. Also, a Destructible Combo with these flags changes to the appropriate Secret Combo instead of the screen's Under Combo. + +- 94 Trigger -> Self Only +If used as an inherent flag with a Trigger Combo Flag (or vice versa), then triggering the Trigger Combo Flag will prevent the Screen Secrets process from changing the other flagged combos in the screen. That is to say even when every singular flag is triggered, it will not immediately trigger the other secret combos, even if the Screen Flag, "All Triggers -> 16-31" is set without accompaniment with other screen flags. + +- 95 Trigger->Self, Secret Tiles +As with 94, but the Secret Tile (16-31) flagged combos are still permitted to change. (Note: the "All Triggers->16-31" Screen Flag overrides this.) + ++------------------------------------+ +| 7.1c STAIR-BASED FLAGS | ++------------------------------------+ + + Only one such flag exists. It is used to replicate the feature in The Legend of Zelda where a stairway could appear underneath a specific Armos combo. + + - 9 Armos -> Secret +When placed on an Armos, causes the "Stairs" secret combo to appear when the Armos is triggered, instead of the screen's Under Combo. + ++------------------------------------+ +| 7.1d SPECIAL ITEM BASED FLAGS | ++------------------------------------+ + + - 10 Armos/Chest -> Item +When placed on an Armos, Treasure Chest, or destructible combo, it causes the room's Special Item to appear when the combo is activated. Note that if the special item is in a treasure chest or under a destructible combo, Link will hold it up even if the Hold Up Item Screen Flag is off, whereas if the item is under an Armos, the flag must be turned on in order for Link to hold up the item. + + - 13 Dive -> Item +When Link dives on this combo (make it a water combo, of course), he will receive the screen's Special Item. Note that Link holds up the special item even if the Hold Up Item Screen Flag is off. + ++------------------------------------+ +| 7.1e WALK EFFECT FLAGS | ++------------------------------------+ + +These flags produce certain effects when Link walks on them. + + - 7 Fairy Ring (Life) +Makes a heart ring appear on screen when Link steps on it, causing his Life to be refilled. + + - 8 Raft Path +Placed in paths to define the path Link travels when using the Raft. It should start on the "dock", and end on a walkable combo. If a path branches, Link takes the clockwise-most path, starting from North (needs confirmation) + + - 12 Raft Branch +Placed at intersections of Raft flag paths to define points the player may change directions by holding down a direction. + + - 15 Zelda (Win Game) +When Link steps on this flag, the game will end, and the credits will roll. + + - 92 Fairy Ring (Magic) +Makes a heart ring appear on screen when Link steps on it, causing his Magic to be refilled. + + - 93 Fairy Ring (All) +Makes a heart ring appear on screen when Link steps on it, causing both his Life AND Magic to be refilled. + + - 103 Raft Bounce +Reverses the direction the raft is moving in. + ++------------------------------------+ +| 7.1f ENEMY PLACEMENT FLAGS | ++------------------------------------+ + + - 32 Trap (Horizontal, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by 'Horz Trap' Combo Type/Flag" enemy data flag on this combo. + + - 33 Trap (Vertical, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by 'Vert Trap' Combo Type/Flag" enemy data flag on this combo. + + - 34 Trap (4-way, Line of Sight) +Generates the lowest-numbered enemy with the "Spawned by '4-Way Trap' Combo Type/Flag" enemy data flag on this combo. + + - 35 Trap (Horizontal, Constant) +Generates the lowest-numbered enemy with the "Spawned by 'LR Trap' Combo Type/Flag" enemy data flag on this combo. + + - 36 Trap (Vertical, Constant) +Generates the lowest-numbered enemy with the "Spawned by 'UD Trap' Combo Type/Flag" enemy data flag on this combo. + + - 37-46 Enemy (0-9) +Causes the indicated screen enemy to appear on that flag, instead of at a random location. + + - 96 No Enemies +Prevents enemies from stepping on this combo. + ++------------------------------------+ +| 7.1g PUSH BLOCK FLAGS | ++------------------------------------+ + + - 52-58 Push Block (*direction*, Once) +Same as the Push Block Trigger flags, but does not trigger secrets. + + - 59-65 Push Block (*direction*, Many) +Same as 52-58, but can be pushed many times. Does not trigger secrets. + + - 67 No Push Blocks +Prevents a block from being pushed onto this combo. Note that solid combos already prevent blocks from being pushed onto them. + + - 91 Block Hole +Causes blocks pushed onto this combo to cycle to the next combo. This is typically used to make blocks that 'sink down' and become walkable terrain, but it can be used for a variety of purposes. + ++------------------------------------+ +| 7.1h VISUAL FLAGS | ++------------------------------------+ + + - 14 Lens Marker +Combos with this flag will appear white when viewed with the Lens of Truth item. + ++------------------------------------+ +| 7.1i SCRIPT-SPECIFIC FLAGS | ++------------------------------------+ + + - 98-102 General Purpose 1-5 (Scripts) +These flags have no built-in effect, but can be given special significance with scripting. + ++----------------------------+ +| 7.2 COLOR SET FIX | ++----------------------------+ + + This changes the CSet of all of the combos on layer 0 to the current CSet. The 'Full Screen' option causes every combo on the layer to be changed, and the 'Dungeon Floor' option changes all but the first two rows and columns of combos. Setting 'All Layers' causes this to be applied to every layer as well. + ++----------------------------+ +| 7.3 NES DUNGEON TEMPLATE | ++----------------------------+ + + In The Legend of Zelda, the dungeon rooms follow a standard template of four walls, each with at most one door. To ease the creation of NES-style quests, a 'dungeon template' can be made and applied quickly to a screen. + + The dungeon template is made in screen 0x83 of the current map. Only the first two rows and columns of combos in layer 0 are used in the template. + + In a usable screen, choosing 'NES Dungeon Template' will let you place the template onto the current screen. You can choose to use a certain combo to fill the 'floor' of the screen, or leave the floor blank. + + Selecting 'Apply Template to All' applies the NES Dungeon Template to every screen in the map. + ++----------------------------+ +| 7.4 PREVIEW MODE | ++----------------------------+ + +This is a screen display mode designed to quickly test combo cycling, screen secrets, and freeform combos. It can be quickly activated by pressing X. In this mode, a list of hotkeys is visible. + + - page up/page down: scroll through hotkey list + - esc/enter: exit Preview Mode. + - r: restore screen to original state. + - c: turn combo cycling on and off. + - s: trigger screen secrets. This can be done multiple times. + - w: toggle walkability visibility. + - f: toggle Combo Flag visibility. + - p: pause all animations, freeform combos and processes. + - a: advance through animations etc. by one frame. + - 1: trigger the screen's tile warp A, changing the current screen. + - 2: trigger the screen's side warp A, changing the current screen. + - 3: enable timed warps. + ++----------------------------+ +| 7.5 DRAWING MODE | ++----------------------------+ + + In version 2.50 of Zelda Classic, three new experimental drawing modes were added: Relational mode, Dungeon Carving mode and Combo Alias mode. + ++----------------------------+ +| 7.5a COMBO ALIAS MODE | ++----------------------------+ + + Combo Aliases are pre-defined combo structures which can be placed on a screen quickly. Unlike Door Combo Sets, they can feature combos on multiple layers. Thus, the current layer setting is irrelevant when placing combo aliases on the screen. + + When you enter Combo Alias mode, the combo selector changes to list the currently defined combo aliases. You can edit combo aliases by right-clicking on an alias. + + In the Combo Alias Editor, you can change which combos a particular alias is comprised from by clicking on different areas of the alias. You can adjust the alias's width and height, as well as choose which layers it uses, by clicking Properties. + + When you've set the alias to use multiple layers, you can toggle between these layers by clicking the radio buttons on the right. You can also switch to other aliases using the dropdown menu in the upper-right corner. + + You can reorganize combo aliases using the Org button. This dialog lets you copy a combo alias from a given slot to a given destination, insert a new empty alias, or delete the current alias. + + If a combo alias uses multiple layers, placing it on a screen will also place its layered combos on the appropriate layers if said layers exist on this screen. + ++----------------------------+ +| 7.5b RELATIONAL MODE | ++----------------------------+ + + Relational mode will automatically place different combos depending on where you draw them. It's meant for creating areas of terrain that are surrounded by a border, such as water. + + In order to use relational mode, all the necessary combos be arranged correctly combo list. See the wiki for the exact order. Select the first combo in the group when drawing. + + Combos that are already present before you switch to relational mode are ignored. For instance, if you use it to draw water, any water already on the screen will not be recognized as such when determining which border combos to use. This also means that you can't switch out of relational mode and back and resume drawing where you left off. + ++----------------------------+ +| 7.5b DUNGEON CARVING MODE | ++----------------------------+ + + Dungeon carving mode will place combos around those you draw yourself. It allows you to draw the floor of an indoor area and have walls added around it automatically. + + Like relational mode, dungeon carving mode requires the necessary combos be organized correctly in the combo list. See the wiki for the order. Select the first combo in the group when drawing. + + When you start drawing in dungeon carving mode, the entire screen will be filled with the wall combo, so use it only before doing any other screen design. + ++----------------------------+ +| 7.6 LIST COMBOS USED | ++----------------------------+ + + This presents a basic list of the combos used on this screen. Combos are listed by combo number, followed by the number of occurences in the screen in parentheses. + ++----------------------------+ +| 7.7 QUEST REPORTS | ++----------------------------+ + + Quest Reports allow the quest maker to quickly see where various resources are used in the quest, as well as identify locations of possible problems. + + In each report, screens are listed by the ZQuest palette used, followed by the map and screen number of the screen. A screen's palette provides some indication of which DMap a screen might be used in. + +Reports include: + - Combo Locations: Lists the screens in which the currently selected combo appears. This includes Freeform Combos, Under Combos and Secret Combos. This doesn't take into account combo cycling, though. + - Combo Type Locations: For each Combo Type, this report lists the locations of combos which use that type. Can be useful for finding the locations of water, lock blocks or Pound combos, among other things. This includes Freeform Combos, Under Combos and Secret Combos. This doesn't take into account combo cycling, though. + - Enemy Locations: For each defined enemy, this report lists the locations of the enemy. This doesn't take into account the possibility of enemies summoning other enemies, enemies placed by scripts, or enemies created as a result of combo types or combo flags. + - Item Locations: For each defined item, this report lists the locations of the item. This doesn't take into account item drop lists, or items placed by scripts. + - Script Locations: For each defined FFC script, this report lists the locations of FFCs that use this script. This also lists the arguments given to the script. + - What Links Here: This lists the screens whose Tile Warp or Side Warp destinations include this screen. That is, screens where Link can warp to this screen. This also lists screens which use the current screen as a layer, so it can be useful for identifying unused layer screens. + +There are also integrity checks. These are used to find possible problems in the quest. + - All: Runs every integrity check. + - Screens: This check searches through the entire quest and attempts to find the following problems: + -- Screens which have the 'Special Item' Room Type but have no means of acquiring the special item + -- Screens which have the 'Enemies->Item' Screen Flag, but have no enemies. + -- Screens which have the 'Enemies->Secret' Screen Flag, but have no enemies. + -- Screens which have combos that are typically replaced with the Under Combo, but the Under Combo is 0. + -- Screens with save point combos, but don't have the 'Use As Save Screen' flag (and thus will return Link to the DMap's entrance when he resumes the game). + -- Screens with a String, but no Guy (or vice versa) + -- Screens whose Room Type requires a Guy or a String, but lack them. + -- Screens whose items are in unwalkable locations (which may not be a problem depending on Link's equipment). + - Warps: This check searches through the entire quest and attempts to find the following problems: + -- Screens whose tile warp destinations are in unwalkable locations. + -- Screens with warps to invalid screens. + -- Screens which are warp destinations but have destination squares in the upper-left corner (i.e its default position) + -- Screens which use the default 'Cave/Item Cellar' warp (which is useful for NES-style quests, but may be a problem for modern-style quests). + -- Screens whose Auto Side Warps or Triforce warps are 'Cave/Item Cellar' type. + ++----------------------------+ +| 8. SCREEN MENU | ++----------------------------+ + + This menu contains various important settings applying to the current screen. + ++----------------------------+ +| 8.1 SCREEN DATA | ++----------------------------+ + + Screen flags affect how a particular screen behaves. They can be divided into Room Type, View, Secrets, Warp, Items, Combos, Save, FFC, Whistle and Misc. Flags. + ++--------------------------------+ +| 8.1a SCREEN FLAGS -> ROOM TYPE | ++--------------------------------+ + + - Treat as Interior Screen +The Dmap type specific attributes to this screen will be set to those on an 'Interior' Dmap, despite what is already set in the Dmap Editor. + + - Treat as NES Dungeon Screen +The Dmap type specific attributes to this screen will be set to those on a 'NES Dungeon' Dmap, despite what is already set in the Dmap Editor. + + - Sideview Gravity +With this checked, Link and enemies will fall toward the bottom of the screen, and an item such as Roc's Feather will cause him to bound upwards. Solid combos will become platforms. Intended for use in sideview areas (such as dungeon passageways) mimicking Link's Awakening's passageway areas. + ++----------------------------+ +| 8.1b SCREEN FLAGS -> VIEW | ++----------------------------+ + + - Invisible Link +Link's position cannot be seen. This is usually used for cutscenes. + + - No Link Marker in Minimap +Instead of a colored dot being shown on the minimap in the passive subscreen, nothing will show. + + - No Subscreen +The subscreen cannot be pulled down, and the passive subscreen is not visible at the top. This is usually used for cutscenes or title screens. + + - ... But Don't Offset Screen +Normally, the screen would be offset if there is no subscreen. This flag fixes that. + + - Layer 2 Is Background +Tiles used on Layer 2 will appear under Layer 0. + + - Layer 3 Is Background +Tiles used on Layer 3 will appear under Layer 0. + + - Dark Room +The screen is initially dark. If either the candle, or wand with magic book is used, the screen reverts to normal lighting. This screen flag can also be toggled by pressing 'D" in the main ZQuest screen. + ++------------------------------+ +| 8.1c SCREEN FLAGS -> SECRETS | ++------------------------------+ + + - Block->Shutters +The shutters door combo opens when a block is pushed, instead of when all the enemies are killed. If there are block trigger flags on the screen, the shutters will not open until a block is pushed onto every block trigger flag. + + - Secrets are Temporary +Instead of this screen's secrets being kept or discarded when traveling to another screen based on the DMap type, they are automatically made temporary. + + - Hit All Triggers->Perm Scrt +The "Secrets" Screen State is only set when Screen Secrets are triggered and no other Trigger Combo Flags exist in the screen. Useful if you want to make a secret that only appears when multiple triggers are triggered. + + - Hit All Triggers->16-31 +The "Secret Tile" Secret Combos are only changed when Screen Secrets are triggered and no other Trigger Combo Flags exist in the screen. Useful if you want to make a secret that only appears when multiple triggers are triggered. + ++----------------------------+ +| 8.1d SCREEN FLAGS -> WARP | ++----------------------------+ + + - Auto-Warps Are Direct +If Link is warped via an Auto-warp combo type, instead of warping to the specified blue warp-return square, he will arrive at the screen at his current (x,y) position. + + - Sensitive Warps Are Direct +If Link is warped via a Sensitive Warp combo type, instead of warping to the specified blue warp-return square, he will arrive at the screen at his current (x,y) position. + + - Use Maze Path +Must be set for the path settings to take effect. See Path for details. + + - Maze Overrides Side Warps +If a maze path is used on a screen with side warps, this flag prevents the side warp from being triggered until the maze path has been solved. If the fourth direction is the side warp, it would be triggered the instant Link solves the maze path. Note that this flag does not work if there is more than one side warp. + + - Sprites Carry Over In Warps +Things like Link weapons and even push blocks (while they're still moving) are carried over when Link warps from one screen to another. + ++----------------------------+ +| 8.1e SCREEN FLAGS -> ITEMS | ++----------------------------+ + + - Hold Up Item +When the item in the room is taken, a sound effect plays and Link holds it above his head. NOTE: This flag is not needed for Link to hold up a special item if the special item is in any treasure chest combo marked with flag 10, any destructible combo (slash, bush, flowers, tall grass, pound) marked with flag 10, or a water combo marked with flag 13. On the other hand, this flag is needed in order for Link to hold up a special item hidden under an Armos combo marked with flag 10. + + - Item Falls From Ceiling +Any item that appears in a room, except for dropped enemy items, will appear to fall from the ceiling. + ++-----------------------------+ +| 8.1f SCREEN FLAGS -> COMBOS | ++-----------------------------+ + + - Combos Affect Midair Link +If this flag is set, combos that affect Link on touch (such as damage combos and warps) will ignore jumping and affect Link mid-jump. + + - Combos Cycle On Screen Init +Cycled combos will cycle when the screen is loaded + + - Damage Combos Ignore Boots +If this flag is set, damage combos on this screen hurt Link regardless of whether or not he possesses boots. + + - Toggle Ring Affect Combos +The rule 'Rings Affect Damage Combos' is applied. + ++----------------------------+ +| 8.1g SCREEN FLAGS -> SAVE | ++----------------------------+ + + - Save Point->Continue Here +Upon quitting the game, Link will continue on this screen the next time he resumes his quest. Note that this should be on a DMap with the Continue Here Flag checked. + + - Save Game On Entry +The instant Link enters this screen, the save screen will appear. + + - Continue Here +If Link dies in the current DMap, he will be taken to the last screen he visited with this flag set. If no such screen exists, he will be taken to the screen at which he entered the DMap. + + - No Continue Here After Warp +If this flag is set, and Link entered the current DMap at this screen, and he dies without visiting a screen with the Continue Here flag set, he will continue in the previous DMap (as if he had never left it) instead of continuing at this screen. + ++----------------------------+ +| 8.1h SCREEN FLAGS -> FFC | ++----------------------------+ + + - FF Combos Wrap Around +If this flag is set and an FFC travels outside the bounds of the screen, the FFC will reappear on the other side of the screen, as if the screen had toroidal topology. + + - No FFC carryover +Free Form Combos will NOT carry over to the next screen from the current, regardless of whether they are set to do so in their specific data or not. + ++------------------------------+ +| 8.1i SCREEN FLAGS -> WHISTLE | ++------------------------------+ + + - Whistle->Stairs +If the whistle is played in this screen, the stairs secret combo is triggered after a brief interval. + + - Whistle->Pal Change +When Link blows the whistle on this screen, the third color in all combos in CSet 3 will incur a color change, in the same way as is seen at the entrance to the level 7 dungeon in the First Quest of the original Legend of Zelda + + - Whistle->Dry Lake +When Link blows the whistle on this screen, all water combos become fully walkable. + ++----------------------------+ +| 8.1j SCREEN FLAGS -> MISC | ++----------------------------+ + + - Toggle 'Allow Ladder' +The rule 'Allow Ladder Anywhere' is applied. In dungeon Dmaps, the ladder is always usable, so this has no effect. + + - Toggle 'No Diving' +The rule 'No Diving' is applied. + + - General Use 1-5 (Scripts) +Open for use by scripts. + ++----------------------------+ +| 8.1k ENVIRONMENTAL ENEMIES | ++----------------------------+ + + - Zora +Spawns one enemy which has the 'Zora' spawn flag. By default, these are Zora enemies. + + - Corner Traps +Spawns one enemy, which has the 'Corner Traps' spawn flag, in each corner of the room. By default, these are Trap (4-Way) enemies. + + - Middle Traps +Spawns two enemies, which has the 'Middle Traps' spawn flag, in the middle of the room. By default, these are Trap (4-Way) enemies. + + - Falling Rocks +Spawns three enemies which have the 'Falling Rocks' spawn flag. By default, these are Rock enemies. + + - Shooting Statues +On each Left Statue, Center Statue and Right Statue-type combo, spawns an enemy with the 'Statue Fire' spawn flag. By default, this is 'Shooter (Fireball)'. + ++----------------------------+ +| 8.1l ENEMY FLAGS | ++----------------------------+ + + - First Enemy Is 'Ring Leader' +If the first enemy on the screen is killed, all other enemies die as well. + + - First Enemy Carries Item +The first enemy on the screen carries the screen item. + + - All Enemies Are Invisible +In version 1.90, enemies in this screen are completely invisible, though their projectiles are not. In later versions, enemies create a slight blur where they are but are difficult to see. In all versions, the enemies are perfectly visible if the player has the amulet. + + - Don't Return If Boss Killed +Enemies on this screen stay dead permanently once the boss on the current DMap is killed. Note that this flag can be useful for events when the trigger enemy is used, because when all enemies are killed on a screen with this flag checked, all enemies, including the trigger enemies, on any screen on the same DMap that also has this flag checked will also disappear permanently. + + - Traps Ignore Walkability +Traps in the room completely ignore walkability. NOTE: Line-of-Sight Traps will ignore walkability regardless of this flag unless the 'Multi-Directional Traps' Rule is turned on. + + - Enemies Carry Over In Warps +All enemies on the screen are warped with Link when he enters a warp. + + - Enemies Always Return +The rule Enemies Always Return applies to this screen. + + - Enemies->Item +The item in the room only appears when all the enemies are killed. + + - Enemies->Secret +Secret combos are triggered when all enemies are killed. + + - Enemies->Secret is Permanent +If the 'Enemies->Secret' flag is checked, secrets triggered by killing all enemies will remain on this screen permanently. NOTE: This flag has no effect on screens that are treated as NES Dungeon screens, as secrets on NES Dungeon screens are always temporary. + ++----------------------------+ +| 8.1m SCREEN DATA | ++----------------------------+ + + - Screen State Carry Over +This convenient feature can be used to make events on one screen affect another, distant screen. If a particular Screen State on this screen is set, it will also be set on the specified screen (but some states can be prevented from carrying over - see below). It is also possible to have Screen State Carry Overs carry secrets to more than one screen, by "chaining" Screen State Carry Overs - that is, setting the Screen State Carry Over of the screen that the first Screen State Carry Over is applied to, to Carry Over to the third screen, and so on. + +In the Next Map dropdown menu, you can set the Map (not DMap) number of the destination screen for the Room State Carryover. In the Next Screen dropdown menu, you can set the number of the destination screen for the Room State Carryover. + + - No Reset +You can choose which Screen States are not reset by the Reset Room combo type. + + - No Carry Over +You can choose which Screen States are not carried over by Room State Carry Over. + + - Screen Midi +Allows one to choose a MIDI resource that is played exclusively on this screen. It overrides the DMap MIDI. + + - Lens Effect +Allows one to hide or show certain layers whenever the Lens of Truth is used. + + - Damage Combo Sensitivity +A value from 1 to 8 that represents how far Link may wander into a damage combo before he gets hurt. A value of 1 is least sensitive--Link's hitbox may only pass half-way into the combo before he takes damage. A value of 8 is most sensitive--If Link's hitbox touches one pixel of the combo, the damage combo affects him. + + - Ocean Sound +This sound effect plays repeatedly on this screen. (In The Legend of Zelda, some overworld screens played an ocean wave sound effect repeatedly.) + + - Boss Roar Sound +Unless the boss flag has been triggered on that DMap, this sound effect plays repeatedly on this screen. + + - Hold Up Item Sound +The ID of a sound effect that will play when Link holds up an item. + + - Secret Sound +The ID of a sound effect that will play when Link first enters the screen. It will only play once, and will not be activated if Link enters the screen in any other way (such as via a warp) + + - Play Secret SFX On Entry +The secret sound plays when the screen is entered. + ++----------------------------+ +| 8.1n TIMED WARP | ++----------------------------+ + +A timed warp is an automatic warp. After a given time from when Link enters the screen, the screen's Side Warp A is triggered. + + - Timed Warp Ticks +60 ticks per second; 0.00 Seconds=No Timed Warp + + - Timed Warps Are Direct. +If Link is warped via the screen's Timed Warp, instead of warping to the specified blue warp-return square, he will arrive at the screen at his current (x,y) position. + + - Secrets Disable Timed Warp +Triggering Secrets on the screen prevents the timed warp from occurring. + + - Timed Warp Is Random (A, B, C, or D) +By default, Side Warp A is used by the warp. If this is checked, it chooses either Side Warp A, B, C or D at random. + ++----------------------------+ +| 8.2 FREEFORM COMBOS | ++----------------------------+ + + Freeform Combos are miscellaneous sprites that consist of a combo, motion values, and script values. They can be used for placing combos unconstrained by the combo grid, making a constantly moving combo, or running a script. Each screen can have a maximum of 32 Freeform Combos. If an FFC uses combo 0, it is considered vacant. + + FFCs are drawn between layer 1 and layer 2, unless its 'Draw Over' flag is set, in which case they will be drawn between layers 4 and 5. + + While a combo's type and inherent flags are still functional when used in an FFC, its solidity data is ignored. + + FFCs have the following editable values: + + - Combo +This is the tile you wish to assign to the Freeform Combo. Even though only one tile is displayed, the combo itself can be made different sizes in the Combo W. and Combo H. fields. + + - Link to +FFCs can be linked to Any movement of the former Freeform Combo is reflected in this "linked" Combo. + + - X Pos +This is the number of pixels from the left of the screen the Combo begins at. Recall that there are sixteen pixels per tile. Also note that if this value becomes smaller than -32 or larger than 288, it will either wrap around or be deactivated. + + - Y Pos +This is the number of pixels from the top of the screen the Combo begins at. Note that if this value becomes smaller than -32 or larger than 208, it will either wrap around or be deactivated. + + - X Speed + This is the initial velocity this Combo has parallel to the X-axis, in pixels per frame. Positive numbers will move the FFC to the right, while a negative number can be entered to make the Combo move leftward. Fractions may also be used. For example, entering an X Speed of 1 will make the Combo move to the right 1 pixel every frame. Entering an X Speed of 0.5 will make the Combo move to the right at 0.5 pixels per frame, which is converted to be 1 pixel every 2 frames (since you cannot have half of a pixel). + + - Y Speed + This is the initial velocity this Combo has parallel to the Y-axis, in pixels per frame. Positive numbers will move the FFC down, while a negative number can be entered to make the Combo move up. Fractions may also be used. For example, entering a Y Speed of 1 will make the Combo move down 1 pixel every frame. Entering a Y Speed of 0.5 will make the Combo move down at 0.5 pixels per frame, which is converted to be 1 pixel every 2 frames (since you cannot have half of a pixel). + + - X Accel +This is the Combo's rightward acceleration. A zero can be entered so that the Combo moves at a constant velocity, or a negative number can be entered so the Combo accelerates in the opposite direction. + + - Y Accel +This is the Combo's downward acceleration. + + - A. Delay +This is the delay, in frames, before the combo begins moving. + + - Combo W. +The Combo W. of a freeform combo denotes the width of the field of effect that the FFC's Combo Type attribute has, in pixels. + + - Combo H. +The Combo H. of a freeform combo denotes the height of the field of effect that the FFC's Combo Type attribute has, in pixels. + + - Tile W. +The Tile W. of a freeform combo denotes how large the width of the Freeform combo will be drawn. It will be drawn with tiles from the tile page, rather than the combo page. If a Freeform combo larger than 1 x 1 tiles is animated, it will need to use the combos 'A.SkipX' and 'A.SkipY' values to animate as desired. + + - Tile H. +The Tile H. of a freeform combo denotes how large the height of the Freeform combo will be drawn. It will be drawn with tiles from the tile page, rather than the combo page. If a Freeform combo larger than 1 x 1 tiles is animated, it will need to use the combos 'A.SkipX' and 'A.SkipY' values to animate as desired. + + - Script +Freeform Combo scripts (ZScript or ZASM) are set via this dropdown menu. By default, an FFC's script will execute immediately - as soon as Link enters the screen. + + - Arguments +These are used to give certain initial variables if a script is attached to the Freeform Combo. This allows for greater customisation of scripts, because the variables no longer need to be completely hard-coded into the script. The D variables are declared within the run() command of a ZScript FFC script. The A variables are almost exclusively used by ZASM scripts. + + - Draw Over +When checked, this Freeform Combo is drawn between layers 4 and 5. + + - Translucent +When checked, this Freeform Combo becomes translucent, or partly visible. + + - Carry-Over +If the 'Carry-Over' flag is checked, when Link warps to a new screen the FFC will be copied over the same-numbered FFC in the destination screen. Motion and scripts will, by default, continue as they were, and will not restart. Note: Carry Over will NOT occur if Link was sent back to the start of the DMap by Whistle Whirlwind, Wizzrobe wind, or by a Wallmaster. + + - Run Script at Screen Init +The Freeform Combo's script will begin running just before Link scrolls onto or appears on the screen. This can be used to "preprocess" a screen - changing and rearranging combos before the screen becomes visible to the player. + + - Only Visible to Lens of Truth +This Freeform Combo appears invisible unless viewed through the Lens of Truth when checked. + + - Script Restarts When Carried Over +Normally, if an FFC is carried over to another screen, its script execution state is also carried over. If this is checked, it will instead restart its script from the beginning once it is carried over. + + - Ethereal + If this flag is checked, the FFC's Combo Type and Inherent Combo Flag are ignored by Zelda Classic, and have no effect. + + - Stationary +This Freeform Combo doesn't move, even though it has speed and acceleration values. Best used on Changers. + + - Is a Changer (Invisible) +This Freeform Combo is a Changer. A Changer is designed to modify the behaviour of any FFCs that move over it, without having to use scripts. Use Changers to make FFCs move back and forth along a predefined area, and make FFCs change their Combos and CSets. Changers are normally invisible, but in ZQuest their locations are denoted by a single multicoloured pixel. The X and Y values of FFC and Changer must be exactly equal during one frame of animation for a Changer to affect an FFC. + +The following flags are Changer-specific: + + - Swap speed with next FFC +If an FFC of number N hits this Changer, its speed and acceleration values are swapped with the speed of FFC number N+1. + + - Swap speed with prev. FFC +If an FFC of number N hits this Changer, its speed and acceleration values swapped with the speed of FFC number N-1. + + - Increase combo ID +When a Freeform Combo hits this Changer, its Combo changes into the next combo in the list. + + - Decrease combo ID +When a Freeform Combo hits this Changer, its Combo changes into the previous combo in the list. + + - Change combo/cset to this +When a Freeform Combo hits this Changer, the Freeform Combo will take on the Changer's Combo and CSet attributes. + ++----------------------------+ +| 8.3 LAYERS | ++----------------------------+ + + + +Old stuff: + + +Tile Warp (F10): +This is used to set the warp from a cave or stair tile. Only one tile warp can be used per screen. Clicking on this brings up the Tile Warp dialog box. +Choose the type of warp you want: +1) Cave/Item Room: This takes Link to Room 80 on the current dmap. It's not necessary to enter any further information. +2) Passageway: This takes Link to passageway (Room 81) of the current dmap. Enter the dmap and screen number of the screen you would like Link to be when he emerges from the passageway. Click on Go to test the warp, and to place the blue square where you want Link to appear on the new screen. +3) Entrance/Exit: Use this to take Link directly to another dmap. Enter the dmap and screen number, Go to test warp and place the green square. +4) Scrolling Warp: This makes it appear as if Link had just walked from the old screen to the new screen. More often used with side warps. Enter the new dmap and screen #, test and place the blue square. +5) Insta-Warp: Link is instantly transported to the blue square on the new dmap/screen #. +6) I-Warp w/ Blkout: Same as Insta-Warp but with blackout effect. +7) I-Warp w/ OpenScr: Open screen...a black screen that parts in the middle and opens like a curtain. +8) I-Warp w/ Zap FX: Zap effects are a sort of scrambling of the screen to make the warp more dramatic. +9) I-Warp w/ Wave FX: Somewhat like the light world/dark world warp in Zelda 3. +10) No Warp: Disables the warp trigger. Link will appear to go down the stairs but will not warp, he will reappear at the top of the stairway. + +Side Warp (F11): +Used when you want Link to warp when he leaves one side of a screen. Choose which side activates the warp on triggers. The mechanics of setting the warp are much like tile warp. Again, only one side warp per screen, but you may have a tile warp and side warp on the same screen. Not used for cave/item room or passageway warps. + +Enemy Flags (F12): +1) Zora: Places one zora on the screen (water required). +2) Corner Traps: Places a spiked "trap" in each corner of the room/screen. +3) Center Traps:Places 2 traps on the center row of a room. +4) Falling Rocks: Will place 3 falling rocks on the screen. +5) Statues Shoot Fire: All lstatue and rstatue combos on the screen will shoot fire at Link. +6) Has Ringleader: One of the enemies on the screen is the "ringleader"; when it dies, they all die. +7) Enemy Carries Item: One of the enemies on the screen will "carry" the selected item. +8) Dungeon Boss: Used in the "boss" room. When the boss is beaten , the boss sound effects in the dungeon will stop. +9) Path:Brings up the Maze Path dialog box. For the path to work, you must also check the "use maze path" screen flag. +Select the 4 directions in the order they should be taken. Only 3 directions can be used...the other direction is entered as the Exit and will take Link back to the screen he entered the maze from. The 4th direction should be the direction of the screen where you want Link to end up. +If the maze path is on the extreme left or right screen of a dmap, you cannot use the direction that would take Link off the map. + +Item (I): This is for selecting Items that will appear on the screen either when Link enters, when the enemies are dead if that screen flag is checked, or that an enemy will be carrying if that enemy flag is checked. Unless an enemy is carrying the item, to place the item where you want it to appear on the screen press PageDown and click the item icon (far left), then click on the place you want the item to be. + +Guy (G): Used to place the "guy" of your choice in a cave or dungeon room. + +Message String (S): Used to select the message string you want the "guy" to be saying. To create a new message string, go to Quest->Strings. + +Room Type (R): + +Special Item: Takes Link to Screen 80. Set the Special Item. In the OW a guy and message string may be used. +1) Pay for Info: A cave or dungeon room that has a guy with info for sale. Set guy and message, then info type number. Create Info Types under Quest->Misc. Data. +2) Secret Money: Cave or dungeon room that gives Link money. Enter the amount, and set the guy and message. +3) Gamble: Creates a gambling room. Set guy and message. +4) Door Repair: Takes money away from Link when he enters. Set guy, message, and repair fee. +5) Heart Container: Gives Link his choice of red potion or heart container. +6) Feed the Goriya: Link must give the "guy" bait so that he will disappear. Set guy and message. Use in a place where Link must get past the guy in order to continue. +7) Level 9 Entrance: Guy that Link cannot get past unless he has the complete triforce. Set guy and message. +8) Potion Shop: A shop that Link must have the letter to buy from. Set guy, message, and shop type number. Create shop types under Quest->Misc. Data. +9) Shop: A regular shop, no letter required. Set guy, message, and shop type number. +10) More Bombs: Increases the number of bombs Link can carry by 4 and gives him the maximum he can carry. Set guy, message, and price. +11) Leave Money or Life: Link must give up a heart container or a certain amount of money. Set guy, message, and price. Use in a place where Link must get past the guy in order to continue. +12) 10 Rupies: Creates a room with 10 rupies set out in a diamond shape. +13) 3-Stair Warp: Creates a warp ring room using Room 81. Enter Warp Ring number from Quest->Misc. Data. +14) Ganon: Makes Ganon the enemy in a dungeon room. +15) Zelda: Used to create a Zelda room to trigger the end game sequence. +16) Item pond: Not implemented yet. +17) Magic upgrade: Makes you use half as much magic per use, effectively doubling your magic. This can only be done once per quest. +18) Learn Slash: Link will be able to use the slash ability after visiting this room. Once per quest. + +Catch All: Information for room types that need additional information will appear in this spot if that room type is selected. + +Enemies (E): +Click here or press E to bring up the Enemy dialog box. +Double-click on a (none) space to bring up the enemy list, choose one and click OK to select it. If you want more than one of that enemy on the current screen you can press C to copy, click on a (none) space and press V to paste. +Paste Enemies: If you copy a screen and go to a new screen, paste enemies will put the same enemies that were on the old screen on the new screen. +Flags brings up the Enemy Flag dialog box. +Pattern: If you want the enemies to enter from the sides of the screen, click on pattern and choose this option. + +Under Combos: +To set an undercombo, first click on the tile you want for the undercombo, then on Under Combo. In the new dialog box are 2 squares. If the tile in the New square is the one you want for the undercombo, click on Set. Set All makes this tile the undercombo for all screens on this map. Undercombos should be set on every screen that has movable objects on it--armos, blocks, etc. Under combo stores both the combo and the CSet. + +Secret Combos: +Brings up the Secret Combo dialog box. + - Burn: (4 squares) Flags #4, #73, #74, and #75, in that order. + - Arrow: (3) Flags #5, #71, and #72 + - Bomb: (2) Flags #6, and #11 + - Stair: For the Stair Icon in the lower dialog box. + - Boomerang: (3) Flags #68, #69, and #70 + - Magic: (2) Flags #76 and #77 + - Sword: (4) Flags #79, #80, #81, and #82 + - Sword Beam: (4) Flags #83, #84, #85, and #86 + - Misc.: (5) Flags #78 (reflected fireball), #87 (hookshot), #88 (wand), #89 (hammer), and #90 (strike). + - Secret Combos 16-31: These combos appear when other flags are triggered. +To set a secret combo, click on the proper square to bring up the Combo Table, then click on the tile you want for the secret combo and press Enter. + +Layers: +Used for layering. While on the base screen, click on Layers and enter the map and screen number where you put the tiles for each layer. Layers 1 and 2 appear under Link, 3 and 4 are over Link but below flying enemies, 5 and 6 are above flyers. To prepare a screen for any layer except 0, first fill it with the walkable transparent (black) tile so that the layers below will show through. +Note: Anything in layer 0 with a push flag on it appears on top of layers 1 and 2. Link is walking on layers 1 and 2, so he can't very well push something below those layers. This allows you to push a pushblock over different combos without changing them all to the same thing (it is actually still doing this, but set up the real floor on layer 1, then the block won't be erasing it, just layer 0, which is covered up by layer 1). +Trans. makes that layer translucent (see-through). +Click the button with the asterisk (*) on it for a particular layer to enter the auto layer setup mode. A new screen will popup. asking you to enter a map number. Basically, every screen on that map will be set up as the selected layer screen for every screen on the current map that doesn't already have a layer map set. + +Palette: This allows you to change a particular screen to any palette in ZQuest. It does not affect the screen in ZC: when playing the quest that screen will still use the palette assigned on the dmap. + ++----------------------------+ +| 9. ETC. MENU | ++----------------------------+ + + - Help +Brings up this zquest.txt help file. + + - About +Brings up a dialog with the ZQuest version number, and credits for the Travels of Link MIDI. + + - Video Mode +In some ports of ZQuest, this can be used to adjust the video mode. + + - Fullscreen +This toggles the fullscreen and windowed view for ZQuest. + + - Options +Brings up the ZQuest preferences pane. Page 1 has these options: + -- Mouse scroll: Allows you to use the mouse to scroll through the combo selector. + -- Save paths: Makes ZQuest remember what directory you were in when you loaded a quest, saved it, grabbed tiles, imported/exported stuff, etc. + -- Palette cycle: Allows you to see palette cycling effects in ZQuest. + -- Vsync: Makes it so that it waits for the monitor to stop drawing before doing graphics work. This can help eliminate flicker. + -- Show Frames Per Second: Tells you how many frames there are per second. + -- Combo Brush: Makes the cursor resemble the current combo being used. + -- Floating Brush: In combination with the combo brush, makes the cursor cast a shadow. + -- Reload Last Quest: With this box checked ZQuest will automatically open the last quest you worked on when you start it. + -- Show Misaligns: This option is only useful in Small Mode. It helps you avoid having a walkable combo on one screen lead into an unwalkable combo on the next screen. + -- Animate Combos: Have this option checked if you want animated combos to be animated in ZQuest. Unchecked, the combos won't appear animated and there will be less cursor flickering. + -- Overwrite Protection: If checked, you won't be able to overwrite existing files when saving in ZQuest. + -- Tile Protection: Enables the aforementioned Tile Protection feature. + -- Use Static For Invalid Data: Draws black and white 'static' in places where no graphics have been defined (such as the tile list). Otherwise, a white X is used. + -- Show Ruleset Dialog When Creating New Quests: If checked, the ruleset dialog is displayed when you create a new quest. + -- Enable Tooltips: Enables tooltips to appear when your cursor hovers over a combo on the screen, or in the combo selector. +Page 2 has these options: + -- Auto-backup Retention: Determines how many permanent backup files should be kept per quest file. Permanent backups have a .qb suffix. + -- Auto-save Interval: Determines how frequently ZQuest saves an auto-save backup of your quest. Auto-save backups have a .qt suffix + -- Auto-save Retention: Determines how many auto-save backups to keep. + -- Uncompressed Auto-Saves: If this is checked, auto-saves are uncompressed, which can save time during the auto-save process. + -- Grid Color: Color of the combo grid that can be toggled in the View menu. + -- Snapshot Format: Image format for ZQuest snapshots. + -- Keyboard Repeat Delay: Delay before a held keyboard key repeats. + -- Keyboard Repeat Rate: Rate at which held keyboard keys repeat. + + - View Pic +With this, you can load and view a graphic from inside ZQ. This feature was useful in the original MS-DOS version of ZQuest, but is now largely irrelevant. + + - The Travels of Link +Plays a rousing piano medley MIDI while you work in ZQuest. Use the menu to choose a particular section of the medley. + + - Play music +Allows you to choose and play any readable music file on your file system through ZQuest. This feature was useful during the DOS incarnation of ZQuest, but is now largely irrelevant. + + - Change track +If you loaded a multi-track format (NSF, GBS, GYM) you can change tracks with this. + + - Stop Tunes +Turns off all music currently being played in ZQuest. + + - Take Snapshot +Takes a screenshot of the ZQuest interface. This feature is primarily designed for bug reporting purposes. + +--- finis. --- diff --git a/output/common/zscript.txt b/output/common/zscript.txt new file mode 100644 index 0000000000..5034d5b6ba --- /dev/null +++ b/output/common/zscript.txt @@ -0,0 +1,2602 @@ + +//================================================ +//--- ZScript built-in functions and variables --- +//================================================ +// +// Functions and variables other than global functions are properties +// of objects. The syntax for using them is [object name]->[property] +// where "[object name]" is the object's name and "[property]" is the +// property. "Link", "Screen" and "Game" are Link, Screen and Game +// objects that are always available and don't need to be instantiated. +// +// In the following, "int" indicates that a parameter is truncated +// by a function to an integer, or that the return value will always +// be an integer. ZScript itself makes no distinction between int and +// float. + + + +//======================== +//--- Global Functions --- +//======================== + +/** +* Computes and returns a random integer between 0 and maxvalue, +* or a negative value between maxvalue and 0 if maxvalue is negative. +*/ +int Rand(int maxvalue); + +/** +* Terminates execution of the current script. Does not return. +*/ +void Quit(); + +/** +* Temporarily halts execution of the current script. This function returns at +* the beginning of the next frame of gameplay. +* Slots 1, 3 and 4 Global scripts and item scripts only execute for one frame, +* so in those scripts Waitframe() is essentially Quit(). +* It is safe to call Waitframe in the active global script. +*/ +void Waitframe(); + +/** +* Halts execution of the script until ZC's internal code has been run (movement, +* collision detection, etc.), but before the screen is drawn. This can only +* be used in the active global script. +*/ +void Waitdraw(); + +/** +* Prints a line containing a string representation of val to allegro.log. +* Useful for debugging scripts. +*/ +void Trace(float val); + +/** +* Prints a boolean state to allegro.log +*/ +void TraceB(bool state); + +/** +* Takes the array pointer as its argument, and prints it as a string to allegro.log +* Maximum 512 characters. Functions from string.zh can be used to split larger strings. +*/ +void TraceS(int s[]); + +/** +* Prints a line in allegro.log representing 'val' in numerical base 'base', +* where 2 <= base <= 36, with minimum digits 'mindigits'. +* Can be useful for checking hex values or flags ORed together, or just to trace +* an integer value, as Trace() always traces to four decimal places. +*/ +void TraceToBase(int val, int base, int mindigits); + +/** +* Traces a newline to allegro.log +*/ +void TraceNL(); + +/** +* Clears allegro.log of all current traces and messages from Zelda Classic/ZQuest. +*/ +void ClearTrace(); + +/** +* Returns the trigonometric sine of the parameter, which is interpreted +* as a degree value. +*/ +float Sin(float deg); + +/** +* Returns the trigonometric cosine of the parameter, which is +* interpreted as a degree value. +*/ +float Cos(float deg); + +/** +* Returns the trigonometric tangent of the parameter, which is +* interpreted as a degree value. The return value is undefined if +* deg is of the form 90 + 180n for an integral value of n. +*/ +float Tan(float deg); + +/** +* Returns the trigonometric sine of the parameter, which is interpreted +* as a radian value. +*/ +float RadianSin(float rad); + +/** +* Returns the trigonometric cosine of the parameter, which is +* interpreted as a radian value. +*/ +float RadianCos(float rad); + +/** +* Returns the trigonometric tangent of the parameter, which is +* interpreted as a radian value. The return value is undefined for +* values of rad near (pi/2) + n*pi, for n an integer. +*/ +float RadianTan(float rad); + +/** +* Returns the trigonometric arctangent of the coordinates, which is +* interpreted as a radian value. +*/ +float ArcTan(int x, int y); + +/** +* Returns the trigonometric arcsine of x, which is +* interpreted as a radian value. +*/ +float ArcSin(float x); + +/** +* Returns the trigonometric arccosine of x, which is +* interpreted as a radian value. +*/ +float ArcCos(float x); + +/** +* Returns the greater of a and b. +*/ +float Max(float a, float b); + +/** +* Returns the lesser of a and b. +*/ +float Min(float a, float b); + +/** +* Returns base^exp. The return value is undefined for base=exp=0. Note +* also negative values of exp may not be useful, as the return value is +* truncated to the nearest integer. +*/ +int Pow(int base, int exp); + +/** +* Returns base^(1/exp). The return value is undefined for exp=0, or +* if exp is even and base is negative. Note also that negative values +* of exp may not be useful, as the return value is truncated to the +* nearest integer. +*/ +int InvPow(int base, int exp); + +/** +* Returns the log of val to the base 10. Any value <= 0 will return 0. +*/ +float Log10(float val); + +/** +* Returns the natural logarithm of val (to the base e). Any value <= 0 will return 0. +*/ +float Ln(float val); + +/** +* Returns val!. val < 0 returns 0. +*/ +int Factorial(int val); + +/** +* Return the absolute value of the parameter, if possible. If the +* absolute value would overflow the parameter, the return value is +* undefined. +*/ +float Abs(float val); + +/** +* Computes the square root of the parameter. The return value is +* undefined for val < 0. +*/ +float Sqrt(float val); + +/** +* Copies the tile specified by scrtile onto the tile space +* specified by desttile. +*/ +void CopyTile(int srctile, int desttile); + +/** +* Swaps the two tiles specified by firsttile and secondtile. +*/ +void SwapTile(int firsttile, int secondtile); + +/** +* Erases the tile specified by tileref. +*/ +void ClearTile(int tileref); + +/** +* Returns the size of the array pointed by 'array' +*/ +int SizeOfArray(int array[]); + + +//=================================== +//--- FFC Functions and Variables --- +//=================================== + +class ffc +{ + /** + * The number of the combo associated with this FFC. + */ + int Data; + + /** + * The number of the script assigned to the FFC. This will be automatically + * set to 0 when the FFC's script halts. A script cannot change the script of + * the FFC running it; in other words, f->Script is read-only when f==this. + * When an FFC's script is changed, its arguments, Misc[], and registers will + * all be set to 0, and it will start running from the beginning. Set + * ffc->InitD[] after setting the script before the script starts running + * to pass arguments to it. + */ + int Script; + + /** + * The cset of the FFC. + */ + int CSet; + + /** + * The FFC's animation delay, in frames. + */ + int Delay; + + /** + * The FFC's X position on the screen. + */ + float X; + + /** + * The FFC's Y position on the screen. + */ + float Y; + + /** + * The FFC's velocity's X-component. + */ + float Vx; + + /** + * The FFC's velocity's Y-component. + */ + float Vy; + + /** + * The FFC's acceleration's X-component. + */ + float Ax; + + /** + * The FFC's acceleration's Y-component. + */ + float Ay; + + /** + * The FFC's set of flags. Use the FFCF_ constants in std.zh as the + * index to access a particular flag. + */ + bool Flags[]; + + /** + * The number of tile columns composing the FFC. + */ + int TileWidth; + + /** + * The number of tile rows composing the FFC. + */ + int TileHeight; + + /** + * The width of the area of effect of the combo associated with the FFC, + * in pixels. + */ + int EffectWidth; + + /** + * The height of the area of effect of the combo associated with the FFC, + * in pixels. + */ + int EffectHeight; + + /** + * The number of the FFC linked to by this FFC. + */ + int Link; + + /** + * The original values of the FFC's 8 D input values as they are stored in + * the .qst file, regardless of whether they have been modified by ZScript. + */ + float InitD[]; + + /** + * An array of 16 miscellaneous variables for you to use as you please. + * These variables are not saved with the ffc. + */ + float Misc[]; + +}; //ffc + + +//==================================== +//--- Link Functions and Variables --- +//==================================== + +namespace Link +{ + /** + * Link's X position on the screen, in pixels. Float values passed to this will be cast to int. + */ + int X; + + /** + * Link's Y position on the screen, in pixels. Float values passed to this will be cast to int. + */ + int Y; + + /** + * Link's Z position on the screen, in pixels. Float values passed to this will be cast to int. + */ + int Z; + + /** + * Whether Link is currently being draw to the screen. Set true to remove him from view. + */ + bool Invisible; + + /** + * If true, Link's collision detection with npcs and eweapons is currently turned off. + * This variable works on a different system to clocks and the level 4 cheat, so it will not + * necessarily return true if they are set. + */ + bool CollDetection; + + /** + * Link's upward velocity, in pixels. If negative, Link will fall. + * The downward acceleration of Gravity (in Init Data) modifies this value every frame. + */ + int Jump; + + /** + * The time, in frames, until Link regains use of his sword. -1 signifies + * a permanent loss of the sword. + */ + int SwordJinx; + + /** + * The time, in frames, until Link regains use of his items. -1 signifies + * a permanent loss of his items. + */ + int ItemJinx; + + /** + * The time, in frames, that Link will be 'drunk'. If positive, the player's + * controls are randomly interfered with, causing Link to move erratically. + * This value is decremented once per frame. As the value of Drunk approaches 0, + * the intensity of the effect decreases. + */ + int Drunk; + + /** + * The direction Link is facing. Use the DIR_ constants in std.zh to set + * or compare this variable. Note: even though Link can move diagonally if the + * quest allows it, his sprite doesn't ever use any of the diagonal directions, + * which are intended for enemies only. + */ + int Dir; + + /** + * The direction Link should bounce in when he is hit. This is mostly useful for + * simulating getting hit by setting Link->Action to LA_GOTHURTLAND. + */ + int HitDir; + + /** + * Link's current hitpoints, in 16ths of a heart. + */ + int HP; + + /** + * Link's current amount of magic, in 32nds of a magic block. + */ + int MP; + + /** + * Link's maximum hitpoints, in 16ths of a heart. + */ + int MaxHP; + + /** + * Link's maximum amount of magic, in 32nds of a magic block. + */ + int MaxMP; + + /** + * Link's current action. Use the LA_ constants in std.zh to set or + * compare this value. The effect of writing to this field is currently + * undefined. + */ + int Action; + + /** + * The item that Link is currently holding up; reading or setting this + * field is undefined if Link's action is not current a hold action. + * Use the I_ constants in std.zh to specify the item, or -1 to show + * no item. Setting HeldItem to values other than -1 or a valid item + * ID is undefined. + */ + int HeldItem; + + /** + * The X position of Link's stepladder, or 0 if no ladder is onscreen. + * This is read-only; while setting it is not syntactically incorrect, + * it does nothing. + */ + int LadderX; + + /** + * The Y position of Link's stepladder, or 0 if no ladder is onscreen. + * This is read-only; while setting it is not syntactically incorrect, + * it does nothing. + int LadderY; + + *** Input Variables *** + /* + * The following Input* boolean values return true if the player is pressing + * the corresponding button, analog stick, or key. Writing to this variable + * simulating the press or release of that button, analog stick, or key. + */ + bool InputStart; + bool InputMap; + bool InputUp; + bool InputDown; + bool InputLeft; + bool InputRight; + bool InputA; + bool InputB; + bool InputL; + bool InputR; + bool InputEx1 + bool InputEx2 + bool InputEx3 + bool InputEx4 + bool InputAxisUp; + bool InputAxisDown; + bool InputAxisLeft; + bool InputAxisRight; + + *** Press Variables *** + /* + * The following Press* boolean values return true if the player pressed + * the corresponding button, analog stick, or key this frame. Writing to this + * variable simulates the press or release of that button, analog stick, + * or keys input press state. + */ + bool PressStart; + bool PressMap; + bool PressUp; + bool PressDown; + bool PressLeft; + bool PressRight; + bool PressA; + bool PressB; + bool PressL; + bool PressR; + bool PressEx1 + bool PressEx2 + bool PressEx3 + bool PressEx4 + bool PressAxisUp; + bool PressAxisDown; + bool PressAxisLeft; + bool PressAxisRight; + + /** + * The mouse's in-game X position. This value is undefined if + * the mouse pointer is outside the Zelda Classic window. + */ + int InputMouseX; + + /** + * The mouse's in-game Y position. This value is undefined if + * the mouse pointer is outside the Zelda Classic window. + */ + int InputMouseY; + + /** + * Whether the left or right mouse buttons are pressed as two flags + * OR'd (|) together; use the MB_ constants or the InputLeftClick() and + * InputRightClick() functions in std.zh to check the button states. + * InputMouseB is read only; while setting it is not syntactically incorrect, + * it does nothing. + */ + int InputMouseB; + + /** + * The current state of the mouse's scroll wheel. The value is negative when + * scrolling down and positive when scrolling up. + */ + int InputMouseZ; + + /** + * True if Link's inventory contains the item whose ID is the index of + * the array access. Use the I_ constants in std.zh as an index into this array. + */ + bool Item[]; + + /** + * Contains the item IDs of what is currently equiped to Link's A and B buttons. + * The first 8 bits contain the A button item, and the second 8 bits contain the B button item. + * Currently it is only possible to retrieve this value and not to set it. + * If you are not comfortable with performing binary operations, + * you can use the GetLinkEquipment'X' functions from std.zh. + */ + int Equipment; + + /** + * The current tile associated with Link. The effect of writing to this variable is undefined. + * Because Link's tile is not determined until he is drawn, this will actually represent + * Link's tile in the previous frame. + */ + int Tile; + + /** + * The current tile associated with Link. The effect of writing to this variable is undefined. + * Because Link's tile is not determined until he is drawn, this will actually represent + * Link's tile flip in the previous frame. + */ + int Flip; + + /** + * The Z-axis height of Link's hitbox, or collision rectangle. + * The lower it is, the lower a flying or jumping enemy must fly in order to hit Link. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int HitZHeight; + + /** + * The X offset of Link's hitbox, or collision rectangle. + * Setting it to positive or negative values will move Link's hitbox left or right. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int HitXOffset; + + /** + * The Y offset of Link's hitbox, or collision rectangle. + * Setting it to positive or negative values will move Link's hitbox up or down. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int HitYOffset; + + /** + * The X offset of Link's sprite. + * Setting it to positive or negative values will move the sprite's tiles left or right relative to its position. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int DrawXOffset; + + /** + * The Y offset of Link's sprite. + * Setting it to positive or negative values will move the sprite's tiles up or down relative to its position. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int DrawYOffset; + + /** + * The Z offset of Link's sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int DrawZOffset; + + /** + * An array of 16 miscellaneous variables for you to use as you please. + * These variables are not saved with Link. + */ + float Misc[]; + + /** + * Warps link to the given screen in the given DMap, just like if he'd + * triggered an 'Insta-Warp'-type warp. + */ + void Warp(int DMap, int screen); + + /** + * This is identical to Warp, but Link's X and Y positions are preserved + * when he enters the destination screen, rather than being set to the + * Warp Return square. + */ + void PitWarp(int DMap, int screen); + + /** + * Sets the A button item to the next one in the given direction based on + * the indices set in the subscreen. This will skip over items if A and B + * would be set to the same item. + * If the quest rule "Can Select A-Button Weapon On Subscreen" is disabled, + * this function does nothing. + */ + SelectAWeapon(int dir); + + /** + * Sets the B button item to the next one in the given direction based on + * the indices set in the subscreen. This will skip over items if A and B + * would be set to the same item. + */ + SelectBWeapon(int dir); + +}; //Link + +//====================================== +//--- Screen Functions and Variables --- +//====================================== + +namespace Screen +{ + /** + * Each screen has 8 general purpose registers for use by script + * programmers. These values are recorded in the save file when the + * player saves their game. Do with these as you will. + * Note that these registers are tied to screen/DMap combinations. + * Encountering the same screen in a different DMap will result in a + * different D[] array. + */ + float D[]; + + /** + * An array of ten integers containing the states of the flags in the + * 10 categories on the Screen Data tabs 1 and 2. Each flag is ORed into the + * Flags[x] value, starting with the top flag as the smallest bit. + * Use the SF_ constants as the array acces for this value, and the + * GetScreenFlags function if you are not comfortable with binary. + * This is read-only; while setting it is not syntactically incorrect, it does nothing. + */ + int Flags[]; + + /** + * An array of 3 integers containing the states of the flags in the + * E.Flags tab of the Screen Data dialog. Each flag is ORed into the + * EFlags[x] value, starting with the top flag as the smallest bit. + * Use the SEF_ constants as the array acces for this value, and the + * GetScreenEFlags function if you are not comfortable with binary. + * This is read-only; while setting it is not syntactically incorrect, it does nothing. + */ + int EFlags[]; + + /** + * The combo ID of the ith combo on the screen, where i is the index + * used to access this array. Combos are counted left to right, top to + * bottom. + */ + int ComboD[]; + + /** + * The CSet of the tile used by the ith combo on the screen, where i is + * the index used to access this array. Combos are counted left to right, + * top to bottom. + */ + int ComboC[]; + + /** + * The placed flag of the ith combo on the screen, where i is the index + * used to access this array. Combos are counted left to right, top to + * bottom. Use the CF_ constants in std.zh to set or compare these values. + */ + int ComboF[]; + + /** + * The inherent flag of the ith combo on the screen, where i is the index + * used to access this array. Combos are counted left to right, top to + * bottom. Use the CF_ constants in std.zh to set or compare these values. + */ + int ComboI[]; + + /** + * The combo type of the ith combo on the screen, where i is the index + * used to access this array. Combos are counted left to right, top to + * bottom. Use the CT_ constants in std.zh to set or compare these values. + */ + int ComboT[]; + + /** + * The walkability mask of the ith combo on the screen, where i is the + * index used to access this array. Combos are counted left to right, top + * to bottom. The least signficant bit is true if the top-left of the combo + * is solid, the second-least signficant bit is true if the bottom-left + * of the combo is is solid, the third-least significant bit is true if the + * top-right of the combo is solid, and the fourth-least significant bit is + * true if the bottom-right of the combo is solid. + */ + int ComboS[]; + + /** + * The X position of the current moving block. If there is no moving block + * on the screen, it will be -1. This is read-only; while setting it is not + * syntactically incorrect, it does nothing. + */ + int MovingBlockX; + + /** + * The Y position of the current moving block. If there is no moving block + * on the screen, it will be -1. This is read-only; while setting it is not + * syntactically incorrect, it does nothing. + */ + int MovingBlockY; + + /** + * The combo used by moving block. If there is no block moving, the value + * is undefined. + */ + int MovingBlockCombo; + + /** + * The CSet used by moving block. If there is no block moving, the value + * is undefined. + */ + int MovingBlockCSet; + + /** + * The current screen's under combo. + */ + int UnderCombo; + + /** + * The current screen's under CSet. + */ + int UnderCSet; + + /** + * An array of miscellaneous status data associated with the current + * screen. + * Screen states involve such things as permanent screen secrets, the + * status of lock blocks and treasure chest combos, and whether items have + * been collected. + * These values are recorded in the save file when the player saves their + * game. Use the ST_ constants in std.zh as indices into this array. + */ + bool State[]; + + /** + * The door type for each of the four doors on a screen. Doors are counted + * using the first four DIR_ constants in std.zh. Use the D_ constants in + * std.zh to get or set these values. + */ + int Door[]; + + /** + * The type of room this screen is (Special Item, Bomb Upgrade, etc) + * This is currently read-only. + * Use the RT_* constants in std.zh + */ + int RoomType; + + /** + * This is the data associated with the room type above. What it means depends + on the room type. For Special Item, it will be the item ID, for a Shop, it + will be the Shop Number, etc. + * Basically, this is what's in the "Catch-all" menu item underneath Room Type. + * If the room type has no data (eg, Ganon's room), this will be undefined. + */ + int RoomData; + + /** + * Triggers screen secrets temporarily. Set Screen->State[ST_SECRET] + * to true beforehand or afterward if you would like them to remain + * permanent. + */ + void TriggerSecrets(); + + /** + * Whether or not the screen is lit. Setting this variable will change the + * lighting setting of the screen until you change screens. + */ + bool Lit; + + /** + * The time, in frames, that the 'wave' screen effect will be in effect. + * This value is decremented once per frame. As the value of Wavy approaches 0, + * the intensity of the waves decreases. + */ + int Wavy; + + /** + * The time, in frames, that the screen will shake. This value is decremented + * once per frame. As the value of Quake approaches 0, the intensity of the + * screen shaking decreases. + */ + int Quake; + + /** + * Sets the current screen's side warp 'warp' to the destination screen, + * DMap and type. If any of the parameters screen, dmap or type are equal + * to -1, they will remain unchanged. If warp is not between 0 and 3, the + * function does nothing. + */ + void SetSideWarp(int warp, int screen, int dmap, int type); + + /** + * Sets the current screen's tile warp 'warp' to the destination screen, + * DMap and type. If any of the parameters screen, dmap or type are equal + * to -1, they will remain unchanged. If warp is not between 0 and 3, the + * function does nothing. + */ + void SetTileWarp(int warp, int screen, int dmap, int type); + + /** + * Returns the destination DMap of the given side warp on the current screen. + * Returns -1 if warp is not between 0 and 3. + */ + void GetSideWarpDMap(int warp); + + /** + * Returns the destination screen of the given side warp on the current + * screen. Returns -1 if warp is not between 0 and 3. + */ + void GetSideWarpScreen(int warp); + + /** + * Returns the warp type of the given side warp on the current screen. + * Returns -1 if warp is not between 0 and 3. + */ + void GetSideWarpType(int warp); + + /** + * Returns the destination DMap of the given tile warp on the current screen. + * Returns -1 if warp is not between 0 and 3. + */ + void GetTileWarpDMap(int warp); + + /** + * Returns the destination screen of the given tile warp on the current + * screen. Returns -1 if warp is not between 0 and 3. + */ + void GetTileWarpScreen(int warp); + + /** + * Returns the warp type of the given tile warp on the current screen. + * Returns -1 if warp is not between 0 and 3. + */ + void GetTileWarpType(int warp); + + /** + * Returns the map of the screen currently being used as the nth layer. + * Values of n less than 1 or greater than 6, or layers that are not set up, + * returns -1. + */ + int LayerMap(int n); + + /** + * Returns the number of the screen currently being used as the nth layer. + * Values of n less than 1 or greater than 6, or layers that are not set up, + * returns -1. + */ + int LayerScreen(int n); + + /** + * Returns the number of items currently present on the screen. Screen + * items, shop items, and items dropped by enemies are counted; Link's + * weapons, such as lit bombs, or enemy weapons are not counted. + * Note that this value is only correct up until the next call to + * Waitframe(). + */ + int NumItems(); + + /** + * Returns a pointer to the numth item on the current screen. The return + * value is undefined unless 1 <= num <= NumItems(). + */ + item LoadItem(int num); + + /** + * Creates an item of the given type at (0,0). Use the I_ constants in + * std.zh to pass into this method. The return value is a pointer to the + * new item. + */ + item CreateItem(int id); + + /** + * Returns a pointer to the numth FFC on the current screen. The return + * value is undefined unless 1 <= num <= ffcs, where ffcs is the number + * of FFCs active on the screen. + */ + ffc LoadFFC(int num); + + /** + * Returns the number of NPCs (enemies and guys) on the screen. + * Note that this value is only correct up until the next call to + * Waitframe(). + */ + int NumNPCs(); + + /** + * Returns a pointer to the numth NPC on the current screen. The return + * value is undefined unless 1 <= num <= NumNPCs(). + */ + npc LoadNPC(int num); + + /** + * Creates an npc of the given type at (0,0). Use the NPC_ constants in + * std.zh to pass into this method. The return value is a pointer to the + * new NPC. + */ + npc CreateNPC(int id); + + /** + * Returns the number of Link weapon projectiles currently present on the screen. + * This includes things like Link's arrows, bombs, magic, etc. Note that this + * value is only correct up until the next call of Waitframe() + */ + int NumLWeapons(); + + /** + * Returns a pointer to the numth lweapon on the current screen. The return + * value is undefined unless 1 <= num <= NumLWeapons(). + */ + lweapon LoadLWeapon(int num); + + /** + * Creates an lweapon of the given type at (0,0). Use the LW_ constants in + * std.zh to pass into this method. The return value is a pointer to the + * new lweapon. + */ + lweapon CreateLWeapon(int type); + + /** + * Returns the number of Enemy weapon projectiles currently present on the screen. + * This includes things like Enemy arrows, bombs, magic, etc. Note that this + * value is only correct up until the next call of Waitframe() + */ + int NumEWeapons(); + + /** + * Returns a pointer to the numth eweapon on the current screen. The return + * value is undefined unless 1 <= num <= NumEWeapons(). + */ + eweapon LoadEWeapon(int num); + + /** + * Creates an eweapon of the given type at (0,0). Use the EW_ constants in + * std.zh to pass into this method. The return value is a pointer to the + * new lweapon. + */ + eweapon CreateEWeapon(int type); + + /** + * Returns true if the screen position (x, y) is solid - that is, if it + * is within the solid portion of a combo on layers 0, 1 or 2. If either + * x or y exceed the screen's bounds, then it will return false. + * It will also return false if the only applicable solid combo is a solid + * water combo that has recently been 'dried' by the whistle. + */ + bool isSolid(int x, int y); + + /** + * Clears all of a certain kind of sprite from the screen. Use the SL_ + * constants in std.zh to pass into this method. + */ + void ClearSprites(int spritelist); + + /* + * Please note: For all draw primitives, if the quest rule 'Subscreen Appears + * Above Sprites' is set,passing the layer argument as 7 will allow drawing + * on top of the subscreen + */ + + /** + * Draws a rectangle on the specified layer of the current screen, using + * (x,y) as the top-left corner and (x2,y2) as the bottom-right corner. + * Then scales the rectangle uniformly about its center by the given + * factor. + * Lastly, a rotation, centered about the point (rx, ry), is performed + * counterclockwise using an angle of rangle degrees. + * A filled rectangle is drawn if fill is true; otherwise, this method + * draws a wireframe. + * The rectangle is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the rectangle will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Rectangle(int layer, int x, int y, int x2, int y2, int color, float scale, int rx, int ry, int rangle, bool fill, int opacity); + + /** + * Draws a circle on the specified layer of the current screen with + * center (x,y) and radius scale*radius. + * Then performs a rotation counterclockwise, centered about the point + * (rx, ry), using an angle of rangle degrees. + * A filled circle is drawn if fill is true; otherwise, this method + * draws a wireframe. + * The circle is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the circle will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Circle(int layer, int x, int y, int radius, int color, float scale, int rx, int ry, int rangle, bool fill, int opacity); + + /** + * Draws an arc of a circle on the specified layer of the current + * screen. The circle in question has center (x,y) and radius + * scale*radius. + * The arc beings at startangle degrees counterclockwise from standard + * position, and ends at endangle degress counterclockwise from standard + * position. The behavior of this function is undefined unless + * 0 <= endangle-startangle < 360. + * The arc is then rotated about the point (rx, ry) using an angle of + * rangle radians. + * If closed is true, a line is drawn from the center of the circle to + * each endpoint of the arc, forming a sector of the circle. If fill + * is also true, a filled sector is drawn instead. + * The arc or sector is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the arc will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Arc(int layer, int x, int y, int radius, int startangle, int endangle, int color, float scale, int rx, int ry, int rangle, bool closed, bool fill, int opacity); + + /** + * Draws an ellipse on the specified layer of the current screen with + * center (x,y), x-axis radius xradius, and y-axis radius yradius. + * Then performs a rotation counterclockwise, centered about the point + * (rx, ry), using an angle of rangle degrees. + * A filled ellipse is drawn if fill is true; otherwise, this method + * draws a wireframe. + * The ellipse is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the ellipse will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Ellipse(int layer, int x, int y, int xradius, int yradius, int color, float scale, int rx, int ry, int rangle, bool fill, int opacity); + + /** + * Draws a cardinal spline on the specified layer of the current screen + * between (x1,y1) and (x4,y4) + * The spline is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the ellipse will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Spline(int layer, int x1, int y1, int x2, int y2, int x3, int y3,int x4, int y4, int color, int opacity); + + /** + * Draws a line on the specified layer of the current screen between + * (x,y) and (x2,y2). + * Then scales the line uniformly by a factor of scale about the line's + * midpoint. + * Finally, performs a rotation counterclockwise, centered about the + + * point (rx, ry), using an angle of rangle degrees. + * The line is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the line will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void Line(int layer, int x, int y, int x2, int y2, int color, float scale, int rx, int ry, int rangle, int opacity); + + /** + * Draws a raw pixel on the specified layer of the current screen + * at (x,y). + * Then performs a rotation counterclockwise, centered about the point + * (rx, ry), using an angle of rangle degrees. + * The point is drawn using the specified index into the entire + * 256-element palette: for instance, passing in a color of 17 would + * use color 1 of cset 1. + * Opacity controls how transparent the point will be. Values other + * than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void PutPixel(int layer, int x, int y, int color, int rx, int ry, int rangle, int opacity); + + /** + * Draws a block of tiles on the specified layer of the current screen, + * starting at (x,y), using the specified cset. + * Starting with the specified tile, this method copies a block of size + * blockh x blockw from the tile sheet to the screen. This method's + * behavior is undefined unless 1 <= blockh, blockw <= 20. + * Scale specifies the actual size in pixels! So scale 1 would mean it is + * only one pixel in size. To use the default sizes of block w,h you must + * set xscale and yscale to -1. These values are not independant of one another, + * so you cannot set xscale and leave yscale at -1. + * rx, ry : these work now, just like the other primitives. + * rangle performs a rotation clockwise using an angle of rangle degrees. + * Flip specifies how the tiles should be flipped when drawn: + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + * If transparency is true, the tiles' transparent regions will be + * respected. + * Opacity controls how transparent the solid portions of the tiles will + * be. Values other than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void DrawTile(int layer, int x, int y, int tile, int blockw, int blockh, int cset, int xscale, int yscale, int rx, int ry, int rangle, int flip, bool transparency, int opacity); + + /** + * Optimized and simpler version of DrawTile() + * Draws a single tile on the current screen much in the same way as DrawTile(). + * See DrawTile() for an explanation on what these arguments do. + */ + void FastTile( int layer, int x, int y, int tile, int cset, int opacity ); + + /** + * Draws a combo on the specified layer of the current screen, + * starting at (x,y), using the specified cset. + * Starting with the specified tile referenced by the combo, + * this method copies a block of size + * blockh x blockw from the tile sheet to the screen. This method's + * behavior is undefined unless 1 <= blockh, blockw <= 20. + * Scale specifies the actual size in pixels! So scale 1 would mean it is + * only one pixel in size. To use the default sizes of block w,h you must + * set xscale and yscale to -1. These values are not independant of one another, + * so you cannot set xscale and leave yscale at -1. + * rx, ry : works now : + * rangle performs a rotation clockwise using an angle of rangle degrees. + * Flip specifies how the tiles should be flipped when drawn: + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + * If transparency is true, the tiles' transparent regions will be + * respected. + * Opacity controls how transparent the solid portions of the tiles will + * be. Values other than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void DrawCombo(int layer, int x, int y, int combo, int w, int h, int cset, int xscale, int yscale, int rx, int ry, int rangle, int frame, int flip, bool transparency, int opacity); + + /** + * Optimized and simpler version of DrawCombo() + * Draws a single combo on the current screen much in the same way as DrawCombo(). + * See DrawCombo() for an explanation on what these arguments do. + */ + void FastCombo( int layer, int x, int y, int combo, int cset, int opacity ); + + /** + * Prints the message string with given ID onto the screen. + * If string is 0, the currently displayed message is removed. + * This method's behavior is undefined if string is less than 0 + * or greater than the total number of messages in the quest. + */ + void Message(int string); + + /** + * Draws a single ASCII character 'glyph' on the specified layer of the current screen, + * using the specified font index (see std.zh for FONT_* list to pass to this method), + * starting at (x,y), using the specified color as the foreground color + * and background_color as the background color. * NOTE * Use -1 for a transparent background. + * The arguments width and height may be used to draw the glyph + * of any arbitrary size begining at 1 pixel up to 512 pixels large. (more than four times the size of the screen) + * Passing 0 or negative values to this will use the default fonts w and h. + * Opacity controls how transparent the is. + * Values other than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void DrawCharacter(int layer, int x, int y, int font,int color, int background_color,int width, int height, int glyph, int opacity ); + + /** + * Draws a zscript 'int' or 'float' on the specified layer of the current screen, + * using the specified font index (see std.zh for FONT_* list to pass to this method), + * starting at (x,y), using the specified color as the foreground color + * and background_color as the background color. * NOTE * Use -1 for a transparent background. + * The arguments width and height may be used to draw the number + * of any arbitrary size begining at 1 pixel up to 512 pixels large. + * Passing 0 or negative values to this will use the default fonts w and h. + * The number can be rendered as type 'int' or 'float' by setting the argument + * "number_decimal_places", which is only valid if set to 0 or <= 4. + * Opacity controls how transparent the is. + * Values other than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void DrawInteger(int layer, int x, int y, int font,int color, int background_color,int width, int height, int number, int number_decimal_places, int opacity); + + /** + * Prints a NULL terminated string up to 256 characters from an int array + * containing ASCII data (*ptr) on the specified layer of the current screen, + * using the specified font index (see std.zh for FONT_* list to pass to this method), + * using the specified color as the foreground color + * and background_color as the background color. * NOTE * Use -1 for a transparent background. + * The array pointer should be passed as the argument for '*ptr', ie. + * int string[] = "Example String"; Screen->DrawString(l,x,y,f,c,b_c,fo,o,string); + * int format tells the engine how to format the string. (see std.zh for TF_* list to pass to this method) + * Opacity controls how transparent the message is. + * Values other than OP_OPAQUE and OP_TRANS are currently undefined. + */ + void DrawString( int layer, int x, int y, int font,int color, int background_color,int format, int ptr[], int opacity ); + + // (Psuedo) 3D drawing + + /** + * Draws a quad on the specified layer with the corners x1,y1 through x4,y4. + * Corners are drawn in a counterclockwise order starting from x1,y1. ( So + * if you draw a "square" for example starting from the bottom-right corner + * instead of the usual top-left, the the image will be textured onto the + * quad so it appears upside-down. -yes, these are rotatable. ) + * From there a single or block of tiles or combos is then texture mapped + * onto the quad using the arguments w, h, cset, flip, and render_mode. + * A positive vale in texture will draw the image from the tilesheet pages, + * whereas a negative value will be drawn from the combo page. 0 will draw combo number 0. + * Both w and h are undefined unless 1 <= blockh, blockw <= 16, and it is a power of + * two. ie: 1, 2 are acceptable, but 2, 15 are not. + + * Flip specifies how the tiles/combos should be flipped when drawn: + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + *** See std.zh for a list of all available render_mode arguments. + */ + void Quad( int layer, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,int w, int h, int cset, int flip, int texture, int render_mode); + + /** + * Draws a triangle on the specified layer with the corners x1,y1 through x4,y4. + * Corners are drawn in a counterclockwise order starting from x1,y1. + * From there a single or block of tiles or combos is then texture mapped + * onto the triangle using the arguments w, h, cset, flip, and render_mode. + * A positive vale in texture will draw the image from the tilesheet pages, + * whereas a negative value will be drawn from the combo page. 0 will draw combo number 0. + * Both w and h are undefined unless 1 <= blockh, blockw <= 16, and it is a power of + * two. ie: 1, 2 are acceptable, but 2, 15 are not. + * Flip specifies how the tiles/combos should be flipped when drawn: + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + *** See std.zh for a list of all available render_mode arguments. + */ + void Triangle( int layer, int x1, int y1, int x2, int y2, int x3, int y3,int w, int h, int cset, int flip, int texture, int render_mode); + + /** + * Draws a Quad on the specified layer similar to Quad. + * [12]pos - x, y, z positions of the 4 corners. + * [8]uv - x, y texture coordinates of the given texture. + * [4]csets - of the corners to interpolate between. + * [2]size - w, h, of the texture. + *** See std.zh for a list of all available render_mode arguments. + */ + void Quad3D( int layer, int pos[], int uv[], int cset[], int size[], int flip, int texture, int render_mode ); + + /** + * Draws a triangle on the specified layer similar to Triangle. + * [9]pos - x, y, z positions of the 3 corners. + * [6]uv - x, y texture coordinates of the given texture. + * [3]csets - of the corners to interpolate between. + * [2]size - w, h, of the texture. + *** See std.zh for a list of all available render_mode arguments. + */ + void Triangle3D( int layer, int pos[], int uv[], int csets[], int size[], int flip, int texture, int render_mode ); + + // Bitmap Drawing + + /** + * Sets the target bitmap for all succesive drawing commands. + * These can be directly to the screen or any one of the available off-screen bitmaps, + * which are generally categorized as -1(screen) or 0-bitmapNumber(off-screen). + *** See std.zh for a complete list of valid render targets (RT_*). + */ + void SetRenderTarget( int bitmap_id ); + + /** + * Draws a source rect from off-screen Bitmap with id of bitmap_id onto + * an area of the screen described by dest rect at the given layer. + * *Example: + * Screen->Bitmap( 6, myBitmapId, 0, 0, 16, 16, 79, 57, 32, 32, 0, true ); + * //Would draw a 16x16 area starting at the upper-left corner of source bitmap to + * //layer 6 of the current screen at coordinates 79,57 with a width and height of 32. + ***Note* Script drawing functions are enqueued and executed in a frame-by-frame basis + based on the order of which layer they need to be drawn to. Drawing to or from + seperate render tagets or bitmaps is no exception! So keep in mind in order to + eliminate unwanted drawing orders or bugs. + */ + void DrawBitmap( int layer, int bitmap_id, int source_x, int source_y, int source_w, int source_h, int dest_x, int dest_y, int dest_w, int dest_h, float rotation, bool mask); + + // Screen/Layer Drawing + + /** + * Draws an entire Layer from source_screen on source_map on the specified layer of the current screen at (x,y). + * If rotation is not zero, it(the entire layer) will rotate about its center. + * Opacity controls how transparent the solid portions of the tiles will + * be. Values other than OP_OPAQUE and OP_TRANS are currently + * undefined. + */ + void DrawLayer(int layer, int source_map, int source_screen, int source_layer, int x, int y, float rotation, int opacity); + + /** + * Draws an entire screen from screen on map on the specified layer of the current screen at (x,y). + * If rotation is not zero, it(the entire screen) will rotate about its center. + */ + void DrawScreen(int layer, int map, int source_screen, int x, int y, float rotation); + +}; //Screen + + +//==================================== +//--- Item Functions and Variables --- +//==================================== + +class item +{ + /** + * Returns whether this item pointer is still valid. An item pointer + * becomes invalid when Link picks up the item, the item fades away, + * or Link leaves the screen. Accessing any variables using an + * invalid item pointer prints an error message to allegro.log and + * does nothing. + */ + bool isValid(); + + /** + * The item's X position on the screen, in pixels. Float values passed to this will be cast to int. + */ + int X; + + /** + * The item's Y position on the screen, in pixels. Float values passed to this will be cast to int. + */ + int Y; + + /** + * The item's upward velocity, in pixels. If negative, the item will fall. + * The downward acceleration of Gravity (in Init Data) modifies this value every frame. + */ + int Jump; + + /** + * An integer representing how the item is to be drawn. Use one of the + * DS_ constants in std.zh to set or compare this value. + */ + int DrawStyle; + + /** + * This item's ID number. Use the I_ constants to compare this value. The effect of writing to this field is currently undefined. + */ + int ID; + + /** + * The starting tile of the item's animation. + */ + int OriginalTile; + + /** + * The current tile associated with this item. + */ + int Tile; + + /** + * This item's CSet. + */ + int CSet; + + /** + * The CSet used during this item's flash frames, if this item flashes. + */ + int FlashCSet; + + /** + * The number of frames in this item's animation. + */ + int NumFrames; + + /** + * The tile that is this item's current animation frame. + */ + int Frame; + + /** + * The speed at which this item animates, in screen frames. + */ + int ASpeed; + + /** + * The amount of time the animation is suspended after the last frame, + * before the animation restarts, in item frames. That is, the total + * number of screen frames of extra wait is Delay*ASpeed. + */ + int Delay; + + /** + * Whether or not the item flashes. A flashing item alternates between + * its CSet and its FlashCSet. + */ + bool Flash; + + /** + * Whether and how the item's tiles should be flipped. + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + */ + int Flip; + + /** + * The pickup flags of the item, which determine what happens when Link + * picks up the item. Its value consists of flags OR'd (|) together; use + * the IP_ constants in std.zh to set or compare these values. + * A special note about IP_ENEMYCARRIED: if the Quest Rule "Hide Enemy- + * Carried Items" is set, then an item carried by an enemy will have its + * X and Y values set to -128 while the enemy is carrying it. If this + * flag is removed from such an item, then it will be moved to the enemy's + * on-screen location. + * If you are not comfortable with performing binary operations, use the ItemPickup functions from std.zh. + */ + int Pickup; + + /** + * Whether to extend the sprite of the item. + */ + int Extend; + + /** + * The number of tile columns composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileWidth; + + /** + * The number of tile rows composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileHeight; + + /** + * The width of the sprite's hitbox, or collision rectangle. + */ + int HitWidth; + + /** + * The height of the sprite's hitbox, or collision rectangle. + */ + int HitHeight; + + /** + * The Z-axis height of the sprite's hitbox, or collision rectangle. + * The greater it is, the higher Link must jump or fly over the sprite to avoid picking up the item. + */ + int HitZHeight; + + /** + * The X offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's hitbox left or right. + */ + int HitXOffset; + + /** + * The Y offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's hitbox up or down. + */ + int HitYOffset; + + /** + * The X offset of the sprite. + * Setting it to positive or negative values will move the sprite's tiles left or right relative to its position. + */ + int DrawXOffset; + + /** + * The Y offset of the sprite. + * Setting it to positive or negative values will move the sprite's tiles up or down relative to its position. + */ + int DrawYOffset; + + /** + * The Z offset of the sprite. + */ + int DrawZOffset; + + /** + * An array of 16 miscellaneous variables for you to use as you please. + * Note that lweapons and eweapons possess exactly the same attributes, + * although their designation affects how they are treated by the engine. + * The values here correspond to both the lweapon and eweapon type. + */ + float Misc[]; + +}; //item + + +//====================================== +//--- Weapon Functions and Variables --- +//====================================== + +class weapon +{ + /** + * Returns whether this weapon pointer is still valid. A weapon pointer + * becomes invalid when the weapon fades away or disappears + * or Link leaves the screen. Accessing any variables using an + * invalid weapon pointer prints an error message to allegro.log and + * does nothing. + */ + bool isValid(); + + /** + * Reads a 'Weapons/Misc' sprite entry in your quest file, and assigns + * the OriginalTile, Tile, OriginalCSet, CSet, FlashCSet, NumFrames, + * Frame, ASpeed, Flip and Flash variables of this weapon based on + * this entry's data. Passing negative values, and values greater than + * 255, will do nothing. + */ + void UseSprite(int id); + + /** + * Ensures that the weapon's graphic is drawn behind Link and enemies. + */ + bool Behind; + + /** + * The weapon's ID number. Use the LW_ or EW_ constants to compare + * this value. The effect of writing to this field is currently undefined. + */ + int ID; + + /** + * The weapon's X position on the screen, in pixels. Float values passed + * to this will be cast to int. + */ + int X; + + /** + * The weapon's Y position on the screen, in pixels. Float values passed + * to this will be cast to int. + */ + int Y; + + /** + * The weapon's Z position on the screen, in pixels. Float values passed + * to this will be cast to int. + */ + int Z; + + /** + * The weapon's falling speed on the screen. Bombs, Bait and + * Fire obey gravity. + */ + int Jump; + + /** + * An integer representing how the weapon is to be drawn. Use one of the + * DS_ constants in std.zh to set or compare this value. + */ + int DrawStyle; + + /** + * The direction that the weapon is facing. Used by certain weapon types + * to determine movement, shield deflection and such. + */ + int Dir; + + /** + * The starting tile of the weapon's animation. + */ + int OriginalTile; + + /** + * The current tile associated with this weapon. + */ + int Tile; + + /** + * The starting CSet of the weapon's animation. + */ + int OriginalCSet; + + /** + * This weapon's current CSet. + */ + int CSet; + + /** + * The CSet used during this weapon's flash frames, if this weapon flashes. + */ + int FlashCSet; + + /** + * The number of frames in this weapon's animation. + */ + int NumFrames; + + /** + * The weapon's current animation frame. + */ + int Frame; + + /** + * The speed at which this weapon animates, in screen frames. + */ + int ASpeed; + + /** + * The amount of damage that this weapon causes to Link/an enemy upon contact. + */ + int Damage; + + /** + * Usually associated with the weapon's velocity. A Step of 100 + * typically means that the weapon moves at approximately one pixel + * per animation frame. + */ + int Step; + + /** + * The weapon's current angle in clockwise radians; used by certain weapon + * types with angular movement. 0 = right, PI/2 = down, etc. Note: if you + * want Link's shield to interact with the weapon correctly, you must set + * its Dir to a direction that approximates this angle. + */ + int Angle; + + /** + * Specifies whether a weapon has angular movement. + */ + bool Angular; + + /** + * Whether the weapon will use the system's code to work out collisions with + * Link and/or enemies (depending on weapon type). Initialised as 'true'. + */ + bool CollDetection; + + /** + * The current state of the weapon. Important to keep track of. A value of + * -1 indicates that it is active, and moves according to the weapon's + * Dir, Step, Angular, and Angle values. Use -1 if you want the engine to + * handle movement and collision. Use any value below -1 if you want a + * dummy weapon that you can control on your own. + * Given a deadstate value of -10, a weapon will turn of its collision + * detection and movement. If it has a positive value, it will + * decrement once per frame until it equals 0, whereupon the weapon is + * removed. If you want to remove the weapon, write one of the WDS_ + * constants in std.zh (appropriate for the weapon) to this variable. + */ + int DeadState; + + /** + * Whether or not the weapon flashes. A flashing weapon alternates between + * its CSet and its FlashCSet. + */ + bool Flash; + + /** + * Whether and how the weapon's tiles should be flipped. + * 0: No flip + * 1: Horizontal flip + * 2: Vertical flip + * 3: Both (180 degree rotation) + */ + int Flip; + + /** + * Whether to extend the sprite of the weapon. + */ + int Extend; + + /** + * The number of tile columns composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileWidth; + + /** + * The number of tile rows composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileHeight; + + /** + * The width of the sprite's hitbox, or collision rectangle. + */ + int HitWidth; + + /** + * The height of the sprite's hitbox, or collision rectangle. + */ + int HitHeight; + + /** + * The Z-axis height of the sprite's hitbox, or collision rectangle. + * The greater it is, the higher Link must jump or fly over the sprite + * to avoid taking damage. + */ + int HitZHeight; + + /** + * The X offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's + * hitbox left or right. + */ + int HitXOffset; + + /** + * The Y offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's + * hitbox up or down. + */ + int HitYOffset; + + /** + * The X offset of the sprite. + * Setting it to positive or negative values will move the sprite's + * tiles left or right relative to its position. + */ + int DrawXOffset; + + /** + * The Y offset of the sprite. + * Setting it to positive or negative values will move the sprite's + * tiles up or down relative to its position. + */ + int DrawYOffset; + + /** + * The Z offset of the sprite. + */ + int DrawZOffset; + + /** + * An array of 16 miscellaneous variables for you to use as you please. + */ + float Misc[]; + +}; //weapon + +typedef weapon lweapon; +typedef weapon eweapon; + + +//========================================= +//--- Itemdata Functions and Variables --- +//========================================= + +class itemdata +{ + /** + * The original values of the item's 8 D input values are they are stored in the + * .qst file, regardles of whether they have been modified by ZScript. + */ + float InitD[]; + + /** + * Loads the item this itemdata is attributed to's name into 'buffer' + */ + void GetName(int buffer[]); + + /** + * The kind of item to which this class belongs (swords, boomerangs, + * potions, etc.) Use the IC_ constants in std.zh to set or compare this + * value. + */ + int Family; + + /** + * The level of this item. Higher-level items replace lower-level items + * when they are picked up. + */ + int Level; + + /** + * The item's power, for most items this is amount of damage dealt but is + * used for other values in some items (ie. Roc's Feather) + */ + int Power; + + /** + * Corresponds to the "Increase Amount" entry in the Item Editor. + * The value of this data member can have two meanings: + * If Amount & 0x8000 is 1, the drain counter for this item is set + * to Amount & 0x3FFF. The game then slowly fills the counter of this item + * (see Counter below) out of the drain counter. Gaining rupees uses the + * drain counter, for example. + * is set to Amount when the item is picked up. + * If Amount & 0x8000 is 0, the counter of this item is increased, if + * Amount & 0x4000 is 1, or decreased, if Amount & 0x4000 is 0, by + * Amount & 0x3FFF when the item is picked up. + */ + int Amount; + + /** + * Corresponds to the "Increase Counter Max" entry in the Item Editor. + * In conjunction with Max (see below) this value controls how the + * maximum value of the counter of this item (see Counter below) is + * modified when the item is picked up. If MaxIncrement is nonzero at that + * time, the counter's new maximum value is at that time set to the + * minimum of its current value plus MaxIncrement, and Max. + * If Max is less than the current maximum of the counter, Max is ignored + * and that maximum is used instead. + */ + int MaxIncrement; + + /** + * Corresponds to the "But Not Above" entry in the Item Editor. + * In conjunction with MaxIncrement (see above) this value controls how + * the maximum value of the counter of this item (see Counter below) is + * modified when the item is picked up. If MaxIncrement is nonzero at that + * time, the counter's new maximum value is at that time set to the + * minimum of its current value plus MaxIncrement, Max. + * If Max is less than the current maximum of the counter, Max is ignored + * and that maximum is used instead. + * Notice that as a special case, if Max = MaxIncrement, the counter's + * maximum value will be forced equal to Max. + */ + int Max; + + /** + * Corresponds to the "Equipment Item" checkbox in the Item Editor. + * If true, Link will keep the item, and it will show up as an item or + * equipment in the subscreen. If false, it may modify the current value + * or maximum value of its counter (see Counter below), then disappear. + * The White Sword and Raft, for instance, have Keep true, and keys and + * rupees have Keep false. + */ + bool Keep; + + /** + * Corresponds to the "Counter Reference" entry in the Item Editor. + * The game counter whose current and modified values might be modified + * when the item is picked up (see Amount, Max, and MaxIncrement above.) + * Use the CT_ constants in std.zh to set or compare this value. + */ + int Counter; + + /** + * Corresponds to the "Sound" entry on the action tab in the Item Editor. + */ + int UseSound; + +}; //itemdata + + +//==================================== +//--- Game Functions and Variables --- +//==================================== + +namespace Game +{ + /** + * Retrieves the number of the current screen within the current map. + */ + int GetCurScreen(); + + /** + * Retrieves the number of the current screen within the current DMap. + */ + int GetCurDMapScreen(); + + /** + * Retrieves the number of the dungeon level of the current DMap. Multiple + * DMaps can have the same dungeon level - this signifies that they share + * a map, compass, level keys and such. + */ + int GetCurLevel(); + + /** + * Retrieves the number of the current map. + */ + int GetCurMap(); + + /** + * Returns the number of the current DMap. + */ + int GetCurDMap(); + + /** + * An array of 512 integers, containing the DMap's flags ORed (|) together. + * Use the 'DMF_' constants, or the 'DMapFlag()' functions from std.zh if you are not comfortable with binary. + */ + int DMapFlags[]; + + /** + * An array of 512 integers containing each DMap's level + */ + int DMapLevel[]; + + /** + * An array of 512 integers containing each DMap's compass screen + */ + int DMapCompass[]; + + /** + * An array of 512 integers containing each DMap's continue screen + */ + int DMapContinue[]; + + /** + * An array of 512 integers containing each DMap's MIDI. + * Positive numbers are for custom MIDIs, and negative values are used for + * the built-in game MIDIs. Because of the way DMap MIDIs are handled + * internally, however, built-in MIDIs besides the overworld, dungeon, and + * level 9 songs won't match up with Game->PlayMIDI() and Game->GetMIDI(). + */ + int DMapMIDI[]; + + /** + * Loads DMap with ID 'DMap's name into 'buffer'. + * See std.zh for appropriate buffer size. + */ + void GetDMapName(int DMap, int buffer[]); + + /** + * Loads DMap with ID 'DMap's title into 'buffer'. + * See std.zh for appropriate buffer size. + */ + void GetDMapTitle(int DMap, int buffer[]); + + /** + * Loads DMap with ID 'DMap's intro string into 'buffer'. + * See std.zh for appropriate buffer size. + */ + void GetDMapIntro(int DMap, int buffer[]); + + /** + * An array of 512 integers containing the X offset of each DMap. + * Game->DMapOffset is read-only; while setting it is not syntactically + * incorrect, it does nothing. + */ + int DMapOffset[]; + + /** + * An array of 512 integers containing the map used by each DMap. + * Game->DMapMap is read-only; while setting it is not syntactically + * incorrect, it does nothing. + */ + int DMapMap[]; + + /** + * The number of times Link has perished during this quest. + */ + int NumDeaths; + + /** + * The current cheat level of the quest player. + */ + int Cheat; + + /** + * Returns the time elapsed in this quest, in 60ths of a second. The + * return value is undefined if TimeValid is false (see below). + */ + int Time; + + /** + * True if the elapsed quest time can be determined for the current quest. + */ + bool TimeValid; + + /** + * This value is true if the current quest session was loaded from a saved + * game, false if the quest was started fresh. + */ + bool HasPlayed; + + /** + * This value is true if the game is running in standalone mode, false if not. + * Game->Standalone is read-only; while setting it is not syntactically + * incorrect, it does nothing. + */ + bool Standalone; + + /** + * The number of NPCs (enemies and guys) on screen i of this map, where + * i is the index used to access this array. This array is exclusively used + * to determine which enemies had previously been killed, and thus won't + * return, when you re-enter a screen. + */ + int GuyCount[]; + + /** + * The DMap where Link will be respawned after quitting and reloading the game. + */ + int ContinueDMap; + + /** + * The map screen where Link will be respawned after quitting and reloading the game. + */ + int ContinueScreen; + + /** + * The DMap where Link will be respawned after dying and continuing. + */ + int LastEntranceDMap; + + /** + * The map screen where Link will be respawned after dying and continuing. + */ + int LastEntranceScreen; + + /** + * The current value of the game counters. Use the CR_ constants in + * std.zh to index into this array. + */ + int Counter[]; + + /** + * The current maximum value of the game counters. Use the CR_ constants + * in std.zh to index into this array. + */ + int MCounter[]; + + /** + * The current value of the game drain counters. Use the CR_ constants + * in std.zh to index into this array. + * Note that if the player hasn't acquired the '1/2 Magic Upgrade' yet, + * then setting the CR_MAGIC drain counter to a negative value will + * drain the magic counter by 2 per frame rather than 1. + */ + int DCounter[]; + + /** + * An array of miscellaneous game values, such as number of heart + * containers and magic drain rate. Use the GEN_ constants in std.zh + * to index into this array. + */ + int Generic[]; + + /** + * The exploration items (map, compass, boss key etc.) of dungeon level i + * currently under the possession of the player, where i is + * the index used to access this array. Each element of this + * array consists of flags OR'd (|) together; use the LI_ constants in + * std.zh to set or compare these values. + */ + int LItems[]; + + /** + * The number of level keys of level i currently under the possession of + * the player, where i is the index used to access this array. + */ + int LKeys[]; + + /** + * Returns the screen flags from screen 'screen' on map 'map', + * interpreted in the same way as Screen->Flags + */ + int GetScreenFlags(int map, int screen, int flagset); + + /** + * Returns the enemy flags from screen 'screen' on map 'map', + * interpreted in the same way as Screen->EFlags + */ + int GetScreenEFlags(int map, int screen, int flagset); + + /** + * As with State, but retrieves the miscellaneous flags of any screen, + * not just the current one. This function is undefined if map is less + * than 1 or greater than the maximum map number of your quest, or if + * screen is greater than 127. + * Note: Screen numbers in ZQuest are usually displayed in hexadecimal. + * Use the ST_ constants in std.zh for the flag parameter. + */ + bool GetScreenState(int map, int screen, int flag); + + /** + * As with State, but sets the miscellaneous flags of any screen, not + * just the current one. This function is undefined if map is less than + * 1 or greater than the maximum map number of your quest, or if + * screen is greater than 127. + * Note: Screen numbers in ZQuest are usually displayed in hexadecimal. + * Use the ST_ constants in std.zh for the flag parameter. + */ + void SetScreenState(int map, int screen, int flag, bool value); + + /** + * Retrieves the value of D[reg] on the given screen of the current + * DMap. + */ + float GetScreenD(int screen, int reg); + + /** + * Sets the value of D[reg] on the given screen of the current DMap. + */ + void SetScreenD(int screen, int reg, float value); + + /** + * Retrieves the value of D[reg] on the given screen of the given + * DMap. + */ + float GetDMapScreenD(int dmap, int screen, int reg); + + /** + * Sets the value of D[reg] on the given screen of the given DMap. + */ + void SetDMapScreenD(int dmap, int screen, int reg, float value); + + /** + * Retrieves the itemdata pointer corresponding to the given item. + * Use the item pointer ID variable or I_ constants in std.zh as values. + */ + itemdata LoadItemData(int item); + + /** + * Plays one of the quest's sound effects. Use the SFX_ constants in + * std.zh as values of soundid. + */ + void PlaySound(int soundid); + + /** + * Changes the current screen MIDI to MIDIid. + * Will revert to the DMap (or screen) MIDI upon leaving the screen. + */ + void PlayMIDI(int MIDIid); + + /** + * Returns the current screen MIDI that is playing. + * Positive numbers are for custom MIDIs, and negative values are used + * for the built-in game MIDIs. + */ + int GetMIDI(); + + /** + * Play the specified enhanced music if it's available. If the music + * cannot be played, the current music will continue. The music will + * revert to normal upon leaving the screen. + * Returns true if the music file was loaded successfully. + * The filename cannot be more than 255 characters. If the music format + * does not support multiple tracks, the track argument will be ignored. + */ + bool PlayEnhancedMusic(int filename[], int track); + + /** + * Load the filename of the given DMap's enhanced music into buf. + * buf should be at least 256 elements in size. + */ + void GetDMapMusicFilename(int dmap, int buf[]); + + /** + * Returns the given DMap's enhanced music track. This is valid but + * meaningless if the music format doesn't support multiple tracks. + */ + int GetDMapMusicTrack(int dmap); + + /** + * Sets the specified DMap's enhanced music to the given filename and + * track number. If the music format does not support multiple tracks, + * the track argument will be ignored. The filename must not be more + * than 255 characters. + */ + void SetDMapEnhancedMusic(int dmap, int filename[], int track); + + /** + * Grabs a particular combo reference from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Don't forget that the screen index should be in hexadecimal, + * and that maps are counted from 1 upwards. + * Position is considered an index, treated the same way as in + * Screen->ComboD[]. + */ + int GetComboData(int map, int screen, int position); + + /** + * Sets a particular combo reference anywhere in the game world, + * based on map (NOT DMap), screen number, and position. + * Don't forget that the screen index should be in hexadecimal, + * and that maps are counted from 1 upwards. + * Position is considered an index, treated the same way as in + * Screen->ComboD[]. + */ + void SetComboData(int map, int screen, int position, int value); + + /** + * Grabs a particular combo's CSet from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Position is considered an index, treated the same way as in + * Screen->ComboC[]. + */ + int GetComboCSet(int map, int screen, int position); + + /** + * Sets a particular combo's CSet anywhere in the game world, + * based on map (NOT DMap), screen number, and position. Position + * is considered an index, treated the same way as in Screen->ComboC[]. + */ + void SetComboCSet(int map, int screen, int position, int value); + + /** + * Grabs a particular combo's placed flag from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Position is considered an index, treated the same way as in + * Screen->ComboF[]. + */ + int GetComboFlag(int map, int screen, int position); + + /** + * Sets a particular combo's placed flag anywhere in the game world, + * based on map (NOT DMap), screen number, and position. Position + * is considered an index, treated the same way as in Screen->ComboF[]. + */ + void SetComboFlag(int map, int screen, int position, int value); + + /** + * Grabs a particular combo's type from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Position is considered an index, treated the same way as in + * Screen->ComboT[]. Note that you are grabbing an actual combo + * attribute as referenced by the combo on screen you're + * referring to. + */ + int GetComboType(int map, int screen, int position); + + /** + * Sets a particular combo's type anywhere in the game world, + * based on map (NOT DMap), screen number, and position. Position + * is considered an index, treated the same way as in Screen->ComboT[]. + * Note that you are grabbing an actual combo attribute as referenced + * by the combo on screen you're referring to, which means that + * setting this attribute will affect ALL references to this combo + * throughout the quest. + */ + void SetComboType(int map, int screen, int position, int value); + + /** + * Grabs a particular combo's inherent flag from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Position is considered an index, treated the same way as in + * Screen->ComboI[]. Note that you are grabbing an actual combo + * attribute as referenced by the combo on screen you're + * referring to. + */ + int GetComboInherentFlag(int map, int screen, int position); + + /** + * Sets a particular combo's inherent flag anywhere in the game world, + * based on map (NOT DMap), screen number, and position. Position + * is considered an index, treated the same way as in Screen->ComboI[]. + * Note that you are grabbing an actual combo attribute as referenced + * by the combo on screen you're referring to, which means that + * setting this attribute will affect ALL references to this combo + * throughout the quest. + */ + void SetComboInherentFlag(int map, int screen, int position, int value); + + /** + * Grabs a particular combo's solidity flag from anywhere in the game + * world, based on map (NOT DMap), screen number, and position. + * Position is considered an index, treated the same way as in + * Screen->ComboS[]. Note that you are grabbing an actual combo + * attribute as referenced by the combo on screen you're + * referring to. + */ + int GetComboSolid(int map, int screen, int position); + + /** + * Sets a particular combo's solidity anywhere in the game world, + * based on map (NOT DMap), screen number, and position. Position + * is considered an index, treated the same way as in Screen->ComboS[]. + * Note that you are grabbing an actual combo attribute as referenced + * by the combo on screen you're referring to, which means that + * setting this attribute will affect ALL references to this combo + * throughout the quest. + */ + void SetComboSolid(int map, int screen, int position, int value); + + /** + * Returns the tile used by combo 'combo' + */ + int ComboTile(int combo); + + /** + * Loads the current save file's name into 'buffer' + * Buffer should be at least 9 elements long + */ + void GetSaveName(int buffer[]); + + /** + * Sets the current file's save name to 'name' + * Buffer should be no more than 9 elements + */ + void SetSaveName(int name[]); + + /** + * Ends the current game and returns to the file select screen + */ + void End(); + + /** + * Saves the current game + */ + void Save(); + + /** + * Displays the save screen. Returns true if the user chose to save, false otherwise. + */ + bool ShowSaveScreen(); + + /** + * Displays the save and quit screen. + */ + void ShowSaveQuitScreen(); + + /** + * Loads 'string' into 'buffer'. Use the function from std.zh + * to remove trailing ' ' characters whilst loading. + */ + void GetMessage(int string, int buffer[]); + + /** + * Returns the number of the script with the given name or -1 if there is + * no such script. + */ + int GetFFCScript(int name[]); + + /** + * If this is false, the "Click to Freeze" setting will not function, ensuring + * that the script can use the mouse freely. This overrides the setting rather + * than changing it, so remembering and restoring the initial value is unnecessary. + */ + bool ClickToFreezeEnabled; +}; //Game + + +//=================================== +//--- NPC Functions and Variables --- +//=================================== + +class npc +{ + /** + * Returns whether or not this NPC pointer is still valid. A pointer + * becomes invalid if the enemy dies or Link leaves the screen. + * Trying to access any variable of an invalid NPC pointer prints + * an error to allegro.log and does nothing. + */ + bool isValid(); + + /** + * Loads the npc's name into 'buffer'. To load an NPC from an ID rather than a pointer, + * use 'GetNPCName' from std.zh + */ + void GetName(int buffer[]); + + /** + * The NPC's enemy ID number. + * npc->ID is read-only; while setting it is not syntactically incorrect, it does nothing. + */ + int ID; + + /** + * The NPC's Type. Use the NPCT_ constants in std.zh to compare this value. + * npc->Type is read-only; while setting it is not syntactically incorrect, it does nothing. + */ + int Type; + + /** + * The NPC's current X coordinate, in pixels. Float values passed to this will be cast to int. + */ + int X; + + /** + * The NPC's current Y coordinate, in pixels. Float values passed to this will be cast to int. + */ + int Y; + + /** + * The NPC's current Z coordinate, in pixels. Float values passed to this will be cast to int. + */ + int Z; + + /** + * The NPC's upward velocity, in pixels. If negative, the NPC will fall. + * The downward acceleration of Gravity (in Init Data) modifies this value every frame. + */ + int Jump; + + /** + * The direction the NPC is facing. Use the DIR_ constants in std.zh to + * set and compare this value. + */ + int Dir; + + /** + * The rate at which the NPC changes direction. For a point of reference, + * the "Octorok (Magic)" enemy has a rate of 16. The effect of writing to + * this field is currently undefined. + */ + int Rate; + + /** + * The extent to which the NPC stands still while moving around the + * screen. As a point of reference, the Zols and Gels have haltrate of + * 16. The effect of writing to this field is currently undefined. + */ + int Haltrate; + + /** + * How likely the NPC is to move towards Link. + * The effect of writing to this field is currently undefined. + */ + int Homing; + + /** + * How likely the NPC is to move towards bait. + * The effect of writing to this field is currently undefined. + */ + int Hunger; + + /** + * The NPC's movement speed. A Step of 100 usually means that + * the enemy moves at approximately one pixel per animation frame. + * As a point of reference, the "Octorok (Magic)" enemy has + * a step of 200. The effect of writing to this field is + * currently undefined. + */ + int Step; + + /** + * Whether the NPC will use the system's code to work out collisions with Link + * Initialised as 'true'. + */ + bool CollDetection; + + /** + * The the NPC's animation frame rate, in screen frames. The effect of + * writing to this field is currently undefined. + */ + int ASpeed; + + /** + * The way the NPC is animated. Use the DS_ constants in std.zh to set or + * compare this value. The effect of writing to this field is currently undefined. + */ + int DrawStyle; + + /** + * The NPC's current hitpoints. A weapon with a Power of 1 removes 2 + * hitpoints. + */ + int HP; + + /** + * The amount of damage dealt to an unprotected Link when he touches this NPC, in + * quarter-hearts. + */ + int Damage; + + /** + * The amount of damage dealt to an unprotected Link by this NPC's weapon, in + * quarter-hearts. + */ + int WeaponDamage; + + /** + * The time, in frames, that the NPC will be stunned. Some types of enemies cannot be stunned. + */ + int Stun; + + /** + * The number of the starting tile used by this NPC. + */ + int OriginalTile; + + /** + * The current tile associated with this NPC. The effect of writing to this variable is undefined. + */ + int Tile; + + /** + * The weapon used by this enemy. Use the WPN_ constants (NOT the EW_ constants) + * in std.zh to set or compare this value. + */ + int Weapon; + + /** + * The items that the NPC might drop when killed. Use the IS_ constants + * in std.zh to set or compare this value. + */ + int ItemSet; + + /** + * The CSet used by this NPC. + */ + int CSet; + + /** + * The boss pallete used by this NPC; this pallete is only used if CSet + * is 14 (the reserved boss cset). Use the BPAL_ constants in std.zh to + * set or compare this value. + */ + int BossPal; + + /** + * The sound effects emitted by the enemy. Use the SFX_ constants in + * std.zh to set or compare this value. + */ + int SFX; + + /** + * Whether to extend the sprite of the enemy. + */ + int Extend; + + /** + * The number of tile columns composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileWidth; + + /** + * The number of tile rows composing the sprite. + * Writing to this is ignored unless Extend is set to values >=3. + */ + int TileHeight; + + /** + * The width of the sprite's hitbox, or collision rectangle. + */ + int HitWidth; + + /** + * The height of the sprite's hitbox, or collision rectangle. + */ + int HitHeight; + + /** + * The Z-axis height of the sprite's hitbox, or collision rectangle. + * The greater it is, the higher Link must jump or fly over the sprite to avoid taking damage. + */ + int HitZHeight; + + /** + * The X offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's hitbox left or right. + */ + int HitXOffset; + + /** + * The Y offset of the sprite's hitbox, or collision rectangle. + * Setting it to positive or negative values will move the sprite's hitbox up or down. + */ + int HitYOffset; + + /** + * The X offset of the sprite. + * Setting it to positive or negative values will move the sprite's tiles left or right relative to its position. + */ + int DrawXOffset; + + /** + * The Y offset of the sprite. In non-sideview screens, this is usually -2. + * Setting it to positive or negative values will move the sprite's tiles up or down relative to its position. + */ + int DrawYOffset; + + /** + * The Z offset of the sprite. This is ignored unless Extend is set to values >=3. + */ + int DrawZOffset; + + /** + * The npc's Defense values, as an array of 18 integers. Use the NPCD_ and NPCDT_ constants + * in std.zh to set or compare these values. + */ + int Defense[]; + + /** + * The npc's Miscellaneous Attributes, as an array of ten integers. + * They are read-only; while setting them is not syntactically incorrect, it does nothing. + */ + int Attributes[]; + + /** + * The npc's Misc. Flags as 14 bits ORed together, starting with 'Damaged by Power 0 Weapons', + * and working down the flags in the order they are shown in the Enemy Editor. + * npc->MiscFlags is read-only; while setting it is not syntactically incorrect, it does nothing. + + * If you are not comfortable with binary operations, you can use 'GetNPCMiscFlag' from std.zh + */ + int MiscFlags; + + /** + * An array of 16 miscellaneous variables for you to use as you please. + */ + float Misc[]; + + /** + * Breaks the enemy's shield if it has one. This works even if the flag + * "Hammer Can Break Shield" is not checked. + void BreakShield(); + +}; //npc + + + diff --git a/output/common/zstrings.txt b/output/common/zstrings.txt new file mode 100644 index 0000000000..f17a159549 --- /dev/null +++ b/output/common/zstrings.txt @@ -0,0 +1,68 @@ ++-----------------------------+ +| STRING CONTROL CODES | ++-----------------------------+ + +Enter these control codes into a message string for special formatting, effects, basic dialog +branching, or modification. (Henceforth, "X" denotes a number from 0 +to 9999.) + ++-----------------------------+ +| FORMATTING CODES | ++-----------------------------+ + +\1\X\X - Text Colour. Changes the following text to a certain colour. Argument 1 is the CSet, and argument 2 is the colour within that CSet. The text in the Preview Pane changes to reflect the addition and modification of this Control Code. + +\2\X - Text Speed. Changes the length of the delay between text characters appearing. If 0, text appears instantaneously. Argument 1 is the speed. + +\25 - New Line. Equivalent to pressing Enter in a document. Best used when text wrapping is enabled. + +\32 through \126 - ASCII Character. Prints a character based on its ASCII code. For example, \91 allows you to display a backslash. + ++-----------------------------+ +| SWITCH CODES | ++-----------------------------+ + + (Note: If you switch to a string that hasn't been created yet, then ZC will act as if you switched to a string with no characters in it. ) + +\3\X\X\X - Goto If Screen Variable. If one of the Screen->D[] variables of the current screen is at or above a certain value, then ZC switches to another string. Argument 1 is the index into the screen's D array, argument 2 is the value, and argument 3 is the string to switch to. + +\4\X\X - Goto If Random. There is a one-in-(argument 1) chance that ZC switches to another string (argument 2). + +\5\X\X - Goto If Item. If Link has a certain item, then ZC switches to another string. Argument 1 is the item ID, and argument 2 is the string to switch to. + +\6\X\X\X - Goto If Counter. If a counter is at or above a certain value, then ZC switches to another string. Argument 1 is the counter, argument 2 is the value, and argument 3 is the string to switch to. + +\7\X\X\X - Goto If Counter %. If a counter is at or above a certain percentage of its maximum, then ZC switches to another string. + +\8\X\X - Goto If Triforce. If Link has acquired the Triforce from a certain level, then ZC switches to another string. Argument 1 is the level, and argument 2 is the string to switch to. + +\9\X\X - Goto If Triforce Count. If Link has acquired a certain number of Triforce pieces, then ZC switches to another string. Argument 1 is the quantity, and argument 2 is the string to switch to. + ++-----------------------------+ +| COUNTER UP/DOWN CODES | ++-----------------------------+ + +\10\X\X - Counter Up. Increases a counter by a certain value. Argument 1 is the counter, and argument 2 is the value. + +\11\X\X - Counter Down. Reduces a counter by a certain value. Argument 1 is the counter, and argument 2 is the value. + +\12\X\X - Counter Set. Sets a counter to a certain value. Argument 1 is the counter, and argument 2 is the value. + +\13\X\X - Counter Up %. Increases a counter by a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\14\X\X - Counter Down %. Reduces a counter by a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\15\X\X - Counter Set %. Sets a counter to a certain percentage of its maximum. Argument 1 is the counter, and argument 2 is the percentage. + +\16\X - Give Item. An item is silently added to Link's inventory. Link does not hold up the item, and the item's Pickup Script does not run - though the item's counter modifications will still take effect. Argument 1 is the item ID. + +\17\X - Take Item. An item is removed from Link's inventory. The item's counter modifications will be undone when this occurs. Argument 1 is the item ID. + ++-----------------------------+ +| AUDIO EFFECT CODES | ++-----------------------------+ + +\20\X - Sound Effect. Argument 1 is the sound effect number. + +\21\X - Play MIDI. Argument 1 is the quest MIDI number. You cannot play the built-in MIDIs using this. + diff --git a/projects/code_blocks/todo.txt b/projects/code_blocks/todo.txt new file mode 100644 index 0000000000..ae55170772 --- /dev/null +++ b/projects/code_blocks/todo.txt @@ -0,0 +1 @@ +todo: generate appropriate projects from vs builds or makefile. \ No newline at end of file diff --git a/projects/vs2008/romview.vcproj b/projects/vs2008/romview.vcproj new file mode 100644 index 0000000000..50b37f1665 --- /dev/null +++ b/projects/vs2008/romview.vcproj @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/vs2008/soundlib.vcproj b/projects/vs2008/soundlib.vcproj new file mode 100644 index 0000000000..f8239f574c --- /dev/null +++ b/projects/vs2008/soundlib.vcproj @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/vs2008/zc.sln b/projects/vs2008/zc.sln new file mode 100644 index 0000000000..0c4dc5d876 --- /dev/null +++ b/projects/vs2008/zc.sln @@ -0,0 +1,36 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zc", "zc.vcproj", "{C716DE8B-1181-4B5D-947C-F8233C562464}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zquest", "zquest.vcproj", "{50ACE952-7298-4317-9AC5-F7823095B346}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "romview", "romview.vcproj", "{EF810A76-BA22-41A6-AEDF-C19E50969355}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "soundlib", "soundlib.vcproj", "{435B52F1-524D-4A5A-88E6-0C7B319A4892}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C716DE8B-1181-4B5D-947C-F8233C562464}.Debug|Win32.ActiveCfg = Debug|Win32 + {C716DE8B-1181-4B5D-947C-F8233C562464}.Debug|Win32.Build.0 = Debug|Win32 + {C716DE8B-1181-4B5D-947C-F8233C562464}.Release|Win32.ActiveCfg = Release|Win32 + {C716DE8B-1181-4B5D-947C-F8233C562464}.Release|Win32.Build.0 = Release|Win32 + {50ACE952-7298-4317-9AC5-F7823095B346}.Debug|Win32.ActiveCfg = Debug|Win32 + {50ACE952-7298-4317-9AC5-F7823095B346}.Debug|Win32.Build.0 = Debug|Win32 + {50ACE952-7298-4317-9AC5-F7823095B346}.Release|Win32.ActiveCfg = Release|Win32 + {50ACE952-7298-4317-9AC5-F7823095B346}.Release|Win32.Build.0 = Release|Win32 + {EF810A76-BA22-41A6-AEDF-C19E50969355}.Debug|Win32.ActiveCfg = Debug|Win32 + {EF810A76-BA22-41A6-AEDF-C19E50969355}.Release|Win32.ActiveCfg = Release|Win32 + {EF810A76-BA22-41A6-AEDF-C19E50969355}.Release|Win32.Build.0 = Release|Win32 + {435B52F1-524D-4A5A-88E6-0C7B319A4892}.Debug|Win32.ActiveCfg = Debug|Win32 + {435B52F1-524D-4A5A-88E6-0C7B319A4892}.Debug|Win32.Build.0 = Debug|Win32 + {435B52F1-524D-4A5A-88E6-0C7B319A4892}.Release|Win32.ActiveCfg = Release|Win32 + {435B52F1-524D-4A5A-88E6-0C7B319A4892}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/projects/vs2008/zc.vcproj b/projects/vs2008/zc.vcproj new file mode 100644 index 0000000000..12b0714390 --- /dev/null +++ b/projects/vs2008/zc.vcproj @@ -0,0 +1,2516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/vs2008/zquest.vcproj b/projects/vs2008/zquest.vcproj new file mode 100644 index 0000000000..b097074631 --- /dev/null +++ b/projects/vs2008/zquest.vcproj @@ -0,0 +1,1877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/vs2010/todo.txt b/projects/vs2010/todo.txt new file mode 100644 index 0000000000..4d94406047 --- /dev/null +++ b/projects/vs2010/todo.txt @@ -0,0 +1 @@ +todo \ No newline at end of file diff --git a/rv_icon.c b/rv_icon.c new file mode 100644 index 0000000000..ad6ffcd1bc --- /dev/null +++ b/rv_icon.c @@ -0,0 +1,528 @@ +#include +/* XPM */ +static const char *allegico_xpm[] = +{ + /* columns rows colors chars-per-pixel */ + "256 256 256 2 ", + " c #14091D", + ". c #0F080E", + "X c #2D1412", + "o c #190C25", + "O c #1E0F2F", + "+ c #250D2A", + "@ c #270E37", + "# c #2C123C", + "$ c #281637", + "% c #32123E", + "& c #38163A", + "* c #30132C", + "= c #342938", + "- c #3B2512", + "; c #4D1615", + ": c #6F1816", + "> c #532F17", + ", c #4B1931", + "< c #512D38", + "1 c #7A2836", + "2 c #6F262F", + "3 c #6E2A1E", + "4 c #714C26", + "5 c #2E1441", + "6 c #331542", + "7 c #351A44", + "8 c #3B1A45", + "9 c #3B1A47", + "0 c #3A2648", + "q c #3B2E57", + "w c #3D3562", + "e c #451B47", + "r c #561D47", + "t c #46234D", + "y c #57244C", + "u c #492853", + "i c #572A56", + "p c #49345A", + "a c #57355B", + "s c #47344B", + "d c #642B58", + "f c #66345A", + "g c #722F4A", + "h c #473B65", + "j c #583C63", + "k c #563768", + "l c #683865", + "z c #723A65", + "x c #534646", + "c c #675B5A", + "v c #734E50", + "b c #4A436A", + "n c #59456A", + "m c #574A75", + "M c #584F76", + "N c #66476A", + "B c #774769", + "V c #644D73", + "C c #6A5777", + "Z c #765979", + "A c #784E71", + "S c #76647E", + "D c #70646A", + "F c #6E635A", + "G c #3F404D", + "H c #881D17", + "J c #952219", + "K c #AC241A", + "L c #A6241A", + "P c #B3261B", + "I c #BA271B", + "U c #B4281C", + "Y c #BE2A1A", + "T c #A1321D", + "R c #872B35", + "E c #912E31", + "W c #AF3430", + "Q c #C22A1B", + "! c #CB2B1C", + "~ c #C1271A", + "^ c #D22E1D", + "/ c #DB2F1D", + "( c #D7301D", + ") c #DB301D", + "_ c #E32F1E", + "` c #E4311F", + "' c #E9321F", + "] c #C33D34", + "[ c #C93627", + "{ c #ED3320", + "} c #E73927", + "| c #F43421", + " . c #FC3622", + ".. c #F53822", + "X. c #FF3B26", + "o. c #FF3E2A", + "O. c #F33E2C", + "+. c #8D5624", + "@. c #976829", + "#. c #A9742B", + "$. c #A64632", + "%. c #C5443B", + "&. c #D64639", + "*. c #FF422D", + "=. c #F6422E", + "-. c #FF4631", + ";. c #FF4935", + ":. c #FF4C39", + ">. c #F44A39", + ",. c #FF513E", + "<. c #F6503D", + "1. c #E94636", + "2. c #8B3348", + "3. c #B23D46", + "4. c #875857", + "5. c #914F55", + "6. c #B25255", + "7. c #B6655B", + "8. c #875779", + "9. c #8E536D", + "0. c #AE5A6B", + "q. c #936571", + "w. c #B86A68", + "e. c #AD6A71", + "r. c #8C6C57", + "t. c #C74C44", + "y. c #C8544B", + "u. c #CA5C53", + "i. c #C65656", + "p. c #D2594F", + "a. c #FE5543", + "s. c #FE5C4B", + "d. c #FA5948", + "f. c #EE5A4B", + "g. c #CC645B", + "h. c #CB625A", + "j. c #D5665B", + "k. c #FE6453", + "l. c #FE6B5B", + "z. c #F56657", + "x. c #F66353", + "c. c #CD6B64", + "v. c #C76966", + "b. c #CD736C", + "n. c #D5746B", + "m. c #CB7875", + "M. c #D27B75", + "N. c #CD6B6E", + "B. c #EA766A", + "V. c #FE7364", + "C. c #FE7B6C", + "Z. c #F77669", + "A. c #EA7D72", + "S. c #FA7E71", + "D. c #F66E61", + "F. c #C85C63", + "G. c #AF8936", + "H. c #AA8F5F", + "J. c #D5827C", + "K. c #EA847A", + "L. c #FE8275", + "P. c #FE8A7D", + "I. c #F8857A", + "U. c #D2B756", + "Y. c #EBD05B", + "T. c #ECD661", + "R. c #C69C38", + "E. c #6B5A86", + "W. c #776885", + "Q. c #7C7488", + "!. c #72688E", + "~. c #625988", + "^. c #895D83", + "/. c #866887", + "(. c #84758D", + "). c #887A94", + "_. c #977A95", + "`. c #936C8B", + "'. c #AC768D", + "]. c #8E79A3", + "[. c #CB7B83", + "{. c #8C8597", + "}. c #95889C", + "|. c #999295", + " X c #8D888B", + ".X c #AC9298", + "XX c #B4A599", + "oX c #988CA4", + "OX c #9B92A4", + "+X c #9994A9", + "@X c #938EAE", + "#X c #A48BA3", + "$X c #A698AB", + "%X c #A89CB2", + "&X c #B596AB", + "*X c #ABA5A6", + "=X c #B6A9A8", + "-X c #ACA2B3", + ";X c #B3A3B5", + ":X c #BAB4B1", + ">X c #9EA0BC", + ",X c #D68A88", + "X:X-X:XnXcXvXcXcXmXvXmXcXmXvXmXmXmXmXlXnXnXnXnXmXlXmXnXmXlXnXnXnXnXxXMXxXnXxXxXxXzXzXxXxXzXzXzXzXMXaXaX:XpXhXj.Q Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q Y j.MXzXzXzXzXzXzXMXxXzXzXnXzXxXMXxXMXxXxXxXnXxXvXnXnXnXlXkXmXlXmXmXnXmXlXmXmXmXmXkXmXnXkXmXmXmXmXkXmXmXmXmXmXmXmXkXmXkXmXmXmXmXmXmXmXmXmXmXmXsXpXsXaXaXaXpXiXpXpX:X:X:X:X:X:X:X*X:X=XaXmXcXmXmXcXmXcXmXcXmXvXcXvXmXmXmXcXkXnXmXmXmXlXnXlXnXnXnXnXnXxXMXxXxXnXnXxXMXnXxXMXzXaXpX:X:X=X=XpXxXNXJ.Q Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q Q n.MXjXjXMXjXMXjXnXxXzXxXzXxXxXxXzXxXxXxXxXxXxXvXvXxXxXxXmXnXcXxXxXmXkXkXmXkXmXnXkXmXmXkXmXmXkXmXmXkXmXmXkXmXmXmXkXmXmXmXkXmXmXkXmXmXkXmXmXmXjXiXiXpXsXsXaXsXpXaXsXNXiXsXsXpXsXiXpX:X*X=XmXmXmXkXmXcXcXmXcXmXcXvXcXkXnXmXlXmXmXlXmXxXcXxXvXvXvXxXxXxXvXxXxXzXnXxXzXMXMXjXpX:X=X*X:X=X*X:XpXzXzXzXJ.[ Q Y Y Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Q J.jXjXMXMXMXMXjXMXjXzXxXzXxXzXxXxXzXxXxXxXxXxXxXxXxXcXxXxXcXlXxXxXcXkXNXmXnXnXkXmXmXlXmXcXcXmXkXkXmXmXkXmXkXmXkXkXmXkXmXkXmXmXkXmXmXkXmXmXkXmXpXpXpXaXaXaXaXpXiXpXiX:X:X=XpXiXpXpXiXaXiX=XaXkXmXmXkXcXcXcXcXcXcXcXxXkXmXmXkXkXnXmXkXcXxXcXxXxXxXcXxXxXxXxXxXxXxXxXzXiX:X=X*X=X:X:X:X*X:X=XaXzXzXzXjXK.%.Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Q Y Y Y Y Y Q Y J.zXjXjXjXMXjXjXMXlXjXxXzXxXzXxXzXxXxXjXxXxXxXxXxXcXxXxXxXxXxXcXcXxXcXmXkXnXkXkXmXmXkXcXcXcXkXkXmXkXmXkXmXkXmXmXkXmXkXmXkXmXkXkXmXkXkXkXmXkXmXzXiXiXaXsXpXiX:X*X*X*X=X*X:X:X:XiX:X=X:X=XiXsXpXkXmXmXkXcXcXcXcXcXcXcXcXmXmXkXmXcXcXlXmXxXcXcXxXxXlXcXxXxXxXxXxXzXaX:X=X*X:X=X:X=X:X*X*X*X=X=XzXxXzXzXzXzXJ.%.Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y [ n.jXjXMXjXMXjXjXjXjXjXnXjXxXjXxXxXxXlXxXxXxXxXxXxXxXlXxXxXkXlXcXcXxXcXcXcXcXkXkXmXlXlXmXcXcXlXmXmXkXmXkXmXkXmXkXkXmXkXmXkXmXkXmXmXkXkXmXmXkXmXkXsXpXsXiX=X=X*X*X:X:X-X=X:X*X*X:X:X*X*X*X=X=XpXsXmXkXmXkXcXcXcXcXcXcXcXcXkXlXmXlXlXcXcXlXcXxXcXxXcXxXxXxXcXjXbXiX*X=X*X*X*X=X=X=X=X*X*X*X:X=X=XjXjXzXjXzXjXzX4X%.Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Q j.zXjXjXjXjXjXMXjXxXxXjXxXxXlXzXzXxXjXxXxXxXlXcXlXxXxXxXlXlXkXxXkXcXcXlXcXkXcXlXcXlXkXmXkXlXmXkXmXkXkXmXkXmXkXkXkXkXkXkXmXmXkXkXkXmXkXmXkXkXkXmXkXsXsXiX=X*X*X*X*X*X=X=X*X:XXX:X*X*X*X*X*X*X*XiXsXkXmXkXkXcXcXkXcXkXcXcXcXkXcXcXcXcXlXcXcXxXcXlXkXlXlXxXsXiX=X*X*X*X*X=X=X=X=X=X*X*X*X*X*X=X=X=XxXjXjXjXjXjXjXNXJ.%.Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Q u.jXjXjXzXjXjXjXjXjXjXjXjXjXjXlXlXlXjXxXlXlXxXlXlXlXlXlXkXlXkXxXlXxXlXcXcXlXlXcXkXlXmXgXgXmXkXkXmXkXmXkXkXkXkXkXmXmXkXmXkXkXkXkXmXkXkXkXkXmXmXkXkXkXsXsX*X*X*X*X*X*X*X*X=X=X*XXXXX*X*X|.*X*X*XXXiXjXkXkXkXmXkXcXcXkXcXcXlXcXlXcXkXkXkXcXlXlXcXlXkXxXjXsX=X=XiX=X=X=X=X=X*X=X=X*X*XXX*X*XXX=X=X=XsXjXjXjXjXjXjXxXlXjXJ.[ Q Y Y Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q %.jXjXjXjXjXjXjXjXjXlXjXMXlXlXxXjXlXlXlXlXlXlXlXlXlXxXlXxXlXxXkXxXkXxXcXlXlXcXcXkXcXkXkXmXgXmXkXkXmXkXkXkXkXmXkXkXkXkXmXkXkXmXmXkXkXkXkXkXkXkXkXkXkXkXjXiX=X*X*X*X*X*X:XXX:X:X:X:X:XXX*X*X*X*X*X=XsXmXkXkXkXkXcXkXcXkXkXkXkXkXcXkXcXlXkXkXcXlXkXkXkXsX=X=X=XuXiX=X=XXX=X=X=XXX|.*X*X*X*X*X*X=X=X=XfXjXjXjXjXjXjXjXjXjXjXJ.Q Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q %.8XjXjXjXjXjXjXjXlXjXjXlXjXlXjXjXlXlXjXxXlXlXlXlXlXlXlXkXkXlXkXxXkXlXkXkXkXkXkXlXkXlXcXgXmXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXmXkXkXkXkXkXkXkXmXkXsX=XXX*X*X:XNXNX:X:X:XXX:X:X:X:X:X=X*XiXsXkXkXkXmXkXkXkXkXkXcXkXkXcXkXcXkXkXcXkXlXcXkXkXlXsXXXiXsXsXsXiXiXiX=XXX=X*X*X*X*X*X.X*X*X=X=X=X=XjXjXxXjXjXjXjXjXjXjXjXfXn.Q Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q Q K.NXfXjXjXjXdXjXjXjXjXlXjXMXhXhXjXlXlXlXjXlXlXlXlXlXlXlXlXlXkXlXlXlXkXlXlXlXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXsX=XXXNX:X:X=X:X=X=XiX:X=X=X*X:XpXpXXXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXkXkXkXkXkXkXkXkXsXqXiXiXbXeXqXsXuXXX=X*X*X*XXX*X*X*XXX*X=XXXuXXXiXlXjXjXlXjXjXjXjXfXfXjXjXjXu.Q Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Y Y Q Q n.fXfXfXjXdXdXjXjXhXjXdXjXlXdXdXlXlXjXhXlXhXlXhXlXgXlXlXlXlXgXlXlXkXgXlXkXkXkXkXgXkXkXkXlXkXkXkXkXkXkXkXkXkXkXkXkXkXkXgXkXkXkXkXkXkXkXkXkXkXkXmXkXmXkXkXkXkXkXgXsXNX:X*XXX:X*X=X*X=X*X=X=X-X*X*X=X*X=X=X=XiXsXjXkXkXkXkXkXgXkXkXkXkXkXkXkXkXkXkXlXlXiXiXXXXXqXsXbXqX=X*X.X|.*X|.*X|.*X|.*X.X*X=XXXXXiXdXjXdXjXdXjXfXfXjXdXfXfXfXfX%.Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Q Y Y Y Y Q Q &.dXfXfXjXdXjXdXjXdXjXjXdXhXlXhXlXlXjXhXlXhXlXlXhXlXlXlXlXgXkXlXlXgXlXlXgXkXkXkXkXkXkXgXkXkXgXkXkXkXkXkXkXgXkXkXgXkXkXgXkXkXgXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXkXlXsX:X*X*X*X-X-X-X-X-X-X-X;X-X-X-X-X%X*X-X%X*X$X$X*XiXiXdXkXgXkXkXgXkXkXkXgXkXkXkXkXlXXX.X=X=X=XqXiXuXXXXX$X|.*X.X*X*X|.*X|.&XXXXXuXXXsXjXhXlXdXlXdXjXjXjXjXfXfXfXfX8X%.Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q %.J.jXfXfXdXdXlXdXdXhXdXhXhXjXdXlXdXdXhXhXhXhXgXhXhXlXhXgXlXgXlXgXlXlXlXgXlXgXlXgXlXgXkXgXgXkXgXkXgXkXkXgXkXgXkXgXkXkXkXkXkXkXkXkXkXkXkXgXkXkXkXkXkXkXgXkXkXlXfXiX-X-X>X-X-X*X;X;X=X;X-X-X-X=X-X-X-X-X-X-X-X-X>X*X-X%X$X*X$X*XiXfXlXlXgXkXgXkXgXgXlXgXhX.XXXiXuXqXqXiXiXiXXXXX.X*XXX&XXXXX*XXXXXXX&XXXXXhXhXdXlXdXdXjXdXhXdXdXfXfXfXfXwXJ.Y Y Y Y Y Y Q Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q ! j.fXfXfXfXdXfXdXdXdXdXhXdXdXhXdXhXhXhXhXhXhXhXhXgXhXhXhXlXgXhXhXlXgXhXhXgXlXgXgXlXgXgXkXgXkXgXgXkXgXkXgXkXgXgXgXkXgXkXkXkXgXkXkXgXkXkXkXkXgXkXkXgXkXkXkXdXiX*X-X-X-X;X-X:X-X-X-X-X-X-X-X-X-X-X%X-X-X%X-X$X-X%X-X$X*X-X%X+X*X+X+X*X*X=XwXgXgXgXkXgXlXgXhXXXXXqXqXfXqXfXqXqXqXiXXX.X.XXXXX.X.X=X.XXXXXXXiXhXhXdXdXhXdXdXdXdXfXdXfXfXdXfXfXdXy.Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q Q &.qXfXeXdXdXdXeXdXhXdXdXdXdXhXdXdXhXhXdXhXhXhXhXhXhXhXgXgXhXgXhXgXhXgXgXgXgXgXhXgXgXgXgXgXgXgXgXgXgXgXgXgXgXgXkXkXgXgXgXgXgXgXgXgXkXkXgXgXkXkXgXgXkXhXqX=X$X-X-X;X;X;X;X-X-X-X-X-X-X-X$X-X-X*X$X-X+X%X$X+X-X*X+X$X>X+X>X$X-X%X$X+X+X+X*XOX=XqXhXgXgXgXgXgX&XqXqXqXqXX*X*X$X+X*X*X+X*XsXhXgXtXqX|.XXiXeXX+X+X%X+X+X+X+XOX$XqXiX:XXXXXXX=XuX.X|.|.|.|.|..X.X.XX+X@X@X@X+X&XuXuXuX&X&X&XuXuXuXuXuXuXuXuXuXX*X$X+X$X&X&X#X$X#X#X#X&X.XuXuXuX[.,XX+X+X+X$XuXuXuX&X&X%X@X@X@X#X#X#X[.uXuXuXX$X>X%XVXuXbXbXuX;XuX;XuX;X&X&X&X&XX@X@X@X>XVXBXCXCXCXZXZXZXbXbXeXuXuX8X,X,X,X,X,X4X,X,XJ.X>X@X>X>XBXBXBXAXCXIXIXIXIXZXZXbXuXeX8XX@X@X>XBXBXCXAXIXIXPXIXPXIXIXZXCXZXZXeXX+X+X>X>XBXAXIXPXPXLXLXPXPXPXIXCXAXCXCXbX8XX>XCXAXPXPXLXLXLXLXLXLXLXIXIXIXCXCXuX,XM.M.M.M.M.M.J.J.M.M.J.m.J.b.M.H.J.b.J.m.e.J. X(.{.e.m.m.J.J.M.J.,X'._.{._._.#X#X#X#X).).(.).).(.Q.Q.Q.Q.Q.q.P.5XP.5X2X2X3X2X3X2X3XP.2XI.3X3X3X1XI.3XI.3XK.3X1XK.1XK.1XK.K.j.! Q ! ! ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q ! Q ! ! ! ! ! ^ D.K.K.K.K.1XK.K.1X3X3X1XK.3XI.3X3X3X3X2XI.3X3X2X2X2XP.2XP.P.P.6X0XP.P.0XP.0XP.yXyXP.0XP.6X0X6X6XP.0XP.yX6X6X`.).).).(.).#X_.(.).(.Q.Q.Q.S Q.{.{.@X@X>X+X@X>X>XAXIXPXLXLXLXLXLXLXLXLXPXPXIXCXbX,XM.M.M.M.M.M.M.M.M.M.M.M.M.J.M.M.M.M.J.J.m.m.m.m.'.`.(.'.m.m.m.J.[.m.,X'._.{._._._.#X#X_.).).).).Q.Q.(.Q.Q.Q.Q.Q.J.P.3X5X2X3X3XP.2X3X2XI.3X3X3XI.I.3X3XK.1XK.1XK.K.,XK.K.J.1XK.z.^ ! ! ! ! ! Q Q Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q Q ! ! ! ! ^ ^ N.K.K.K.K.K.1XK.K.K.K.I.3XI.K.I.I.3XI.I.3X2XI.I.I.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.0X6XP.P.6X0XP.0XP.7XJ.(.(.).(.(._._._./.Q.(.Q.Q.Q.Q. X@X@X@X@X+X@X@XBXAXIXPXLXLXLXLXLXLXLXLXLXLXIXuX,Xm.M.N.M.M.m.M.b.m.m.M.N.M.M.m.M.b.M.m.M.b.J.m.m.m.m.M.m.e. X'.M.m.e.'.[.M.'.`._.#X_._.'.#X#X_.(.).!.).Q.!.(.Q.Q.W.Q.q.7XP.P.P.P.2XI.P.I.3XI.K.3XI.3XI.K.I.K.K.I.1XK.K.K.K.K.K.K.K.j.! ! ! ! Q Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ! ! ^ ^ B.K.J.K.K.K.K.K.K.K.K.I.I.I.K.I.3XI.3XI.P.I.I.2XP.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.0X0XP.P.0XP.6X5X6X5X5X4Xq.(.).(.(.)._._.(.(.(.W.Q.Q.S Q.@X@X@X@X@XoX@X>XCXIXPXLXLXLXLXLXLXLXLXLXLXZXXBXAXPXLXLXLXLXLXLXLXLXLXPXeX[.M.b.n.b.m.b.m.b.b.b.n.M.b.b.n.M.b.n.b.J.b.J.b.c.J.w.w.m.J.w.w.m.J.J.b.b.m.e.(.'.M.,X(._.#X'.#X#X_._.).(.Q.!.(.(.Q.!.Q.Q.Q.W.e.P.I.I.P.P.I.I.P.P.I.I.K.I.I.I.K.I.K.K.K.K.K.A.K.K.K.K.K.K.M.^ ! ! ! ^ Q ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q Q Q ! ! ! ^ ^ ^ A.K.A.K.K.A.K.I.I.A.K.I.K.I.I.I.A.I.I.I.I.I.I.I.I.I.I.I.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.0XP.P.5X5X5XP.P.5Xq.Q.(.(.!._.#X_.(.W.W.Q.Q.S Q.).].@X{.@X].@X>XVXBXIXPXLXLXLXLXLXLXLXLXnX,XJ.M.M.b.J.n.b.n.b.b.n.n.b.b.b.M.b.b.b.J.b.b.b.c.b.b.w.e.w.J.w.e.e.J.w.b.m.b.b.e.(._.m.m.'.`._.].#X].#X_._.(.Q.(.Q.W.Q.S Q.S Q.W.S K.I.L.P.L.P.I.I.I.I.I.I.I.K.I.I.S.K.I.K.K.I.3XA.A.3XA.K.A.A.^ ! ! ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q ! Q ! ! ! ! ! ^ ^ ^ A.K.K.A.A.K.A.K.A.I.A.I.I.A.I.A.I.I.I.I.I.L.I.I.I.I.I.I.P.P.P.P.P.P.P.P.P.P.P.P.P.0XP.P.P.6XP.5X5X5XP..XQ.Q.Q.W.(._._.`./.Q.W.W.S S Q.{.].{.@X].Q.@X%XBXIXPXPXLXLXLXLXLXLXPXbX,XM.M.M.M.b.c.n.b.b.b.b.n.b.b.b.b.b.n.b.n.b.b.b.n.b.b.J.e.H.e.w.w.e. Xw.m.w.b.b.M.m.q.`.[.m.m.[._.#X'.#X'._.).(./.W.(./.!.S !.W.Q.S Q.J.P.P.P.L.I.I.I.I.I.K.I.I.I.I.I.K.I.A.A.I.A.A.K.A.A.K.K.K.M.^ ^ ^ ! ! Q ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ! ^ / ^ [.A.A.A.A.K.A.A.K.A.S.S.A.I.A.I.S.I.S.I.I.I.L.I.P.L.L.I.L.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.6X5X5XP.q.W.Q.W.Q.(._._._.W.W.W.W.!.Q.Q.].oXoX].!.{.@XVXBXIXPXLXLXLXLXLXLXPX8X[.J.M.m.m.n.b.n.b.b.n.b.c.b.c.b.n.b.b.n.b.n.n.b.b.b.b.b.m.w.'.e.e.w.e.e.w.b.e.m.b.b.b.w.e.e.N.[.M.'.'._.#X_._.`.(.(.Q.!.Q.S Q.!.S S !.S H.I.S.S.P.S.P.S.I.w.r.q.e.m.K.I.K.A.I.A.A.A.I.A.A.A.A.A.B.J.( ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Y Q Q Q ! ! ! ! ! ! ^ ^ ^ A.A.A.A.A.S.S.A.S.A.A.I.A.I.S.S.A.I.I.S.L.L.L.L.L.L.L.L.L.L.L.L.P.P.P.P.P.P.P.P.P.P.6XP.P.6XP.P.P.2XJ.W.Q./.W.W.`._._././.W.W.S W.Q.].'._._.!.{.oX@XVXBXIXIXPXLXLXLXLXJX4XM.M.M.m.n.n.b.n.c.c.c.c.c.b.c.c.b.c.c.c.n.b.c.c.b.c.b.c.b.b.e.e.w.w.w.w.e.J.w.e.w.c.b.v.b.e.e.[.[.N.N.'._.].'._.(.(./.W.Q.Q.!.S Q.S !.S S ~.J.S.P.S.P.S.S.e.D D F F D D r.m.A.A.S.A.A.A.A.A.A.A.A.K.K.^ ^ ^ ! ! ! ! ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Q Y Q Q Q Q ! ! ! ! ^ ^ ^ ^ / B.A.A.A.A.A.A.A.S.A.A.S.S.S.A.S.S.S.S.S.L.S.S.L.S.L.L.S.L.P.L.P.L.P.P.P.P.P.P.P.P.P.6XP.P.P.P.P.P.2Xq.W.W.W.W.W.`.'.`./.W.^./.W.(.(.'.#X{.].Q.@X].@XVXCXCXIXPXPXPXPXKXM.M.M.n.n.N.n.c.c.c.c.c.c.n.c.c.b.b.c.c.b.c.c.c.c.c.b.c.b.n.c.e.e.e.w.w.w.w.w.w.w.w.w.v.b.b.v.v.v.F.`.'.N.'.`.'._._.(./.Q.W.W.Q.S Q.S S !.C !.~.'.S.P.S.S.S.w.4.r.r.D c F c D c D e.M.A.A.A.A.A.A.A.A.A.B.^ ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ! ^ ! / ^ B.A.A.B.A.S.A.A.A.A.S.A.S.A.A.I.S.S.S.S.S.S.L.S.L.S.L.S.L.L.L.P.L.L.L.L.P.P.P.P.P.P.P.P.P.P.P.P.P.J.!.W.W.W.W.(._._.`.W.W.W.W.W.`.`.].{.!.!.Q.].@X>XBXBXCXAXIXIXIXZXM.m.m.b.n.N.c.c.c.c.c.c.c.n.c.c.c.c.c.c.c.c.b.b.c.c.c.b.c.c.n.c.e.e.q.`.q.e.e.q.w.b.w.w.c.w.v.v.N.F.N.`.'.N.N.'._._.`./.(./.Q.W.!.!.D !.S S S W.W.H.S.S.S.S.M.q.q.e.q.r.D F F F c c c F r.b.A.A.A.A.n.A.B.n.( ^ ^ ! ! ! ! ! ! Q Q Y Q Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ! ^ ! ^ ^ / / z.K.B.K.B.B.B.Z.K.L.B.L.A.S.Z.S.Z.S.S.S.S.S.S.S.S.S.S.L.L.L.L.L.L.L.L.L.P.L.L.P.P.P.P.P.L.P.P.P.P.e.!.S W.S S Q._._.`./.S S W.W.`.'.).Q.!.].`._.@X%XVXBXBXCXCXAXCXN.N.n.n.c.c.c.c.c.c.c.c.c.c.c.c.j.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.e.q.q.q.Q.S S S q.w.H.c.v.w.w.g.v.v.v.e.Q.e.N.'.^.`.`.(././.W.W.W.W.S ~.S S S C S D M.L.L.L.r.e.e.v.w.q.r.4.F D F c c M c c F e.A.A.B.A.B.n./ ^ ^ ! ( ! Q ! ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q ! ! ! ! ^ ^ ^ ^ / ^ j.B.B.B.B.B.K.Z.Z.B.Z.B.S.Z.A.S.S.S.Z.S.S.Z.S.S.C.S.S.S.L.L.L.L.C.L.L.L.P.L.P.L.L.P.P.L.P.P.P.P.P.D C W.S !.W.(._.`.8.W.S S W.W._._.!.Q.!.).)._.].$X%X;X;XBXBX;Xm.N.N.c.c.c.c.c.g.c.c.g.g.c.g.c.c.c.c.g.g.c.c.g.j.c.c.c.c.c.g.c.c.w.q.e.q.8.C S E.W.W.q.e.w.e.q.w.w.c.g.g.e./.`.N.'.`././.W./.^.W.W.W.W.S S S !.S ~.Q.D F F w.e.7.0.7.c.w.q.4.D v c D c c c c c c c c 4.w.B.B.z.^ ^ / ^ ! ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Y ! ! ! ! ! ! ^ ^ ( ( / f.K.B.B.B.B.B.B.B.L.B.L.S.A.S.Z.Z.S.S.S.C.S.Z.S.S.S.S.S.C.L.L.L.L.L.L.L.L.L.P.P.P.P.L.P.P.P.P.L.J.C S W.W.W.W.)._.`./.W.W.S /.W.].].Q.!.!.(.).].].%X#XVXVXVX%Xm.j.c.c.j.c.c.c.c.g.c.g.c.g.g.c.c.g.c.g.c.g.c.j.c.c.c.c.j.c.c.c.c.c.0.r.0.e.q.S E.S ~.E.S S q.S S 8.q.w.7.w.w./.W.'.w.^././.W./.W.W.W.W.W.S !.W.S S ~.Q.Q.F D q.r.v.r.r.N.7.4.v c D c c c c c c c c c c c c F r.p./ ( ^ ^ ! ! Q ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Q Q ! ! ! Q ! ! ^ ^ ^ ( ( / &.B.B.B.B.B.Z.B.B.B.Z.B.Z.Z.B.Z.Z.S.Z.S.C.C.S.Z.C.C.C.S.L.L.C.L.L.L.L.L.L.L.L.L.L.L.L.L.L.L.P.L.e.S W.S S S /.`.'.`./.W.Z W./.!.Q.!.Q.!.!.!.!.).].].#X@X@X@X'.c.c.c.g.c.g.g.g.g.v.g.g.g.g.c.g.g.j.g.g.g.g.c.g.g.g.g.g.c.g.g.c.g.h.0.q.q.q.q.Z S C ~.C S ~.D !.~.C S q.w.7.w.8.W.^.e.`.W.W./.W.W.Z W.Z /.S ~.S ~.S C D D F F r.w.v.5.0.N.w.F c c c c F c c c c c c c c c c c c > : ~ ^ ^ ( ! ^ ! ! Q ! Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Q Q Q Q Q ! ! ! ! ! ^ ^ ^ ( ( / &.B.B.B.B.B.B.Z.Z.Z.B.Z.Z.Z.Z.S.Z.C.C.Z.Z.Z.C.C.C.C.C.C.V.L.C.L.L.C.L.L.L.L.L.L.L.L.L.P.L.P.L.I.S S W.S C W./.`._.`./.8.W./.W.!.!.).(.E.E.!.!.].'.#XoX].@X_.w.g.g.g.g.g.g.g.j.h.h.g.g.g.h.g.h.g.g.g.g.h.g.g.j.g.g.h.g.h.g.g.g.g.w.9.q.q.0.q.8.W.C D ~.~.~.C ~.C ~.C Z q.0.7.q.E.W.q.e.W.S W.S E.W.S S W.S C S C S E.!.H.F F H.e.q.4.r.v.7.4.F v F F B 4.c v F F D c c c c c c = . X : K ! / ! ! ! ! ! ~ Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q ! Q ! ! ! ! ^ ^ ^ / / ( 1.B.B.B.B.D.B.B.B.Z.B.Z.B.Z.Z.Z.Z.Z.Z.Z.C.Z.Z.Z.Z.C.C.C.L.C.L.C.L.L.C.L.L.L.L.L.L.L.L.L.L.P.L.J.C C Z S S E./.`._.`.`.^.8./.!.!.).`./.E.E.!.W._.]._.].].{.e.F.g.g.g.g.h.g.g.g.g.h.h.g.g.g.h.g.h.g.g.g.h.h.j.h.h.g.g.g.h.g.g.g.7.q.Z Z q.r.q.8.Z S ~.~.D E.C S C C C S 9.q.w.q.E.W./.q.W.E.W.S W.Z E.Z W.W.C C S C S !.H.U.|.H.4.4.4.r.7.4.q.4.F F 4.4.F F F 4.4.4.4.v F c v c X X . . . ; H ! ~ ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q Q ! ! ^ ^ ^ ^ ( ( / / &.B.B.B.D.B.B.D.B.Z.D.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.S.Z.C.V.C.C.C.C.L.C.L.L.L.L.L.L.L.L.L.L.L.P.e.C C S C C Z W.`._.'.`.`././.W.W.'.'.E.E.W./.!.`.).!.).].`.i.h.u.h.h.h.h.h.u.h.h.g.g.h.h.h.h.j.h.h.h.h.h.h.u.h.h.h.h.h.h.h.h.h.7.Z C S Z 9.q.8.D D q.S D q.D S C C ~.C q.7.w.8.W.W.^.q.8.S Z S S S S C W.E.S C S S C S qXT.NXNXF 4.4.5.r.5.r.0.4.4.4.4.r.4.4.4.4.4.4.r.4.4.F v ; X X X X X . ; H P Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ! ^ ^ ^ ( ( / / / f.z.B.B.D.D.B.D.D.B.D.D.Z.Z.V.Z.V.Z.Z.Z.V.Z.Z.Z.Z.C.C.C.C.C.L.C.C.L.C.L.L.L.L.L.L.L.L.L.L.L.q.C C C C S S /.`.`.`.`.`.`./.W.`.[.'.E.8.e././.(.!.!.!.!.e.u.u.h.h.h.h.h.h.h.h.u.g.u.p.h.u.u.u.h.u.h.h.h.h.u.h.h.h.h.u.h.h.h.h.9.C M C C 9.9.Z Z 8.0.r.e.5.7.q.q.S C D 0.7.0./.W.8.q.^.8.W.C E.Z Z E.C W.W.C C C C S D qXNXT.NX4.4.4.0.7.g.7.h.7.w.g.7.7.v.7.w.v.7.7.7.7.7.7.6.J H H H H : : ; ; ; I ! ! Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ~ ! ! ! ! ^ ^ ^ ( ( ) ) ( f.B.D.z.B.B.D.B.B.D.D.Z.D.Z.V.Z.D.V.V.V.V.V.Z.Z.Z.Z.C.L.l.l.L.l.L.l.L.L.L.L.L.l.L.L.L.L.C.L.D C C C C Z S S /.`.`.`._.^.^.^.'.N.`.^.^.q.`././.!.!.!./.7.y.u.u.h.u.h.u.u.h.u.h.u.h.u.h.u.u.u.u.u.u.h.u.u.u.u.h.u.u.h.h.u.u.7.D C V C Z 9.9.8.A 4.5.7.0.5.7.6.0.D C Z 7.v.e.W./.q.0.8.S C C Z C S C C W.Z C C E.C C C XXT.U.U.q.r.7.7.g.j.j.g.j.j.c.j.g.g.g.j.g.g.j.g.h.7.6.$.H : : : ; ; ; X ; K ! ! ! ~ ~ ~ ~ Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Q Y Q Q Q ! ! ! ! ^ ^ ^ ( ( ) ) ) ) &.z.B.j.D.D.D.D.D.B.D.D.Z.D.D.V.V.V.V.V.V.V.V.Z.Z.Z.Z.l.L.L.l.L.L.L.L.l.L.L.L.L.L.L.L.L.L.Z.c C C Z C C Z Z ^.`.`.`.`.^.^.^.'.[.^.0.0.`.^.^././.^.E.0.u.h.u.u.u.u.u.u.p.u.h.u.u.u.u.h.u.h.h.u.u.u.u.u.u.h.u.u.h.u.u.u.u.i.4.C C C D Z 4.9.D 8.9.0.r.5.0.7.7.5.9.C A 0.w.0.Z ^.q.e.9.C Z C C S Z S C W.Z C C C S C S H.H.q.H.7.v.g.j.h.u.7.7.6.6.7.6.6.6.7.r.6.5.5.4.4.4.4.3 ; ; X X X . ; J ~ ! ! ~ ~ ~ ~ Q Q Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ^ ^ ^ ^ ( ( ( ) ) ) 1.j.D.D.B.D.D.z.B.z.D.D.D.D.D.D.D.D.V.V.D.V.V.V.V.Z.V.L.l.L.L.l.L.L.l.L.L.L.L.L.l.k.L.V.L.b.C C C C C Z S Z ^.^.`.`.`.^.'.N.N.'.^.0.^.0.^.`.^.E.W./.6.y.u.u.u.u.u.u.u.u.u.u.u.u.p.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.0.M M V Z A A Z 9.A Z 9.5.5.0.7.5.5.7.9.C C q.0.0.Z e.0.0.8.C C C C C Z C C S Z C C S C C S q.F G r.J.j.c.g.6.5.4.4.4.v r.4.4.v 4.4.v 4.4.4.v v v ; X X . . X : / ! ! ! ! ! ~ Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ~ ! ! ! ! ^ ^ ( ( ( ) ) ) } z.D.D.z.z.j.D.D.z.D.D.l.D.D.D.D.D.D.D.D.D.V.V.V.V.Z.k.L.l.L.k.L.L.l.L.l.l.L.L.L.L.L.L.L.e.V C C C C C C Z Z W.8.8./.^.0.N.F.'.9.0.^.0.`.0.^.Z E.q.i.u.y.u.y.y.u.y.u.u.u.u.y.u.u.y.u.u.y.u.p.u.u.y.h.y.y.i.i.u.h.y.u.u.B M M V C C D 9.D Z A 4.9.4.9.6.5.7.0.D M C /.7.0.8.e.0.0.8.C C C C C Z C C Z C C C C C C C 8.c x F H.h.h.6.5.4.v v F v v 4.4.4.4.5.4.4.v v v v x X . . . ; ~ / ! / ! ! ! ! ! ~ Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q ~ ~ ! ! ! ! ! ! ( ( ( ) ) ) ` ` ` f.j.z.B.D.D.z.D.z.B.D.l.D.l.D.D.D.D.D.D.D.D.D.V.V.V.L.k.L.L.L.l.L.L.L.L.L.k.L.L.L.k.L.C.r.V C C M C C C C Z C Z S Z E.0.N.[.0.`.0.0.'.0.0.^.W.E.0.y.7.y.y.u.y.u.u.u.y.u.u.y.u.u.u.u.y.u.u.u.y.u.u.y.u.u.u.y.u.y.u.p.6.M M M M C C A B Z D A 9.D A 9.5.7.6.5.C M ~.S 0.6.0.w.0.0.D V C V C Z C C C C Z C C Z Z C Z D x r.c 7.7.7.+.v v x v v v 4.5.5.4.@.v v v v v x x = . . X H ^ / ! ^ ^ ! ! ! ! ~ Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y ~ ~ ~ ! ! ! ! ^ ( ! ^ / ( ) ) ) / _ 1.z.j.z.z.j.B.z.z.z.D.D.l.D.D.l.l.D.D.D.l.D.D.D.D.Z.k.L.L.k.k.L.l.L.l.k.L.L.k.L.L.L.C.C.9.V N C V C V C C C A C Z C A 0.N.N.F.^.0.0.0.0.'.0.Z Z 6.y.y.u.y.y.y.y.y.y.y.y.y.y.y.u.y.p.y.y.y.u.y.y.y.y.y.y.y.p.u.y.p.6.c m M M n M N C V V V A A A V V 5.5.5.A M M ~.C 9.7.0.0.q.9.C V V V V C A C C A C Z Z Z Z C Z V F H.F v 5.5.v v v x x x v v +.5.4.v v x x x x x x X . : I ) ( ( ! / ^ ! ! ! ! ! Q Q ~ Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Q Y Q Q Q ~ ! ! ! ! ^ ^ ( ( / / ( ) ` / _ 1.j.z.z.z.z.z.D.z.D.z.z.D.l.l.l.l.l.D.l.D.l.D.D.D.D.k.L.k.L.k.L.l.L.L.k.L.L.L.L.k.L.C.C.F M V V V c V C N V C C D C A '.F.'.F.0.6.0.F.0.e.`.Z q.y.y.y.y.y.y.y.y.y.y.y.p.y.y.y.y.p.u.y.u.y.y.u.y.y.y.y.u.y.y.y.y.y.v b M b M n M V M M n V D B C M c 5.6.D M M C ~.C 9.7.7.0.0.9.C V V M C C C C V C C C Z Z Z Z Z V v H.r.v v v v x x x x x v v v v v x x x x x x x x ; J _ / ( ( ( / ^ ^ ! ^ ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q ! ! ! ! ! ! ( ! ( ^ ( ) ) / _ _ _ f.z.z.z.B.z.z.z.z.D.l.z.z.l.l.l.l.l.l.l.D.D.D.D.D.l.k.L.k.L.k.L.k.L.L.k.L.k.L.k.L.L.Z.N V V V V V V V N V V N M M A F.F.F.F.0.6.0.'.F.0.0.8.6.y.y.y.y.y.y.y.y.y.y.y.#.y.y.y.y.y.u.y.y.y.y.y.y.y.y.y.y.y.6.y.y.5.M M b M n m M c n M M n A B V M B 5.5.C M M M ~.~.9.0.0.0.0.D M V n V M c V V V V C Z Z Z W.Z Z A F r.r.4 v v v x x x x x v g v x x x x x G x x v $.! _ / / / ( / / ! ^ ^ ! ! ! ~ ! Q ~ Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ! ! / ^ ( ( ) ) ) _ _ _ ` 1.x.z.z.z.z.j.z.z.D.z.z.l.k.l.l.k.l.l.D.l.l.D.D.D.L.k.L.k.l.L.l.L.V.V.L.V.U.l.l.L.l.B.V n V V V V V n V M c M V n E.F.N.F.F.0.6.0.0.0.0.0.0.3.t.i.t.t.i.t.p.t.i.t.y.y.y.y.y.y.y.%.y.y.y.y.t.y.t.y.t.y.y.y.%.6.c M b M b M M M b b M b N B B B V B 5.5.M m M C ~.M 8.6.0.8.9.C V V n M c V V V V V C C A 8.Z ^.8.^.B r.r.v v v x x x x x x x x x s x = x G x 4 v y.1.` ` ) ` ) ) ^ / ! ( ! ! ! ! ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q ! Q ! ! ^ ^ ^ ^ ( / / ) ) ` _ ` ` } p.z.z.z.x.x.z.z.z.z.z.l.k.l.z.l.k.l.l.l.l.l.l.D.L.k.l.k.L.k.l.k.l.L.l.V.L.l.L.l.L.j.n n c M N N N V V n n N V M z F.F.F.j.F.6.0.0.F.0.F.0.F.i.&.t.t.t.t.t.t.t.t.y.%.%.y.y.%.y.p.%.y.t.t.y.y.t.y.y.y.y.t.6.n b b b b b b b c n M M b N B 4.4.B 5.5.B m m C ~.~.V 8.6.0.Z Z M M N N n M V V V V V A Z ^.^.^.^.^.9.D v x v 5.x < v x 4 4 x x x x x G G x x 4 5.j.z.} ' ` ` ) ) / / / ( ^ ( ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ! ^ / ^ ( ( ) ` ) _ _ ` ` f.z.z.z.x.x.x.z.z.z.k.k.l.z.k.k.k.l.l.l.l.l.l.l.k.k.l.L.L.l.L.k.V.V.L.l.l.l.l.L.l.c.n M M c n C n n n n M n n n ^.6.F.F.F.i.i.0.8.0.0.F.3.&.i.i.t.t.t.t.t.t.t.y.y.y.y.t.%.y.y.%.y.%.y.t.t.t.y.t.t.t.y.t.v b n b b b b b b n b M b n c B z 5.5.5.2.B l A W.E.C C 9.5.Z C V M N N n n M V V n N V V A ^.^.^.^.^.^.D v 7.p.5.+.x 1 v x x x x G = G x x x 5.j.z.x.1._ _ / ` ) ) / / ( ( ( ! ! ! ! ! ! Q Q Y Y Q Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Q Y Q ! ! ! ! ! ^ ( ^ ^ / / ) ) ) ` _ ` ` ' } z.f.x.z.x.z.f.z.k.z.k.k.k.k.l.k.l.k.k.l.l.l.l.k.L.l.l.k.k.L.l.l.l.l.L.l.L.L.l.V.j.c n N V n N n n n n N n n N 8.6.F.F.F.i.3.0.0.0.3.0.F.3.3.&.t.t.t.t.t.t.t.t.%.y.%.t.y.%.%.y.%.y.t.t.t.t.t.y.t.t.t.v b b b b b b b M b M b b M n B B v v z 5.5.B A 8.q.^.Z A 9.9.C M M n n n n n n V V n N A Z Z `.^.^.`.^.^.A 7.l.k.x.5.v 5.1 v < G = x = x s 4 y.z.x.x.f.1.' ` _ ) ) ) ( ( ( ^ ^ ^ ^ ! ! ! ! Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q ! ! ! ! ! ! ^ ( ( ( ) ) _ ) _ ` _ ' ' f.f.x.x.x.x.k.x.k.k.x.k.x.k.k.k.k.l.l.z.l.l.l.l.l.l.l.l.l.L.k.l.L.l.l.l.k.l.L.V.j.n N V n n V n n n x n n n n 9.6.F.F.F.i.i.i.0.6.F.F.t.t.t.t.t.t.t.t.t.t.&.t.y.%.t.t.%.y.t.t.y.y.y.%.t.t.t.t.t.6.g b b b n b b b b b b b b b n N B B z B 5.2.2.B 9.9.^.^.9.8.A V C m m m N n n n n V N m N C A ^.^.`.^.^.^.^.A j.k.l.k.x.5.4 4 = G G = = x x 5.f.f.x.f.z.f.{ _ _ _ ) _ ) ( ) ( ( ^ ^ ^ Q ^ ! ! Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! Q ! ! ! ! / ^ ( ( / ) ) / _ _ ` _ ' ' 1.x.f.f.f.x.x.x.x.x.s.k.s.k.k.k.k.k.k.z.k.l.l.l.l.l.l.l.l.l.l.l.l.l.l.L.L.l.l.V.7.N n N N n N n n n n b n a N 9.i.p.i.p.i.i.i.i.i.3.F.t.t.%.t.%.t.%.t.t.t.t.%.%.t.%.t.t.t.&.%.%.%.t.%.%.y.t.%.t.v b b w h n b b G b b b b b b a N B f N N N B z 9.^.8.F.0.6.2.V M M b b m n n n n n V n n N A Z ^.^.^.^.'.'.^.B x.l.k.k.k.s.5.x x = = x x $.#.x.x.f.x.z.f.} { _ ' _ _ / ) ) / ( ( ^ ^ ! ^ ! Q ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! Q ! ! ! ^ ^ ( ( / ) ) / _ _ ` ' ' { } f.x.f.x.f.x.s.x.x.s.k.x.k.k.k.k.k.l.k.l.l.k.l.l.l.k.k.L.l.l.L.l.l.l.k.l.l.l.V.7.N N V N n N n a n a a b n n 9.3.i.F.F.i.t.i.i.i.i.i.t.3.%.t.%.t.] t.t.%.%.t.%.t.t.%.%.t.t.t.t.t.%.t.t.%.%.3.v w b b b b G b b b G b w b G b n n N N n j N f z z ^.0.0.F.0.9.m M M m n n N n n n n N n N l A 8.^.^.^.^.^.`.^.D z.k.l.k.k.k.k.y.+.+.6.p.f.k.x.f.x.f.x.f.f.{ { ' ` _ _ _ ` ) ( ( ( ^ ^ ( ! ! ! Q Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ! ^ ^ ^ ( ( / ) ) _ _ _ _ _ ' ' { O.f.f.x.d.x.f.s.x.s.k.s.k.s.k.k.k.k.k.k.k.l.l.k.l.l.l.l.l.l.l.l.l.k.L.l.L.l.V.7.V N B N n n n n b n h x h x 9.6.y.p.i.i.i.i.i.i.t.i.t.t.t.%.t.] t.%.%.t.] t.t.%.%.t.%.%.%.%.%.t.%.%.%.%.%.v h b p n b b b b b b b b b b b b a n j n b n N N l ~.E.^.0.6.0.z m M V m b M n n b n N n j N V 8.^.^.^.9.^.9.8.^.5.k.k.k.k.k.k.k.k.z.k.s.x.s.x.k.x.f.x.f.f.1.' ' _ ` _ _ / ) ) ) ( ( ^ ^ ! ! ! ! ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ! ^ ^ ( ( ( / ) ` / _ ` ` ' ' ' { { f.x.d.f.x.s.s.x.s.x.s.s.k.k.k.s.k.k.k.k.k.k.l.l.l.R.k.L.L.s.s.k.L.l.l.L.l.l.w.N N N N n n n j h p b p b n z 5.t.i.F.3.F.i.3.i.&.i.t.] 3.%.] %.%.t.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.5.+.2.z n f h h h h h b b h h b b h h b n N j n j N B E.~.E.^.0.0.z V m M n m b n x n x n N n n n B Z ^.8.8.8.A 9.8.8.5.k.k.k.k.k.k.k.s.x.s.s.s.x.s.f.f.x.f.d.f.{ ' ' ` ` ` _ / ) ( ) / ( ^ ^ ^ ! ! Q ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Y Q Q Q ! ! ! ! ^ ^ ^ ( ( / ) ) ) _ ` ` ' ' ' ' { O.f.f.x.d.x.s.s.d.s.s.s.s.s.k.s.k.k.k.k.k.k.k.k.k.l.l.s.k.k.L.L.s.l.l.k.l.l.6.N B N n j n j j a b p b s p z 9.t.t.F.0.F.t.F.i.i.3.t.%.&.%.%.%.t.W %.%.%.%.%.%.%.t.%.%.%.%.%.%.%.$.f w j g 5.g v h b h b w w w w h w h h k n a j j j N 9.B E.!.^.0.0.8.~.k m V n b n l j a j n n a j N A ^.^.8.B A z A 8.^.6.k.k.k.s.k.s.s.s.s.d.x.x.s.d.x.d.d.f.f.O.{ { ` ' ` ` ` ` _ ( ) ( ( ^ ^ ^ ! ! ! ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ! ^ ^ ^ ( ( / ) ) { / ` ` ` ' { { ' | >.f.f.d.s.f.s.d.s.s.s.s.s.k.k.k.k.k.k.k.l.k.k.l.l.k.l.l.k.s.s.k.l.l.l.l.l.i.N A N N n j j x b p p p s w d 9.i.3.3.0.F.t.&.i.&.i.%.] 3.&.] %.] %.%.] %.%.%.%.%.%.%.%.%.%.%.W 2.f w w h z 5.E g b h h w b w b n p h h k k n N N n d 9.5.^.^.^.^.^.8.~.k k M n m b n N n b j j j j k N 8.^.8.9.B N B A 8.^.6.s.s.k.s.k.s.s.s.s.s.s.s.d.d.x.f.f.f.>.{ { { _ ` ' ` / ` / ) ) ^ / ^ ^ ( ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q ! ! ! ! ^ ^ ( ( / / ) ) _ / _ _ ' ' { { { { | f.d.f.s.s.f.d.s.s.s.s.s.s.s.s.s.k.s.k.k.k.k.k.k.l.k.k.k.L.k.k.l.l.l.l.l.h.N A B N n j j p b a x p w x l 9.3.6.9.0.0.t.F.i.3.&.] &.] 3.] ] %.] %.] ] %.] ] %.] %.%.[ %.$.5.f b G w b 2.W W v a w p b p a v z j h h k m f N j b z 9.^.'.'.`.'.^.z k m ~.m n b b j l a b n n n j j N 8.8.A B f N l B 8.A p.s.k.k.s.d.s.s.s.d.s.d.d.d.d.d.d.d.f.=.{ { } _ ' _ ` _ ` ) ) ) / ^ ^ ( ^ ! ! ! ! ! Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ! ( ( ( ( / ) ) _ _ _ ` ' ' { { { { { >.f.d.d.d.d.d.d.d.d.d.s.s.s.k.s.k.k.k.k.k.k.k.k.k.k.l.k.L.k.l.k.l.l.l.l.z.N 8.A l j j j h a p p x b 0 k z 6.3.A ^.i.i.3.F.F.3.&.3.] &.t.] %.] %.] %.] %.W ] %.] W 5.g 2.g g n j a x 2.6.E 2.a h p f v v 2.v k b k k k k k k z 9.^.[.'.'.].^.E.M m m m m b b h N f a a n n j j N A ^.9.B f n n N z 8.4.k.k.k.s.s.s.s.s.d.d.d.d.d.f.d.d.f.d.1.' { ' ' ' ` ' ` _ _ / / / ( / ( ^ ! ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! Q ! ! ! ! ( ^ ( ( / ) _ ) _ ` ` ' ' { { { | { ..a.d.f.d.d.d.d.d.d.d.s.s.s.s.s.s.s.k.s.k.k.k.k.k.l.k.k.s.l.l.k.l.l.l.z.z.z 8.A A N j j p p p p p s s u l 3.t.9.l 9.i.3.3.3.i.] &.] ] ] ] ] ] %.W %.] %.%.%.] $.g p p f v g 1 f f v E E $.2.n a N g g g f h w w h b h ~.k ~.z ^.'.&XuX'.].!.V ~.k m m h b b h a n p n a j j j N ^.^.z N a a f k z z 3.s.s.s.s.s.s.s.d.d.d.d.a.d.d.d.d.d.<.| ' { ' ..' ' _ ` _ _ _ / ) ^ ( ^ ^ ( ! ! ! ! ! Q Q Y Y Y Q Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Y Q Q ! ! ! ( ! ^ ^ ( ( / ) ) } _ ` _ ' ' } { { { { ' O.a.a.a.d.a.d.a.d.d.d.s.d.s.s.k.s.k.k.k.k.k.k.k.k.k.k.k.l.k.l.l.l.k.l.l.B Z ^.A l j p p p p w s s q q n 5.t.3.9.z 6.F.3.F.t.] ] ] ] ] ] ] ] ] ] ] ] ] %.] ] 2.a p w x 2.5.g a a g 2.E E R v f g f f p w p h w b m k k m z ^.'.uXuXuX&X].~.~.m k m b b m h k a a p j l a k j A Z z z f n a a l N 8.6.s.s.s.s.d.d.d.d.d.d.d.a.a.a.f.d.<.=.{ { { ' ' ' _ ' _ / / / / / / / ^ ^ ^ ^ ! ! Q ! Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q ! ! ! ! ! ( ( ( ( ( ( ) ) / _ ` _ ' ' ` ' { { | | | >.a.f.a.a.a.d.a.a.d.d.d.d.s.s.s.s.s.s.s.k.k.k.k.k.k.k.k.k.k.k.k.l.l.k.5.A A A A k p p p p p q q 0 0 p 2.6.3.3.9.5.i.i.t.t.3.&.] ] ] ] ] ] ] ] ] [ [ W W W E a w p f 2.1 p q w j g 5.R 2.g g f p w w q h w k w k k k ~.^.].CXCXuXVX].!.m m m ~.~.h b h h j l p a N n p k z A 8.l l j p a a a z 9.p.s.s.s.s.d.d.a.d.a.a.a.a.f.a.f.a.=...{ ' ..{ ' ' ' _ ` _ / / / / ( ( ( / ! ! ! ! ^ Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q I Q Q ! ! ! ! ! ^ ^ ( / ) ) ) ) _ _ _ ' ' ' { { | { | | O.O.f.a.a.a.a.a.a.d.d.d.d.s.s.s.s.s.k.s.k.k.k.k.k.k.k.k.k.k.k.L.k.k.k.6.E.8.8.A l a p p p q x q 0 q s g 6.t.%.6.3.3.3.t.3.3.] ] ] ] ] %.W ] ] W W W E E E 1 f h p g E g w q w w a v R 2.g x h q w w w p h h h ~.k V W.VXCXCXCXCX&X].E.E.m m ~.m w m b h k a p j j a j k B 8.z l h a a p a a z 5.d.d.s.d.s.d.d.a.d.a.a.a.a.a.a.a.1.| { { { { { { ' ' ' ` _ ) ) ) ) ) ^ ^ ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ( ( / ( ^ ) ) ) ` _ _ _ ` ' { ' { { { | | ..O.a.a.a.a.a.a.a.a.a.a.d.d.s.d.s.s.s.s.s.s.s.k.k.k.k.k.k.k.s.s.k.k.k.p.A 8.E.8.z a p p p q q q 0 0 s a 2.3.%.%.%.3.3.3.0.3.] ] W W W [ ] W E g g a p p s f g f f g g u w q q p s g 2.1 a p q w w p w w h h h k ~.^.].BXCXCXCXCXVX].E.~.l m m w b w w k k a k N a i j l 8.A z a a p p s a a B 6.s.a.s.s.a.a.d.a.a.a.a.a.a.a.f.>.O.| | | { { ' ' ' ` ` _ _ ` ) ) ) ) ) ^ ^ ^ ^ ! ! ! ! Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q ! Q ! ! ! ^ ^ ^ ^ / / ( ) ` ) _ ' _ ' ' ' { { { | | | | | O.a.a.a.a.a.a.a.a.a.d.d.d.d.s.s.s.s.s.s.k.k.s.s.k.k.s.k.k.k.k.k.k.k.z z ^.E.z N p u p q s q 0 0 = q f 3.t.t.] 3.9.z z 9.3.3.W W ] [ W R a s p w q q w a g R R g p q q q q p i 2.E g p q w w q w h w b k m l E.].BXCXCXCXCX&X].!.~.~.m ~.m w k h a l k a j j a a j B 8.z a i p a a s a a f <.s.s.a.a.a.a.a.a.a.a.a.a.a.a.a.O...| | { | { { ' ' ` ` _ _ ) ` ) ) ( ( ^ ^ ^ ! ! ! ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! Q ! ! ! ^ ^ ^ ^ ^ ) ( ) _ _ ' _ ` ' { { ' { { | | ..| | O.>.a.a.a.a.a.a.a.d.d.a.d.d.s.s.s.k.s.s.s.k.k.k.k.k.s.k.k.k.k.k.k.5.z 8.8.A N a p p p q s 0 0 0 0 p 2.3.3.t.3.3.z z 9.t.] ] ] W ] ] $.g a a g g g a g R W W +.i p q q p a R E E g p q w q w p p w h k k E.VXCXBXCXIXCXBX].].~.~.~.~.b b m w u k k i j k a p a N 8.z f i p a a u p p f 5.d.d.d.s.a.s.a.a.a.a.:.a.a.<.a.-.| ..| | { { { { { ' ' _ _ _ ` ) ) ) ( ( ^ ^ ^ ^ ! ! Q ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ^ ^ ^ ^ ( / ( ) ` ` _ ` ` ' ' { { { { { | | ..| | .o.:.a.a.a.a.a.a.a.d.a.d.d.s.s.s.s.s.s.s.s.s.k.s.k.s.k.k.k.k.k.k.6.A B 9.8.N j p p p q 0 0 0 G = = d 2.6.W ] 3.2.9.2.3.[ W E W W ] %.W R g R $.E E E W W W E $.1 g i a 1 R R g i q q w w h p p h h k ~.].VXBXBXCXCXCX].].].!.~.~.m b n n h a a u k j j p i k B B f a u p u p p u u a &.d.s.a.d.d.a.a.,.a.,.a.a.a.a.=. .| ..| | { { { { { ` ` ` _ _ _ ) ) ^ ) ^ ^ ^ ! ! ! ! ! ! Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ! ! ^ ( ( / ( ) ) ( _ ` ` ' ' { { { { { | | | . . .o.>.:.:.:.a.,.,.a.a.a.a.d.s.a.s.s.s.s.s.s.s.s.s.s.s.k.s.k.k.k.s.f.B z z z A l a u p 0 0 q q = = 0 q 2.2.3.] ] 3.3.3.W ] W 2.g W W W Y W R g 1 E W W W E E E E E R R 1 1 g y u q q q i i i p h h k ~.].VXVXBXCXCXCXVX].].E.~.~.~.m m h h u a u p j j u u a z 9.z a p u u u s u u a v s.a.a.d.a.a.,.,.a.,.,.;.>.a.o...| ....| { { { { { { ' ' ` _ _ ) _ ) ) ) ) ^ ^ ^ ! ! ! ! ! Q Y Y Q Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ! ! ! ! ! ^ ^ ^ ( / ) ( _ _ _ ` ` ' ` { { { { | { | ..| . . .o.>.:.a.,.,.a.,.a.a.a.a.,.s.,.s.s.s.s.s.s.s.s.k.k.s.k.s.s.k.k.k.5.z l z A z j p p p u 0 0 0 0 = 7 i 3.2.3.] 3.] ] ] ~ W R f g W W W W R a y R W W R 1 y g R $.1 R 1 g a u u u i d 2.2.d p h h ~.!.VXVXVXVXBXVXVX].].^.~.~.~.~.h b h p i i u k N a u p l A z a u u u 0 q t u u a t.a.d.d.a.a.a.a.a.,.,.,.a.>.:.O. . .| ..| | { { { { ' ' ' ` ` _ _ ) ^ ) ) ( ^ ^ ^ ! ! ! ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y ~ Q Q ! ! ! ! ^ ^ ! ( / ( ( ) ) _ ` ` ` ` ` { { { { { | | | | | . .o.;.:.,.,.,.a.a.a.a.a.s.s.,.s.s.s.s.s.s.s.s.s.s.s.s.k.k.s.k.s.y.l f l z A N i u p 0 0 0 0 0 = 9 9 d 2.2.3.] ] 3.W W W E g i E W U W W 1 g 1 E E 1 u q u i g 1 1 1 1 2 g 1 2.R 2.R 2.d a h ~.!.@X@XVXVXVXVX].].].!.~.].~.~.b ~.k h u y u k l a i u j B B l s u u s 0 0 u s i g d.a.a.a.a.a.a.,.,.,.,.,.a.o.o. .| | ...| { { { { { ' ' ` ` _ _ ) _ ) ) ^ ( ^ ^ ^ ! ! ! ! Q Q Q Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ! ! ! ! ! ^ ^ / / ( ) _ _ _ _ ` ` ' ` { { { { | | | .| . . . .o.:.:.,.,.,.,.a.a.a.,.a.a.a.R.s.s.a.s.s.s.s.s.s.s.s.s.s.k.k.s.g l a f B A l y < , = = = 0 = $ = = a f g %.%.] W E W W E g g E K W W E R R E E R g g y 2 g 1 1 R R R E R R R R 2.d d ~.~.].].].].].VXVX].].].~.].~.~.~.k m ~.w u i u p N l u u k l B f i u u 0 q 0 0 0 u u %.a.a.a.a.a.a.a.,.:.a.:.:.o.o. . .| | .| | { | { { ' ' ' / { _ _ / ) ) ( ( ( ^ ^ ^ ! ! ! ! ~ ~ Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q Q ! ! ! ^ ^ ^ ^ ( ) ( ( _ ` _ ) ` ' { { { { { { | ..| .| . . . .o.;.,.,.,.,.,.a.:.a.a.a.a.,.,.a.s.d.s.s.d.d.s.s.s.s.s.s.s.s.6.a i i f B l < 3 1 > - = = q 0 = = 0 d i f W ] W W W W W E R R E K W W W E K T E L E E R 1 1 1 R R R R R R 1 g 2.2.9.^.~.].].].VX].].].].~.].].~.~.~.~.~.k w u y u h l l u u u l A f u u u 0 0 0 = 0 u u g d.a.a.a.a.a.,.,.,.:.:.:.:.o. . . . .| | | | { { { { { ' ' ` { _ ) _ ) / ( ) ( ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y ~ Q Q ! ! ! ! ! ^ ^ ^ ( ( ( ) _ ) _ _ ` ' ` { { { | | | ..| | . . . . . .o.:.,.:.,.a.a.a.a.a.a.a.a.d.s.d.s.s.s.s.s.d.s.s.s.k.s.s.s.s.g a u a z B g 3 R E < X * = 0 $ = $ t g i g W W ] W W T E W W W W L E L E L W E E R R 1 1 1 2 H R R 1 R 1 1 2.9.A ].].].].].].].~.].~.~.].!.~.~.~.~.~.k h u i u u l z a u u j z z i t q u t 0 0 0 0 u s %.d.a.a.a.a.:.a.,.,.a.:.;.o. . . . .| .| O.| { { { { { ' ' _ ` ` _ / ) ) / ^ ( ^ ^ ^ ! ! ! ! ~ Q Q Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Q Q Q Q ! ! ! ! ^ ^ / ( / ) ) ) ` _ ` ` ' { { { { { { { | | .| . . . . . .*.;.:.:.,.:.a.,.a.a.a.a.d.a.a.a.s.a.a.d.d.s.s.s.s.s.s.s.a.6.a t y a z 2.3 3 K E - X - = 0 = $ 7 , 2.g g E W [ W T E E E E W R 1 g 1 1 E J 1 r < y 1 R 1 R 1 1 R 1 g 2.z E.^.^.^.E.~.].~.~.].E.~.].!.!.~.~.~.~.m h i i y u l z a t u a z z u u t u 0 0 7 # 0 t u 1 a.<.a.a.,.,.a.:.,.:.:.;.o. . . . . . .| .| | | { { ' { ' ` _ ` ) ) { ) ( ( ) ^ ^ ^ ! ! ! ! ! ~ Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q ! ! Q Q ! ^ ^ ( ^ ( / ^ ) ) _ _ _ ` ` ' { ' { { { | | .| | . . . . . .X.*.-.:.a.:.a.,.,.,.a.a.d.a.a.a.s.s.s.s.a.s.s.s.s.s.s.s.s.d.y u u i a 2.E 3 E W > - X - = = & $ = < 2.R 2.3.I 3.K L R 1 R E E 1 r r y 1 R R 1 1 1 R R 2 R R 1 g 2.9.8.z ^.^.^.^.^.~.E.~.~.E.~.~.~.~.~.~.~.m w p u d i p l z a t t p z z i t t t t 0 0 5 0 0 0 s &.a.a.,.,.,.,.:.a.:.:.;.o. . . . .| . . ...| | { { { { { ' ` _ _ _ _ ` ) ) / ^ ^ ^ ^ ! ! ! Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ^ ( ! ( / ) ) ) _ _ _ ` ' ' { { { { { { | ..| . . . . . . . .X.o.;.:.:.:.,.,.,.,.a.,.a.a.a.s.a.a.a.s.,.a.a.s.a.s.s.s.,.5.i t t u g K 3 > J > o * * = 0 0 = = * < 2.2.2.W 3.2.2.R R 2 2 R R R g r r r 1 H H R H 1 1 2 1 g z B A A z A z E.~.z z E.~.~.E.].!.~.~.~.~.~.w w t i y u l z l t 0 p l z i u 9 u t 0 7 = $ 7 0 0 W a.a.,.,.,.,.:.:.:.:.-.o. . . . . . . .| | ..| | { { { { ' ' ' ' ` _ ) ) ) / / ) ^ ^ ^ ! ! ! Q ! ~ Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ^ ^ ! ( / ) ) _ / _ _ ` ' ' ' { { | { | | ..| | . . . . . .X.X.X.o.-.:.:.,.,.,.,.,.a.a.a.a.a.,.s.a.a.s.s.s.a.s.a.a.s.s.%.k t 9 t g W E ; * 3 ; X X X * = 0 $ $ % r R 2.W W 3.2.d 1 H 1 2 2 H R 1 r r r 1 2 2 1 1 1 g g z l l k k k k l z z ~.E.z ~.~.~.~.~.~.m m k k w k y y k l z k u 0 u z z i 9 0 0 u 9 0 # $ = 0 0 g d.a.,.,.,.,.,.,.:.:.-.o.o. . . . . . . .| | ..| | { { { { ' ' _ ` _ _ ) ) ) ( / ^ ^ ^ ^ ^ ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q Q ! ! ! ^ ^ ^ ( ( ) ) ) _ _ _ ` _ ` ' { { { { { | .| | . . . . . .X.X.X.X.o.-.:.;.,.,.,.,.,.a.a.,.,.s.,.s.a.a.a.a.s.s.a.s.d.d.f.l d u e e E U H - X 2 3 - X X & 7 $ @ @ e r R 2.R 3.2.2.R R 1 r 2 2 R H R 2 H 1 2 2 2 r i k u h u k k k k m l ~.z ~.~.~.~.~.m k m m k k 9 u w u a z z i t e u z z i e 0 9 0 0 7 $ $ = & # & &.<.,.,.,.,.,.:.:.:.-.X.X.o. . . . . . . .| | | | { | { { ' ' ' ' ` _ _ ) / ) ( / ) ^ ^ ^ ! ! ! Q Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Q Y Y Q Q Q ! ! ! ! ! ^ ^ ( ( ^ ) ) _ ` ` ` ` ` { ' { { | { | | | .| . . . . . .X.X.X.X.*.*.;.,.;.,.,.,.,.,.,.,.a.a.a.a.a.a.s.a.s.s.a.s.s.<.f z a t 7 < H E H X X ; H > + X * 7 7 $ = = $ s g R 2.2.2.2.2.R R r 1 1 2 1 2 1 2 2 y i u u u u i k k u k l l k k ~.~.k b m h m m b k u 9 e r i l z l i t 0 y l l y 9 9 t 0 9 7 # $ $ 6 = 7 W ,.,.a.a.:.,.:.:.;.o.o.X.X.X. .X. . . . .| .| | | { | { { ' ' ' ' { / _ _ ) ) ( ( ^ ^ ^ ^ ! Q ! ~ Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ~ ! Q ! ! ^ ^ ^ ^ ( ) ) ) ) ) _ ` ` ' ' ' { { { { | | ..| . . . . . . .X.X.X.X.X.o.-.;.,.,.,.,.,.,.a.,.a.a.a.a.a.a.a.a.a.a.a.a.a.p.s l z a u e , ; 3 2 * X ; R > X X , 7 = $ $ $ $ & y g 1 R d 2.2.2.2.R R 1 1 r r y d d d i i i i i k u k k l m k k k k k k k k w w w e e e i k l B l u e t i l z r e 9 9 0 0 9 5 $ $ = = 5 1 a.,.,.,.:.:.:.:.-.*.o.o.X.X.X. . . . . .| . .| | | | ' { { { ' ` ' ` / ) ) ) ) ^ ( ^ ^ ^ ! ! ! ! ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ~ ! ! ! ^ ^ ^ ^ ) ) ) ) ) _ ` ` ` ' { { { { { | | ..| . . . . . .X.X.X.X.*.X.X.*.*.-.;.,.;.:.,.,.,.,.a.,.a.a.,.a.a.a.a.a.s.a.&.0 u k z d u e ; X - : ; X ; 3 ; X * 0 0 0 $ $ $ $ = 7 0 r r 2.2.d 2.2.2.R 2.R g g d g d d d i k w k k k k k h h w w k k h w w u 9 9 9 t i k z z f t 9 e k z d e 9 7 9 9 0 5 $ O * $ $ # < f.,.,.:.:.:.:.:.-.*.o.o.o.X.X.X. . . . . . . .| ..| { ' | ' { ' ` ' ` { / ` ` ) ) / ( ^ ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! ! ! ! ! ^ / / ^ ) ) ) _ _ ` ` _ ' ' { ' { | { | ..| | | . . . . . .X.X.X.o.*.X.X.*.-.;.;.,.,.,.,.,.,.,.,.a.,.a.a.a.a.a.a.a.1 9 9 e i l f t e , X - ; ; X - 3 ; X $ 7 0 5 = $ $ $ $ = e e r d R 2.R d d g g g g d i a i k p p w u w q w w w w w w w w t e 9 9 9 9 i i z z l i t 9 u i z d e 9 7 7 9 7 5 = + O $ $ $ & ] >.,.,.,.:.:.;.-.o.o.o.X.X.X.X. . . . .X. .| | | ..{ | | ' ' ' ' ' ' ` _ _ / ) ) ) / ( ^ ^ ^ ! ! ! ! Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q ~ ! ! ! ^ ^ ^ / ) ( ) _ _ _ _ ` _ ' ' ' { } | | | ..| .| . . . . . .X.X.X.*.X.X.*.*.*.-.-.,.,.,.,.,.,.a.,.,.a.a.a.a.a.d.d.3.9 9 8 e t u z i t , , ; ; ; - X X 3 ; $ 5 7 7 7 5 $ $ $ $ $ 5 9 0 r r y y y y y t r y i u u q q q 9 w q q q w q w w w 9 e 9 6 6 9 u i l z z k i 9 9 t l l y t 7 7 7 9 0 5 $ O * = $ $ = W ,.,.:.:.:.;.;.*.*.o.o.o.X.X.X.X. . . . . . .| .| ......{ { { { ' ' ' ` _ _ / ) ( ( ( ( ^ ^ ^ ! ! ! Q Q Q Y Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q Q ! ! ! ^ ! ^ / ) ( ( ) _ ) _ ` _ ' ' { { { { { | | ..| .| . . . . .X.X.X.X.X.X.*.X.*.*.*.-.;.,.;.,.,.,.,.,.,.:.a.a.a.a.W e e 9 9 u u e i l t t & & - * X X X X ; * 5 7 7 7 0 7 5 $ $ $ $ $ 5 6 e e e t y y t r y i r t t 9 9 q 9 9 9 9 9 9 9 9 w 6 9 9 e r i k l z k i 9 9 e i z d r e 7 6 7 9 7 5 $ o O $ & * $ $.<.,.,.:.,.:.-.*.*.*.o.o.o.X.X.X. . . . .X. . . .| ..| { ' { ..' ' ' ' _ ` _ ) _ ) ) ( ( ( / ^ ! ! Q ! Q ~ ! Y Y Y Q Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Q Q Q ! ! ! ^ ^ ^ ) ) ) ( ( ) ` _ ' _ _ { { { { { { | ..| | . . . . . . .X.X.X.*.*.X.*.*.*.*.*.-.-.;.,.,.,.,.,.,.a.a.a.a.E i u 9 0 i k u 9 u f e 7 6 5 7 & , = , - * $ 7 q 5 5 0 7 7 0 5 5 $ 5 $ 5 5 @ 5 6 8 0 t e t e t e e 9 e 9 9 9 9 6 6 5 5 9 9 9 e i d k l z z i e 9 9 u k f y t 8 6 # 7 7 5 $ O o o * & O O E <.:.,.:.;.;.*.*.*.*.o.o.*.o.*.X.X.X. . . . . .| | ...| ' | { ' ' ' ' ' ` ` / ` ` ) / / ( ^ / ^ ! ! ! Q Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ! Q ! ! ^ ^ ^ ( ^ ) ) ) _ _ _ _ ' ' ' { ' { | | | ..| .| . . . . .X.X.X.X.X.X.*.*.*.*.*.*.-.-.-.;.;.,.,.,.,.:.:.a.1 y e 6 7 i k u 6 9 i d e 8 7 7 $ 6 8 e y a i q 7 5 5 7 5 7 7 7 7 7 7 5 5 5 5 5 # $ $ $ # & 6 6 9 6 5 5 5 5 5 5 5 % 6 6 e 9 u k d k z l l i e 9 9 t d d d r e 8 6 % # 5 5 $ O o o + = * O E ,.,.:.:.;.-.-.*.*.*.*.o.o.X.o.X.X.X. .X. . . . . .| | ..| | | { | ' ' ' ` ' _ _ _ / ( ( / ( ^ ! ! ^ ! ! Q Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q ~ ! ~ ! ^ ^ ^ ( ^ ) ) ) ) _ _ ` ' ' ' { { { { | | | | | . . .X. . . .X.X.X.X.o.o.o.*.o.*.o.-.-.-.-.-.;.,.,.,.,.1.r r e 9 9 k a u 9 9 u l y 8 5 5 $ $ $ $ 5 8 y d f i 9 5 7 7 7 5 9 6 9 9 7 9 9 9 7 9 e e e 9 7 & & % $ * # & 6 6 6 9 e e i i d k l l l d i e 9 9 9 k d d r e e % # # # 6 $ $ o o o o * * O T ,.:.,.;.-.-.-.-.*.*.*.*.o.o.X.X.X.X.X. . . . . . .| | | | ' | ' { { { ' ' _ ` _ _ / ) ) ( / ( / ^ ^ ! ~ ! ~ Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Q Y Y Y Q Q Q ! Q ! ! ! ^ ^ ^ ) ^ ) ) ) ) _ _ _ ` { ' { { { { { | | | | . . . . . .X.X.X.o.o.o.o.o.*.*.-.o.-.-.-.-.-.;.;.;.1.r y e 9 9 i k e 9 9 u z d e 8 5 5 $ $ $ $ $ 5 7 e i l l u 9 7 7 6 9 9 9 9 9 9 9 t t t t t e r t t e e e e e t e i r y d d d l l l l i t 9 6 9 e i d d i e e e # # # 6 7 # O o o o o * + * $.,.,.:.;.;.-.-.-.*.*.*.*.o.o.o.*.X.X.X.X. . . . . . . . ...| | ' | { { { ' ' _ _ _ ) ` ) ) ( ( / ! ^ ! ! ! Q ! Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I Q Q ! ! ! ^ ^ ^ ( ) ) ) ` ) _ _ ' _ _ { { { { | | | .. . ...| . . . . .X.X.X.o.o.o.o.*.*.o.-.-.-.-.-.-.-.;.#.r e 9 6 9 k u t 6 9 i l d e 7 & $ $ # = $ $ $ $ 6 8 8 r d d k u e 9 6 9 9 q 5 9 9 t t 9 t t t u i u y u u i y i d d d l z z l i i t 9 9 9 9 t i d d i e e 6 6 5 $ # # % $ O o o o + + , W :.:.-.;.-.-.-.-.-.*.*.*.*.o.o.o.X.X.X.X. . . . . . . .| | ..' | ' ' ' { ' ' ' ` ` _ ` ) ) ) ( ( / ^ ^ ! ! ! Q Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q ~ Q ~ ~ ! ! ^ ^ ^ ( ) ( ( ) _ _ _ ` ' ' ' } { { ' ' | | ..| . . . . . . .X.X.X.X.o.o.o.o.*.-.o.-.-.-.*.-.-.W ; e 9 6 9 i i 9 9 9 u d y e % 6 % $ $ $ 5 $ 5 $ @ $ # 6 7 e e d l k u t 9 7 7 5 9 9 9 t e t u u i u i i a d d a f k d d i i t e 9 6 6 9 9 i d d y r e 9 9 5 @ @ 5 $ # 5 $ o o o X o + , 1.:.;.;.-.-.-.-.-.-.*.*.*.*.o.*.o.X.o.X.X.X. . . . . . . .| ..| | | | ..{ { ' ' _ ` _ / / _ ( ( ) ( ! ^ ^ ! Q Q ~ Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Q Q Q Q ! ^ ^ ^ ^ ) ) ( ( ` ) _ _ _ ' ' ' { { { { | | | | | . . . . . .X.X.X.X.X.o.o.o.-.o.-.-.-.-.-.-.E , e 6 5 9 i u 9 6 9 i d i e 6 6 6 $ $ O # # @ % 9 % $ $ $ $ 6 5 6 e y d d d u e 9 6 7 6 9 9 9 e e 9 t 9 e t t t 9 9 9 9 9 9 9 6 9 9 u u d d d r e e 6 % 5 @ @ @ @ @ # % + o o o 1 ;.;.;.;.;.-.-.-.*.-.-.*.*.*.*.X.o.X.X.X.X.X. . . . . . .| | | ..| { | | ' { } ' ` ' ` _ ` ) ) ( ( ( ( ^ ^ ! ^ Q ! Q Q Q Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ~ Q [ Q ! ! ^ ^ ) ^ / _ ) ) _ _ _ ` _ ' ' ' { ' | | | | .| . . . . . . . .X.X.o.o.o.o.o.-.o.o.o.-.o.3 e e 6 5 9 i u 9 5 6 i l i e 6 6 6 7 6 $ $ & 7 % e e e e $ $ + @ 5 5 5 6 9 i i d d k i u q 9 9 9 9 7 7 9 9 9 9 7 7 7 9 9 6 9 9 t i i i d d r e e 6 6 6 @ @ O + O @ # # @ o o o o * $.;.-.;.;.;.-.-.-.-.-.*.*.*.*.*.o.o.o.*.*.X.X.X. . . . . . . . .| { | { ' ' ' ' ' ` ` ` _ _ / ` ) ( / ^ / ^ ^ ^ Q Q Q ! Q Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y I Q Q ~ Q Q ! Q ! ^ ^ ^ ^ ) ( ) ) _ _ _ ` ' ' ' { { ' { | | | .. .| . . . . . . .X.X.*.o.o.o.o.o.-.-.o.} , e 9 5 # 9 i u 6 5 6 i d r e 6 5 5 6 7 7 $ % # 7 6 & , e e e $ O O O @ @ @ 5 5 6 e e i d d d k d i u u t t t t 9 t e u u i d d d d d r r e 6 9 6 5 @ @ O + o + @ % @ @ o . 3 1.;.;.-.;.;.-.;.;.-.-.-.-.*.*.*.*.o.*.X.X.X.X.X. . . . .X. . .| | ..| | | | ' | ' ' ' ` ` _ _ _ ) ) ) ^ ( ^ ( ^ ! Q ! Y Q ~ Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y I Q Q Q Q Q Q Q ! ^ ^ ^ ^ ) ) ( ) ) ) _ ` ` ` ' ' ' ' | ' { | ..| | . . . . .X. . .X.X.X.X.o.o.o.o.-.[ , e & 5 5 9 u u 9 5 6 r d y , % # 5 & 6 5 5 5 $ O + * + + & e r e $ $ O O O @ @ @ 5 5 5 6 6 e t r i y d d d d i d d l d d i i r r e e 6 6 5 @ 5 5 5 O O O + @ + @ @ @ o . ; %.;.;.;.;.;.;.;.;.-.-.-.-.-.*.*.*.*.o.*.X.*.X.X.X.X. . . . . . .| .| .| | | ' ' ' ' ' ' ' ` _ ) ) ) ) ( / ( ^ ^ ! ! Q Q Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Y Q Q Y Q Q Q ! ! ^ ^ ^ ) ( ) ) ` _ _ _ ` _ { { ' { { { { | | | . . . .| . . .o.X.X.*.X.*.o.o.*.W 9 9 6 6 6 9 i e 9 5 5 i d d e % @ 5 6 6 @ 5 @ @ o o o + $ 9 e e 6 % + @ O @ 5 @ 5 @ @ 5 5 5 5 5 5 6 8 8 9 9 9 e e 9 6 6 & 6 % % @ @ 5 @ O O @ @ @ @ O @ O O o . . E -.-.:.-.:.-.:.;.;.-.-.-.-.-.-.*.*.*.*.o.o.o.o.X.X.X. . . . . .| . .| | | | { { } { { ' ' _ ` _ ` _ ) ) ) ) ) ^ ^ ^ ! ! ~ Q Q Q Q Q I Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Y Q Q Q Q ! ^ ^ ^ ^ ^ ) ( ) _ ) _ ` _ ' ' { { { { { | { | | | . . . . . . .X.X.X.X.X.o.*.J 6 9 6 5 6 9 u u 9 5 6 k d r e % @ % 6 6 5 5 @ o * T &.] W 2 8 e 9 e % # @ @ 5 @ 5 @ @ @ @ @ @ @ @ @ @ 5 5 @ 5 @ # # 5 6 % 6 @ @ @ O O O O @ 5 @ O o . 2 ] :.:.:.-.;.-.-.:.-.;.-.;.-.-.-.*.*.*.*.o.o.o.o.X.X.X.X. .o. . . . . . .| | | { | { { { { ' ' _ _ _ ) _ ) ) ) ^ ^ ^ ^ ^ ! ~ ! Q Q Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Y Q ! Q ! ! ^ ^ ^ ( ) ( ) ) ) _ _ ' _ ' ' ' { { | | | | | .| . . . . . .X.X.X.X.o.| 2 6 9 6 5 9 t u e 6 6 6 i d r e @ 5 6 5 6 6 5 @ O o E >.:.:.:.:.:.W 2 6 & e e 6 6 5 6 % 5 @ @ @ @ @ @ @ @ @ @ O O O @ @ @ @ @ # @ @ O @ O @ 5 @ O o o . . . . o 2 ] -.:.:.;.;.-.;.;.-.-.;.-.-.-.-.*.-.*.*.*.*.o.o.o.o.X.X.X.X. . . . .| . .| ..| | { { { { { ' ' _ } _ _ ) ` ) ) ^ ) ^ ^ ^ ! ! ~ Q Q I ~ Q Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Q Y Y Q Q Y Q Q Q Q ! ^ ^ ^ ( ( ) ) ) ) _ _ _ _ ` ' { { ' { { | | O.| | . . . . . . . .X.X.( , 9 6 5 5 9 9 u e 6 5 9 i z i 6 6 @ @ @ 6 5 5 @ O o + + o R ;.:.:.:.:.:.:.a.:.W , 6 % , r , % % 6 5 % 6 # 5 5 5 @ # @ # @ @ @ @ @ % % @ @ @ @ 6 @ @ O o . . . ; [ -.:.-.:.:.;.;.:.;.;.:.-.-.;.-.-.-.-.*.*.*.*.o.o.o.o.o.X.X.X. . . . . . . .| | ..| | | { { { ' ' ' ' ) _ _ _ ) ( ) ) ^ ^ ^ ^ ^ Q ~ Q Q ~ Q Q Y Y Y Q Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I Y Q Q Q ! ^ ^ ^ ( ( ^ ) ) ) ) _ ` } ' ' ' { ' { { { | | | .| . . . . . . . .I & e 6 % 5 9 u u 9 6 5 e i l r e 6 % @ 6 6 6 @ @ O o O & * 2 :.:.:.:.:.:.:.:.:.:.:.:.W , @ & % @ * @ * & & 8 6 6 & % % 6 % % % % % 6 % % @ % * @ + + . . . X : ] :.;.;.;.:.;.;.;.;.-.;.;.;.-.-.;.-.-.-.*.*.*.*.*.o.o.X.X.X.X.X.X. . . . . . . .| .| | | { { ' { ' ' _ ' ` _ ) ` ) ( ) ^ ^ ^ ^ ! ! ~ Q Q Y ~ Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Q Q Q Y Q Q Q ~ ! ^ ^ ^ ^ ) ) ) ` _ _ _ _ ` ` ' ' { { { | { | | | .| . . . . . .J % e 6 5 6 6 u u 9 6 6 e i d d 6 5 @ % % 5 6 5 @ O o o @ * * O.:.:.:.:.:.:.:.:.:.:.:.:.:.a.W 2 5 @ + + + o + + * % % & , 6 , & % % * * * , , + + o . . . . + E 1.:.:.:.:.;.:.;.;.-.;.;.;.;.;.-.;.-.-.-.-.-.*.*.*.*.o.*.o.X.*.X.X.X. . . . . . .| | | ..| { { { ' { { ' ' _ _ _ _ _ ) ) ) ^ ) ^ ^ ^ ! ~ ~ Q Q Y Q Y Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I Q I ~ ~ ! ^ ^ ^ ( ) ) ) ) _ ) _ _ _ ` ' ' { { { | | | | | | . . . . . .2 % 6 6 6 6 9 u t 9 6 6 e i d r e 5 5 5 5 6 6 5 5 @ o o @ @ @ W ;.:.;.:.:.:.:.:.:.:.:.:.:.:.:.:.;.O.W , * + + o o o o + o o + + + + o + . . . o o o , 3 W >.:.:.:.;.:.:.:.:.;.;.:.;.;.;.;.-.-.-.-.-.*.-.*.*.*.*.o.o.o.o.X.X.X.X. . . . . .| .| | ..| | | { { { { ' ' ' _ _ _ _ ) ) ( ( ) ^ ^ ^ ^ ! [ Q I Q I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q Y ~ Q I ! ! ^ ^ ) ^ ) ) ) ) ) _ _ _ _ _ { ' { ' { { { | | | | . . .{ : 6 e 6 6 6 9 e t 9 9 6 e i d r e 6 6 5 @ 6 6 6 5 @ + o + * @ 2 ;.:.:.;.:.;.:.:.:.:.:.:.:.:.:.:.:.a.;.a.a.} W 2 * + o + o o o . o + o + , H E ] :.:.:.;.:.;.:.:.:.-.;.;.;.;.-.;.;.-.;.-.-.-.-.-.-.*.*.*.*.*.o.X.X.*.*.X.X.X. . . . . . . . .| | | | { { { { ' { _ _ _ _ _ ) ` ) ) ( ) ) ^ ^ ! ~ I Q Q I Y Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I Q I ~ ~ [ ! ^ / ) ^ ) ) ) ) ` ) _ _ ' ' ' { { { { { | | | | .| ^ , 5 6 6 5 6 9 u e 9 6 6 9 d z r e % 6 5 6 5 5 5 5 @ O o o & * , 1.;.;.:.:.;.;.:.;.:.:.:.,.;.:.:.:.:.:.:.:.:.:.:.:.>.} W E 1 , * * * + + + + X * X , ; 2 2 R E W ] 1.:.:.:.:.;.:.:.:.:.:.;.:.:.;.;.;.;.;.-.;.-.;.;.*.;.*.-.;.*.*.*.*.*.o.o.o.X.X.X.X. . . . . . . .| .| | | | { { { { { ' ' _ ' _ _ ) ` ) ^ ) ^ ^ ^ ^ ! ! ~ Q Q Y I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Y I Q I I ~ ! ! ^ ^ ) ^ ) ) ) ) _ _ _ _ ' ' ' { { { | { | ..| | I , 5 6 6 5 6 9 u u 9 9 6 e k d r r 6 @ @ 5 @ 6 5 5 @ O o @ * @ U ;.;.:.;.;.:.:.:.:.:.:.;.;.:.:.:.:.:.:.:.:.;.:.:.:.:.:.a.:.:.;.>.1.1.1.1.1.O.>.>.-.-.:.:.;.:.;.-.:.:.:.;.;.:.:.:.:.;.;.;.:.;.;.;.;.;.;.;.;.;.;.;.;.;.;.*.*.*.*.*.*.*.o.o.o.X.*.X.X.X.X. . . . . . . .| ....| | { { { { } ' ' ' ` _ _ ` ) ) ) ) ) / ^ ^ ! [ ~ Q I I Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I Q Q [ ~ ! ^ ^ ^ ^ ) ) ) ) ) ` _ _ ` _ ' ' } { { | ..' ) E 2 @ % 5 5 5 6 9 u e 9 6 9 e d z r e 6 @ 5 6 5 6 6 5 @ O o o @ @ 2 o.;.;.;.;.:.:.:.;.:.;.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.;.;.:.:.:.:.:.:.:.:.:.:.:.:.;.:.:.;.;.:.:.:.:.:.;.;.;.:.;.;.;.;.;.;.;.-.-.;.;.-.*.;.*.;.*.*.*.*.*.o.o.o.o.X.X.X.X.X.X. . . . . .| | ...| | { { { { ' ' ' _ ` _ _ ) ) ) ) ) ^ ) ^ ^ ! [ ~ ~ ~ ~ I I Q Y Y Q Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Y Y Y Y Q Q I Y ~ I ~ I ! ^ ^ / ) ^ ) ) ) _ ) _ _ _ ' ' ' { ' { ' &.4 2 % 6 6 # 5 6 e e 9 9 6 9 e d d d e 6 % @ @ % 6 6 % 5 O o o o O @ , O.;.;.-.;.;.;.;.;.:.;.:.;.:.:.;.:.;.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.;.:.:.:.:.:.:.;.;.;.;.:.;.;.;.;.;.-.-.;.;.-.;.-.-.-.;.*.*.*.*.*.*.*.*.o.o.o.o.X.X.X. . . . . . . .| .| .| | { | { { { ' ' _ ' _ _ ) _ ) ) ) ) ^ ^ ^ ^ ! Q ~ ~ ~ I Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q I Q I Y Y Q [ ! ^ ^ ^ ^ ( ) ) ) ) } _ _ ' _ ' { ' { { ( G.4 < 5 6 # 5 5 9 e e 6 6 9 t k z r e e 5 5 5 5 6 6 5 5 @ o o o + + @ W -.-.;.;.;.;.;.;.;.;.:.:.;.;.;.:.:.:.:.-.:.;.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.;.:.:.:.;.:.;.:.;.;.:.:.;.;.;.;.;.;.;.;.;.;.-.;.-.;.-.-.-.-.-.*.*.*.*.*.*.o.o.o.o.X.X.X. . . . . .X. . . .| | ..{ { ' | { { ' ' ' ` ` _ _ ) ` ) ) ) ( ( ^ ^ ^ ! Q Q Q I I Q ~ Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I Y ~ Y Q Y ! ^ ^ ^ ) / ) ) ) / _ _ ` ` ' ' ' { ) H.T.> = 6 # # 5 9 e e 9 6 9 e d d d e 6 6 6 @ 5 5 6 6 5 O O + + @ 2 o.-.;.;.;.;.;.-.;.;.;.;.;.;.:.;.,.;.:.:.:.:.;.-.:.:.;.:.:.:.:.:.;.:.:.;.:.:.;.;.:.:.;.:.;.:.:.:.;.:.:.:.;.;.:.:.;.;.;.;.;.;.;.;.;.-.;.-.;.;.-.-.-.-.-.-.*.*.*.*.*.*.o.o.o.o.X.X.X.X.X.X. . . . . .| | | ..| | { { { { { { ' ` ` ` _ ) ` ) ) ) ( ( ^ ^ ^ ! ~ ~ I Q I ~ Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I I Y Y Y Q ^ ^ ( ( / ( ) ) ) ) _ _ ` _ ' ' ) H.T.U.4 * 6 % 7 8 e 9 9 6 9 i d z d 9 9 6 6 6 % 6 @ 6 @ @ O o o o + @ , 1.;.;.-.-.;.;.;.;.;.;.;.;.;.;.:.;.;.:.;.:.;.:.:.:.:.:.:.:.;.:.;.;.:.;.-.:.:.:.;.:.:.:.:.;.:.:.:.:.;.;.;.;.:.:.;.;.;.-.;.;.-.;.;.;.;.;.-.;.-.-.-.-.-.-.-.*.*.*.*.*.*.o.o.*.X.X.X.X.X. . . . . . . .| | | .| | | { { { { ' ' ` ` ` _ ` _ ) ( ) ( ) ^ ^ ^ ^ ~ ~ Y Q Y I I I Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q ~ U Y Y Q Q ! ! ^ ! ( / ) ) ) _ ) _ ` ` _ _ @.T.T.Y.4 - 7 7 t t e 9 6 9 u d z r e 9 6 5 6 @ @ 6 6 5 @ @ o o + O $ Y *.-.;.-.;.-.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.:.;.:.:.;.;.:.;.:.:.:.:.:.:.:.;.;.:.:.;.:.;.;.:.;.;.:.;.:.;.:.;.;.;.;.;.;.;.;.;.;.;.;.-.;.-.-.-.;.-.-.-.*.-.*.*.*.*.*.o.o.o.o.X.*.X.X.X.X. . . . . . . .| ...| | { { { { { { ' ' ' ` _ _ ) ` ) ) ( ( ( ^ ^ ^ [ Q I Q Y U I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q Y I I Y I ~ ! ^ ^ ^ ^ / ^ ) ) ) ` ) _ ` [ 4 T.T.Y.Y.R.> t e t e 9 6 9 i d z r e 6 6 @ 5 5 5 5 5 6 5 @ o + + * 1 -.-.-.;.-.-.-.;.;.-.;.;.;.-.;.;.;.;.;.;.;.;.;.;.:.:.;.:.;.:.;.;.:.;.;.:.;.:.;.:.;.:.;.:.;.;.:.;.:.;.;.;.;.;.;.;.;.;.-.;.;.;.;.;.;.;.;.-.;.-.-.-.-.-.*.*.*.*.*.*.o.o.o.o.o.X.X.X.X.X. . . . . . . .| | | ..| | ' | | { { { ' ` _ ` _ ) _ ) ) ) ) ^ ^ ^ ^ ! Q Q Q I Q U Q Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Q I I I Q I I ! ^ [ ^ ^ ) ) ) ) ) _ ) _ +.@.Y.T.Y.Y.Y.@.< t e 8 9 9 r d 2.r e 6 6 @ 5 @ 5 5 6 5 @ @ o o o o + + , O.:.o.-.-.-.-.-.-.;.;.;.;.-.;.;.;.-.;.;.-.;.;.;.;.;.;.;.;.;.;.:.:.;.:.:.;.:.;.:.;.:.;.:.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.-.-.;.;.*.;.*.;.*.-.-.-.-.*.*.*.*.*.*.o.o.o.o.X.*.X.X.X. . . . . . . .| .| ...| | ' { { ' { ' ` ' _ ` ` _ _ ) ) ) ( ) ( ^ ^ ^ Q ~ I Y I U I Q Q Y Y Q Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y I I I Q I ~ ! ^ ^ ^ ) ^ ) ) ) ) } $.G.G.T.T.Y.Y.T.U.4 < & 7 9 i d z d e 6 6 % @ @ 5 6 6 5 @ O O o o o * + % [ o.o.-.-.-.-.-.-.-.-.*.*.;.;.;.-.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.-.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.-.;.;.;.;.;.;.;.;.;.;.-.-.;.;.-.-.-.-.;.*.;.-.-.-.*.*.*.*.*.*.o.o.*.X.o.X.X.X.X.X. . . . .X. . . .| | ..| | | { { { { { ' _ _ ` ` ) _ _ ) ) ( ( ( ( ^ ^ ! ~ I I I I U Q Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Y I I I I Q I Q ^ ^ ^ ^ / ^ ) ( ` T U.H.G.T.T.Y.Y.T.T.G.- = = i d z r e 9 6 5 5 6 6 5 6 6 5 @ O o + + @ H o.;.o.o.o.-.-.-.-.-.-.;.;.;.-.-.;.-.-.-.;.;.;.;.;.-.;.;.;.;.-.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.-.;.;.;.*.;.-.;.;.-.-.;.-.-.-.-.*.;.*.-.*.*.*.*.*.*.*.o.*.o.X.o.X.X.X.X.X. .X. . . . . . .| ...| | | { { { { ' ' ' ' ' ` _ _ ) ) ) ) ( ( ( ^ ^ ^ ! I I [ I I I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y I I Y Y I ~ ! ^ ^ ^ ( ( ( ( ^ R.T.U.G.U.T.Y.Y.T.T.T.@.- G l z d e e 6 6 5 @ 5 6 6 5 5 @ O o o O O @ , O.*.*.*.-.o.-.o.-.-.*.-.*.-.-.;.-.;.-.-.-.;.;.-.-.-.;.;.;.;.;.;.;.;.;.-.-.;.;.;.;.;.-.;.;.;.;.-.;.;.;.;.;.;.-.;.-.;.-.-.-.;.-.-.-.-.-.-.-.-.*.*.*.*.*.*.*.*.X.*.*.X.X.X.X.X.X.X. . . . . . . . . .| | ..| | | { { { { { _ { ' _ _ _ _ ) ) ) ) ) ( ( ^ ^ ^ ! I Y I I I U I Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Q Y I P U Y Y I ~ ! ^ ^ ^ ( _ / +.T.T.T.@.U.T.U.@.U.Y.U.R.@.G z r e 9 6 5 @ 6 5 5 6 % 5 # O O o o + O % [ o.o.o.*.o.-.o.-.*.-.-.-.-.-.-.-.-.-.-.-.-.-.-.;.-.;.;.-.;.-.-.;.;.;.;.;.;.;.;.-.;.;.;.;.;.;.;.;.;.-.-.;.-.-.;.;.;.-.-.-.-.-.-.-.-.-.*.-.-.*.*.*.*.*.*.*.*.*.*.X.X.*.*.X.X.X.X.X. . . . . . . . .| .....| { { { { { { { { _ ` ` _ ) { ) ) ) ^ ) ( ( ^ ^ ! ! I I I I I I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I I I Y I ~ Q ! ^ ^ ( ( } #.T.T.T.G.G.T.H.4 G.R.G.G.R.4 r e 9 6 % @ 6 @ 5 5 5 % @ @ O o o O o * L o.o.o.o.o.*.*.-.o.*.*.*.*.-.*.-.-.-.-.-.-.;.-.-.;.-.-.-.-.;.;.;.-.-.;.-.;.-.;.;.;.;.-.-.;.-.;.-.-.;.;.;.-.-.-.*.;.-.-.-.-.-.-.-.-.-.-.-.*.*.*.*.*.*.*.*.o.o.o.X.X.X.X.X.X.X.X. . . . . . . . .| .| ..| | { { { { { { { { ) ` ` ` ) _ _ ) ) ) ) ^ ( ^ ^ ! Q I I Y I I I Y ~ Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y P I I I I ~ [ ^ ^ ^ ( ^ G.T.T.T.U.T.T.4 U.G.+.G.4 > 4 4 r 6 5 6 @ 5 6 5 5 5 @ @ O O o O , o. .o.o.o.o.o.o.*.*.*.*.*.-.*.*.*.*.-.-.-.-.-.-.-.-.;.-.;.-.-.-.-.;.-.-.-.-.;.-.-.;.;.-.;.-.-.-.;.-.-.-.-.-.;.-.;.;.-.-.-.-.-.-.-.-.*.-.*.*.*.*.*.*.*.o.o.o.o.*.X.*.*.X.X.X. .X. . . . . . . .| .| ....| { | { { { { { { _ ` ` ` _ _ ) / ) ) ) ^ ) ^ ^ ^ ! Y I I I I I I Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y Y I I Y I I ~ Q ^ ^ ^ ) r.T.T.T.T.T.U.4 U.R.4 > - . . ; 4 < $ $ $ 5 5 5 5 5 @ O o o + + O * ) X.X.o.o.o.o.o.o.o.o.*.*.*.*.*.*.*.*.*.-.-.-.-.-.-.-.-.-.*.-.-.-.;.-.;.-.;.;.-.;.;.-.-.-.;.-.-.-.-.-.-.-.-.-.-.-.-.*.-.-.-.-.*.;.*.*.*.*.*.*.*.*.*.o.o.o.o.*.*.X.X.*.X.X.X.X. .X. . .X. . . . .| .....| | ' { { { { ' ' ' _ ` _ _ _ ) ) ) ) ) / ( ^ ^ ^ ! Y Y U Y I U U Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y P I I I I I ! ^ ^ ^ / @.T.T.T.T.T.G.4 R.G.> . . . . . . > 4 5 5 6 7 5 5 @ O o o + o @ K X.X.X.X.X.X.o.o.o.o.o.o.o.*.*.*.*.*.*.*.*.*.*.*.-.*.-.-.-.-.-.-.-.-.-.-.-.*.-.-.*.-.-.-.-.-.-.-.-.-.-.-.-.-.-.*.;.*.;.-.-.-.*.*.*.*.*.*.*.*.*.*.o.o.o.o.o.o.X.X.X.X.X.X.X.X. . . . . . . . . .| | ....{ | | | { { { { ' ' ' _ ` _ / } ` ) ) ) / ( ^ ^ ^ ^ Y Y I Y Y P Y Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXQ Q Y Y Y Y Q Y P U I U ~ I ! ^ ^ / T U.T.T.T.Y.4 @.G.4 X . . . . . . . > v s 6 8 # @ O o o + @ : X.X. .X.X.X.X.o.o.o.o.*.o.o.o.o.*.*.*.*.*.*.*.*.*.*.*.*.*.-.-.-.-.-.-.*.*.-.-.-.-.-.-.*.-.-.-.-.-.-.-.*.-.-.-.-.;.*.*.*.*.*.*.*.*.*.*.*.*.*.*.o.o.*.*.*.o.*.X.X.X.X.X.X.X. . . . . . . . . .| | .....| | ' ' ' { ' { ' ' ' ' ` _ _ ) ) ) ) ) ^ ( ( ^ ^ ^ Q I I I I U U Y Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y U U I P I I U Q ^ ^ ^ @.Y.T.T.R.> G.4 - . . . . . X X - X > 4 g 7 5 O O o o o + o * { .X. .X.X.X.X.X.X.X.o.X.o.*.o.o.X.o.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.-.-.-.*.-.*.-.*.;.*.-.-.-.-.*.-.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.o.o.*.o.o.X.X.X.X.o.X.X.X.X. . . . . . . . . . . .| .....| ' { | | ' { { ' ' ' _ ` _ ) _ _ ) ) ) ^ ) ( ^ ( ! ! I I I U I U I Q Y Y Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y I U U I U Y Y ! ^ ^ T G.U.R.G.4 4 - . . . . . . X > > > > 4 4 4 < O o o O + Y . . . . .X. .X.X.X.X.*.X.*.X.X.o.o.o.o.o.o.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.-.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.o.o.o.o.*.o.o.X.X.X.X.X.X.X.X.X.X. . . . . . . . .| | | ...| | ..| { | { { { ' ' ' _ ` _ _ ) ) ) ) ) ) ) ( ^ ^ ^ ! Y I P I I U U Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I U U U Y U I Q ^ ( ) 3 R.G.G.4 - . . . . . X X ; > 4 +.@.@.4 3 4 4 $ + O * < . . . . . . . .X. .X.X.X.X.X.*.X.*.o.o.o.*.o.o.o.o.o.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.-.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.o.*.o.X.o.o.o.o.X.o.o.X.*.X.X.X.X. .X. . . . . . . . . . . . .| | | { ' { ' { ' { { ' ` _ ' ' ` ) _ { ) ) ) ( ( ( ^ ^ ^ ^ Q I I I I P P Y Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I I I Y I U I Q ^ ( 3 > 4 > . . . . . > X X - > 4 +.+.#.G.G.@.4 4 4 x = X $ O x $. . . . . . . . . .X. .X.X.X.X.X.X.o.X.o.o.X.o.o.o.o.o.o.o.o.X.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.X.X.*.*.X.X.*.*.o.o.o.o.X.o.X.X.X.X.X.X. .X. . . . . . . . . . .| | | ..| | | | ' | { { { ' ' _ ' ` ` _ _ ) ) ) ) ) ^ ) ^ ^ ^ ^ Y I I I P I P I Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y P P U U I I I Y [ > - - . . . . . . - - - > 3 +.@.#.#.#.#.#.#.#.+.4 +.4 4 4.@.! | . . . . . . . . . . .X.X.X.X.X.X.X.X.o.X.o.o.o.o.o.o.o.o.o.*.o.o.o.X.*.*.*.o.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.X.*.X.*.X.*.*.X.*.X.X.X.o.X.X.X.X.X.X.X.X.X.X.X. . . . . . . . . . . .| | ..| | | { | ' ' { { { ' _ ` ' ` _ _ ` ) _ ) ) ) ^ ) ^ ^ ^ ! ! I U I P I P P Y Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q Y P P I P Y I I Q 2 & . . . . . X - > > 4 +.+.#.R.#.#.#.+.#.#.#.#.3 > - > P ...... . . . . . . . . . . . .X. .X.X.X.X.X.X.X.X.X.*.*.X.*.*.o.o.o.*.o.o.o.o.o.o.o.o.o.o.o.o.*.o.o.o.o.*.*.X.*.o.o.*.*.X.X.*.o.X.X.*.X.o.X.X.X.X.o.o.o.o. . . . . . . . . . . . ... .| | ..| | | { { { { { { { ' ' ' _ } _ _ ) _ ) ( ) ^ ) ( ( ^ ! ^ Q I I U Y P P P Y Q Y Y Q Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y P P P P Y P I ~ 3 6 @ . . . . . X - > 4 4 +.#.#.#.#.#.@.+.+.#.#.#.4 > ; Q { ..| | | . .| . . . . . . . . . .X.X.X.X.X.X.X.X.X.X.X.X.X.X.o.o.X.o.o.o.o.*.o.o.*.o.*.o.o.o.o.o.o.o.o.o.X.*.X.o.o.X.X.*.X.X.X.*.X.X.X.X.X.o.X.X.X. . . . . . . . . . . . . .| .| | .| | | { | { { { ' { | ' ' ' _ _ ` _ ) ) ` ( ) ) ) ^ ) ^ ^ ^ ! Y U U I P P P P Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Q Y Y Y Y Q Y P P P I U I I 2 8 $ & * - X X > > > +.+.@.#.#.#.@.@.+.+.#.#.#.T > X / { { | ....| .| . . . . . . . . . . . . . .X. .X.X.X.X.X.X.X.X.X.X.o.X.X.X.*.o.o.o.o.o.X.o.o.o.o.o.X.*.o.o.o.X.X.o.o.*.X.X.X.*.X.X.X.X.X.X.X.X.X. .X. . . . . . . . . . . . . .| | | | ....| | { { { { { { { ' ' ` ' ` ` _ _ { ) ) ) ) ) ( ( ( ( ^ ^ ! Y I Y I U P P U Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y P P P P U P : % @ e e > > > 4 +.+.@.#.#.#.+.@.+.+.#.#.#.#.+.> > J { ..| | | | | ..| | .| . . . . . . . . . . . . . .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.o.X.X.X.X.X.o.X.X.X.X.X.*.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X. .X. . . . . . . . . . . . . .| .| .. .| | | | | { { { { { { { ' ' _ _ ` _ _ ) ) ) ( ) ) / ( ( ^ ! ^ ! I U I U U U P U Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Y P P P I P 3 % % e r r 2 +.+.+.@.#.G.G.@.+.@.@.#.#.> +.+.> > 3 { { { | | { | | ....| .| .| . . .| . . . . . . . .X. . .X.X. .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X. .X. . . . . . . . . . . . . . . . .| .| | .....| | { | { { { { { { ' ' ` _ ' ` _ _ { / ) ( ) ) ) ^ ( ^ ^ ^ ! Q P I U P I P U Y Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Y U P P P 2 % 6 e r r r 2 E @.#.#.#.@.+.+.+.+.@.#.> 4 > - 3 / { ' { ' ' | { | | | ....| | . .| . . . . . . . . . . . . . . .X. .X.X. .X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.*.X. . .X.X.X. . . . . . . . . . . . . . . . .| .| | ....| | | { | { { { { { { ' ' ' _ ` ` _ _ ) _ ) ) / ) / ( ) ^ ^ ^ ! I P I P P P P P Y Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q U P P P H # e , r r r r , > +.+.@.+.+.+.+.@.#.#.+.> - 4 ^ ' ' ' { ' { { | | { | | | | ..| | | . . . . . . . . . . . . . . . . . .X. . . .X.X. . .X.X. .X.X.X. .X. .X.X.X.X. .X. . .X.X. . . . . . . . . . . . . . . . . . .| . ... . .| | | | | | { { { { { { ' { ' { ` ' ` ` _ ` ) _ ) / ) ( ( ^ ) ^ ^ ^ ^ ! Y P I P I P P K I Q Y Y Y Y Q Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y P P P : % e e , e , , & X ; > 3 3 +.+.+.@.G.#.+.3 3 ( _ ' ' ' { { { ' ' | ' | { | | | .. .| .| . .| . . . . . . . . . . . . . . . . . . . . .X. . . . . . . . . . . . . . .X. . . . . . . . . . . . . . . . . . . . .| .. .| | | ....| | | | { | { { ' { { { ' ' ` ` ` ` _ _ _ _ _ ) ( ) ) / ) ^ ^ ^ ^ ! U U P P P P P P P I Q Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q I P P H * * , & * * & * * + * - > 4 +.@.#.#.4 > : _ ` ` _ ' ' ' ' { { { ' ' ..' ....{ | | ...| | . .| .| . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .X. . . . . . . . ... .| | | | ....| | | | { { { { { { { { { ' ' ` ` ` ` _ _ ) ) { ^ ( ) / / ( ( ( ^ ! ~ I P P I P P P P P Y Q Q Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Q Y Y Y ~ I P P L L L L K P K K Y Q Q ~ [ J 3 +.+.4 ; J { _ _ ` ` _ ' ' ' ' { { ..' ' ..' { { ..| | { ....| | .| .| . . .| . . . . . . . . .X. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .| | .| | .| ....| | | | { { | { { { { { { ' ' ' ' _ _ _ _ _ ` ) ) ) ) ) ( / ^ / ^ ^ ! Y I I P P P P K P P I Q Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Q I P P P P P P P I I I ^ ^ ^ ^ ) ( ( _ / / / ) _ _ _ ` ' ` _ ' _ ' ' ' ' ' ' { { { { | { | | { ..| ..| . .| | .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .| . .| | .| | | ...| | | { | { | { { ' { ' { ' ' ` ' ' _ ' ` _ ) ` ) _ ) ) ( ) ( ( ^ ^ ^ ! I I I P P P P P K P Y Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y ~ I P K K P P P P P P U ! ^ ^ ^ ( ( / / / / ) ) _ ) _ _ ) { _ ' ' ' ' ..' ' { { { { { { { ' | | { ......| | .| .| | .| .| . . . . . . . . . . . . . .| . . . . . . . . . .| . . . .| .| | .| | .| ....| | | | | { { | { { { ' { { { { ' ' ` ' _ ` ` _ _ _ ` ) ) ) ) ( / ) ( ^ ^ ^ ! Y P I P P P P K P P I Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Q Y Y Y Y Y Q I P K K P P P P P I I Q ^ ^ ^ ( ( / ) ( ) ) ) _ { ) _ ` _ ' _ ' ' ' ' ' { { ' ' ..' ' ..{ | { | | | | | ..| | | | | .| .| .| . . . . . . .| . . . . . . . . . .| ... . . .| .| . .| .| | | ....| | | | | { { { { { { { ' { { ' ' ' ' ' ' ` ` ` _ _ ) _ ) ) ) ) ( ) ^ ( ^ ^ ( Q P P P P P P P P K P Y ~ Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q I P P K K P P P P P U I ! ^ ^ ( ( ( ) ) ) ) ) ) _ ) _ _ _ ' ' _ _ ' ' ' ' ..' ' ' ' ..{ { | { | { | | | | .. ..... .| | | | .| | | .| .| . . ...| ..| .. . . . .| | .| | .| .| | ..| ..| | | | | | { { { | { { { { { { { ' ' ' ' ' _ _ ` _ _ ) ) _ ) ) ( ) ) ) ) ( ( ^ ^ ! Y I P P P P P P K K P Y Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Q Y P K P P P U P P P U Y ! ^ ^ ^ ( ) ) ^ ) ) ) ) ) { _ ) ' _ ' ' _ ' ' ' ' ' ..' ' ' { { { { { | | { ..{ | | | | { ..| ......| | | | | | | .| | | | .| .| | | | | | | ...| ..| ..| { | | | | { { { { { { { { { { { { { ' ' { ' ' ' _ ` ` _ _ ` ` _ ) ) ) ) ) ^ ) ( ^ ^ ^ Q Y P P P P P P P K K P Y ~ Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y ~ I Q Q P K K K P P P P U U U Q ! ^ ^ ) ^ ) ( ) ^ ) ) ) / _ / _ _ _ ' _ ' ' ' ' ' ' ' ..{ { ' { { { ' | { { { { ..{ | | | | | | .. ........... ... .| | .......... .| | ......| | { | | | | | { ' | | { | { { { { { { { { } ' ' ' ` ' _ ` ` ` _ _ ) ) ` ) ) ) ) ^ ) ) ^ ( ^ ! Q U U P P P P P P K K I Y ~ Y Y Y Y Y Y Q UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Q U K K P P P K P P I P Y Q ^ ^ ( ( ( / ^ ) ) ) ) ` ) ` _ _ ` ` ` ' _ ' ' ' ' ' ' ..' ' ..' ..' { { { | { ' { | { ..| | | | | | | | | | | | | | { | | | | | | .| | | | | | { | { { | { | { { { { { { { { { { ' ' ' ' ' _ _ ` ` ` _ _ ` ) ` ) ) ) ) / ^ ( ( ( ^ ^ ! I U P P P K P P P K K Y Y Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Q Y Q Y K K K P P K P K P P I Y ! ^ ^ ( ^ / ) / / ( ) ) ` ) _ _ ` _ _ ` _ _ ` ' ' ' ' ' ' ' ' ..' { { { { ' | | { { { { | { { | { | { { | { | | | | | | | | | { { { ' { | { { { { | { { { { { { { { { { { ' ' ' ' _ ' _ _ ` _ ` _ _ _ ) _ ) ) ) ) ( / / ( ( ^ ^ ! Q U U U K P P P P L K K I ~ Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Q Y P K K P P P P P P P P I ! ! ^ ( ) ) ) ) _ ( ) ) ) _ ) _ _ _ _ ` ` _ ` ' ' ' _ ' ' ' ' ' { { { { { { { { { { { { { | { { { { ` { ' | ' | { ' ' { { { { { | ' | { { { { { { { { ' { { ' { { { ` { ' ' ' ` _ _ ' _ ` _ _ _ ) ) _ ) ) ) ) ) / ( / ( ^ ! ! U P P U K P P K P K L P Y Q Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXI Y Y Y Y Y Y Y Q Y P L K K P K P P P P P P Y ! ^ ^ ^ ^ ) ) ( ) ) ( ) _ ) ` _ _ _ _ ' ` ` _ ' ' ' ' ' ' ' { { ' ' { { { { { { { { { { { { { { { { | ' | ' | | ' | { | { ' ' | { { { { { { ' { { { { { { { { ` ` ` ' _ _ ` ' _ _ _ _ _ ( ) ` _ ( ( ) ) ) ^ ( ( ^ ^ ! Y P U P U K U P K P K K P Y Q Y Y Y Y Y Y Y Y UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXU Q Y Y Y Y Y Y Q Q P P K K P K K P P P P U U Q ! ^ ^ ^ / ^ ) ) ) ) ) ) ) _ ) _ ) _ _ ` ` ` _ ` ' ' ` ' ' ' ' ' { { { { { { { { { { { { { { { { { { { { ' | { { { { ' ' ' { { { { { { { { ' { ' ' ' ' ' ` ` ` ` _ ' ` ` _ _ _ _ ) ) _ _ ) ) ) ) ( ) ^ ( / ^ ! Y P P P P P P P P K K K K U Q Q Y Y Y Y Y Y Y U UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXP Y Y Y Y Y Y Y Y Y Y P K K K K P K P U P P U U Q ^ ^ ^ ) ^ ) ) ) ) ) ( ` ( _ ` ` _ _ _ _ ` ` ` ' ' _ ' ' ' ' ` ' ' ' ` { { { { { { { { { { { { { { { ' ' ' { { { } { { { { { { { ' ` ' ' ' ' ' ' ` ` ` ` ` _ ` _ _ _ _ ` ) _ ` ) ( ) ) ) ^ / ( ( ( ^ ! Q U U P P P K P K K K K K P I Q Q Y Y Y Y Y Y Y U UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXL Y Y Y Y Y Y Y Y Q Y P K K K P P K K U K U U U U Q ^ ^ ^ ) ) ^ ) ) ( ) ( ` ) ) ) { _ _ ` _ _ _ ` ` ' _ _ ' ` ' ' ' ` ' { ' ' { { ` { { { { { { { { ' | ' { { { ' ' ' ' ' ' ' ' ' ' ' ' _ ' _ ' ` ` ` ` ` _ _ _ _ ) _ _ ) ` ( ( ) ) ) ^ ^ ) ) ^ ^ ~ P P P P P P P P K K K K K P ~ Y Y Y Y Y Y Y Y Y L UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXY Y Y Y Y Y Y Y Y Q I P L K K K K U P K P P U U U Q ^ ^ ^ ) ^ / ) ^ ) ) ) ) ) ) _ / / _ _ _ _ _ ` ` ` ` ` _ _ ' ' _ ` ' _ ' ` ` { _ { _ { { ' ' ' ' ' ' ' ' ' ' ' ` ' ` ' ' _ _ _ ' ` ` ` _ ` _ _ _ _ _ _ _ / ) ) ( ( ) ) ) ) ) ^ ) / ^ [ Q U U P P P P P K K K K K K P I ~ Q Y Y Y Y Y Y Q P UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXK Y Y Y Y Y Y Y Q Y Y U K K K K U K P K P P P U U U ~ ! ^ ( ( ( ^ ( ) ) ) ) ) / / ` / ` ) ` _ / ` _ _ ` _ ` ` ` ` ' _ ` ` ` ` ' ' ' ` ` ' ` ' ' ' ' ` ` ' ` _ _ ' _ _ ' { ` ` { ) ` _ _ _ _ _ _ ` ` _ ) ) ) ) ) ) ) ) ^ ) ) ^ ) ^ ! Q U U U U P K K K K P P K K L U Y Q Q Y Y Y Y Y Y Y K UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXL Q Y Y Y Y Y Y Y Q Q I P K K K K K K K K P U K U U U Q [ ^ ( ) ( / ^ / ) ) / ) / / ` ) ) _ ` ) _ _ / _ _ _ _ _ _ _ _ _ ` ' ` ` ` _ _ _ _ _ _ _ _ / ` ` ` ` ` ` _ ` _ _ _ _ _ _ _ _ ` ) ) ` _ ) ) ) ) ) ) ) ) ( ( ( ( ) ^ ^ ! Q U U U U K U P K K P K K L L P I Q Y Y Y Y Y Y Y Y Y L UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXH U Y Y Y Y Y Y Y Y Q Y P K L K K K K K K K K U P U U P I ! ! / ^ ) ) ^ ) ( ) / / ) ) ( ` ` / / / ` ` ` _ _ _ _ _ ) _ _ _ ` _ ` ` _ _ _ } ` ` _ { ` ` { _ _ _ _ ` _ _ / _ _ ) { ) ) ` ) ) ^ ) ^ ) ) ) ) ) ( ( ) ^ ( ^ ! U U U U U U U U K K K K K K K K I Q Q Q Y Y Y Y Y Y Q U H UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXL Y Y Y Y Y Y Y Y Q Y I P K K K K K K K P K P K U U P U U ~ [ ^ ^ ) ^ ( ) ) ) ) ) ( ) ) ) / ` ) ) / _ ) ) / { { ) _ _ _ _ _ _ _ / _ ` _ _ _ _ _ _ / _ _ _ ) ` { ) _ / ) ) ) ) ) ) ) ) ) ) ) ) ) ) ^ ) ( ( ^ ! ~ U U U U K K K K K K K K K K K L P Y Q Y Y Y Y Y Y Y Y Y K UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXJ Y Y Y Y Y Y Y Y Q ~ Q I P L K K K K K K K K U K U U U U U I Q ! ^ ( ( ( ( ( ( ( ( ) ) ( ( ) ) ) ) ) ) ) ) { / ) _ _ ) { ) ) _ ` ) ) _ ) { ` ) _ _ _ / / ` ^ ) ) { ) ) ) ) ) ) ) ) ) ^ ) ( ) ) [ ) ^ ~ I U U U U U K P K K K K K K K K L P I Q Q Q Y Y Y Y Y Y Y U J UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: K Q Y Y Y Y Y Y I Q Q Q I K L K K K K K K K K K K U U K U U U I Q ! ( ( ( ( ( ( / ( ( ) ) ) ) ( ) ) ) ) ) ^ ) ) ) ) ) ) ) ) ` ) _ / ) ) _ ) ) ) ) ) ) ) ) ) ^ / / ) ( ) ) ^ / ) ^ ) ) ^ ) ! ~ I U U U U U K K K K K K K K K K K L K I Q Y Y Y Y Y Y Y Y Y Y L : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXH I Y Y Y Y Y Y Y Y Y Q Q I K L K K K K K K K K K K U K U U U U U U Y ! ( ( ( ( ( / ^ / ( ( / / / ( / ) ) ( / ) / ^ / ) ) ) ) ) ) ) ) ) ( ) ) ) ) ( ) ( ) ( ) ) ) ^ ) ^ ) ^ ( ( ^ [ Q U U U U U U K K U K K K K K K K K K L K I Y Q Q Y Y Y Y Y Y Y Y Y J UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: L Y Y Y Y Y Y Y Y I Q Q Q U K L K K K K K K K K K K K P K U P U U P U I Q ! ( ( ( ( ( ( / / / / ( ) ) ) ) _ / / ) ) ) ) ) ) ) ) ^ / ( ( ) ) ) ) ) ^ ^ / / ) ^ ) ) ^ ^ ^ Q U U U P K U U K K K K K K K K K K K K L L K I ~ Q Y Y Y Y Y Y Y Y Y Y L : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: U U Y Y Y Y Y Y Y Q Q Q Y U P L L K L L K K K K K P K U K K U K U U U U U I Q [ ! ^ ( ( ( ^ ^ ^ ) [ ) ) ^ ( ( ^ ) ) ^ / / ( ( ( ) ^ / ( ( ( ( ) ( ( ( ( [ ! Q U U U U K W P P K K P P K K K K K K K K L K L P U Q Q Q Y Y Y Y Y Y Y Y I K : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; J I Y Y Q Y Y Y Y Y Y Q Q Y I P L L K L K K K K K K K K K K K U K K K U U U U U U I ~ Q ^ [ ^ ) ) ) ( ( ( ^ ) ( ( ^ ( ( ( ( ( ( ( ( ) ) ( ! [ Q Y I U U U U U U U U K K P K K K K K K K K K K K L L L P I ~ Q Q Q Y Y Y Y Y Y Y Y Y J ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: J Y Y Y Y Y Y Y Y Y Q Q Q Q Q P K L L L L L K K K K K K K K K K K U U K U K U U U K U U U I I I Q ! ! ! ^ ! ^ ^ ! ! ^ ! ! Q Q Y U U U U U U K U K U K K U K K K K K K K K K K K K K K L L L K P I Q ~ Q Q Y Y Y Y Y Y Y Q Q L ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: L Y Y Y Y Y Y Y Y Y Y Q Q Q ~ I P L L K K L L K K K K K K K K K K K P K K K K U U U K U K U U K U U K U U U P U K U K U K U U K U K K U K U K K U K K K K K K K K K K K K L L K L L K I Q Q Q Y Y Y Y Y Y Y Y Y Y Y L : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo : K Q Y Y Y Y Y Y Y Y Y Q Q Q Q Y U K L L K L K K K K K K K K K K K K K K K U K K K K K U K U U K U K K U K U K W U U K U K K K K K K K K K K K K K K K K L K K K L L K L L K U Y Q Q Q Q Y Y Y Y Y Y Y Y Y Q P : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXX : K Q Y Y Q Y Y Y Y Y Y Q Y Q ~ Q I U K L L L L L L K K K K K K L K L K K K L K K K K K K K K K U K K K K K K K K K K K K K K K K L K K K K K L K L L K K L L L L K P Y Q Q ~ Y Y Y Y Y Y Y Y Y Y Y Y L : X UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: L Y Y Y Y Y Y Y Y Y Y Y ~ Q Q Q ~ ~ P K K L L L L L L L K K K K K L K L K K K K L K K L L L L K K K K K K K L K K K L L K K K K K K L K L L L K L L L K I I ~ ~ Q Y Q Y Y Y Y Y Y Y Y Y Y I L : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: J I Y Y Y Y Y Y Y Y Y Y Y Y [ ~ ~ ~ ~ I U K L L L L L L L L L K L K T K L L K K L K K L K K K K L K L L K L K K K K L L L K L L L L L L K K K I [ ~ ~ ~ ~ ~ Y Y Y Y Y Y Q Y Y Q Y I J : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; H K Q Q Q Y Y Y Y Y Y Y I I Q Y Q Q Q Q Q I U K K L L L L L K L L L L L K L L K L L L L L K L K L L L K L L L L L L L L L L K K U I Y Q ~ ~ Q Q Y Y Y Y Y Y Y Y Y Y Y Y Y P H ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: J Y Y Y Y Y Y Y Y ~ I Y Y Y Y Q Y Q Q Q Q Q Y I U U K K K L L L L L L L L L L L L L L L L L L L L L L L L K K P P Y Y Q Q Q Q Q Q ~ ~ Y Y Y Y Y Y Y Y Y Y Y Y I J : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; : L Y Y Y Y Y I Y Q Y Y Y Y Y Y Y Y Q Q Q Q Q Q Q Q I I I U U P K P K K L L L L K L L K K U U I I I ~ Q Q Q Q Q Y Q Q Y Y Y Y I Q Y Y Y Y Y Y Y Y Y Y L H ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; H L Y ! ~ Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y I Q Q Q ~ ~ ~ ~ Q Y Y Q Y Q Q Q I Q I Q Q Q Q Q Q ~ Q Q Q Y Y Y Y Y Y Y Y Y Y Q ~ I Y Y Y Y Y Y I L H ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; : L K Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Q Y Q Q Q Q Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Q U J : ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: J L U Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Q Y Y Y Y Y Y Y Y Y Y Y U L J : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX; H J U I Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y I K L H ; UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: : J L U I Y Y Y Y Y Y Q Q Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y I P L J : : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX: : J J L L K P P U Y Y Y Y Y Y Y Y U P K L L J J : : UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX" +}; +#if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR +extern void *allegro_icon; +CONSTRUCTOR_FUNCTION(static void _set_allegro_icon(void)); +static void _set_allegro_icon(void) +{ + allegro_icon = allegico_xpm; +} +#endif diff --git a/rv_icon.icns b/rv_icon.icns new file mode 100644 index 0000000000..646442fded Binary files /dev/null and b/rv_icon.icns differ diff --git a/rv_icon.ico b/rv_icon.ico new file mode 100644 index 0000000000..216a21f648 Binary files /dev/null and b/rv_icon.ico differ diff --git a/rv_icon.rc b/rv_icon.rc new file mode 100644 index 0000000000..86eccd1245 --- /dev/null +++ b/rv_icon.rc @@ -0,0 +1 @@ +allegro_icon ICON MOVEABLE PURE LOADONCALL DISCARDABLE "./rv_icon.ico" diff --git a/rv_icon.xpm b/rv_icon.xpm new file mode 100644 index 0000000000..d265807e02 --- /dev/null +++ b/rv_icon.xpm @@ -0,0 +1,549 @@ +/* XPM */ +static const unsigned char * rv_icon_xpm[] = { +"32 32 514 2", +" c None", +"! c black", +"# c #1D2DBF", +"$ c #1F2FC0", +"% c #404DCA", +"& c #5E69D3", +"' c #6F79D7", +"( c #6E78D7", +") c #5C67D2", +"* c #3C49C9", +"+ c #1E2EC0", +", c #1E2EBF", +"- c #1C2CBE", +". c #4653CC", +"0 c #8E96E1", +"1 c #C4C8F1", +"2 c #CED1F4", +"3 c #CDD1F5", +"4 c #C0C4F0", +"5 c #868EDF", +"6 c #3D4AC9", +"7 c #3745C7", +"8 c #99A0E5", +"9 c #C5C9F2", +": c #C5C9F4", +"; c #C5C9F5", +"< c #C5CAF6", +"= c #C5CAF7", +"> c #C3C6EA", +"? c #C2C5E2", +"@ c #C4C8F2", +"A c #8E95E1", +"B c #2E3DC4", +"C c #B6BBEE", +"D c #BBC0F2", +"E c #BBC1F4", +"F c #BBC1F6", +"G c #BCC1F8", +"H c #BCC2F9", +"I c #BCC1F6", +"J c #B7B8D7", +"K c #B4B5BE", +"L c #BBC0F1", +"M c #B1B6EA", +"N c #4D59C9", +"O c #1F2EBF", +"P c #1B2BBE", +"Q c #626DD5", +"R c #B0B6EE", +"S c #B0B7F1", +"T c #B1B7F4", +"U c #B1B8F7", +"V c #B2B8F9", +"W c #B2B9FB", +"X c #B2B9FC", +"Y c #B2B9FD", +"Z c #AFB4E5", +"[ c #AAADBA", +"] c #A9ACB7", +"^ c #AEB3E2", +"_ c #AFB5EB", +"` c #ACAECD", +"a c #A8A9B3", +"b c #ACB0D8", +"c c #5763D1", +"d c #1A2ABE", +"e c #3F4CCB", +"f c #A4AAEB", +"g c #A5ACF0", +"h c #A6ADF4", +"i c #A6AEF7", +"j c #A7AEFA", +"k c #A7AFFD", +"l c #A8B0FE", +"m c #A8B1FE", +"n c #AAAFF3", +"o c #AEA9D1", +"p c #AFA4AF", +"q c #B0A2AE", +"r c #ADA2B5", +"s c #AAA4C7", +"t c #A7ABE7", +"u c #A0A4C9", +"v c #9D9EB5", +"w c #9D9EB6", +"x c #A4ABE8", +"y c #A3AAEA", +"z c #3C4AC9", +"{ c #1A2AC0", +"| c #8189E2", +"} c #99A1ED", +"~ c #9AA2F2", +" ! c #9AA3F7", +"!! c #9BA4FB", +"#! c #9CA5FE", +"$! c #9DA7FE", +"%! c #9FA8FD", +"&! c #A59FCC", +"'! c #A895A3", +"(! c #A3929B", +")! c #A2929C", +"*! c #A3929C", +"+! c #A3929D", +",! c #A6949F", +"-! c #A6939C", +".! c #9B99A1", +"0! c #9195A1", +"1! c #9295B9", +"2! c #99A1EC", +"3! c #8089E1", +"4! c #1A2ABF", +"5! c #1A29BE", +"6! c #303ECB", +"7! c #8D96E9", +"8! c #8E96F0", +"9! c #8E98F5", +":! c #8F99FA", +";! c #909BFE", +"! c #9D90B7", +"?! c #9B8693", +"@! c #98868B", +"A! c #A38F9B", +"B! c #A892AD", +"C! c #9E92C9", +"D! c #9890C6", +"E! c #998AAA", +"F! c #9C8898", +"G! c #9C8895", +"H! c #9088A2", +"I! c #8E98F3", +"J! c #8D96EF", +"K! c #8D96E8", +"L! c #303ECA", +"M! c #1A29C1", +"N! c #4552D6", +"O! c #818BEB", +"P! c #828CF3", +"Q! c #838EF9", +"R! c #848FFD", +"S! c #8893FF", +"T! c #8B96FF", +"U! c #8F88C0", +"V! c #937B8D", +"W! c #978187", +"X! c #C2AAAD", +"Y! c #E2D6DE", +"Z! c #A79FD4", +"[! c #8183D1", +"]! c #7D82D2", +"^! c #857FB8", +"_! c #867DB7", +"`! c #998199", +"a! c #8F7883", +"b! c #8685CC", +"c! c #838EF8", +"d! c #828CF2", +"e! c #818BEA", +"f! c #4552D5", +"g! c #1A29C0", +"h! c #1A2AC6", +"i! c #4856DC", +"j! c #7580EE", +"k! c #7682F5", +"l! c #7783FC", +"m! c #7A87FE", +"n! c #7F8BFF", +"o! c #818AF0", +"p! c #8C7289", +"q! c #896E80", +"r! c #A88994", +"s! c #E9E2EB", +"t! c #9C9EDE", +"u! c #6A71CF", +"v! c #6A72CE", +"w! c #6C72CA", +"x! c #706FB8", +"y! c #7170BD", +"z! c #8D78AB", +"{! c #8B7082", +"|! c #816F8E", +"}! c #7580ED", +"~! c #6F76C1", +" # c #747EE4", +"!# c #4755DA", +"## c #1A2AC4", +"$# c #1B2BCB", +"%# c #3E4DDF", +"&# c #6976F0", +"'# c #6B78F7", +"(# c #6C7AFE", +")# c #717FFF", +"*# c #7683FF", +"+# c #7973BB", +",# c #876986", +"-# c #896A81", +".# c #98788A", +"0# c #7975C1", +"1# c #5D65CC", +"2# c #5C64CC", +"3# c #6663B0", +"4# c #77607F", +"5# c #72618C", +"6# c #796597", +"7# c #816378", +"8# c #7D6575", +"9# c #6573A6", +":# c #5C5E86", +";# c #5B5D7D", +"<# c #333B8D", +"=# c #1826B4", +"># c #1C2CCF", +"?# c #2C3DE0", +"@# c #5E6BF1", +"A# c #5F6EFA", +"B# c #6271FE", +"C# c #6876FF", +"D# c #6C7BFF", +"E# c #716095", +"F# c #7B5A76", +"G# c #7560A7", +"H# c #755E9A", +"I# c #4F58C8", +"J# c #5059C9", +"K# c #5058C9", +"L# c #5158C5", +"M# c #6D526F", +"N# c #6B537B", +"O# c #695684", +"P# c #6F5B96", +"Q# c #76556B", +"R# c #785A72", +"S# c #566394", +"T# c #515386", +"U# c #4F517D", +"V# c #1F2678", +"W# c #1928BC", +"X# c #1A29BF", +"Y# c #1A2AC2", +"Z# c #1C2DD1", +"[# c #1E30E1", +"]# c #4C5BF1", +"^# c #5463FB", +"_# c #5868FE", +"`# c #5E6EFF", +"a# c #6272FF", +"b# c #695282", +"c# c #684559", +"d# c #5D56BA", +"e# c #5450BE", +"f# c #424BC6", +"g# c #424CC7", +"h# c #434CC5", +"i# c #5B4776", +"j# c #6A444C", +"k# c #64466A", +"l# c #6E5180", +"m# c #6F4D68", +"n# c #6C4960", +"o# c #7F5C87", +"p# c #5359B4", +"q# c #444776", +"r# c #4651C0", +"s# c #1E30DF", +"t# c #1C2DCF", +"u# c #1A2AC3", +"v# c #1C2ED2", +"w# c #1E30E2", +"x# c #2E40F0", +"y# c #4959FB", +"z# c #4E5FFF", +"{# c #5465FF", +"|# c #5969FF", +"}# c #664E8B", +"~# c #5A384A", +" $ c #59489D", +"!$ c #4347C3", +"#$ c #3640C3", +"$$ c #3D3EAE", +"%$ c #4D3A78", +"&$ c #543968", +"'$ c #613B4E", +"($ c #7A557C", +")$ c #7F5674", +"*$ c #674054", +"+$ c #6A4466", +",$ c #694776", +"-$ c #4D5DFA", +".$ c #4959FA", +"0$ c #2E40EE", +"1$ c #1E30E0", +"2$ c #1C2DD0", +"3$ c #1A2AC1", +"4$ c #2033EF", +"5$ c #3547FB", +"6$ c #4456FF", +"7$ c #4B5DFF", +"8$ c #5061FF", +"9$ c #6052B1", +":$ c #58334B", +";$ c #46346D", +"<$ c #423CAF", +"=$ c #38349D", +">$ c #413079", +"?$ c #482F65", +"@$ c #4F315C", +"A$ c #7B505F", +"B$ c #BA95A7", +"C$ c #774A58", +"D$ c #5E3554", +"E$ c #5E375D", +"F$ c #513E8A", +"G$ c #4355FE", +"H$ c #3547FA", +"I$ c #2033ED", +"J$ c #2236F9", +"K$ c #3448FE", +"L$ c #4154FF", +"M$ c #4759FF", +"N$ c #4B54E2", +"O$ c #432C67", +"P$ c #2C203D", +"Q$ c #3C2A76", +"R$ c #342C95", +"S$ c #34287F", +"T$ c #382878", +"U$ c #5C3B76", +"V$ c #8F6177", +"W$ c #845464", +"X$ c #5E3255", +"Y$ c #582E55", +"Z$ c #47233E", +"[$ c #414ADC", +"]$ c #3347FE", +"^$ c #2236F8", +"_$ c #1F32EC", +"`$ c #1D2FDE", +"a$ c #1C2CCD", +"b$ c #1D2FDD", +"c$ c #1F32EB", +"d$ c #2135F7", +"e$ c #253AFE", +"f$ c #3246FF", +"g$ c #3D51FF", +"h$ c #424AD7", +"i$ c #4E2650", +"j$ c #241A43", +"k$ c #391B35", +"l$ c #401D48", +"m$ c #42215C", +"n$ c #4E254F", +"o$ c #562943", +"p$ c #5A2D49", +"q$ c #562952", +"r$ c #50244D", +"s$ c #3C1830", +"t$ c #38369E", +"u$ c #3245FF", +"v$ c #2439FE", +"w$ c #2135F6", +"x$ c #1F32EA", +"y$ c #1D2FDC", +"z$ c #1C2BCB", +"{$ c #1B2AC7", +"|$ c #1D2FD9", +"}$ c #1F31E7", +"~$ c #2134F3", +" % c #2337FD", +"!% c #2A3EFF", +"#% c #3537C4", +"$% c #4A204C", +"%% c #491D42", +"&% c #3A152D", +"'% c #431B3B", +"(% c #491C3E", +")% c #4C2046", +"*% c #4C2148", +"+% c #4F234F", +",% c #4B1E45", +"-% c #3E1636", +".% c #2B1028", +"0% c #2F30A1", +"1% c #3145FF", +"2% c #293EFF", +"3% c #2236FC", +"4% c #2034F2", +"5% c #1E31E6", +"6% c #1D2FD7", +"7% c #1B2AC5", +"8% c #1C2ED3", +"9% c #2033EE", +":% c #2235F9", +";% c #3128A1", +"<% c #491B3F", +"=% c #46183F", +">% c #350E26", +"?% c #2F2E97", +"@% c #3A3ABD", +"A% c #381E5D", +"B% c #35102A", +"C% c #341029", +"D% c #2E0C24", +"E% c #240D28", +"F% c #252170", +"G% c #3241E1", +"H% c #3247FF", +"I% c #2D41FF", +"J% c #2135F8", +"K% c #1E2FE0", +"L% c #1C2BC7", +"M% c #1D2FDB", +"N% c #2136E5", +"O% c #353683", +"P% c #481A3F", +"Q% c #471A42", +"R% c #370F28", +"S% c #2B1E62", +"T% c #3549FE", +"U% c #374AFF", +"V% c #384BFF", +"W% c #3748F3", +"X% c #3543E2", +"Y% c #3646EC", +"Z% c #374AFD", +"[% c #3549FF", +"]% c #2E42FF", +"^% c #283CFE", +"_% c #2236FB", +"`% c #1C2AC5", +"a% c #1A28BD", +"b% c #4087D3", +"c% c #437C9B", +"d% c #481D47", +"e% c #3B102B", +"f% c #270F2D", +"g% c #2D3CE9", +"h% c #3045FF", +"i% c #3348FF", +"j% c #3448FF", +"k% c #2237FC", +"l% c #2135F4", +"m% c #1D30DE", +"n% c #1A29BD", +"o% c #1B28BD", +"p% c #3470B1", +"q% c #0F2534", +"r% c #25385C", +"s% c #2A1D33", +"t% c #252BB0", +"u% c #263AFE", +"v% c #2C40FF", +"w% c #2F43FF", +"x% c #2E43FF", +"y% c #1A28BC", +"z% c #1A28BB", +"{% c #2A1D6D", +"|% c #233560", +"}% c #266498", +"~% c #1D3F9E", +" & c #2135F9", +"!& c #2337FC", +"#& c #263BFE", +"$& c #1D2FD5", +"%& c #1B28BC", +"&& c #1928B8", +"'& c #1B26AF", +"(& c #1C24A5", +")& c #1D33BE", +"*& c #1F31E8", +"+& c #2134F2", +",& c #1B27B8", +"-& c #1928BA", +".& c #1928B6", +"0& c #171A78", +"1& c #1A28B9", +"2& c #1A26B3", +"3& c #1C2BC6", +"4& c #1D2FD8", +"5& c #1C2AC3", +"6& c #1A26B2", +"7& c #1928B9", +"8& c #17176B", +"9& c #161048", +":& c #1926B1", +";& c #1B26B2", +"<& c #1D2ED2", +"=& c #1D2FDF", +">& c #1D2DD0", +"?& c #1C2AC1", +"@& c #1B26B1", +"A& c #1A26B4", +"B& c #1925AA", +"C& c #160C38", +"D& c #150413", +"E& c #171972", +"F& c #1927B6", +"G& c #1A25AE", +"H& c #1B25AF", +"I& c #1B27B6", +"J& c #1B28BB", +"K& c #1B28BA", +"L& c #1B27B5", +"M& c #1B25AE", +"N& c #1927B3", +"O& c #171666", +"P& c #15020B", +"Q& c #150310", +"R& c #171252", +"S& c #181E8A", +"T& c #1926AF", +"U& c #1925AC", +"V& c #181D83", +"W& c #16104A", +" ", +" ", +" # $ % & ' ( ) * + , ", +" - . 0 1 2 3 3 3 3 2 4 5 6 # ", +" , 7 8 9 : ; < = = > ? < ; : @ A B ", +" - ) C D E F G H H I J K L G F E D M N O ", +" P Q R S T U V W X Y Z [ ] ^ W V _ ` a b c , ", +" d e f g h i j k l m n o p q r s t u v w x y z ", +" { | } ~ !!!#!$!%!&!'!(!)!*!+!,!-!.!0!1!~ 2!3!4! ", +" 5!6!7!8!9!:!;!!?!@!A!B!C!D!E!F!G!H!I!9!J!K!L!5! ", +" M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!]!^!_!`!a!b!c!d!e!f!g! ", +" 5!h!i!j!k!l!m!n!o!p!q!r!s!t!u!v!w!x!y!z!{!|!}!~! #!###5! ", +" 5!$#%#&#'#(#)#*#+#,#-#.#0#1#2#1#3#4#5#6#7#8#9#:#;#<#=#5! ", +" g!>#?#@#A#B#C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#X# ", +" Y#Z#[#]#^#_#`#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#r#s#t#g! ", +" u#v#w#x#y#z#{#|#}#~# $!$#$$$%$&$'$($)$*$+$,$-$.$0$1$2$3$ ", +" u#v#w#4$5$6$7$8$9$:$;$<$=$>$?$@$A$B$C$D$E$F$G$H$I$1$2$3$ ", +" 3$Z#1$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$[$]$^$_$`$t#g! ", +" X#a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$x$y$z$X# ", +" 5!{$|$}$~$ %!%#%$%%%&%'%(%)%*%+%,%-%.%0%1%2%3%4%5%6%7%5! ", +" 5!M!8%w#9%:%;%<%=%>%?%@%A%B%C%D%E%F%G%H%I%e$J%I$K%2$g! ", +" 5!L%M%N%O%P%Q%R%S%T%U%V%W%X%Y%Z%[%H%]%^%_%4%}$|$`%5! ", +" 5!a%Z#b%c%d%e%f%g%h%H%i%j%j%i%H%h%I%^%k%l%x$m%a$a%5! ", +" n%o%p%q%r%s%t%u%!%v%]%w%x%]%v%2%e$_%l%c$[#8%y%n% ", +" z%{%|%}%~%4% &!&v$#&#&#&u%v$3%J%4%x$[#$&%&y% ", +" &&'&(&)&`$*&I$+&w$J%J$ &J%w$4%I$}$m%Z#,&-&.& ", +" 0&1&2&3&|$[#5%x$_$I$I$_$x$5%K%4&5&6&7&8& ", +" 9&:&2&;&5&<&y$=&1$1$`$M%>&?&@&A&B&C& ", +" D&E&F&2&G&H&I&J&K&L&M&G&A&N&O&P& ", +" Q&R&S&T&&&F&F&&&U&V&W&P& ", +" ", +" "}; \ No newline at end of file diff --git a/rv_icon_small.xpm b/rv_icon_small.xpm new file mode 100644 index 0000000000..0db9341f32 --- /dev/null +++ b/rv_icon_small.xpm @@ -0,0 +1,171 @@ +/* XPM */ +static const unsigned char * rv_icon_small_xpm[] = { +"16 16 152 2", +" c None", +"! c black", +"# c #4451CB", +"$ c #7C85DC", +"% c #9AA1E5", +"& c #99A0E5", +"' c #7A83DB", +"( c #404DC9", +") c #2D3BC3", +"* c #9098E3", +"+ c #C0C5F4", +", c #C0C5F7", +"- c #BCBED8", +". c #C0C5F5", +"0 c #8A92E0", +"1 c #2A39C1", +"2 c #2433C1", +"3 c #979EE7", +"4 c #ABB2F4", +"5 c #ACB3FA", +"6 c #ADB4FD", +"7 c #AEB1E9", +"8 c #ADA8B3", +"9 c #AEACD6", +": c #AAAFE5", +"; c #A3A5BB", +"< c #939ADF", +"= c #5662D5", +"> c #949CF1", +"? c #959FFB", +"@ c #99A2FE", +"A c #9F97C4", +"B c #A28F99", +"C c #A392AB", +"D c #9E90AB", +"E c #9E8F9A", +"F c #9093BC", +"G c #949CF0", +"H c #5661D4", +"I c #1A29C0", +"J c #616DE3", +"K c #7D88F7", +"L c #818DFE", +"M c #8A87CE", +"N c #977D8A", +"O c #CAC0D5", +"P c #7F81D0", +"Q c #7778C3", +"R c #877AAE", +"S c #887798", +"T c #7A84E6", +"U c #606CDF", +"V c #1B2BC6", +"W c #4C5BE8", +"X c #6674FB", +"Y c #6F7DFF", +"Z c #7B6693", +"[ c #836893", +"] c #5D63C7", +"^ c #565FC9", +"_ c #6D5A86", +"` c #715E8F", +"a c #7B5E72", +"b c #5A6292", +"c c #3F4480", +"d c #1928BB", +"e c #1B2BCA", +"f c #2E3FE9", +"g c #5161FD", +"h c #5B6BFF", +"i c #64476C", +"j c #534DB6", +"k c #3E45BF", +"l c #504187", +"m c #6A4760", +"n c #714D6C", +"o c #704C70", +"p c #4B56C8", +"q c #2C3CDB", +"r c #1B2BC8", +"s c #1F31E8", +"t c #3447FC", +"u c #495BFF", +"v c #524191", +"w c #3C2F74", +"x c #382E8B", +"y c #4B316C", +"z c #926678", +"{ c #633856", +"| c #4E3980", +"} c #3346FC", +"~ c #1F31E6", +" ! c #1B2AC5", +"!! c #1E30E2", +"#! c #2237F9", +"$! c #3443F0", +"%! c #492B6D", +"&! c #371938", +"'! c #461E4A", +"(! c #50254A", +")! c #4E2346", +"*! c #391F51", +"+! c #313FE6", +",! c #2236F8", +"-! c #1E30E1", +".! c #1A2AC3", +"0! c #1A29BE", +"1! c #1D2ED6", +"2! c #2635D4", +"3! c #421E58", +"4! c #37153C", +"5! c #353FD4", +"6! c #37309E", +"7! c #332987", +"8! c #2D30A5", +"9! c #3144F7", +":! c #273BFE", +";! c #2033EF", +"! c #316695", +"?! c #352140", +"@! c #282CB1", +"A! c #2E43FF", +"B! c #3145FF", +"C! c #2E42FF", +"D! c #2134F4", +"E! c #1E30DF", +"F! c #1B29C1", +"G! c #1928BA", +"H! c #212788", +"I! c #1F41B5", +"J! c #2033F0", +"K! c #2236F9", +"L! c #2438FC", +"M! c #1E30DE", +"N! c #1B29C0", +"O! c #17145E", +"P! c #1A27B7", +"Q! c #1C2CCC", +"R! c #1E30E0", +"S! c #1C2BCA", +"T! c #1A27B5", +"U! c #171357", +"V! c #150721", +"W! c #181973", +"X! c #1A23A5", +"Y! c #1A28B8", +"Z! c #1A28B7", +"[! c #1923A3", +"]! c #18186F", +"^! c #15061C", +" ", +" # $ % & ' ( ", +" ) * + , , - . + 0 1 ", +" 2 3 4 5 6 7 8 9 : ; < 2 ", +" = > ? @ A B C D E F G H ", +" I J K L M N O P Q R S T U I ", +" V W X Y Z [ ] ^ _ ` a b c d ", +" e f g h i j k l m n o p q r ", +" e s t u v w x y z { | } ~ r ", +" !!!#!$!%!&!'!(!)!*!+!,!-!.! ", +" 0!1!2!3!4!5!6!7!8!9!:!;!!?!@!A!B!B!C!:!D!E!F! ", +" G!H!I!J!K!L!L!,!;!M!N!G! ", +" O!P!Q!R!~ ~ E!S!T!U! ", +" V!W!X!Y!Z![!]!^! ", +" "}; \ No newline at end of file diff --git a/src/EditboxModel.cpp b/src/EditboxModel.cpp new file mode 100644 index 0000000000..0d758875f3 --- /dev/null +++ b/src/EditboxModel.cpp @@ -0,0 +1,635 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "EditboxNew.h" +#include "zc_alleg.h" +#include "jwin.h" +#include "zdefs.h" +#include "editbox.h" +#include "gui.h" +#include + +extern FONT *lfont, *sfont3; +extern FONT *pfont; +extern bool is_large; +extern int d_timer_proc(int msg, DIALOG *d, int c); + +static DIALOG help_dlg[] = +{ + { jwin_win_proc, 0, 0, 320, 240, 0, vc(15), 0, D_EXIT, 0, 0, (void *) "ZQuest Help", NULL, NULL }, + { jwin_frame_proc, 4, 23, 312, 213, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_editbox_proc, 6, 25, 308, 209, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *) close_dlg, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int Unicode::indexToOffset(std::string &s, int i) +{ + return uoffset(s.c_str(), i); +} + +void Unicode::insertAtIndex(std::string &s, int c, int i) +{ + char temp[50]; + int bytes = usetc(temp, c); + usetc(temp+bytes,0); + int offset = indexToOffset(s,i); + s = s.substr(0,offset) + temp + s.substr(offset, s.size()-offset); +} + +void Unicode::extractRange(std::string &s, std::string &dest, int first, int last) +{ + int firstoffset = indexToOffset(s,first); + int lastoffset = indexToOffset(s,last); + dest = s.substr(firstoffset, lastoffset-firstoffset); +} + +void Unicode::removeRange(std::string &s, int first, int last) +{ + int firstoffset = indexToOffset(s,first); + int lastoffset = indexToOffset(s,last); + s = s.substr(0,firstoffset) + s.substr(lastoffset, s.size()-lastoffset); +} + +int Unicode::getCharAtIndex(std::string &s, int i) +{ + int offset = indexToOffset(s,i); + return ugetc(s.c_str()+offset); +} + +int Unicode::getCharWidth(int c, FONT *f) +{ + if(c == '\n') + return 0; + + if(c == '\t') + return TABSIZE*getCharWidth(' ', f); + + char temp[50]; + int width = usetc(temp, c); + usetc(temp+width,0); + return text_length(f,temp); +} + +int Unicode::getCharWidth(const char *s, int offset) +{ + return uwidth(s+offset); +} + +int Unicode::getCharAtOffset(const char *s, int offset) +{ + return ugetc(s+offset); +} + +std::pair Unicode::munchWord(std::string &s, int startoffset, FONT *f) +{ + unsigned int endoffset; + + for(endoffset = startoffset; endoffset < s.size(); endoffset++) + { + int c = Unicode::getCharAtIndex(s,endoffset); + { + if(c == ' ' || c == '\t') + break; + } + } + + std::pair rval; + rval.first = endoffset-startoffset; //guaranteed >= 1 + rval.second = text_length(f,s.substr(startoffset, endoffset-startoffset).c_str()); + return rval; +} + +void Unicode::textout_ex_nonstupid(BITMAP *bmp, FONT *f, std::string &s, int x, int y, int fg, int bg) +{ + unsigned int offset = 0; + std::string newstring; + const char *txt = s.c_str(); + + while(offset < s.size()) + { + int c = ugetc(txt+offset); + + int width = uwidth(txt); + offset+=width; + char temp[50]; + + if(c == '\n') + continue; + + if(c == '\t') + { + int temp_offset = 0; + + for(int i=0; i x) + break; + } + + if(offset == s.size() ||c == '\n') + return index; + + //else try the next char, see if it's closer + if(x-pixwidth+lastwidth < pixwidth - x) + return index; + + return index+1; +} + +int Unicode::getLength(std::string &s) +{ + int length=0; + unsigned int offset=0; + const char *buf = s.c_str(); + + while(offset < s.length()) + { + offset += Unicode::getCharWidth(buf,offset); + length++; + } + + return length; +} + +bool TextSelection::hasSelection() +{ + return (start != end); +} + +std::pair TextSelection::getSelection() +{ + if(start < end) + return std::pair(start,end); + + return std::pair(end, start); +} + +void TextSelection::clearSelection() +{ + start=end=0; + isselecting = false; +} + +void TextSelection::restartSelection(EditboxCursor &cursor) +{ + isselecting = true; + start=end=cursor.getPosition(); +} + +void TextSelection::adjustSelection(EditboxCursor &cursor) +{ + assert(isselecting); + end = cursor.getPosition(); +} + +void TextSelection::ensureSelecting(EditboxCursor &cursor) +{ + if(!isselecting) + { + restartSelection(cursor); + } +} + +void EditboxCursor::operator ++(int) +{ + if((unsigned int)index < host.getBuffer().size()-1) + index++; + + setPreferredX(); +} + +void EditboxCursor::operator --(int) +{ + if(index > 0) + index--; + + setPreferredX(); +} + +void EditboxCursor::setPreferredX() +{ + preferredX = host.findCursor().x; +} + +void EditboxCursor::insertChar(int c) +{ + if(host.isReadonly()) + return; + + Unicode::insertAtIndex(host.getBuffer(),c,index); + CursorPos cp = host.findCursor(); + Unicode::insertAtIndex(cp.it->line, c, cp.index); + cp.it->numchars++; + host.markAsDirty(cp.it); + host.getView()->update(); + (*this)++; +} + +void EditboxCursor::deleteChar() +{ + if(host.isReadonly()) + return; + + //DO NOT let you delete the last char of the buffer + if(index == int(host.getBuffer().size())-1) + { + return; + } + + Unicode::removeRange(host.getBuffer(),index,index+1); + //check if newline was deleted + CursorPos cp = host.findCursor(); + int c = Unicode::getCharAtIndex(cp.it->line, cp.index); + + if(c == '\n') + { + cp.it->newlineterminated = false; + } + + Unicode::removeRange(cp.it->line, cp.index, cp.index+1); + cp.it->numchars--; + host.markAsDirty(cp.it); + host.getView()->update(); +} + +void EditboxCursor::insertString(std::string s) +{ + if(host.isReadonly()) + return; + + int length = Unicode::getLength(s); + + for(int i=0; iline, cp.index); + std::string newline = cp.it->line.substr(offset, cp.it->line.size()-offset); + LineData newld = {newline, cp.it->numchars-cp.index, cp.it->newlineterminated,true,NULL}; + cp.it->line = cp.it->line.substr(0,offset); + Unicode::insertAtIndex(cp.it->line, c, cp.index); + cp.it->numchars = cp.index+1; + cp.it->newlineterminated = true; + cp.it->dirtyflag = true; + std::list::iterator next = cp.it; + next++; + host.getLines().insert(next,newld); + next--; + host.markAsDirty(next); + host.markAsDirty(cp.it); + host.getView()->update(); + (*this)++; +} + +CursorPos EditboxModel::findCursor() +{ + return findIndex(cursor.getPosition()); +} + +CursorPos EditboxModel::findIndex(int totalindex) +{ + int lineno = 0; + int curindex = 0; + CursorPos rval; + + for(std::list::iterator it = lines.begin(); it != lines.end(); it++) + { + curindex += it->numchars; + rval.it = it; + + if(curindex > totalindex) + break; + + lineno++; + } + + int offinline = totalindex-curindex+rval.it->numchars; + rval.lineno = lineno; + rval.index = offinline; + std::string &str = rval.it->line; + rval.x = 0; + + for(int i=0; igetFont()); + } + + return rval; +} + +void EditboxModel::markAsDirty(std::list::iterator line) +{ + //coalesce lines that are NOT newline-terminated + std::list::reverse_iterator rit = std::list::reverse_iterator(line); + + //find start of line + while(rit != lines.rend() && !rit->newlineterminated) + { + rit++; + } + + line = rit.base(); + + while(!line->newlineterminated) + { + std::list::iterator next = line; + next++; + assert(next != lines.end()); + line->numchars += next->numchars; + destroy_bitmap(next->strip); + line->line += next->line; + line->newlineterminated = next->newlineterminated; + lines.erase(next); + } + + line->dirtyflag=true; +} + +void EditboxModel::copy() +{ + if(!getSelection().hasSelection()) + return; + + std::pair sel = getSelection().getSelection(); + Unicode::extractRange(getBuffer(), clipboard, sel.first, sel.second); +} + +void EditboxModel::cut() +{ + copy(); + + if(!isReadonly()) + clear(); +} + +void EditboxModel::clear() +{ + if(isReadonly()) + return; + + //ultimate annoying. + //kill some lines + if(!getSelection().hasSelection()) + return; + + std::pair sel = getSelection().getSelection(); + getCursor().updateCursor(sel.first); + getSelection().clearSelection(); + Unicode::removeRange(getBuffer(),sel.first, sel.second); + CursorPos start = findIndex(sel.first); + CursorPos end = findIndex(sel.second); + + if(start.lineno == end.lineno) + { + //thank god, an easy case + //slight complication if the \n was deleted + if(end.index == end.it->numchars) + end.it->newlineterminated = false; + + int numremoved = end.index-start.index; + Unicode::removeRange(end.it->line, start.index, end.index); + end.it->numchars -= numremoved; + markAsDirty(end.it); + getView()->update(); + return; + } + else + { + //truncate starting line + start.it->newlineterminated = false; + start.it->line = start.it->line.substr(0, start.index); + start.it->numchars = start.index; + //count the number of lines to munch + std::list::iterator it = start.it; + int numtomunch=0; + + for(it++; it != end.it; ++it) ++numtomunch; + + //and now munch + for(int i=0; istrip); + getLines().erase(it); + } + + //munch the last line + it = start.it; + it++; + + //there's a complication if the whole line is deleted + if(it->numchars == end.index) + { + it->newlineterminated = false; + } + + it->numchars -= end.index; + it->line = it->line.substr(end.index, it->line.size()-end.index); + markAsDirty(start.it); + getView()->update(); + } +} + +void EditboxModel::paste() +{ + if(isReadonly()) + return; + + CursorPos cp = findCursor(); + int offset = Unicode::indexToOffset(getBuffer(), getCursor().getPosition()); + buffer = buffer.substr(0,offset) + clipboard + buffer.substr(offset, buffer.size()-offset); + //nevermind, THIS is the ultimate annoying + //break up the lines int he clipboard + std::list toinsert; + makeLines(toinsert,clipboard); + //now split up the line being pasted onto + offset = Unicode::indexToOffset(cp.it->line, cp.index); + std::string therest = cp.it->line.substr(offset, cp.it->line.size()-offset); + LineData therestline; + therestline.line = therest; + therestline.numchars = cp.it->numchars-cp.index; + therestline.newlineterminated = cp.it->newlineterminated; + therestline.strip = NULL; + cp.it->line = cp.it->line.substr(0,offset); + cp.it->newlineterminated = false; + cp.it->numchars = cp.index; + //insert the damn lines + std::list::iterator it = cp.it; + it++; + getLines().insert(it, therestline); + + for(std::list::reverse_iterator toiit = toinsert.rbegin(); toiit != toinsert.rend(); toiit++) + { + std::list::iterator iter = cp.it; + iter++; + getLines().insert(iter, *toiit); + } + + it = cp.it; + it++; + + for(unsigned int i=0; i 1 || (toinsert.size() == 1 && toinsert.begin()->newlineterminated == true)) + { + markAsDirty(cp.it); + } + + //update cursor + getCursor().updateCursor(getCursor().getPosition()+Unicode::getLength(clipboard)); + getView()->update(); +} + +void EditboxModel::makeLines(std::list &target, std::string &source) +{ + target.clear(); + std::string &str = source; + const char *buf = str.c_str(); + int startoffset = 0; + int startindex = 0; + int endindex = 0; + int lineno; + lineno=0; + int endoffset; + + for(endoffset = 0; endoffset != int(str.size()); endindex++) + { + int width = Unicode::getCharWidth(buf, endoffset); + int c = Unicode::getCharAtOffset(buf, endoffset); + + if(c == '\n') + { + //end of line + endoffset+=width; + endindex++; + LineData ld; + ld.line = str.substr(startoffset, endoffset-startoffset); + ld.numchars = endindex-startindex; + ld.newlineterminated = true; + ld.dirtyflag = true; + ld.strip = NULL; + target.push_back(ld); + startindex = endindex+1; + startoffset = endoffset; + continue; + } + + endoffset+=width; + } + + if(endoffset != startoffset) + { + LineData ld; + ld.line = str.substr(startoffset, endoffset-startoffset); + ld.numchars = endindex-startindex; + ld.newlineterminated = false; + ld.dirtyflag = true; + ld.strip = NULL; + target.push_back(ld); + } +} + +void EditboxModel::doHelp() +{ + std::string helpstr = ""; + + if(!helpfile) + return; + + FILE *hb = fopen(helpfile, "r"); + + if(!hb) + { + return; + } + + char c = fgetc(hb); + + while(!feof(hb)) + { + helpstr+=c; + c = fgetc(hb); + } + + fclose(hb); + + help_dlg[0].dp2= lfont; + + if(is_large) + { + help_dlg[0].w=800; + help_dlg[0].h=600; + help_dlg[1].w=800-8; + help_dlg[1].h=600-27; + help_dlg[2].w=800-8-4; + help_dlg[2].h=600-27-4; + } + + help_dlg[2].dp = new EditboxModel(helpstr, new EditboxWordWrapView(&help_dlg[2],(is_large?sfont3:pfont),view->getDialog()->fg,view->getDialog()->bg,BasicEditboxView::HSTYLE_EOTEXT),true); + help_dlg[2].bg = view->getDialog()->bg; + zc_popup_dialog(help_dlg,2); + delete(EditboxModel*)(help_dlg[2].dp); +} + diff --git a/src/EditboxNew.h b/src/EditboxNew.h new file mode 100644 index 0000000000..195d1263b8 --- /dev/null +++ b/src/EditboxNew.h @@ -0,0 +1,359 @@ +#ifndef EDITBOXNEW_H +#define EDITBOXNEW_H + +#include +#include +#include + + +#ifdef _MSC_VER +#pragma warning(disable: 4355) +#endif + +class EditboxModel; +class EditboxCursor; +struct DIALOG; +struct FONT; +struct BITMAP; + +class Unicode +{ +public: + static const int TABSIZE = 4; + static int indexToOffset(std::string &s, int i); + static void insertAtIndex(std::string &s, int c, int i); + static void extractRange(std::string &s, std::string &dest, int first, int last); + static void removeRange(std::string &s, int first, int last); + static int getCharAtIndex(std::string &s, int i); + static int getCharWidth(int c, FONT *f); + static std::pair munchWord(std::string &s, int startoffset, FONT *f); + static int getCharWidth(const char *s, int offset); + static int getCharAtOffset(const char *s, int offset); + static void textout_ex_nonstupid(BITMAP *bmp, FONT *f, std::string &s, int x, int y, int fg, int bg); + static int getIndexOfWidth(std::string &s, int x, FONT *f); + static int getLength(std::string &s); +}; + +class TextSelection +{ +public: + TextSelection() : isselecting(false), start(0), end(0) {} + void restartSelection(EditboxCursor &cursor); + void adjustSelection(EditboxCursor &cursor); + bool hasSelection(); + void ensureSelecting(EditboxCursor &cursor); + bool isSelecting() + { + return isselecting; + } + void clearSelection(); + std::pair getSelection(); + void doneSelection() + { + isselecting=false; + } +private: + bool isselecting; + int start; + int end; +}; + +struct LineData +{ + std::string line; + int numchars; + bool newlineterminated; + bool dirtyflag; + BITMAP *strip; +}; + +class EditboxView +{ +public: + EditboxView(DIALOG *Host, FONT *TextFont) : textfont(TextFont), dbuf(NULL), host(Host), model(NULL) {} + void initialize(EditboxModel *model); + void lineDown(); + void lineUp(); + void pageUp(); + void pageDown(); + void lineHome(); + void lineEnd(); + void update(); + virtual void scrollUp() {} + virtual void scrollDown() {} + FONT *getFont() + { + return textfont; + } + virtual void draw(); + virtual void ensureCursorOnScreen() {} + virtual ~EditboxView(); + virtual bool mouseClick(int, int) + { + return false; + } + virtual bool mouseDrag(int, int) + { + return false; + } + virtual bool mouseRelease(int, int) + { + return false; + } + DIALOG *getDialog() + { + return host; + } +protected: + virtual void enforceHardLimits() {} + void invertRectangle(int x1, int y1, int x2, int y2); + virtual int getAreaHeight()=0; + FONT *textfont; + BITMAP *dbuf; + virtual void layoutPage()=0; + virtual void init() {} + DIALOG *host; + EditboxModel *model; +}; + +struct CursorPos +{ + int lineno; + int index; + int x; + std::list::iterator it; +}; + +class EditboxCursor +{ +public: + EditboxCursor(EditboxModel &model) : visible(true), host(model), index(0), preferredX(0) {} + void insertChar(int c); + void insertString(std::string s); + void updateCursor(int new_index) + { + index = new_index; + } + void invertVisibility() + { + visible = !visible; + } + bool isVisible() + { + return visible; + } + int getPosition() + { + return index; + } + void operator++(int); + void operator--(int); + int getPreferredX() + { + return preferredX; + } + void setPreferredX(); + void insertNewline(); + void deleteChar(); +private: + bool visible; + EditboxModel &host; + int index; + int preferredX; + //NOT IMPLEMENTED: DO NOT USE + EditboxCursor(EditboxCursor &); + EditboxCursor &operator =(EditboxCursor &); +}; + +class EditboxModel +{ +public: + EditboxModel(std::string &Buffer, EditboxView *View, bool ReadOnly = false, char *hf = NULL) : helpfile(hf), lines(), buffer(Buffer), view(View), readonly(ReadOnly), cursor(*this), clipboard(""), s() {} + TextSelection &getSelection() + { + return s; + } + EditboxCursor &getCursor() + { + return cursor; + } + EditboxView *getView() + { + return view; + } + std::string &getBuffer() + { + return buffer; + } + ~EditboxModel() + { + delete view; + } + std::list &getLines() + { + return lines; + } + CursorPos findCursor(); + CursorPos findIndex(int totalindex); + void markAsDirty(std::list::iterator line); + bool isReadonly() + { + return readonly; + } + void makeLines(std::list &target, std::string &source); + void copy(); + void cut(); + void clear(); + void paste(); + void doHelp(); +private: + char *helpfile; + std::list lines; + std::string &buffer; + EditboxView *view; + bool readonly; + EditboxCursor cursor; + std::string clipboard; + TextSelection s; + //NOT IMPLEMENTED; DO NOT USE + EditboxModel &operator=(EditboxModel &); +}; + +struct CharPos +{ + std::list::iterator it; + int lineIndex; + int totalIndex; +}; + +class BasicEditboxView : public EditboxView +{ +public: + BasicEditboxView(DIALOG *Host, FONT *TextFont, int FGColor, int BGColor, int Highlight_Style) : EditboxView(Host, TextFont), + view_x(0), view_y(0), fgcolor(FGColor), bgcolor(BGColor), hstyle(Highlight_Style) {} + ~BasicEditboxView(); + void ensureCursorOnScreen(); + void scrollUp(); + void scrollDown(); + void scrollLeft(); + void scrollRight(); + void draw(); + bool mouseClick(int x, int y); + bool mouseDrag(int x, int y); + bool mouseRelease(int x, int y); + static const int HSTYLE_EOLINE = 0; + static const int HSTYLE_EOTEXT = 1; + int getForeground() + { + return fgcolor; + } + int getBackground() + { + return bgcolor; + } +protected: + void createStripBitmap(std::list::iterator it, int width); + virtual void drawExtraComponents()=0; + void init(); + int getAreaHeight() + { + return area_height; + } + void enforceHardLimits(); + int area_xstart; + int area_ystart; + int area_width; + int area_height; + int view_width; + int view_x; + int view_y; + + CharPos findCharacter(int x, int y); + int fgcolor; + int bgcolor; + int hstyle; +}; + +class EditboxVScrollView : public BasicEditboxView +{ +public: + EditboxVScrollView(DIALOG *Host, FONT *TextFont, int FGColor, int BGColor, int Highlight_Style=HSTYLE_EOLINE) : BasicEditboxView(Host, TextFont, FGColor, BGColor, Highlight_Style), sbarpattern(NULL) {} + + ~EditboxVScrollView(); + bool mouseClick(int x, int y); + bool mouseDrag(int x, int y); + bool mouseRelease(int x, int y); +protected: + virtual bool mouseDragOther(int x, int y) + { + x=x; + y=y; /*these are here to bypass compiler warnings about unused arguments*/ return false; + } + virtual bool mouseClickOther(int x, int y) + { + x=x; + y=y; /*these are here to bypass compiler warnings about unused arguments*/ return false; + } + void drawExtraComponents(); + void init(); + int bottomarrow_y; + BITMAP *sbarpattern; +private: + int toparrow_x; + int toparrow_y; + int toparrow_state; + int bottomarrow_x; + int bottomarrow_state; + int baroff; + int barlen; + int barstate; + int barstarty; + +}; + +class EditboxWordWrapView : public EditboxVScrollView +{ +public: + EditboxWordWrapView(DIALOG *Host, FONT *TextFont, int FGColor, int BGColor, int Highlight_Style=HSTYLE_EOLINE) : EditboxVScrollView(Host, TextFont, FGColor, BGColor, Highlight_Style) {} +protected: + void layoutPage(); +}; + +class EditboxNoWrapView : public EditboxVScrollView +{ +public: + EditboxNoWrapView(DIALOG *Host, FONT *TextFont, int FGColor, int BGColor, int Highlight_Style=HSTYLE_EOLINE) : EditboxVScrollView(Host, TextFont, FGColor, BGColor, Highlight_Style) {} + void init(); +protected: + void layoutPage(); + void drawExtraComponents(); + bool mouseDragOther(int x, int y); + bool mouseRelease(int x, int y); + bool mouseClickOther(int x, int y); + int leftarrow_y; + int rightarrow_y; +private: + int leftarrow_x; + int leftarrow_state; + int rightarrow_x; + int rightarrow_state; + int hbaroff; + int hbarlen; + int hbarstate; + int hbarstartx; +}; + +class EditboxScriptView : public EditboxNoWrapView +{ +public: + EditboxScriptView(DIALOG *Host, FONT *TextFont, int FGColor, int BGColor, int Highlight_Style=HSTYLE_EOLINE) : EditboxNoWrapView(Host, TextFont, FGColor, BGColor, Highlight_Style), linetext(NULL) {} + void init(); + ~EditboxScriptView(); +protected: + void drawExtraComponents(); +private: + BITMAP *linetext; +}; + +#endif + diff --git a/src/EditboxView.cpp b/src/EditboxView.cpp new file mode 100644 index 0000000000..dfea80fcda --- /dev/null +++ b/src/EditboxView.cpp @@ -0,0 +1,976 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "EditboxNew.h" +#include "zc_alleg.h" +#include "jwin.h" +#include +#include + +extern int scheme[]; + +//#ifndef _MSC_VER +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) +//#endif + +//#ifdef _ZQUEST_SCALE_ +extern volatile int myvsync; +extern int zqwin_scale; +extern BITMAP *hw_screen; +//#endif + +extern bool is_zquest(); + +void EditboxView::update() +{ + assert(model); + layoutPage(); +} + +void EditboxView::initialize(EditboxModel *new_model) +{ + model = new_model; + //add a "ghost newline" to the buffer if necessary + + std::string nl = ""; + Unicode::insertAtIndex(nl,'\n',0); + unsigned int nlsize = (unsigned int)nl.size(); + + if(model->getBuffer().size() < nlsize || model->getBuffer().substr(model->getBuffer().size()-nlsize,nlsize) != nl) + model->getBuffer() += nl; + + dbuf = create_bitmap_ex(8, host->w, host->h); + init(); + update(); +} + +void EditboxView::draw() +{ + assert(model); +} + +EditboxView::~EditboxView() +{ + destroy_bitmap(dbuf); +} + +/////////////////////////////////////////////////////////////////////////////////////// + +void EditboxView::lineUp() +{ + CursorPos cp = model->findCursor(); + std::list::reverse_iterator it = std::list::reverse_iterator(cp.it); + + if(it != model->getLines().rend()) + { + int startindex = model->getCursor().getPosition()-it->numchars-cp.index; + int index = Unicode::getIndexOfWidth(it->line, model->getCursor().getPreferredX(), textfont); + model->getCursor().updateCursor(startindex+index); + } +} + +void EditboxView::lineDown() +{ + CursorPos cp = model->findCursor(); + std::list::iterator it = cp.it; + it++; + int startindex = model->getCursor().getPosition()+cp.it->numchars-cp.index; + + if(it != model->getLines().end()) + { + int index = Unicode::getIndexOfWidth(it->line, model->getCursor().getPreferredX(), textfont); + model->getCursor().updateCursor(startindex+index); + } +} + +void EditboxView::lineHome() +{ + CursorPos cp = model->findCursor(); + int newindex = model->getCursor().getPosition()-cp.index; + model->getCursor().updateCursor(newindex); + model->getCursor().setPreferredX(); +} + +void EditboxView::lineEnd() +{ + CursorPos cp = model->findCursor(); + int newindex = model->getCursor().getPosition()-cp.index+cp.it->numchars-1; + model->getCursor().updateCursor(newindex); + model->getCursor().setPreferredX(); +} + +void EditboxView::pageDown() +{ + int textheight = text_height(textfont); + int height = getAreaHeight(); + int numlines = height/textheight; + + for(int i=0; i invmap; + RGB color; + //don't wast time drawing in stupid places + x1 = zc_max(x1, 0); + x1 = zc_min(x1, host->w); + x2 = zc_max(x2,0); + x2 = zc_min(x2, host->w); + y1 = zc_max(y1, 0); + y1 = zc_min(y1, host->h); + y2 = zc_max(y2, 0); + y2 = zc_min(y2, host->h); + + for(int i=x1; i::iterator it = invmap.find(c); + int invcolor; + + if(it == invmap.end()) + { + get_color(c, &color); + unsigned char r = 4*(((~color.r)&0x3F)+1)-1; + unsigned char g = 4*(((~color.g)&0x3F)+1)-1; + unsigned char b = 4*(((~color.b)&0x3F)+1)-1; + invcolor = makecol(r,g,b); + invmap[c] = invcolor; + } + else + invcolor = it->second; + + putpixel(dbuf, i,j,invcolor); + } + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void BasicEditboxView::init() +{ + area_xstart = host->x+2; + area_ystart = host->y+2; + area_width = zc_max(0, host->w-20); //scrollbar + area_height = host->h-4; + view_width = area_width; + + //make the initial lines + model->makeLines(model->getLines(), model->getBuffer()); +} + +void BasicEditboxView::ensureCursorOnScreen() +{ + CursorPos cp = model->findCursor(); + int textheight = text_height(textfont); + int cystart = cp.lineno*textheight; + int cyend = cystart+textheight; + view_y = zc_min(view_y, cystart); + view_y = zc_max(view_y, cyend-area_height); + view_x = zc_min(view_x, cp.x); + view_x = zc_max(view_x, cp.x-area_width); + //enforce hard limits + enforceHardLimits(); +} + +void BasicEditboxView::enforceHardLimits() +{ + int textheight = text_height(textfont); + int ymost = zc_max(area_height, (int)model->getLines().size()*textheight); + view_y = zc_max(view_y, 0); + view_y = zc_min(view_y, ymost-area_height); + int xmost = zc_max(area_width, view_width); + view_x = zc_max(view_x, 0); + view_x = zc_min(view_x, xmost-area_width); +} + +BasicEditboxView::~BasicEditboxView() +{ + for(std::list::iterator it = model->getLines().begin(); it != model->getLines().end(); it++) + { + destroy_bitmap(it->strip); + } + + model->getLines().clear(); +} + +CharPos BasicEditboxView::findCharacter(int x, int y) +{ + int absolutey = y-area_ystart+view_y; + int textheight = text_height(textfont); + int lineno = absolutey/textheight; + lineno = zc_max(lineno, 0); + lineno = zc_min(lineno, (int)(model->getLines().size())-1); + int totalindex = 0; + //NOTE: future optimization opportunity + std::list::iterator it = model->getLines().begin(); + + for(int i=0; inumchars; + it++; + } + + CharPos rval; + rval.it = it; + rval.lineIndex = Unicode::getIndexOfWidth(it->line, -area_xstart+x+view_x, textfont); + rval.totalIndex = totalindex + rval.lineIndex; + return rval; +} + +void BasicEditboxView::scrollDown() +{ + int textheight = text_height(textfont); + view_y += textheight; + enforceHardLimits(); +} + +void BasicEditboxView::scrollUp() +{ + int textheight = text_height(textfont); + view_y -= textheight; + enforceHardLimits(); +} + +void BasicEditboxView::scrollLeft() +{ + view_x -= 4; + enforceHardLimits(); +} + +void BasicEditboxView::scrollRight() +{ + view_x += 4; + enforceHardLimits(); +} + +void BasicEditboxView::draw() +{ + rectfill(dbuf, 0, 0, host->w, host->h, bgcolor); + set_clip_rect(dbuf, area_xstart-host->x, area_ystart-host->y, area_xstart-host->x+area_width-1, area_ystart-host->y+area_height-1); + + int textheight = text_height(textfont); + int y = -view_y; + + for(std::list::iterator it = model->getLines().begin(); it != model->getLines().end(); it++) + { + if(y >= area_ystart-host->y-textheight && y <= area_ystart+host->y + area_height) + blit((*it).strip, dbuf, 0, 0, area_xstart-host->x-view_x, area_ystart-host->y+y, view_width, textheight); + + y+=textheight; + } + + set_clip_rect(dbuf, 0,0,host->w,host->h); + + //draw cursor + if(model->getCursor().isVisible()) + { + CursorPos cp = model->findCursor(); + //int textheight = text_height(textfont); + int cursory = cp.lineno*text_height(textfont); + //GAH, too many damn coordinate offsets :-/ + vline(dbuf, area_xstart-host->x+cp.x-view_x-1, area_ystart-host->y+cursory-view_y-1, area_ystart-host->y+cursory-view_y+textheight, fgcolor); + } + + //draw selection + set_clip_rect(dbuf, area_xstart-host->x, area_ystart-host->y, area_xstart-host->x+area_width-1, area_ystart-host->y+area_height-1); + + if(model->getSelection().hasSelection()) + { + std::pair selection = model->getSelection().getSelection(); + CursorPos selstart = model->findIndex(selection.first); + CursorPos selend = model->findIndex(selection.second); + + if(selstart.lineno == selend.lineno) + { + //invert the selection rectangle + int starty = area_ystart-host->y-view_y+selstart.lineno*textheight; + int startx = area_xstart-host->x+selstart.x-view_x; + int endx = area_xstart-host->x+selend.x-view_x; + invertRectangle(startx, starty, endx, starty+textheight); + } + else + { + //do the starting line + int starty = area_ystart-host->y-view_y + selstart.lineno*textheight; + int startx = area_xstart-host->x+selstart.x-view_x; + int endx; + + if(hstyle == HSTYLE_EOLINE) + { + endx= area_xstart-host->x+area_width-view_x; + } + else + { + endx = area_xstart-host->x+selstart.it->strip->w-view_x; + } + + invertRectangle(startx,starty,endx,starty+textheight); + //do intermediate lines + std::list::iterator it = selstart.it; + it++; + + for(int line = selstart.lineno+1; line < selend.lineno; line++,it++) + { + int endx2; + + if(hstyle == HSTYLE_EOLINE) + { + endx2=area_xstart-host->x+area_width-view_x; + } + else + { + endx2 = area_xstart-host->x+it->strip->w-view_x; + } + + invertRectangle(area_xstart-host->x-view_x, area_ystart-host->y-view_y+line*textheight, endx2, area_ystart-host->y-view_y+(line+1)*textheight); + } + + //do the last line + endx = area_xstart-host->x+selend.x-view_x; + invertRectangle(area_xstart-host->x-view_x,area_ystart-host->y-view_y+selend.lineno*textheight, endx, area_ystart-host->y-view_y+(selend.lineno+1)*textheight); + } + } + + set_clip_rect(dbuf, 0,0,host->w,host->h); + drawExtraComponents(); + vsync(); + blit(dbuf, screen, 0, 0, host->x, host->y,host->w, host->h); + set_clip_rect(screen, 0, 0,SCREEN_W,SCREEN_H); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif +} + +bool BasicEditboxView::mouseClick(int x, int y) +{ + //set the cursor + CharPos cp = findCharacter(x,y); + model->getCursor().updateCursor(cp.totalIndex); + model->getCursor().setPreferredX(); + model->getSelection().restartSelection(model->getCursor()); + return true; +} + +bool BasicEditboxView::mouseDrag(int x, int y) +{ + int textheight = text_height(textfont); + + if(model->getSelection().isSelecting()) + { + std::pair oldsel = model->getSelection().getSelection(); + CharPos cp = findCharacter(x,y); + model->getCursor().updateCursor(cp.totalIndex); + model->getSelection().adjustSelection(model->getCursor()); + + if(y < area_ystart) + { + view_y = zc_max(0, view_y-1); + } + + if(y > area_ystart+area_height) + { + int ymost = zc_max(area_height, (int)model->getLines().size()*textheight); + view_y = zc_min(ymost-area_height, view_y+1); + } + + if(x < area_xstart) + view_x = zc_max(0, view_x-1); + + if(x > area_xstart+area_width) + { + int xmost = zc_max(area_width, view_width); + view_x = zc_min(xmost-area_width, view_x+1); + } + + if(oldsel != model->getSelection().getSelection()) + { + return true; + } + } + + return false; +} + +bool BasicEditboxView::mouseRelease(int x, int y) +{ + x=x; + y=y; //these are here to bypass compiler warnings about unused arguments + model->getSelection().doneSelection(); + return false; +} + +void BasicEditboxView::createStripBitmap(std::list::iterator it, int width) +{ + //now create the bitmap + int textheight = text_height(textfont); + + if(it->strip) + destroy_bitmap(it->strip); + + it->strip = create_bitmap_ex(8,width,textheight); + rectfill(it->strip, 0,0,width, textheight, bgcolor); + Unicode::textout_ex_nonstupid(it->strip, textfont, (*it).line, 0, 0, fgcolor, bgcolor); +} + +//////////////////////////////////////////////////////////////////////////////////////// + +void EditboxVScrollView::init() +{ + BasicEditboxView::init(); + toparrow_x = host->x+host->w-16; + toparrow_y = host->y; + toparrow_state=0; + bottomarrow_x = host->x+host->w-16; + bottomarrow_y = host->y+host->h-16; + bottomarrow_state = 0; + barstate = 0; +} + +void EditboxVScrollView::drawExtraComponents() +{ + int textheight = text_height(textfont); + //draw the scrollbar + draw_arrow_button(dbuf, toparrow_x-host->x, toparrow_y-host->y, 16, 16, true, toparrow_state*3); + draw_arrow_button(dbuf, bottomarrow_x-host->x, bottomarrow_y-host->y, 16, 16, false, bottomarrow_state*3); + + if(!sbarpattern) + { + sbarpattern = create_bitmap_ex(bitmap_color_depth(screen),2,2); + putpixel(sbarpattern, 0, 1, scheme[jcLIGHT]); + putpixel(sbarpattern, 0, 1, scheme[jcLIGHT]); + putpixel(sbarpattern, 0, 1, scheme[jcLIGHT]); + putpixel(sbarpattern, 0, 1, scheme[jcLIGHT]); + } + + drawing_mode(DRAW_MODE_COPY_PATTERN, sbarpattern, 0, 0); + int barstart = toparrow_y + 16 - host->y; + int barend = bottomarrow_y - host->y-1; + + if(barstart < barend) + rectfill(dbuf, toparrow_x-host->x, barstart, toparrow_x-host->x+15, barend, 0); + + solid_mode(); + //compute the bar button, based on view_y + int totallen = (int)model->getLines().size()*textheight; + int available = bottomarrow_y-(toparrow_y+16); + + if(available < 0) + { + baroff=barlen=0; + } + + else + { + //area_height:totallen = barlen:available + barlen = (available*area_height)/zc_max(totallen,area_height)+1; + //clip to reasonable values + barlen = zc_max(barlen, 8); + baroff = zc_min(baroff, available-barlen); + + //view_y:(totallen-area_height) = baroff:(available-barlen) + if(totallen <= area_height) + baroff=0; + else + baroff = ((available-barlen)*view_y)/(totallen-area_height); + + } + + if(barlen > 0) + { + jwin_draw_button(dbuf, toparrow_x-host->x, toparrow_y+16-host->y+baroff, 16, barlen, false, 1); + } +} + +EditboxVScrollView::~EditboxVScrollView() +{ + destroy_bitmap(sbarpattern); +} + +bool EditboxVScrollView::mouseClick(int x, int y) +{ + //check if in text area + if(area_ystart <= y && y <= area_ystart+area_height) + { + if(area_xstart <= x && x <= area_xstart+area_width) + { + return BasicEditboxView::mouseClick(x,y); + } + + if(toparrow_x <= x && x <= toparrow_x + 16) + { + // clicked on an arrow, or the slider + if(barstate == 1) + { + //adjust + int deltay = barstarty-y; + barstarty = y; + //deltay:(available-barlen) = dealtaview_y:(totallen-area_height) + int available = bottomarrow_y-(toparrow_y+16); + int textheight = text_height(textfont); + int totallen = (int)model->getLines().size()*textheight; + + if(available > barlen) + view_y -= ((totallen-area_height)*deltay)/(available-barlen); + + enforceHardLimits(); + return true; + } + + if(toparrow_y <= y && y <= toparrow_y + 16) + { + //clicked on top arrow + scrollUp(); + toparrow_state = 1; + return true; + } + + if(bottomarrow_y <= y && y <= bottomarrow_y + 16) + { + scrollDown(); + bottomarrow_state = 1; + return true; + } + else + { + //clicked the slider + if(toparrow_y+16+baroff <= y && y <= toparrow_y+16+baroff+barlen) + { + //clicked the bar itself + barstarty = y; + barstate = 1; + return true; + } + else + { + //"teleport" + //adjust click by half of length of slider + y -= toparrow_y+16+barlen/2; + int available = bottomarrow_y-(toparrow_y+16); + int textheight = text_height(textfont); + int totallen = (int)model->getLines().size()*textheight; + + //y:(available-barlen)= view_y:(totallen-area_height) + if(available <= barlen) + view_y=0; + else + view_y = (y*(totallen-area_height))/(available-barlen); + + enforceHardLimits(); + return true; + } + } + } + } + + return mouseClickOther(x,y); +} + +bool EditboxVScrollView::mouseDrag(int x, int y) +{ + int textheight; + textheight = text_height(textfont); + + if(model->getSelection().isSelecting()) + { + return BasicEditboxView::mouseDrag(x,y); + } + else + { + //maybe pressing arrow, or sliding? + if(toparrow_state == 1) + { + scrollUp(); + return true; + } + + if(bottomarrow_state == 1) + { + scrollDown(); + return true; + } + + if(barstate == 1) + { + //fake a click + //first, clip the coords + int fakex = toparrow_x+1; + return mouseClick(fakex,y); + } + + return mouseDragOther(x,y); + } +} + +bool EditboxVScrollView::mouseRelease(int x, int y) +{ + BasicEditboxView::mouseRelease(x,y); + toparrow_state = 0; + bottomarrow_state = 0; + barstate = 0; + return false; +} + +////////////////////////////////////////////////////////////////////////////////////// +void EditboxWordWrapView::layoutPage() +{ + //check all lines + for(std::list::iterator it = model->getLines().begin(); it != model->getLines().end(); it++) + { + if(!it->dirtyflag) + continue; + + int numchars = (*it).numchars; + std::string &s = (*it).line; + //accumulate up until the maximum line width + int totalwidth=0; + int i; + + for(i=0; i offandwidth = Unicode::munchWord(s,i,textfont); + totalwidth += offandwidth.second; + i += offandwidth.first-1; + continue; + } + } + else + { + int c = Unicode::getCharAtIndex(s,i); + + if(c == ' ' || c == '\t' || c == '\n') + { + //whitespace + totalwidth += Unicode::getCharWidth(c, textfont); + + if(totalwidth > area_width) + break; + } + else + { + std::pair offandwidth = Unicode::munchWord(s,i,textfont); + totalwidth += offandwidth.second; + + if(totalwidth > area_width) + break; + + i += offandwidth.first-1; + } + } + } + + if(i < numchars) + { + //we have wrapped early. + std::string newline = s.substr(i,s.size()-i); + LineData newdata = {newline, numchars-i, true, true,NULL}; + std::list::iterator it2 = it; + it2++; + model->getLines().insert(it2,newdata); + (*it).line = s.substr(0,i); + (*it).numchars = i; + (*it).newlineterminated = false; + } + + totalwidth=0; + //efficiency opportunity + int length = Unicode::getLength(it->line); + + for(int j=0; jline,j),textfont); + } + + createStripBitmap(it, totalwidth); + (*it).dirtyflag = false; + } +} + +////////////////////////////////////////////////////////////////////////////////////// + +void EditboxNoWrapView::layoutPage() +{ + view_width = area_width; + + for(std::list::iterator it = model->getLines().begin(); it != model->getLines().end(); it++) + { + int length = Unicode::getLength(it->line); + int totalwidth=0; + + //efficiency opportunity + for(int i=0; iline,i),textfont); + } + + if(totalwidth > view_width) + view_width=totalwidth; + + if(!it->dirtyflag) + continue; + + createStripBitmap(it, totalwidth); + (*it).dirtyflag=false; + } +} + +void EditboxNoWrapView::init() +{ + EditboxVScrollView::init(); + bottomarrow_y -= 16; + area_height -=16; + leftarrow_x = host->x; + leftarrow_y = host->y+host->h-16; + leftarrow_state=0; + rightarrow_x = host->x+host->w-32; + rightarrow_y = host->y+host->h-16; + rightarrow_state = 0; + hbarstate = 0; +} + +void EditboxNoWrapView::drawExtraComponents() +{ + EditboxVScrollView::drawExtraComponents(); + int textheight; + textheight = text_height(textfont); + //draw the scrollbar + draw_arrow_button_horiz(dbuf, leftarrow_x-host->x, leftarrow_y-host->y, 16, 16, true, leftarrow_state*3); + draw_arrow_button_horiz(dbuf, rightarrow_x-host->x, rightarrow_y-host->y, 16, 16, false, rightarrow_state*3); + drawing_mode(DRAW_MODE_COPY_PATTERN, sbarpattern, 0, 0); + int hbarstart = leftarrow_x + 16 - host->x; + int hbarend = rightarrow_x - host->x-1; + + if(hbarstart < hbarend) + rectfill(dbuf, hbarstart, leftarrow_y-host->y, hbarend, leftarrow_y-host->y+15, 0); + + solid_mode(); + //compute the bar button, based on view_y + int totallen = view_width; + int available = rightarrow_x-(leftarrow_x+16); + + if(available < 0) + { + hbaroff=hbarlen=0; + } + + else + { + //area_width:totallen = barlen:available + hbarlen = (available*area_width)/zc_max(totallen,area_width)+1; + //clip to reasonable values + hbarlen = zc_max(hbarlen, 8); + hbaroff = zc_min(hbaroff, available-hbarlen); + + //view_x:(totallen-area_width) = baroff:(available-hbarlen) + if(totallen <= area_width) + hbaroff = 0; + else + hbaroff = ((available-hbarlen)*view_x)/(totallen-area_width); + } + + if(hbarlen > 0) + { + jwin_draw_button(dbuf, leftarrow_x-host->x+hbaroff+16, leftarrow_y-host->y, hbarlen, 16, false, 1); + } +} + +bool EditboxNoWrapView::mouseRelease(int x, int y) +{ + leftarrow_state = 0; + rightarrow_state = 0; + hbarstate = 0; + return EditboxVScrollView::mouseRelease(x,y); +} + +bool EditboxNoWrapView::mouseDragOther(int x, int) +{ + //maybe pressing arrow, or sliding? + if(leftarrow_state == 1) + { + scrollLeft(); + return true; + } + + if(rightarrow_state == 1) + { + scrollRight(); + return true; + } + + if(hbarstate == 1) + { + //fake a click + //first, clip the coords + int fakey = leftarrow_y+1; + return mouseClick(x,fakey); + } + + return false; +} + +bool EditboxNoWrapView::mouseClickOther(int x, int y) +{ + if(leftarrow_x <= x && x <= rightarrow_x+16) + { + if(leftarrow_y <= y && y <= leftarrow_y+16) + { + // clicked on an arrow, or the slider + if(hbarstate == 1) + { + //adjust + int deltax = hbarstartx-x; + hbarstartx = x; + //deltax:(available-hbarlen) = dealtaview_x:(totallen-area_width) + int available = rightarrow_x-(leftarrow_x+16); + int totallen = view_width; + + if(available > hbarlen) + view_x -= ((totallen-area_width)*deltax)/(available-hbarlen); + + enforceHardLimits(); + return true; + } + + if(leftarrow_x <= x && x <= leftarrow_x + 16) + { + //clicked on left arrow + scrollLeft(); + leftarrow_state = 1; + return true; + } + + if(rightarrow_x <= x && x <= rightarrow_x + 16) + { + scrollRight(); + rightarrow_state = 1; + return true; + } + else + { + //clicked the slider + if(leftarrow_x+16+hbaroff <= x && x <= leftarrow_x+16+hbaroff+hbarlen) + { + //clicked the bar itself + hbarstartx = x; + hbarstate = 1; + return true; + } + else + { + //"teleport" + //adjust click by half of length of slider + x -= leftarrow_x+16+hbarlen/2; + int available = rightarrow_x-(leftarrow_x+16); + int totallen = view_width; + + //x:(available-hbarlen)= view_x:(totallen-area_width) + if(available <= hbarlen) + view_x=0; + else + view_x = (x*(totallen-area_width))/(available-hbarlen); + + enforceHardLimits(); + return true; + } + } + } + } + + return false; +} + +void EditboxScriptView::init() +{ + EditboxNoWrapView::init(); + bottomarrow_y-=16; + area_height-=16; + leftarrow_y-=16; + rightarrow_y-=16; + linetext = create_bitmap_ex(8,host->w,16); +} + +EditboxScriptView::~EditboxScriptView() +{ + if(linetext) destroy_bitmap(linetext); +} + +void EditboxScriptView::drawExtraComponents() +{ + EditboxNoWrapView::drawExtraComponents(); + rectfill(linetext, 0,0,linetext->w, linetext->h, scheme[jcMEDLT]); + CursorPos cp = model->findCursor(); + char temp[60]; + sprintf(temp, "Line %d", cp.lineno+1); + //center text + int textheight = text_height(textfont); + int padding = 16-textheight; + int offset = padding/2; + textout_ex(linetext, textfont, temp, 2,offset,fgcolor, -1); + blit(linetext, dbuf, 0,0, 0, leftarrow_y-host->y+16,linetext->w,linetext->h); +} + diff --git a/src/aglogo.cpp b/src/aglogo.cpp new file mode 100644 index 0000000000..02d0de16fa --- /dev/null +++ b/src/aglogo.cpp @@ -0,0 +1,188 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// aglogo.cc +// +// Armageddon games logo with fire field generator. +// Adapted from code written by Midnight and included in +// SPHINX C-- examples. +// (Tweaked by Jeremy Craner.) +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "zc_alleg.h" +#include "zdefs.h" +#include "zeldadat.h" +#include "zc_malloc.h" + +extern DATAFILE* data; + +extern bool sbig; +extern int screen_scale; +extern int joystick_index; + + +static void SetCols(RGB* pal) +{ + + byte firepal[256*3]; + word DI,BX=0; + + firepal[0]=0; + firepal[1]=0; + firepal[2]=0; + + do + { + word AX = BX * 64 / 85; + byte DL = AX; + + DI = BX+BX+BX; + firepal[DI+3] = DL; + firepal[DI+3+1] = 0; + + if(BX<75) + firepal[DI+3+2] = BX<8 ? (BX<<1)+12 : 20; + else firepal[DI+3+2] = BX-75; + + firepal[DI+3+85+85+85] = 63; + firepal[DI+3+85+85+85+1] = DL; + firepal[DI+3+85+85+85+2] = 0; + + firepal[DI+3+85+85+85+85+85+85] = 63; + firepal[DI+3+85+85+85+85+85+85+1] = 63; + firepal[DI+3+85+85+85+85+85+85+2] = DL; + + ++BX; + } + while(BX < 85); + + firepal[255*3]=0; + firepal[255*3+1]=0; + firepal[255*3+2]=0; + DI=0; + + for(int i=0; i<256; i++) + { + pal[i].r = firepal[DI++]; + pal[i].g = firepal[DI++]; + pal[i].b = firepal[DI++]; + } +} + +static void AddFire(BITMAP* firebuf,word N) +{ + while(N) + { + int cx = (rand()%10+1)<<1; + int x = rand()%314; + byte color = (rand()&127) + 128; + + while(cx) + { + firebuf->line[200][x]=color; + firebuf->line[202][x]=color; + ++x; + --cx; + } + + --N; + } +} + +static void CopyAvg(BITMAP* fire) +{ + for(int y=4; y<204; y+=2) + { + for(int x=2; x<336; x+=2) + { + byte* si=&(fire->line[y][x-2]); + int AX = (*si + *(si+2) + *(si+4) + fire->line[y+2][x]) >> 2; + AX = (AX + fire->line[y-2][x]) >> 1; + + if(AX>128) + AX-=2; + else if(AX>12) + AX-=4; + else if(AX>8) + AX-=2; + else if(AX>0) + --AX; + + AX=(AX<<8)+AX; + ((word*)fire->line[y-4])[x>>1]=AX; + ((word*)fire->line[y-3])[x>>1]=AX; + } + } +} + +int aglogo(BITMAP *frame, BITMAP *firebuf, int resx, int resy) +{ + // frame should be 320x200, firebuf at least 340x206 + PALETTE pal; + SetCols(pal); + PALETTE workpal; + set_palette(black_palette); + clear_bitmap(frame); + clear_bitmap(firebuf); + clear_bitmap(screen); + + for(int f=0; f<128; f++) + { + AddFire(firebuf,(f>>3)+1); + CopyAvg(firebuf); + } + + int fadecnt=0; + bool blackout=false; + play_sample((SAMPLE*)data[WAV_00_AGFIRE].dat,255,128,1000,true); + + do + { + AddFire(firebuf,17); + CopyAvg(firebuf); + blit(firebuf,frame,8,0,0,0,320,198); + draw_rle_sprite(frame,(RLE_SPRITE*)data[RLE_AGTEXT].dat,24,90); + vsync(); + + if(sbig) + stretch_blit(frame,screen, 0,0,320,198, (resx-(320*screen_scale))>>1, (resy-(198*screen_scale))>>1, 320*screen_scale,198*screen_scale); + else + blit(frame,screen, 0,0,(resx-320)>>1, (resy-198)>>1, 320,198); + + poll_joystick(); + + if((keypressed()||joy[joystick_index].button[0].b||joy[joystick_index].button[1].b)&&fadecnt>=32) + blackout=true; + + if(!blackout) + { + if(fadecnt<64) //I get some problems here when fade_interpolate takes invalid parameters. + { + if(!(++fadecnt < 0)) + fade_interpolate(black_palette,pal,workpal,fadecnt,0,255); + + set_palette_range(workpal,0,255,false); + } + } + else + { + if(!(--fadecnt < 0)) + fade_interpolate(black_palette,pal,workpal,fadecnt,0,255); + + set_palette_range(workpal,0,255,false); + } + } + while(fadecnt>0); + + stop_sample((SAMPLE*)data[WAV_00_AGFIRE].dat); + clear_keybuf(); + return 0; +} + diff --git a/src/aglogo.h b/src/aglogo.h new file mode 100644 index 0000000000..7a77aaf34a --- /dev/null +++ b/src/aglogo.h @@ -0,0 +1,21 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// aglogo.h +// +// Armageddon games logo with fire field generator. +// Adapted from code written by Midnight and included in +// SPHINX C-- examples. +// (Tweaked by Jeremy Craner.) +// +//-------------------------------------------------------- + +#ifndef _AGLOGO_H_ +#define _AGLOGO_H_ + +extern DATAFILE* data; + +int aglogo(BITMAP *frame, BITMAP *firebuf, int resx, int resy); +#endif + diff --git a/src/angelscript/aszc.cpp b/src/angelscript/aszc.cpp new file mode 100644 index 0000000000..0d60936882 --- /dev/null +++ b/src/angelscript/aszc.cpp @@ -0,0 +1,659 @@ +#include "aszc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scriptData.h" +#include "util.h" +#include "scriptarray/scriptarray.h" +#include "scriptstdstring/scriptstdstring.h" +#include "scriptbuilder/scriptbuilder.h" +#include "scriptmath/scriptmath.h" +#include +#include +#include + +extern LinkClass Link; + +// Global variables from link.cpp +extern int directWpn; + +static sprite* currentSprite; +static enemy* currentEnemy; +static item* currentItem; +static weapon* currentWeapon; +static sprite* getRealSprite(); +static enemy* getRealEnemy(); +static item* getRealItem(); +static weapon* getRealWeapon(); +static LinkClass* getRealLink(); +static void assignSpriteScript(sprite* spr, const char* scriptName); + +static asIScriptEngine* asEngine=0; + +static void messageCallback(const asSMessageInfo* msg, void* param) +{ + const char* type; + switch(msg->type) + { + case asMSGTYPE_WARNING: + type="Warning"; + break; + + case asMSGTYPE_INFORMATION: + type="Info"; + break; + + case asMSGTYPE_ERROR: + default: + type="Error"; + break; + } + + al_trace("%s: %s (%d, %d): %s\n", type, msg->section, msg->row, msg->col, msg->message); +} + +static void fixCons(fix* addr) +{ + new(addr) fix(0); +} + +static void fixConsCopy(fix* addr, const fix& other) +{ + new(addr) fix(other); +} + +static void fixConsInt(fix* addr, int value) +{ + new(addr) fix(value); +} + +static void fixConsFloat(fix* addr, float value) +{ + new(addr) fix(value); +} + +static int fixComp(fix f1, fix f2) +{ + if(f1f2) + return 1; + return 0; +} + +static int fixV(fix& f) +{ + return f.v; +} + +static void fixVAND(fix& f, unsigned int andVal) +{ + f.v&=andVal; +} + +static fix fixSin(fix& f) +{ + // You'd think casting to double would be okay, but nope. + return sin(f); +} + +static void registerFix() +{ + asEngine->RegisterObjectType("fix", sizeof(fix), asOBJ_VALUE|asOBJ_POD|asOBJ_APP_CLASS_CAK|asOBJ_APP_CLASS_ALLINTS); + + // Constructors + asEngine->RegisterObjectBehaviour("fix", asBEHAVE_CONSTRUCT, "void fix()", asFUNCTION(fixCons), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectBehaviour("fix", asBEHAVE_CONSTRUCT, "void fix(const fix &in)", asFUNCTION(fixConsCopy), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectBehaviour("fix", asBEHAVE_CONSTRUCT, "void fix(int)", asFUNCTION(fixConsInt), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectBehaviour("fix", asBEHAVE_CONSTRUCT, "void fix(float)", asFUNCTION(fixConsFloat), asCALL_CDECL_OBJFIRST); + + // Arithmetic + asEngine->RegisterObjectMethod("fix", "fix opNeg() const", asMETHODPR(fix, operator-, () const, fix), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix opAdd(fix) const", asFUNCTIONPR(operator+, (fix, fix), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opAdd(int) const", asFUNCTIONPR(operator+, (fix, int), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opAdd(float) const", asFUNCTIONPR(operator+, (fix, float), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opSub(fix) const", asFUNCTIONPR(operator-, (fix, fix), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opSub(int) const", asFUNCTIONPR(operator-, (fix, int), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opSub(float) const", asFUNCTIONPR(operator-, (fix, float), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opMul(fix) const", asFUNCTIONPR(operator*, (fix, fix), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opMul(int) const", asFUNCTIONPR(operator*, (fix, int), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opMul(float) const", asFUNCTIONPR(operator*, (fix, float), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opDiv(fix) const", asFUNCTIONPR(operator/, (fix, fix), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opDiv(int) const", asFUNCTIONPR(operator/, (fix, int), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opDiv(float) const", asFUNCTIONPR(operator/, (fix, float), fix), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "fix opPostInc()", asMETHODPR(fix, operator++, (), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix opPostDec()", asMETHODPR(fix, operator--, (), fix&), asCALL_THISCALL); + + // Assignment + asEngine->RegisterObjectMethod("fix", "fix& opAssign(fix)", asMETHODPR(fix, operator=, (const fix&), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opAssign(int)", asMETHODPR(fix, operator=, (const int), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opAssign(float)", asMETHODPR(fix, operator=, (const float), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opAddAssign(const fix &in)", asMETHODPR(fix, operator+=, (fix), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opSubAssign(const fix &in)", asMETHODPR(fix, operator-=, (fix), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opMulAssign(const fix &in)", asMETHODPR(fix, operator*=, (fix), fix&), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "fix& opDivAssign(const fix &in)", asMETHODPR(fix, operator/=, (fix), fix&), asCALL_THISCALL); + + // Allegro's comparison operators return int, not bool. Not sure if + // this might be a problem on platforms where they're not the same size. + asEngine->RegisterObjectMethod("fix", "bool opEquals(const fix) const", asFUNCTIONPR(operator==, (fix, fix), int), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "bool opEquals(const int) const", asFUNCTIONPR(operator==, (fix, int), int), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "bool opEquals(const float) const", asFUNCTIONPR(operator==, (fix, float), int), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "int opCmp(const fix) const", asFUNCTION(fixComp), asCALL_CDECL_OBJFIRST); + + // Casts + asEngine->RegisterObjectMethod("fix", "int opImplConv() const", asMETHODPR(fix, operator int, () const, int), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "float opImplConv() const", asMETHODPR(fix, operator float, () const, float), asCALL_THISCALL); + asEngine->RegisterObjectMethod("fix", "double opImplConv() const", asMETHODPR(fix, operator double, () const, double), asCALL_THISCALL); + + // x.v + asEngine->RegisterObjectMethod("fix", "int getV()", asFUNCTION(fixV), asCALL_CDECL_OBJFIRST); + asEngine->RegisterObjectMethod("fix", "void vAND(uint)", asFUNCTION(fixVAND), asCALL_CDECL_OBJFIRST); + + // And more + asEngine->RegisterObjectMethod("fix", "fix sin()", asFUNCTION(fixSin), asCALL_CDECL_OBJFIRST); +} + +// All the classes are registered together first because their methods +// need to take each other as arguments. +static void registerTypes() +{ + asEngine->RegisterObjectType("__RealSprite", sizeof(sprite), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterGlobalFunction("__RealSprite@ __getRealSprite()", asFUNCTION(getRealSprite), asCALL_CDECL); + asEngine->RegisterObjectType("__RealLink", sizeof(LinkClass), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterGlobalFunction("__RealLink@ __getRealLink()", asFUNCTION(getRealLink), asCALL_CDECL); + asEngine->RegisterObjectType("__RealEnemy", sizeof(ASEnemy), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterGlobalFunction("__RealEnemy@ __getRealEnemy()", asFUNCTION(getRealEnemy), asCALL_CDECL); + asEngine->RegisterObjectType("__RealItem", sizeof(item), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterGlobalFunction("__RealItem@ __getRealItem()", asFUNCTION(getRealItem), asCALL_CDECL); + asEngine->RegisterObjectType("__RealWeapon", sizeof(weapon), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterGlobalFunction("__RealWeapon@ __getRealWeapon()", asFUNCTION(getRealWeapon), asCALL_CDECL); + asEngine->RegisterObjectType("mapscr", sizeof(mapscr), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterObjectType("FFC", sizeof(FFC), asOBJ_REF|asOBJ_NOCOUNT); + asEngine->RegisterInterface("spriteIF"); // Dummy interface for getters +} +void TraceI(int i) { al_trace("%d\n", i); } +void registerGlobalFunctions() // And properties... Whatever. +{ + asEngine->RegisterGlobalFunction("void TraceI(int)", asFUNCTION(TraceI), asCALL_CDECL); + asEngine->RegisterGlobalProperty("const int frame", &frame); + asEngine->RegisterGlobalProperty("const int db", &db); + asEngine->RegisterGlobalProperty("const bool BSZ", &BSZ); + asEngine->RegisterGlobalProperty("const int fadeclk", &fadeclk); + asEngine->RegisterGlobalProperty("bool watch", &watch); + asEngine->RegisterGlobalProperty("const int whistleclk", &whistleclk); + asEngine->RegisterGlobalProperty("int wallm_load_clk", &wallm_load_clk); + asEngine->RegisterGlobalProperty("int hasitem", &hasitem); + asEngine->RegisterGlobalProperty("const int playing_field_offset", &playing_field_offset); + asEngine->RegisterGlobalProperty("const int loadside", &loadside); + asEngine->RegisterGlobalProperty("int guycarryingitem", &guycarryingitem); + asEngine->RegisterGlobalProperty("int16 lensclk", &lensclk); + asEngine->RegisterGlobalProperty("int currmap", &currmap); + asEngine->RegisterGlobalProperty("int currscr", &currscr); + asEngine->RegisterGlobalProperty("int dlevel", &dlevel); + asEngine->RegisterGlobalProperty("int directWpn", &directWpn); + asEngine->RegisterGlobalProperty("bool pull_link", &pull_link); + asEngine->RegisterGlobalProperty("bool toogam", &toogam); + + asEngine->RegisterGlobalFunction("int rand()", asFUNCTION(rand), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("mapscr@ getTmpscr(int)", asFUNCTION(asGetTmpscr), asCALL_CDECL); + asEngine->RegisterGlobalFunction("mapscr@ getTmpscr2(int)", asFUNCTION(asGetTmpscr2), asCALL_CDECL); + asEngine->RegisterGlobalFunction("mapscr@ getTmpscr3(int)", asFUNCTION(asGetTmpscr3), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("int hit_enemy(int, int, int, int, int, int, int)", asFUNCTION(hit_enemy), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getFFCAt(int, int)", asFUNCTION(getFFCAt), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void loadpalset(int, int)", asFUNCTION(loadpalset), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void music_stop()", asFUNCTION(music_stop), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void playLevelMusic()", asFUNCTION(playLevelMusic), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void setupscreen()", asFUNCTION(setupscreen), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool screenFlagSet(int)", asFUNCTION(asScreenFlagIsSet), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getComboType(int)", asFUNCTION(asGetComboType), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getSpriteTile(int)", asFUNCTION(getSpriteTile), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool questRuleEnabled(int)", asFUNCTION(asQuestRuleEnabled), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void sfx(int, int=128)", asFUNCTION(asSFX), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void stop_sfx(int)", asFUNCTION(asStopSFX), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool iswater(int)", asFUNCTION(asIsWater), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool _walkflag(int, int, int)", asFUNCTION(_walkflag), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int MAPCOMBO(int x, int y)", asFUNCTION(MAPCOMBO), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int MAPFLAG(int x, int y)", asFUNCTION(MAPFLAG), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int MAPCOMBOFLAG(int x, int y)", asFUNCTION(MAPCOMBOFLAG), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int MAPFFCOMBOFLAG(int x, int y)", asFUNCTION(MAPFFCOMBOFLAG), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int COMBOTYPE(int x, int y)", asFUNCTION(COMBOTYPE), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int FFCOMBOTYPE(int x, int y)", asFUNCTION(FFCOMBOTYPE), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool findentrance(int, int, int, bool)", asFUNCTION(findentrance), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool m_walkflag(int, int, int, int=-1000, int=-1000)", asFUNCTION(m_walkflag), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool isdungeon(int=-1, int=-1)", asFUNCTION(isdungeon), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int select_dropitem(int, int, int)", asFUNCTION(select_dropitem), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int addenemy(int, int, int, int, int)", asFUNCTIONPR(addenemy, (int, int, int, int, int), int), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void kill_em_all()", asFUNCTION(kill_em_all), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void setGuyGridAt(int, int, int)", asFUNCTION(asSetGuyGridAt), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool getmapflag(int=32)", asFUNCTION(getmapflag), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void setmapflag(int=32)", asFUNCTIONPR(setmapflag, (int), void), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void change_counter(int, int16)", asFUNCTION(asChangeCounter), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void change_dcounter(int, int16)", asFUNCTION(asChangeDCounter), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int get_generic(int)", asFUNCTION(asGetGeneric), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getGravity()", asFUNCTION(asGetGravity), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getTerminalVelocity()", asFUNCTION(asGetTerminalVelocity), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int decGuyCount(int)", asFUNCTION(asDecGuyCount), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("int getItemProp(int, int)", asFUNCTION(asGetItemProp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int current_item(int)", asFUNCTIONPR(current_item, (int), int), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int current_item_id(int, bool=true)", asFUNCTION(current_item_id), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int current_item_power(int)", asFUNCTION(current_item_power), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int set_item(int, bool)", asFUNCTION(asSetItem), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void setLevelItem(int, int)", asFUNCTION(asSetLevelItem), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getitem(int, bool=false)", asFUNCTION(getitem), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("int getWeaponProp(int, int)", asFUNCTION(asGetWeaponProp), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("int getComboProp(int, int)", asFUNCTION(asGetComboProp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getComboClassProp(int, int)", asFUNCTION(asGetComboClassProp), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("spriteIF@ __getGuy(int)", asFUNCTION(asGetGuyObject), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int numGuys()", asFUNCTION(asNumGuys), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int getGuyProp(int, int)", asFUNCTION(asGetGuyProp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void swapGuys(int, int)", asFUNCTION(asSwapGuys), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("spriteIF@ __getItem(int)", asFUNCTION(asGetItemObject), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int numItems()", asFUNCTION(asNumItems), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void deleteItem(int)", asFUNCTION(asDeleteItem), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void placeitem(int, int, int, int, int=0)", asFUNCTION(asPlaceItem), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("spriteIF@ __getLwpn(int)", asFUNCTION(asGetLwpnObject), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int numLwpns()", asFUNCTION(asNumLwpns), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("spriteIF@ __getEwpn(int)", asFUNCTION(asGetEwpnObject), asCALL_CDECL); + asEngine->RegisterGlobalFunction("int numEwpns()", asFUNCTION(asNumEwpns), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void deleteEwpn(int)", asFUNCTION(asDeleteEwpn), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("void addDecoration(int, int, int)", asFUNCTION(asAddDecoration), asCALL_CDECL); + asEngine->RegisterGlobalFunction("void moveChainLinks(int, int)", asFUNCTION(asMoveChainLinks), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("void runZScript(uint8, uint16, uint8=255)", asFUNCTION(ZScriptVersion::RunScript), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("bool Up()", asFUNCTION(asInputUp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool Down()", asFUNCTION(asInputDown), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool Left()", asFUNCTION(asInputLeft), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool Right()", asFUNCTION(asInputRight), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cAbtn()", asFUNCTION(asCAbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cBbtn()", asFUNCTION(asCBbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cSbtn()", asFUNCTION(asCSbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cMbtn()", asFUNCTION(asCMbtn), asCALL_CDECL); // Menu again... + asEngine->RegisterGlobalFunction("bool cLbtn()", asFUNCTION(asCLbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cRbtn()", asFUNCTION(asCRbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cPbtn()", asFUNCTION(asCPbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cEx1btn()", asFUNCTION(asCEx1btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cEx2btn()", asFUNCTION(asCEx2btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cEx3btn()", asFUNCTION(asCEx3btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool cEx4btn()", asFUNCTION(asCEx4btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool AxisUp()", asFUNCTION(asInputAxisUp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool AxisDown()", asFUNCTION(asInputAxisDown), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool AxisLeft()", asFUNCTION(asInputAxisLeft), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool AxisRight()", asFUNCTION(asInputAxisRight), asCALL_CDECL); + + asEngine->RegisterGlobalFunction("bool rUp()", asFUNCTION(asRUp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rDown()", asFUNCTION(asRDown), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rLeft()", asFUNCTION(asRLeft), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rRight()", asFUNCTION(asRRight), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rAbtn()", asFUNCTION(asRAbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rBbtn()", asFUNCTION(asRBbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rSbtn()", asFUNCTION(asRSbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rMbtn()", asFUNCTION(asRMbtn), asCALL_CDECL); // Menu button. Hmm... + asEngine->RegisterGlobalFunction("bool rLbtn()", asFUNCTION(asRLbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rRbtn()", asFUNCTION(asRRbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rPbtn()", asFUNCTION(asRPbtn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rEx1btn()", asFUNCTION(asREx1btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rEx2btn()", asFUNCTION(asREx2btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rEx3btn()", asFUNCTION(asREx3btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rEx4btn()", asFUNCTION(asREx4btn), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rAxisUp()", asFUNCTION(asRAxisUp), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rAxisDown()", asFUNCTION(asRAxisDown), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rAxisLeft()", asFUNCTION(asRAxisLeft), asCALL_CDECL); + asEngine->RegisterGlobalFunction("bool rAxisRight()", asFUNCTION(asRAxisRight), asCALL_CDECL); +} + +void registerMapscr() +{ + asEngine->RegisterObjectProperty("mapscr", "uint16 undercombo", asOFFSET(mapscr, undercombo)); + asEngine->RegisterObjectProperty("mapscr", "uint8 undercset", asOFFSET(mapscr, undercset)); + asEngine->RegisterObjectProperty("mapscr", "uint16 catchall", asOFFSET(mapscr, catchall)); + asEngine->RegisterObjectProperty("mapscr", "uint8 secretsfx", asOFFSET(mapscr, secretsfx)); + + asEngine->RegisterObjectMethod("mapscr", "uint16 get_data(int)", asMETHOD(mapscr, getData), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_data(int, uint16)", asMETHOD(mapscr, setData), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "uint8 get_cset(int)", asMETHOD(mapscr, getCSet), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_cset(int, uint8)", asMETHOD(mapscr, setCSet), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "uint8 get_sflag(int)", asMETHOD(mapscr, getSFlag), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_sflag(int, uint8)", asMETHOD(mapscr, setSFlag), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "uint16 get_secretcombo(int)", asMETHOD(mapscr, getSecretCombo), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_secretcombo(int, uint16)", asMETHOD(mapscr, setSecretCombo), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "uint8 get_secretcset(int)", asMETHOD(mapscr, getSecretCSet), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_secretcset(int, uint8)", asMETHOD(mapscr, setSecretCSet), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "uint8 get_secretflag(int)", asMETHOD(mapscr, getSecretFlag), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "void set_secretflag(int, uint8)", asMETHOD(mapscr, setSecretFlag), asCALL_THISCALL); + asEngine->RegisterObjectMethod("mapscr", "FFC@ get_ffcs(int)", asMETHOD(mapscr, getFFC), asCALL_THISCALL); +} + +void registerFFC() +{ + asEngine->RegisterObjectMethod("FFC", "void modCombo(int16)", asMETHOD(FFC, modCombo), asCALL_THISCALL); + asEngine->RegisterObjectMethod("FFC", "void setCombo(uint16)", asMETHOD(FFC, setCombo), asCALL_THISCALL); + asEngine->RegisterObjectMethod("FFC", "void setCSet(uint16)", asMETHOD(FFC, setCSet), asCALL_THISCALL); +} + +void registerSprite() +{ + // Most variables and functions aren't in here yet. + // These should be moved entirely into the script classes when no uses in C++ remain. + asEngine->RegisterObjectProperty("__RealSprite", "int uid", asOFFSET(sprite, uid)); + asEngine->RegisterObjectProperty("__RealSprite", "fix x", asOFFSET(sprite, x)); + asEngine->RegisterObjectProperty("__RealSprite", "fix y", asOFFSET(sprite, y)); + asEngine->RegisterObjectProperty("__RealSprite", "fix z", asOFFSET(sprite, z)); + asEngine->RegisterObjectProperty("__RealSprite", "fix fall", asOFFSET(sprite, fall)); + asEngine->RegisterObjectProperty("__RealSprite", "int tile", asOFFSET(sprite, tile)); + asEngine->RegisterObjectProperty("__RealSprite", "int shadowtile", asOFFSET(sprite, shadowtile)); + asEngine->RegisterObjectProperty("__RealSprite", "int cs", asOFFSET(sprite, cs)); + asEngine->RegisterObjectProperty("__RealSprite", "int flip", asOFFSET(sprite, flip)); + asEngine->RegisterObjectProperty("__RealSprite", "int c_clk", asOFFSET(sprite, c_clk)); + asEngine->RegisterObjectProperty("__RealSprite", "int clk", asOFFSET(sprite, clk)); + asEngine->RegisterObjectProperty("__RealSprite", "int misc", asOFFSET(sprite, misc)); + asEngine->RegisterObjectProperty("__RealSprite", "fix xofs", asOFFSET(sprite, xofs)); + asEngine->RegisterObjectProperty("__RealSprite", "fix yofs", asOFFSET(sprite, yofs)); + asEngine->RegisterObjectProperty("__RealSprite", "fix zofs", asOFFSET(sprite, zofs)); + asEngine->RegisterObjectProperty("__RealSprite", "int hxofs", asOFFSET(sprite, hxofs)); + asEngine->RegisterObjectProperty("__RealSprite", "int hyofs", asOFFSET(sprite, hyofs)); + asEngine->RegisterObjectProperty("__RealSprite", "int hxsz", asOFFSET(sprite, hxsz)); + asEngine->RegisterObjectProperty("__RealSprite", "int hysz", asOFFSET(sprite, hysz)); + asEngine->RegisterObjectProperty("__RealSprite", "int hzsz", asOFFSET(sprite, hzsz)); + asEngine->RegisterObjectProperty("__RealSprite", "int txsz", asOFFSET(sprite, txsz)); + asEngine->RegisterObjectProperty("__RealSprite", "int tysz", asOFFSET(sprite, tysz)); + asEngine->RegisterObjectProperty("__RealSprite", "int id", asOFFSET(sprite, id)); + asEngine->RegisterObjectProperty("__RealSprite", "int dir", asOFFSET(sprite, dir)); + asEngine->RegisterObjectProperty("__RealSprite", "bool angular", asOFFSET(sprite, angular)); + asEngine->RegisterObjectProperty("__RealSprite", "bool canfreeze", asOFFSET(sprite, canfreeze)); + asEngine->RegisterObjectProperty("__RealSprite", "double angle", asOFFSET(sprite, angle)); + asEngine->RegisterObjectProperty("__RealSprite", "int lasthit", asOFFSET(sprite, lasthit)); + asEngine->RegisterObjectProperty("__RealSprite", "int lasthitclk", asOFFSET(sprite, lasthitclk)); + asEngine->RegisterObjectProperty("__RealSprite", "int drawstyle", asOFFSET(sprite, drawstyle)); + asEngine->RegisterObjectProperty("__RealSprite", "int extend", asOFFSET(sprite, extend)); + asEngine->RegisterObjectProperty("__RealSprite", "uint8 scriptcoldet", asOFFSET(sprite, scriptcoldet)); + + asEngine->RegisterObjectMethod("__RealSprite", "void draw()", asMETHOD(sprite, scriptDraw), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealSprite", "void drawcloaked()", asMETHOD(sprite, scriptDrawCloaked), asCALL_THISCALL); +} + +void registerLink() +{ + asEngine->RegisterObjectProperty("__RealLink", "bool tapping", asOFFSET(LinkClass, tapping)); + asEngine->RegisterObjectProperty("__RealLink", "bool stomping", asOFFSET(LinkClass, stomping)); + asEngine->RegisterObjectProperty("__RealLink", "int ladderx", asOFFSET(LinkClass, ladderx)); + asEngine->RegisterObjectProperty("__RealLink", "int laddery", asOFFSET(LinkClass, laddery)); + asEngine->RegisterObjectProperty("__RealLink", "int charging", asOFFSET(LinkClass, charging)); + asEngine->RegisterObjectProperty("__RealLink", "int spins", asOFFSET(LinkClass, spins)); + asEngine->RegisterObjectProperty("__RealLink", "int drunkclk", asOFFSET(LinkClass, drunkclk)); + asEngine->RegisterObjectProperty("__RealLink", "int hoverclk", asOFFSET(LinkClass, hoverclk)); + asEngine->RegisterObjectProperty("__RealLink", "int hclk", asOFFSET(LinkClass, hclk)); + asEngine->RegisterObjectProperty("__RealLink", "int attackclk", asOFFSET(LinkClass, attackclk)); + asEngine->RegisterObjectProperty("__RealLink", "int attack", asOFFSET(LinkClass, attack)); + asEngine->RegisterObjectProperty("__RealLink", "int attackid", asOFFSET(LinkClass, attackid)); + asEngine->RegisterObjectProperty("__RealLink", "int drownclk", asOFFSET(LinkClass, drownclk)); + asEngine->RegisterObjectProperty("__RealLink", "int slashxofs", asOFFSET(LinkClass, slashxofs)); + asEngine->RegisterObjectProperty("__RealLink", "int slashyofs", asOFFSET(LinkClass, slashyofs)); + asEngine->RegisterObjectProperty("__RealLink", "uint8 hopclk", asOFFSET(LinkClass, hopclk)); + asEngine->RegisterObjectProperty("__RealLink", "uint8 diveclk", asOFFSET(LinkClass, diveclk)); + asEngine->RegisterObjectProperty("__RealLink", "uint8 inlikelike", asOFFSET(LinkClass, inlikelike)); + asEngine->RegisterObjectProperty("__RealLink", "int shiftdir", asOFFSET(LinkClass, shiftdir)); + asEngine->RegisterObjectProperty("__RealLink", "int sdir", asOFFSET(LinkClass, sdir)); + asEngine->RegisterObjectProperty("__RealLink", "int hopdir", asOFFSET(LinkClass, hopdir)); + asEngine->RegisterObjectProperty("__RealLink", "int holddir", asOFFSET(LinkClass, holddir)); + asEngine->RegisterObjectProperty("__RealLink", "int landswim", asOFFSET(LinkClass, landswim)); + asEngine->RegisterObjectProperty("__RealLink", "bool ilswim", asOFFSET(LinkClass, ilswim)); + asEngine->RegisterObjectProperty("__RealLink", "bool walkable", asOFFSET(LinkClass, walkable)); + asEngine->RegisterObjectProperty("__RealLink", "int action", asOFFSET(LinkClass, action)); + asEngine->RegisterObjectProperty("__RealLink", "fix climb_cover_x", asOFFSET(LinkClass, climb_cover_x)); + asEngine->RegisterObjectProperty("__RealLink", "fix climb_cover_y", asOFFSET(LinkClass, climb_cover_y)); + asEngine->RegisterObjectProperty("__RealLink", "fix falling_oldy", asOFFSET(LinkClass, falling_oldy)); + asEngine->RegisterObjectProperty("__RealLink", "bool diagonalMovement", asOFFSET(LinkClass, diagonalMovement)); + + asEngine->RegisterObjectMethod("__RealLink", "int getAction()", asMETHOD(LinkClass, getAction), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealLink", "void hitlink(int)", asMETHOD(LinkClass, hitlink), asCALL_THISCALL); +} + +void registerEnemy() +{ + // Only a fraction of the variables and functions + asEngine->RegisterObjectProperty("__RealEnemy", "int o_tile", asOFFSET(ASEnemy, o_tile)); + asEngine->RegisterObjectProperty("__RealEnemy", "int frate", asOFFSET(ASEnemy, frate)); + asEngine->RegisterObjectProperty("__RealEnemy", "int hp", asOFFSET(ASEnemy, hp)); + asEngine->RegisterObjectProperty("__RealEnemy", "int hclk", asOFFSET(ASEnemy, hclk)); + asEngine->RegisterObjectProperty("__RealEnemy", "int stunclk", asOFFSET(ASEnemy, stunclk)); + asEngine->RegisterObjectProperty("__RealEnemy", "int fading", asOFFSET(ASEnemy, fading)); + asEngine->RegisterObjectProperty("__RealEnemy", "int superman", asOFFSET(ASEnemy, superman)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool mainguy", asOFFSET(ASEnemy, mainguy)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool did_armos", asOFFSET(ASEnemy, did_armos)); + asEngine->RegisterObjectProperty("__RealEnemy", "uint8 item_set", asOFFSET(ASEnemy, item_set)); + asEngine->RegisterObjectProperty("__RealEnemy", "uint8 grumble", asOFFSET(ASEnemy, grumble)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool itemguy", asOFFSET(ASEnemy, itemguy)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool count_enemy", asOFFSET(ASEnemy, count_enemy)); + asEngine->RegisterObjectProperty("__RealEnemy", "fix step", asOFFSET(ASEnemy, step)); + asEngine->RegisterObjectProperty("__RealEnemy", "fix floor_y", asOFFSET(ASEnemy, floor_y)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool dying", asOFFSET(ASEnemy, dying)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool ceiling", asOFFSET(ASEnemy, ceiling)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool leader", asOFFSET(ASEnemy, leader)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool scored", asOFFSET(ASEnemy, scored)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool script_spawned", asOFFSET(ASEnemy, script_spawned)); + asEngine->RegisterObjectProperty("__RealEnemy", "uint flags", asOFFSET(ASEnemy, flags)); + asEngine->RegisterObjectProperty("__RealEnemy", "uint flags2", asOFFSET(ASEnemy, flags2)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 family", asOFFSET(ASEnemy, family)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 dcset", asOFFSET(ASEnemy, dcset)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 anim", asOFFSET(ASEnemy, anim)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 dp", asOFFSET(ASEnemy, dp)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 wpn", asOFFSET(ASEnemy, wpn)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 rate", asOFFSET(ASEnemy, rate)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 hrate", asOFFSET(ASEnemy, hrate)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 homing", asOFFSET(ASEnemy, homing)); + asEngine->RegisterObjectProperty("__RealEnemy", "fix dstep", asOFFSET(ASEnemy, dstep)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc1", asOFFSET(ASEnemy, dmisc1)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc2", asOFFSET(ASEnemy, dmisc2)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc3", asOFFSET(ASEnemy, dmisc3)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc4", asOFFSET(ASEnemy, dmisc4)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc5", asOFFSET(ASEnemy, dmisc5)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc6", asOFFSET(ASEnemy, dmisc6)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc7", asOFFSET(ASEnemy, dmisc7)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc8", asOFFSET(ASEnemy, dmisc8)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc9", asOFFSET(ASEnemy, dmisc9)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dmisc10", asOFFSET(ASEnemy, dmisc10)); + asEngine->RegisterObjectProperty("__RealEnemy", "int16 bgsfx", asOFFSET(ASEnemy, bgsfx)); + asEngine->RegisterObjectProperty("__RealEnemy", "int dummy_int1", asOFFSET(ASEnemy, dummy_int1)); + asEngine->RegisterObjectProperty("__RealEnemy", "int clk2", asOFFSET(ASEnemy, clk2)); + asEngine->RegisterObjectProperty("__RealEnemy", "int sclk", asOFFSET(ASEnemy, sclk)); + asEngine->RegisterObjectProperty("__RealEnemy", "uint16 s_tile", asOFFSET(ASEnemy, s_tile)); + asEngine->RegisterObjectProperty("__RealEnemy", "int scriptFlags", asOFFSET(ASEnemy, scriptFlags)); + asEngine->RegisterObjectProperty("__RealEnemy", "bool haslink", asOFFSET(ASEnemy, haslink)); + + asEngine->RegisterObjectMethod("__RealEnemy", "void leave_item()", asMETHOD(ASEnemy, leave_item), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "bool canmove(int, fix, int, int, int, int, int)", asMETHODPR(ASEnemy, canmove, (int, fix, int, int, int, int, int), bool), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void fireWeapon()", asMETHOD(ASEnemy, fireWeapon), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "bool isFiring() const", asMETHOD(ASEnemy, isFiring), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void updateFiring()", asMETHOD(ASEnemy, updateFiring), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void setBreathTimer(int)", asMETHOD(ASEnemy, setBreathTimer), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void setAttackOwner(int)", asMETHOD(ASEnemy, setAttackOwner), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void activateDeathAttack()", asMETHOD(ASEnemy, activateDeathAttack), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void draw()", asMETHOD(ASEnemy, scriptDraw), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void drawblock()", asMETHOD(ASEnemy, scriptDrawBlock), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void drawshadow()", asMETHOD(ASEnemy, scriptDrawShadow), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void masked_draw(int, int, int, int)", asMETHOD(ASEnemy, scriptMaskedDraw), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void overtilecloaked16(int, int, int, int)", asMETHOD(ASEnemy, overTileCloaked16), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void overtile16(int, int, int, int, int)", asMETHOD(ASEnemy, overTile16), asCALL_THISCALL); + + asEngine->RegisterObjectMethod("__RealEnemy", "void stopBGSFX()", asMETHOD(ASEnemy, stopBGSFX), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void playDeathSFX()", asMETHOD(ASEnemy, playDeathSFX), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "void playHitSFX(int)", asMETHOD(ASEnemy, playHitSFX), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "int defenditemclass(int, int)", asMETHOD(ASEnemy, scriptDefendItemClass), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "int getDefendedItemPower()", asMETHOD(ASEnemy, getDefendedItemPower), asCALL_THISCALL); + asEngine->RegisterObjectMethod("__RealEnemy", "int takehit(__RealWeapon@)", asMETHOD(ASEnemy, defaultTakeHit), asCALL_THISCALL); +} + +void registerItem() +{ + asEngine->RegisterObjectProperty("__RealItem", "int pickup", asOFFSET(item, pickup)); + asEngine->RegisterObjectProperty("__RealItem", "int clk2", asOFFSET(item, clk2)); +} + +void registerWeapon() +{ + asEngine->RegisterObjectProperty("__RealWeapon", "int power", asOFFSET(weapon, power)); + asEngine->RegisterObjectProperty("__RealWeapon", "int type", asOFFSET(weapon, type)); + asEngine->RegisterObjectProperty("__RealWeapon", "int parentid", asOFFSET(weapon, parentid)); + asEngine->RegisterObjectProperty("__RealWeapon", "int parentitem", asOFFSET(weapon, parentitem)); + asEngine->RegisterObjectProperty("__RealWeapon", "uint16 aframe", asOFFSET(weapon, aframe)); + asEngine->RegisterObjectProperty("__RealWeapon", "int o_tile", asOFFSET(weapon, o_tile)); + asEngine->RegisterObjectProperty("__RealWeapon", "int o_cset", asOFFSET(weapon, o_cset)); + asEngine->RegisterObjectProperty("__RealWeapon", "bool aimedBrang", asOFFSET(weapon, aimedBrang)); + + asEngine->RegisterObjectMethod("__RealWeapon", "void adjustDraggedItem(int)", asMETHOD(weapon, adjustDraggedItem), asCALL_THISCALL); +} + +void initializeAngelScript() +{ + asEngine=asCreateScriptEngine(); + asEngine->SetMessageCallback(asFUNCTION(messageCallback), 0, asCALL_CDECL); + RegisterScriptArray(asEngine, true); + RegisterStdString(asEngine); + RegisterScriptMath(asEngine); + registerFix(); + registerTypes(); + registerGlobalFunctions(); + registerMapscr(); + registerFFC(); + registerSprite(); + registerLink(); + registerEnemy(); + registerItem(); + registerWeapon(); + + // These should be moved into a .dat file eventually; there's no reason + // to let users edit them. They might even be distributed as bytecode. + CScriptBuilder builder; + builder.StartNewModule(asEngine, "everything"); + + builder.AddSectionFromFile("angelscript/common.as"); + + builder.AddSectionFromFile("angelscript/sprite.as"); + builder.AddSectionFromFile("angelscript/link.as"); + builder.AddSectionFromFile("angelscript/enemy.as"); + builder.AddSectionFromFile("angelscript/weapon.as"); + + builder.AddSectionFromFile("angelscript/aquamentus.as"); + builder.AddSectionFromFile("angelscript/fairy.as"); + builder.AddSectionFromFile("angelscript/fallingRock.as"); + builder.AddSectionFromFile("angelscript/fire.as"); + builder.AddSectionFromFile("angelscript/digdogger.as"); + builder.AddSectionFromFile("angelscript/dodongo.as"); + builder.AddSectionFromFile("angelscript/ganon.as"); + builder.AddSectionFromFile("angelscript/ghini.as"); + builder.AddSectionFromFile("angelscript/gleeok.as"); + builder.AddSectionFromFile("angelscript/gohma.as"); + builder.AddSectionFromFile("angelscript/guy.as"); + builder.AddSectionFromFile("angelscript/item.as"); + builder.AddSectionFromFile("angelscript/keese.as"); + builder.AddSectionFromFile("angelscript/lanmola.as"); + builder.AddSectionFromFile("angelscript/leever.as"); + builder.AddSectionFromFile("angelscript/manhandla.as"); + builder.AddSectionFromFile("angelscript/moldorm.as"); + builder.AddSectionFromFile("angelscript/npc.as"); + builder.AddSectionFromFile("angelscript/other.as"); + builder.AddSectionFromFile("angelscript/patra.as"); + builder.AddSectionFromFile("angelscript/patraBS.as"); + builder.AddSectionFromFile("angelscript/peahat.as"); + builder.AddSectionFromFile("angelscript/projectileShooter.as"); + builder.AddSectionFromFile("angelscript/spinningTile.as"); + builder.AddSectionFromFile("angelscript/tektite.as"); + builder.AddSectionFromFile("angelscript/trapConstant.as"); + builder.AddSectionFromFile("angelscript/trapLOS.as"); + builder.AddSectionFromFile("angelscript/trigger.as"); + builder.AddSectionFromFile("angelscript/walkingEnemy.as"); + builder.AddSectionFromFile("angelscript/wallMaster.as"); + builder.AddSectionFromFile("angelscript/wizzrobe.as"); + builder.AddSectionFromFile("angelscript/zora.as"); + builder.BuildModule(); + + // Create global Link + currentSprite=&Link; + assignSpriteScript(&Link, "LinkClass"); + Link.scriptInit(); + /* + asIScriptContext* context=asEngine->CreateContext(); + asIScriptModule *module=asEngine->GetModuleByIndex(0); + asIScriptFunction* func=module->GetFunctionByDecl("void init()"); + context->Prepare(func); + context->Execute(); + context->Release(); + */ +} + +void shutDownAngelScript() +{ + asEngine->ShutDownAndRelease(); +} + +// This is kind of ugly, but it'll do... +static sprite* getRealSprite() +{ + return currentSprite; +} + +static enemy* getRealEnemy() +{ + return currentEnemy; +} + +static item* getRealItem() +{ + return currentItem; +} + +static LinkClass* getRealLink() +{ + return &Link; +} + +static weapon* getRealWeapon() +{ + return currentWeapon; +} + +static void assignSpriteScript(sprite* spr, const char* scriptName) +{ + currentSprite=spr; + + asIScriptModule *module=asEngine->GetModuleByIndex(0); + asIObjectType* objType=module->GetObjectTypeByName(scriptName); + asIScriptObject* scriptObj=(asIScriptObject*)asEngine->CreateScriptObject(objType); + spr->setScriptData(new EntityScriptData(scriptObj, asEngine->CreateContext())); +} + +void assignEnemyScript(enemy* en, const char* scriptName) +{ + currentEnemy=en; + assignSpriteScript(en, scriptName); +} + +void assignItemScript(item* it, const char* scriptName) +{ + currentItem=it; + assignSpriteScript(it, scriptName); +} + +void assignWeaponScript(weapon* w, const char* scriptName) +{ + currentWeapon=w; + assignSpriteScript(w, scriptName); +} diff --git a/src/angelscript/aszc.h b/src/angelscript/aszc.h new file mode 100644 index 0000000000..9087501381 --- /dev/null +++ b/src/angelscript/aszc.h @@ -0,0 +1,14 @@ +#ifndef _ANGELSCRIPT_ASZC_H_ +#define _ANGELSCRIPT_ASZC_H_ + +class enemy; +class item; +class weapon; + +void initializeAngelScript(); +void shutDownAngelScript(); +void assignEnemyScript(enemy* en, const char* scriptName); +void assignItemScript(item* it, const char* scriptName); +void assignWeaponScript(weapon* w, const char* scriptName); + +#endif diff --git a/src/angelscript/scriptData.cpp b/src/angelscript/scriptData.cpp new file mode 100644 index 0000000000..c7116dc6ee --- /dev/null +++ b/src/angelscript/scriptData.cpp @@ -0,0 +1,25 @@ +#include "scriptData.h" + +EntityScriptData::EntityScriptData(asIScriptObject* o, asIScriptContext* c): + object(o), + context(c) +{ +} + +EntityScriptData::~EntityScriptData() +{ + context->Release(); + object->Release(); +} + +asIScriptFunction* EntityScriptData::getFunction(const char* decl) +{ + return object->GetObjectType()->GetMethodByDecl(decl); +} + +void EntityScriptData::runFunction(asIScriptFunction* func) +{ + context->Prepare(func); + context->SetObject(object); + context->Execute(); +} diff --git a/src/angelscript/scriptData.h b/src/angelscript/scriptData.h new file mode 100644 index 0000000000..3d7b52f8f7 --- /dev/null +++ b/src/angelscript/scriptData.h @@ -0,0 +1,67 @@ +#ifndef _ZC_ANGELSCRIPT_SCRIPTDATA_H_ +#define _ZC_ANGELSCRIPT_SCRIPTDATA_H_ + +#include + +// The script data and context. +// This class was created in anticipation of greater complexity. +// It doesn't do much at the moment. +class EntityScriptData +{ +public: + EntityScriptData(asIScriptObject* object, asIScriptContext* context); + ~EntityScriptData(); + + asIScriptFunction* getFunction(const char* decl); + + void runFunction(asIScriptFunction* func); + + // I'm not entirely certain this is safe in case of type mismatches + // (e.g. a function takes a byte and is given a word), but it seems + // to work just fine. + template + void runFunction(asIScriptFunction* func, T t) + { + context->Prepare(func); + context->SetObject(object); + setArg(0, t); + context->Execute(); + } + + template + void runFunction(asIScriptFunction* func, T t, U u) + { + context->Prepare(func); + context->SetObject(object); + setArg(0, t); + setArg(1, u); + context->Execute(); + } + + template + inline T getLastResult() const + { + return *reinterpret_cast(context->GetAddressOfReturnValue()); + } + + inline asIScriptObject* getObject() + { + return object; + } + +private: + asIScriptObject* object; + asIScriptContext* context; + + inline void setArg(int arg, int val) + { + context->SetArgDWord(arg, val); + } + + inline void setArg(int arg, asIScriptObject* val) + { + context->SetArgObject(arg, val); + } +}; + +#endif diff --git a/src/angelscript/scriptarray/scriptarray.cpp b/src/angelscript/scriptarray/scriptarray.cpp new file mode 100644 index 0000000000..1668e13feb --- /dev/null +++ b/src/angelscript/scriptarray/scriptarray.cpp @@ -0,0 +1,1944 @@ +#include +#include +#include +#include +#include // sprintf +#include + +#include "scriptarray.h" + +using std::string; + +BEGIN_AS_NAMESPACE + +// This macro is used to avoid warnings about unused variables. +// Usually where the variables are only used in debug mode. +#define UNUSED_VAR(x) (void)(x) + +// Set the default memory routines +// Use the angelscript engine's memory routines by default +static asALLOCFUNC_t userAlloc = asAllocMem; +static asFREEFUNC_t userFree = asFreeMem; + +// Allows the application to set which memory routines should be used by the array object +void CScriptArray::SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc) +{ + userAlloc = allocFunc; + userFree = freeFunc; +} + +static void RegisterScriptArray_Native(asIScriptEngine *engine); +static void RegisterScriptArray_Generic(asIScriptEngine *engine); + +struct SArrayBuffer +{ + asDWORD maxElements; + asDWORD numElements; + asBYTE data[1]; +}; + +struct SArrayCache +{ + asIScriptFunction *cmpFunc; + asIScriptFunction *eqFunc; + int cmpFuncReturnCode; // To allow better error message in case of multiple matches + int eqFuncReturnCode; +}; + +// We just define a number here that we assume nobody else is using for +// object type user data. The add-ons have reserved the numbers 1000 +// through 1999 for this purpose, so we should be fine. +const asPWORD ARRAY_CACHE = 1000; + +static void CleanupObjectTypeArrayCache(asIObjectType *type) +{ + SArrayCache *cache = reinterpret_cast(type->GetUserData(ARRAY_CACHE)); + if( cache ) + { + cache->~SArrayCache(); + userFree(cache); + } +} + +CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length) +{ + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + + return 0; + } + + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(length, ot); + + return a; +} + +CScriptArray* CScriptArray::Create(asIObjectType *ot, void *initList) +{ + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + + return 0; + } + + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(ot, initList); + + return a; +} + +CScriptArray* CScriptArray::Create(asIObjectType *ot, asUINT length, void *defVal) +{ + // Allocate the memory + void *mem = userAlloc(sizeof(CScriptArray)); + if( mem == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + + return 0; + } + + // Initialize the object + CScriptArray *a = new(mem) CScriptArray(length, defVal, ot); + + return a; +} + +CScriptArray* CScriptArray::Create(asIObjectType *ot) +{ + return CScriptArray::Create(ot, asUINT(0)); +} + +// This optional callback is called when the template type is first used by the compiler. +// It allows the application to validate if the template can be instantiated for the requested +// subtype at compile time, instead of at runtime. The output argument dontGarbageCollect +// allow the callback to tell the engine if the template instance type shouldn't be garbage collected, +// i.e. no asOBJ_GC flag. +static bool ScriptArrayTemplateCallback(asIObjectType *ot, bool &dontGarbageCollect) +{ + // Make sure the subtype can be instantiated with a default factory/constructor, + // otherwise we won't be able to instantiate the elements. + int typeId = ot->GetSubTypeId(); + if( typeId == asTYPEID_VOID ) + return false; + if( (typeId & asTYPEID_MASK_OBJECT) && !(typeId & asTYPEID_OBJHANDLE) ) + { + asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId); + asDWORD flags = subtype->GetFlags(); + if( (flags & asOBJ_VALUE) && !(flags & asOBJ_POD) ) + { + // Verify that there is a default constructor + bool found = false; + for( asUINT n = 0; n < subtype->GetBehaviourCount(); n++ ) + { + asEBehaviours beh; + asIScriptFunction *func = subtype->GetBehaviourByIndex(n, &beh); + if( beh != asBEHAVE_CONSTRUCT ) continue; + + if( func->GetParamCount() == 0 ) + { + // Found the default constructor + found = true; + break; + } + } + + if( !found ) + { + // There is no default constructor + ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default constructor"); + return false; + } + } + else if( (flags & asOBJ_REF) ) + { + bool found = false; + + // If value assignment for ref type has been disabled then the array + // can be created if the type has a default factory function + if( !ot->GetEngine()->GetEngineProperty(asEP_DISALLOW_VALUE_ASSIGN_FOR_REF_TYPE) ) + { + // Verify that there is a default factory + for( asUINT n = 0; n < subtype->GetFactoryCount(); n++ ) + { + asIScriptFunction *func = subtype->GetFactoryByIndex(n); + if( func->GetParamCount() == 0 ) + { + // Found the default factory + found = true; + break; + } + } + } + + if( !found ) + { + // No default factory + ot->GetEngine()->WriteMessage("array", 0, 0, asMSGTYPE_ERROR, "The subtype has no default factory"); + return false; + } + } + + // If the object type is not garbage collected then the array also doesn't need to be + if( !(flags & asOBJ_GC) ) + dontGarbageCollect = true; + } + else if( !(typeId & asTYPEID_OBJHANDLE) ) + { + // Arrays with primitives cannot form circular references, + // thus there is no need to garbage collect them + dontGarbageCollect = true; + } + else + { + assert( typeId & asTYPEID_OBJHANDLE ); + + // It is not necessary to set the array as garbage collected for all handle types. + // If it is possible to determine that the handle cannot refer to an object type + // that can potentially form a circular reference with the array then it is not + // necessary to make the array garbage collected. + asIObjectType *subtype = ot->GetEngine()->GetObjectTypeById(typeId); + asDWORD flags = subtype->GetFlags(); + if( !(flags & asOBJ_GC) ) + { + if( (flags & asOBJ_SCRIPT_OBJECT) ) + { + // Even if a script class is by itself not garbage collected, it is possible + // that classes that derive from it may be, so it is not possible to know + // that no circular reference can occur. + if( (flags & asOBJ_NOINHERIT) ) + { + // A script class declared as final cannot be inherited from, thus + // we can be certain that the object cannot be garbage collected. + dontGarbageCollect = true; + } + } + else + { + // For application registered classes we assume the application knows + // what it is doing and don't mark the array as garbage collected unless + // the type is also garbage collected. + dontGarbageCollect = true; + } + } + } + + // The type is ok + return true; +} + +// Registers the template array type +void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") == 0 ) + RegisterScriptArray_Native(engine); + else + RegisterScriptArray_Generic(engine); + + if( defaultArray ) + { + int r = engine->RegisterDefaultArrayType("array"); assert( r >= 0 ); + UNUSED_VAR(r); + } +} + +static void RegisterScriptArray_Native(asIScriptEngine *engine) +{ + int r = 0; + UNUSED_VAR(r); + + // Register the object type user data clean up + engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE); + + // Register the array type as a template + r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); + + // Register a callback for validating the subtype before it is used + r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback), asCALL_CDECL); assert( r >= 0 ); + + // Templates receive the object type as the first parameter. To the script writer this is hidden + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint, const T &in)", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, asUINT, void *), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + + // Register the factory that will be used for initialization lists + r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in type, int&in list) {repeat T}", asFUNCTIONPR(CScriptArray::Create, (asIObjectType*, void*), CScriptArray*), asCALL_CDECL); assert( r >= 0 ); + + // The memory management methods + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptArray,AddRef), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptArray,Release), asCALL_THISCALL); assert( r >= 0 ); + + // The index operator returns the template subtype + r = engine->RegisterObjectMethod("array", "T &opIndex(uint)", asMETHODPR(CScriptArray, At, (asUINT), void*), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "const T &opIndex(uint) const", asMETHODPR(CScriptArray, At, (asUINT) const, const void*), asCALL_THISCALL); assert( r >= 0 ); + + // The assignment operator + r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asMETHOD(CScriptArray, operator=), asCALL_THISCALL); assert( r >= 0 ); + + // Other methods + r = engine->RegisterObjectMethod("array", "void insertAt(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeAt(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void insertLast(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeLast()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); + // TODO: Should length() and resize() be deprecated as the property accessors do the same thing? + r = engine->RegisterObjectMethod("array", "uint length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reserve(uint)", asMETHOD(CScriptArray, Reserve), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void resize(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc()", asMETHODPR(CScriptArray, SortAsc, (), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc(uint, uint)", asMETHODPR(CScriptArray, SortAsc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc()", asMETHODPR(CScriptArray, SortDesc, (), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc(uint, uint)", asMETHODPR(CScriptArray, SortDesc, (asUINT, asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reverse()", asMETHOD(CScriptArray, Reverse), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(const T&in) const", asMETHODPR(CScriptArray, Find, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(uint, const T&in) const", asMETHODPR(CScriptArray, Find, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(const T&in) const", asMETHODPR(CScriptArray, FindByRef, (void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(uint, const T&in) const", asMETHODPR(CScriptArray, FindByRef, (asUINT, void*) const, int), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asMETHOD(CScriptArray, operator==), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + + // Register virtual properties + r = engine->RegisterObjectMethod("array", "uint get_length() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void set_length(uint)", asMETHODPR(CScriptArray, Resize, (asUINT), void), asCALL_THISCALL); assert( r >= 0 ); + + // Register GC behaviours in case the array needs to be garbage collected + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(CScriptArray, GetRefCount), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asMETHOD(CScriptArray, SetFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(CScriptArray, GetFlag), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(CScriptArray, EnumReferences), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(CScriptArray, ReleaseAllHandles), asCALL_THISCALL); assert( r >= 0 ); + +#if AS_USE_STLNAMES == 1 + // Same as length + r = engine->RegisterObjectMethod("array", "uint size() const", asMETHOD(CScriptArray, GetSize), asCALL_THISCALL); assert( r >= 0 ); + // Same as isEmpty + r = engine->RegisterObjectMethod("array", "bool empty() const", asMETHOD(CScriptArray, IsEmpty), asCALL_THISCALL); assert( r >= 0 ); + // Same as insertLast + r = engine->RegisterObjectMethod("array", "void push_back(const T&in)", asMETHOD(CScriptArray, InsertLast), asCALL_THISCALL); assert( r >= 0 ); + // Same as removeLast + r = engine->RegisterObjectMethod("array", "void pop_back()", asMETHOD(CScriptArray, RemoveLast), asCALL_THISCALL); assert( r >= 0 ); + // Same as insertAt + r = engine->RegisterObjectMethod("array", "void insert(uint, const T&in)", asMETHOD(CScriptArray, InsertAt), asCALL_THISCALL); assert( r >= 0 ); + // Same as removeAt + r = engine->RegisterObjectMethod("array", "void erase(uint)", asMETHOD(CScriptArray, RemoveAt), asCALL_THISCALL); assert( r >= 0 ); +#endif +} + +CScriptArray &CScriptArray::operator=(const CScriptArray &other) +{ + // Only perform the copy if the array types are the same + if( &other != this && + other.GetArrayObjectType() == GetArrayObjectType() ) + { + // Make sure the arrays are of the same size + Resize(other.buffer->numElements); + + // Copy the value of each element + CopyBuffer(buffer, other.buffer); + } + + return *this; +} + +CScriptArray::CScriptArray(asIObjectType *ot, void *buf) +{ + // The object type should be the template instance of the array + assert( ot && std::string(ot->GetName()) == "array" ); + + refCount = 1; + gcFlag = false; + objType = ot; + objType->AddRef(); + buffer = 0; + + Precache(); + + asIScriptEngine *engine = ot->GetEngine(); + + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = engine->GetSizeOfPrimitiveType(subTypeId); + + // Determine the initial size from the buffer + asUINT length = *(asUINT*)buf; + + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } + + // Copy the values of the array elements from the buffer + if( (ot->GetSubTypeId() & asTYPEID_MASK_OBJECT) == 0 ) + { + CreateBuffer(&buffer, length); + + // Copy the values of the primitive type into the internal buffer + if( length > 0 ) + memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); + } + else if( ot->GetSubTypeId() & asTYPEID_OBJHANDLE ) + { + CreateBuffer(&buffer, length); + + // Copy the handles into the internal buffer + if( length > 0 ) + memcpy(At(0), (((asUINT*)buf)+1), length * elementSize); + + // With object handles it is safe to clear the memory in the received buffer + // instead of increasing the ref count. It will save time both by avoiding the + // call the increase ref, and also relieve the engine from having to release + // its references too + memset((((asUINT*)buf)+1), 0, length * elementSize); + } + else if( ot->GetSubType()->GetFlags() & asOBJ_REF ) + { + // Only allocate the buffer, but not the objects + subTypeId |= asTYPEID_OBJHANDLE; + CreateBuffer(&buffer, length); + subTypeId &= ~asTYPEID_OBJHANDLE; + + // Copy the handles into the internal buffer + if( length > 0 ) + memcpy(buffer->data, (((asUINT*)buf)+1), length * elementSize); + + // For ref types we can do the same as for handles, as they are + // implicitly stored as handles. + memset((((asUINT*)buf)+1), 0, length * elementSize); + } + else + { + // TODO: Optimize by calling the copy constructor of the object instead of + // constructing with the default constructor and then assigning the value + // TODO: With C++11 ideally we should be calling the move constructor, instead + // of the copy constructor as the engine will just discard the objects in the + // buffer afterwards. + CreateBuffer(&buffer, length); + + // For value types we need to call the opAssign for each individual object + for( asUINT n = 0; n < length; n++ ) + { + void *obj = At(n); + asBYTE *srcObj = (asBYTE*)buf; + srcObj += 4 + n*ot->GetSubType()->GetSize(); + engine->AssignScriptObject(obj, srcObj, ot->GetSubType()); + } + } + + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); +} + +CScriptArray::CScriptArray(asUINT length, asIObjectType *ot) +{ + // The object type should be the template instance of the array + assert( ot && std::string(ot->GetName()) == "array" ); + + refCount = 1; + gcFlag = false; + objType = ot; + objType->AddRef(); + buffer = 0; + + Precache(); + + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); + + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } + + CreateBuffer(&buffer, length); + + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); +} + +CScriptArray::CScriptArray(const CScriptArray &other) +{ + refCount = 1; + gcFlag = false; + objType = other.objType; + objType->AddRef(); + buffer = 0; + + Precache(); + + elementSize = other.elementSize; + + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + + CreateBuffer(&buffer, 0); + + // Copy the content + *this = other; +} + +CScriptArray::CScriptArray(asUINT length, void *defVal, asIObjectType *ot) +{ + // The object type should be the template instance of the array + assert( ot && std::string(ot->GetName()) == "array" ); + + refCount = 1; + gcFlag = false; + objType = ot; + objType->AddRef(); + buffer = 0; + + Precache(); + + // Determine element size + if( subTypeId & asTYPEID_MASK_OBJECT ) + elementSize = sizeof(asPWORD); + else + elementSize = objType->GetEngine()->GetSizeOfPrimitiveType(subTypeId); + + // Make sure the array size isn't too large for us to handle + if( !CheckMaxSize(length) ) + { + // Don't continue with the initialization + return; + } + + CreateBuffer(&buffer, length); + + // Notify the GC of the successful creation + if( objType->GetFlags() & asOBJ_GC ) + objType->GetEngine()->NotifyGarbageCollectorOfNewObject(this, objType); + + // Initialize the elements with the default value + for( asUINT n = 0; n < GetSize(); n++ ) + SetValue(n, defVal); +} + +void CScriptArray::SetValue(asUINT index, void *value) +{ + // At() will take care of the out-of-bounds checking, though + // if called from the application then nothing will be done + void *ptr = At(index); + if( ptr == 0 ) return; + + if( (subTypeId & ~asTYPEID_MASK_SEQNBR) && !(subTypeId & asTYPEID_OBJHANDLE) ) + objType->GetEngine()->AssignScriptObject(ptr, value, objType->GetSubType()); + else if( subTypeId & asTYPEID_OBJHANDLE ) + { + void *tmp = *(void**)ptr; + *(void**)ptr = *(void**)value; + objType->GetEngine()->AddRefScriptObject(*(void**)value, objType->GetSubType()); + if( tmp ) + objType->GetEngine()->ReleaseScriptObject(tmp, objType->GetSubType()); + } + else if( subTypeId == asTYPEID_BOOL || + subTypeId == asTYPEID_INT8 || + subTypeId == asTYPEID_UINT8 ) + *(char*)ptr = *(char*)value; + else if( subTypeId == asTYPEID_INT16 || + subTypeId == asTYPEID_UINT16 ) + *(short*)ptr = *(short*)value; + else if( subTypeId == asTYPEID_INT32 || + subTypeId == asTYPEID_UINT32 || + subTypeId == asTYPEID_FLOAT || + subTypeId > asTYPEID_DOUBLE ) // enums have a type id larger than doubles + *(int*)ptr = *(int*)value; + else if( subTypeId == asTYPEID_INT64 || + subTypeId == asTYPEID_UINT64 || + subTypeId == asTYPEID_DOUBLE ) + *(double*)ptr = *(double*)value; +} + +CScriptArray::~CScriptArray() +{ + if( buffer ) + { + DeleteBuffer(buffer); + buffer = 0; + } + if( objType ) objType->Release(); +} + +asUINT CScriptArray::GetSize() const +{ + return buffer->numElements; +} + +bool CScriptArray::IsEmpty() const +{ + return buffer->numElements == 0; +} + +void CScriptArray::Reserve(asUINT maxElements) +{ + if( maxElements <= buffer->maxElements ) + return; + + if( !CheckMaxSize(maxElements) ) + return; + + // Allocate memory for the buffer + SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*maxElements)); + if( newBuffer ) + { + newBuffer->numElements = buffer->numElements; + newBuffer->maxElements = maxElements; + } + else + { + // Out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + return; + } + + // TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves + // This should really be using the objects copy/move constructor to copy each object + // to the new location. It would most likely be a hit on the performance though. + memcpy(newBuffer->data, buffer->data, buffer->numElements*elementSize); + + // Release the old buffer + userFree(buffer); + + buffer = newBuffer; +} + +void CScriptArray::Resize(asUINT numElements) +{ + if( !CheckMaxSize(numElements) ) + return; + + Resize((int)numElements - (int)buffer->numElements, (asUINT)-1); +} + +// Internal +void CScriptArray::Resize(int delta, asUINT at) +{ + if( delta < 0 ) + { + if( -delta > (int)buffer->numElements ) + delta = -(int)buffer->numElements; + if( at > buffer->numElements + delta ) + at = buffer->numElements + delta; + } + else if( delta > 0 ) + { + // Make sure the array size isn't too large for us to handle + if( delta > 0 && !CheckMaxSize(buffer->numElements + delta) ) + return; + + if( at > buffer->numElements ) + at = buffer->numElements; + } + + if( delta == 0 ) return; + + if( buffer->maxElements < buffer->numElements + delta ) + { + // Allocate memory for the buffer + SArrayBuffer *newBuffer = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1 + elementSize*(buffer->numElements + delta))); + if( newBuffer ) + { + newBuffer->numElements = buffer->numElements + delta; + newBuffer->maxElements = newBuffer->numElements; + } + else + { + // Out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + return; + } + + // TODO: memcpy assumes the objects in the array doesn't hold pointers to themselves + // This should really be using the objects copy/move constructor to copy each object + // to the new location. It would most likely be a hit on the performance though. + memcpy(newBuffer->data, buffer->data, at*elementSize); + if( at < buffer->numElements ) + memcpy(newBuffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements-at)*elementSize); + + // Initialize the new elements with default values + Construct(newBuffer, at, at+delta); + + // Release the old buffer + userFree(buffer); + + buffer = newBuffer; + } + else if( delta < 0 ) + { + Destruct(buffer, at, at-delta); + // TODO: memmove assumes the objects in the array doesn't hold pointers to themselves + // This should really be using the objects copy/move constructor to copy each object + // to the new location. It would most likely be a hit on the performance though. + memmove(buffer->data + at*elementSize, buffer->data + (at-delta)*elementSize, (buffer->numElements - (at-delta))*elementSize); + buffer->numElements += delta; + } + else + { + // TODO: memmove assumes the objects in the array doesn't hold pointers to themselves + // This should really be using the objects copy/move constructor to copy each object + // to the new location. It would most likely be a hit on the performance though. + memmove(buffer->data + (at+delta)*elementSize, buffer->data + at*elementSize, (buffer->numElements - at)*elementSize); + Construct(buffer, at, at+delta); + buffer->numElements += delta; + } +} + +// internal +bool CScriptArray::CheckMaxSize(asUINT numElements) +{ + // This code makes sure the size of the buffer that is allocated + // for the array doesn't overflow and becomes smaller than requested + + asUINT maxSize = 0xFFFFFFFFul - sizeof(SArrayBuffer) + 1; + if( elementSize > 0 ) + maxSize /= elementSize; + + if( numElements > maxSize ) + { + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Too large array size"); + + return false; + } + + // OK + return true; +} + +asIObjectType *CScriptArray::GetArrayObjectType() const +{ + return objType; +} + +int CScriptArray::GetArrayTypeId() const +{ + return objType->GetTypeId(); +} + +int CScriptArray::GetElementTypeId() const +{ + return subTypeId; +} + +void CScriptArray::InsertAt(asUINT index, void *value) +{ + if( index > buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return; + } + + // Make room for the new element + Resize(1, index); + + // Set the value of the new element + SetValue(index, value); +} + +void CScriptArray::InsertLast(void *value) +{ + InsertAt(buffer->numElements, value); +} + +void CScriptArray::RemoveAt(asUINT index) +{ + if( index >= buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return; + } + + // Remove the element + Resize(-1, index); +} + +void CScriptArray::RemoveLast() +{ + RemoveAt(buffer->numElements-1); +} + +// Return a pointer to the array element. Returns 0 if the index is out of bounds +const void *CScriptArray::At(asUINT index) const +{ + if( buffer == 0 || index >= buffer->numElements ) + { + // If this is called from a script we raise a script exception + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Index out of bounds"); + return 0; + } + + if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + return *(void**)(buffer->data + elementSize*index); + else + return buffer->data + elementSize*index; +} +void *CScriptArray::At(asUINT index) +{ + return const_cast(const_cast(this)->At(index)); +} + +void *CScriptArray::GetBuffer() +{ + return buffer->data; +} + + +// internal +void CScriptArray::CreateBuffer(SArrayBuffer **buf, asUINT numElements) +{ + *buf = reinterpret_cast(userAlloc(sizeof(SArrayBuffer)-1+elementSize*numElements)); + + if( *buf ) + { + (*buf)->numElements = numElements; + (*buf)->maxElements = numElements; + Construct(*buf, 0, numElements); + } + else + { + // Oops, out of memory + asIScriptContext *ctx = asGetActiveContext(); + if( ctx ) + ctx->SetException("Out of memory"); + } +} + +// internal +void CScriptArray::DeleteBuffer(SArrayBuffer *buf) +{ + Destruct(buf, 0, buf->numElements); + + // Free the buffer + userFree(buf); +} + +// internal +void CScriptArray::Construct(SArrayBuffer *buf, asUINT start, asUINT end) +{ + if( (subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + { + // Create an object using the default constructor/factory for each element + void **max = (void**)(buf->data + end * sizeof(void*)); + void **d = (void**)(buf->data + start * sizeof(void*)); + + asIScriptEngine *engine = objType->GetEngine(); + asIObjectType *subType = objType->GetSubType(); + + for( ; d < max; d++ ) + { + *d = (void*)engine->CreateScriptObject(subType); + if( *d == 0 ) + { + // Set the remaining entries to null so the destructor + // won't attempt to destroy invalid objects later + memset(d, 0, sizeof(void*)*(max-d)); + + // There is no need to set an exception on the context, + // as CreateScriptObject has already done that + return; + } + } + } + else + { + // Set all elements to zero whether they are handles or primitives + void *d = (void*)(buf->data + start * elementSize); + memset(d, 0, (end-start)*elementSize); + } +} + +// internal +void CScriptArray::Destruct(SArrayBuffer *buf, asUINT start, asUINT end) +{ + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + asIScriptEngine *engine = objType->GetEngine(); + + void **max = (void**)(buf->data + end * sizeof(void*)); + void **d = (void**)(buf->data + start * sizeof(void*)); + + for( ; d < max; d++ ) + { + if( *d ) + engine->ReleaseScriptObject(*d, objType->GetSubType()); + } + } +} + + +// internal +bool CScriptArray::Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache) +{ + if( !asc ) + { + // Swap items + const void *TEMP = a; + a = b; + b = TEMP; + } + + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + { + // Simple compare of values + switch( subTypeId ) + { + #define COMPARE(T) *((T*)a) < *((T*)b) + case asTYPEID_BOOL: return COMPARE(bool); + case asTYPEID_INT8: return COMPARE(signed char); + case asTYPEID_UINT8: return COMPARE(unsigned char); + case asTYPEID_INT16: return COMPARE(signed short); + case asTYPEID_UINT16: return COMPARE(unsigned short); + case asTYPEID_INT32: return COMPARE(signed int); + case asTYPEID_UINT32: return COMPARE(unsigned int); + case asTYPEID_FLOAT: return COMPARE(float); + case asTYPEID_DOUBLE: return COMPARE(double); + default: return COMPARE(signed int); // All enums fall in this case + #undef COMPARE + } + } + else + { + int r = 0; + + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Allow sort to work even if the array contains null handles + if( *(void**)a == 0 ) return true; + if( *(void**)b == 0 ) return false; + } + + // Execute object opCmp + if( cache && cache->cmpFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); + + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } + + r = ctx->Execute(); + + if( r == asEXECUTION_FINISHED ) + { + return (int)ctx->GetReturnDWord() < 0; + } + } + } + + return false; +} + +void CScriptArray::Reverse() +{ + asUINT size = GetSize(); + + if( size >= 2 ) + { + asBYTE TEMP[16]; + + for( asUINT i = 0; i < size / 2; i++ ) + { + Copy(TEMP, GetArrayItemPointer(i)); + Copy(GetArrayItemPointer(i), GetArrayItemPointer(size - i - 1)); + Copy(GetArrayItemPointer(size - i - 1), TEMP); + } + } +} + +bool CScriptArray::operator==(const CScriptArray &other) const +{ + if( objType != other.objType ) + return false; + + if( GetSize() != other.GetSize() ) + return false; + + asIScriptContext *cmpContext = 0; + bool isNested = false; + + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + // TODO: Ideally this context would be retrieved from a pool, so we don't have to + // create a new one everytime. We could keep a context with the array object + // but that would consume a lot of resources as each context is quite heavy. + cmpContext = objType->GetEngine()->CreateContext(); + } + } + + // Check if all elements are equal + bool isEqual = true; + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + for( asUINT n = 0; n < GetSize(); n++ ) + if( !Equals(At(n), other.At(n), cmpContext, cache) ) + { + isEqual = false; + break; + } + + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + cmpContext->Release(); + } + + return isEqual; +} + +// internal +bool CScriptArray::Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const +{ + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + { + // Simple compare of values + switch( subTypeId ) + { + #define COMPARE(T) *((T*)a) == *((T*)b) + case asTYPEID_BOOL: return COMPARE(bool); + case asTYPEID_INT8: return COMPARE(signed char); + case asTYPEID_UINT8: return COMPARE(unsigned char); + case asTYPEID_INT16: return COMPARE(signed short); + case asTYPEID_UINT16: return COMPARE(unsigned short); + case asTYPEID_INT32: return COMPARE(signed int); + case asTYPEID_UINT32: return COMPARE(unsigned int); + case asTYPEID_FLOAT: return COMPARE(float); + case asTYPEID_DOUBLE: return COMPARE(double); + default: return COMPARE(signed int); // All enums fall here + #undef COMPARE + } + } + else + { + int r = 0; + + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Allow the find to work even if the array contains null handles + if( *(void**)a == *(void**)b ) return true; + } + + // Execute object opEquals if available + if( cache && cache->eqFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->eqFunc); assert(r >= 0); + + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } + + r = ctx->Execute(); + + if( r == asEXECUTION_FINISHED ) + return ctx->GetReturnByte() != 0; + + return false; + } + + // Execute object opCmp if available + if( cache && cache->cmpFunc ) + { + // TODO: Add proper error handling + r = ctx->Prepare(cache->cmpFunc); assert(r >= 0); + + if( subTypeId & asTYPEID_OBJHANDLE ) + { + r = ctx->SetObject(*((void**)a)); assert(r >= 0); + r = ctx->SetArgObject(0, *((void**)b)); assert(r >= 0); + } + else + { + r = ctx->SetObject((void*)a); assert(r >= 0); + r = ctx->SetArgObject(0, (void*)b); assert(r >= 0); + } + + r = ctx->Execute(); + + if( r == asEXECUTION_FINISHED ) + return (int)ctx->GetReturnDWord() == 0; + + return false; + } + } + + return false; +} + +int CScriptArray::FindByRef(void *ref) const +{ + return FindByRef(0, ref); +} + +int CScriptArray::FindByRef(asUINT startAt, void *ref) const +{ + // Find the matching element by its reference + asUINT size = GetSize(); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Dereference the pointer + ref = *(void**)ref; + for( asUINT i = startAt; i < size; i++ ) + { + if( *(void**)At(i) == ref ) + return i; + } + } + else + { + // Compare the reference directly + for( asUINT i = startAt; i < size; i++ ) + { + if( At(i) == ref ) + return i; + } + } + + return -1; +} + +int CScriptArray::Find(void *value) const +{ + return Find(0, value); +} + +int CScriptArray::Find(asUINT startAt, void *value) const +{ + // Check if the subtype really supports find() + // TODO: Can't this be done at compile time too by the template callback + SArrayCache *cache = 0; + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( !cache || (cache->cmpFunc == 0 && cache->eqFunc == 0) ) + { + asIScriptContext *ctx = asGetActiveContext(); + asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId); + + // Throw an exception + if( ctx ) + { + char tmp[512]; + + if( cache && cache->eqFuncReturnCode == asMULTIPLE_FUNCTIONS ) +#if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) + sprintf_s(tmp, 512, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); +#else + sprintf(tmp, "Type '%s' has multiple matching opEquals or opCmp methods", subType->GetName()); +#endif + else +#if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) + sprintf_s(tmp, 512, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); +#else + sprintf(tmp, "Type '%s' does not have a matching opEquals or opCmp method", subType->GetName()); +#endif + ctx->SetException(tmp); + } + + return -1; + } + } + + asIScriptContext *cmpContext = 0; + bool isNested = false; + + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + // TODO: Ideally this context would be retrieved from a pool, so we don't have to + // create a new one everytime. We could keep a context with the array object + // but that would consume a lot of resources as each context is quite heavy. + cmpContext = objType->GetEngine()->CreateContext(); + } + } + + // Find the matching element + int ret = -1; + asUINT size = GetSize(); + + for( asUINT i = startAt; i < size; i++ ) + { + // value passed by reference + if( Equals(At(i), value, cmpContext, cache) ) + { + ret = (int)i; + break; + } + } + + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + cmpContext->Release(); + } + + return ret; +} + + + +// internal +// Copy object handle or primitive value +void CScriptArray::Copy(void *dst, void *src) +{ + memcpy(dst, src, elementSize); +} + + +// internal +// Return pointer to array item (object handle or primitive value) +void *CScriptArray::GetArrayItemPointer(int index) +{ + return buffer->data + index * elementSize; +} + +// internal +// Return pointer to data in buffer (object or primitive) +void *CScriptArray::GetDataPointer(void *buffer) +{ + if ((subTypeId & asTYPEID_MASK_OBJECT) && !(subTypeId & asTYPEID_OBJHANDLE) ) + { + // Real address of object + return reinterpret_cast(*(size_t*)buffer); + } + else + { + // Primitive is just a raw data + return buffer; + } +} + + +// Sort ascending +void CScriptArray::SortAsc() +{ + Sort(0, GetSize(), true); +} + +// Sort ascending +void CScriptArray::SortAsc(asUINT startAt, asUINT count) +{ + Sort(startAt, count, true); +} + +// Sort descending +void CScriptArray::SortDesc() +{ + Sort(0, GetSize(), false); +} + +// Sort descending +void CScriptArray::SortDesc(asUINT startAt, asUINT count) +{ + Sort(startAt, count, false); +} + + +// internal +void CScriptArray::Sort(asUINT startAt, asUINT count, bool asc) +{ + // Subtype isn't primitive and doesn't have opCmp + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + if( !cache || cache->cmpFunc == 0 ) + { + asIScriptContext *ctx = asGetActiveContext(); + asIObjectType* subType = objType->GetEngine()->GetObjectTypeById(subTypeId); + + // Throw an exception + if( ctx ) + { + char tmp[512]; + + if( cache && cache->cmpFuncReturnCode == asMULTIPLE_FUNCTIONS ) +#if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) + sprintf_s(tmp, 512, "Type '%s' has multiple matching opCmp methods", subType->GetName()); +#else + sprintf(tmp, "Type '%s' has multiple matching opCmp methods", subType->GetName()); +#endif + else +#if defined(_MSC_VER) && _MSC_VER >= 1500 && !defined(__S3E__) + sprintf_s(tmp, 512, "Type '%s' does not have a matching opCmp method", subType->GetName()); +#else + sprintf(tmp, "Type '%s' does not have a matching opCmp method", subType->GetName()); +#endif + + ctx->SetException(tmp); + } + + return; + } + } + + // No need to sort + if( count < 2 ) + { + return; + } + + int start = startAt; + int end = startAt + count; + + // Check if we could access invalid item while sorting + if( start >= (int)buffer->numElements || end > (int)buffer->numElements ) + { + asIScriptContext *ctx = asGetActiveContext(); + + // Throw an exception + if( ctx ) + { + ctx->SetException("Index out of bounds"); + } + + return; + } + + asBYTE tmp[16]; + asIScriptContext *cmpContext = 0; + bool isNested = false; + + if( subTypeId & ~asTYPEID_MASK_SEQNBR ) + { + // Try to reuse the active context + cmpContext = asGetActiveContext(); + if( cmpContext ) + { + if( cmpContext->GetEngine() == objType->GetEngine() && cmpContext->PushState() >= 0 ) + isNested = true; + else + cmpContext = 0; + } + if( cmpContext == 0 ) + { + // TODO: Ideally this context would be retrieved from a pool, so we don't have to + // create a new one everytime. We could keep a context with the array object + // but that would consume a lot of resources as each context is quite heavy. + cmpContext = objType->GetEngine()->CreateContext(); + } + } + + // Insertion sort + for( int i = start + 1; i < end; i++ ) + { + Copy(tmp, GetArrayItemPointer(i)); + + int j = i - 1; + + while( j >= start && Less(GetDataPointer(tmp), At(j), asc, cmpContext, cache) ) + { + Copy(GetArrayItemPointer(j + 1), GetArrayItemPointer(j)); + j--; + } + + Copy(GetArrayItemPointer(j + 1), tmp); + } + + if( cmpContext ) + { + if( isNested ) + { + asEContextState state = cmpContext->GetState(); + cmpContext->PopState(); + if( state == asEXECUTION_ABORTED ) + cmpContext->Abort(); + } + else + cmpContext->Release(); + } +} + +// internal +void CScriptArray::CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src) +{ + asIScriptEngine *engine = objType->GetEngine(); + if( subTypeId & asTYPEID_OBJHANDLE ) + { + // Copy the references and increase the reference counters + if( dst->numElements > 0 && src->numElements > 0 ) + { + int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; + + void **max = (void**)(dst->data + count * sizeof(void*)); + void **d = (void**)dst->data; + void **s = (void**)src->data; + + for( ; d < max; d++, s++ ) + { + void *tmp = *d; + *d = *s; + if( *d ) + engine->AddRefScriptObject(*d, objType->GetSubType()); + // Release the old ref after incrementing the new to avoid problem incase it is the same ref + if( tmp ) + engine->ReleaseScriptObject(tmp, objType->GetSubType()); + } + } + } + else + { + if( dst->numElements > 0 && src->numElements > 0 ) + { + int count = dst->numElements > src->numElements ? src->numElements : dst->numElements; + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + // Call the assignment operator on all of the objects + void **max = (void**)(dst->data + count * sizeof(void*)); + void **d = (void**)dst->data; + void **s = (void**)src->data; + + asIObjectType *subType = objType->GetSubType(); + for( ; d < max; d++, s++ ) + engine->AssignScriptObject(*d, *s, subType); + } + else + { + // Primitives are copied byte for byte + memcpy(dst->data, src->data, count*elementSize); + } + } + } +} + +// internal +// Precache some info +void CScriptArray::Precache() +{ + subTypeId = objType->GetSubTypeId(); + + // Check if it is an array of objects. Only for these do we need to cache anything + // Type ids for primitives and enums only has the sequence number part + if( !(subTypeId & ~asTYPEID_MASK_SEQNBR) ) + return; + + // The opCmp and opEquals methods are cached because the searching for the + // methods is quite time consuming if a lot of array objects are created. + + // First check if a cache already exists for this array type + SArrayCache *cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( cache ) return; + + // We need to make sure the cache is created only once, even + // if multiple threads reach the same point at the same time + asAcquireExclusiveLock(); + + // Now that we got the lock, we need to check again to make sure the + // cache wasn't created while we were waiting for the lock + cache = reinterpret_cast(objType->GetUserData(ARRAY_CACHE)); + if( cache ) + { + asReleaseExclusiveLock(); + return; + } + + // Create the cache + cache = reinterpret_cast(userAlloc(sizeof(SArrayCache))); + memset(cache, 0, sizeof(SArrayCache)); + + // If the sub type is a handle to const, then the methods must be const too + bool mustBeConst = (subTypeId & asTYPEID_HANDLETOCONST) ? true : false; + + asIObjectType *subType = objType->GetEngine()->GetObjectTypeById(subTypeId); + if( subType ) + { + for( asUINT i = 0; i < subType->GetMethodCount(); i++ ) + { + asIScriptFunction *func = subType->GetMethodByIndex(i); + + if( func->GetParamCount() == 1 && (!mustBeConst || func->IsReadOnly()) ) + { + asDWORD flags = 0; + int returnTypeId = func->GetReturnTypeId(&flags); + + // The method must not return a reference + if( flags != asTM_NONE ) + continue; + + // opCmp returns an int and opEquals returns a bool + bool isCmp = false, isEq = false; + if( returnTypeId == asTYPEID_INT32 && strcmp(func->GetName(), "opCmp") == 0 ) + isCmp = true; + if( returnTypeId == asTYPEID_BOOL && strcmp(func->GetName(), "opEquals") == 0 ) + isEq = true; + + if( !isCmp && !isEq ) + continue; + + // The parameter must either be a reference to the subtype or a handle to the subtype + int paramTypeId; + func->GetParam(0, ¶mTypeId, &flags); + + if( (paramTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) != (subTypeId & ~(asTYPEID_OBJHANDLE|asTYPEID_HANDLETOCONST)) ) + continue; + + if( (flags & asTM_INREF) ) + { + if( (paramTypeId & asTYPEID_OBJHANDLE) || (mustBeConst && !(flags & asTM_CONST)) ) + continue; + } + else if( paramTypeId & asTYPEID_OBJHANDLE ) + { + if( mustBeConst && !(paramTypeId & asTYPEID_HANDLETOCONST) ) + continue; + } + else + continue; + + if( isCmp ) + { + if( cache->cmpFunc || cache->cmpFuncReturnCode ) + { + cache->cmpFunc = 0; + cache->cmpFuncReturnCode = asMULTIPLE_FUNCTIONS; + } + else + cache->cmpFunc = func; + } + else if( isEq ) + { + if( cache->eqFunc || cache->eqFuncReturnCode ) + { + cache->eqFunc = 0; + cache->eqFuncReturnCode = asMULTIPLE_FUNCTIONS; + } + else + cache->eqFunc = func; + } + } + } + } + + if( cache->eqFunc == 0 && cache->eqFuncReturnCode == 0 ) + cache->eqFuncReturnCode = asNO_FUNCTION; + if( cache->cmpFunc == 0 && cache->cmpFuncReturnCode == 0 ) + cache->cmpFuncReturnCode = asNO_FUNCTION; + + // Set the user data only at the end so others that retrieve it will know it is complete + objType->SetUserData(cache, ARRAY_CACHE); + + asReleaseExclusiveLock(); +} + +// GC behaviour +void CScriptArray::EnumReferences(asIScriptEngine *engine) +{ + // TODO: If garbage collection can be done from a separate thread, then this method must be + // protected so that it doesn't get lost during the iteration if the array is modified + + // If the array is holding handles, then we need to notify the GC of them + if( subTypeId & asTYPEID_MASK_OBJECT ) + { + void **d = (void**)buffer->data; + for( asUINT n = 0; n < buffer->numElements; n++ ) + { + if( d[n] ) + engine->GCEnumCallback(d[n]); + } + } +} + +// GC behaviour +void CScriptArray::ReleaseAllHandles(asIScriptEngine *) +{ + // Resizing to zero will release everything + Resize(0); +} + +void CScriptArray::AddRef() const +{ + // Clear the GC flag then increase the counter + gcFlag = false; + asAtomicInc(refCount); +} + +void CScriptArray::Release() const +{ + // Clearing the GC flag then descrease the counter + gcFlag = false; + if( asAtomicDec(refCount) == 0 ) + { + // When reaching 0 no more references to this instance + // exists and the object should be destroyed + this->~CScriptArray(); + userFree(const_cast(this)); + } +} + +// GC behaviour +int CScriptArray::GetRefCount() +{ + return refCount; +} + +// GC behaviour +void CScriptArray::SetFlag() +{ + gcFlag = true; +} + +// GC behaviour +bool CScriptArray::GetFlag() +{ + return gcFlag; +} + +//-------------------------------------------- +// Generic calling conventions + +static void ScriptArrayFactory_Generic(asIScriptGeneric *gen) +{ + asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot); +} + +static void ScriptArrayFactory2_Generic(asIScriptGeneric *gen) +{ + asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + asUINT length = gen->GetArgDWord(1); + + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length); +} + +static void ScriptArrayListFactory_Generic(asIScriptGeneric *gen) +{ + asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + void *buf = gen->GetArgAddress(1); + + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, buf); +} + +static void ScriptArrayFactoryDefVal_Generic(asIScriptGeneric *gen) +{ + asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + asUINT length = gen->GetArgDWord(1); + void *defVal = gen->GetArgAddress(2); + + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = CScriptArray::Create(ot, length, defVal); +} + +static void ScriptArrayTemplateCallback_Generic(asIScriptGeneric *gen) +{ + asIObjectType *ot = *(asIObjectType**)gen->GetAddressOfArg(0); + bool *dontGarbageCollect = *(bool**)gen->GetAddressOfArg(1); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = ScriptArrayTemplateCallback(ot, *dontGarbageCollect); +} + +static void ScriptArrayAssignment_Generic(asIScriptGeneric *gen) +{ + CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *self = *other; + gen->SetReturnObject(self); +} + +static void ScriptArrayEquals_Generic(asIScriptGeneric *gen) +{ + CScriptArray *other = (CScriptArray*)gen->GetArgObject(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnByte(self->operator==(*other)); +} + +static void ScriptArrayFind_Generic(asIScriptGeneric *gen) +{ + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->Find(value)); +} + +static void ScriptArrayFind2_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->Find(index, value)); +} + +static void ScriptArrayFindByRef_Generic(asIScriptGeneric *gen) +{ + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->FindByRef(value)); +} + +static void ScriptArrayFindByRef2_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + gen->SetReturnDWord(self->FindByRef(index, value)); +} + +static void ScriptArrayAt_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + + gen->SetReturnAddress(self->At(index)); +} + +static void ScriptArrayInsertAt_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + void *value = gen->GetArgAddress(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->InsertAt(index, value); +} + +static void ScriptArrayRemoveAt_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->RemoveAt(index); +} + +static void ScriptArrayInsertLast_Generic(asIScriptGeneric *gen) +{ + void *value = gen->GetArgAddress(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->InsertLast(value); +} + +static void ScriptArrayRemoveLast_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->RemoveLast(); +} + +static void ScriptArrayLength_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + + gen->SetReturnDWord(self->GetSize()); +} + +static void ScriptArrayResize_Generic(asIScriptGeneric *gen) +{ + asUINT size = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + + self->Resize(size); +} + +static void ScriptArrayReserve_Generic(asIScriptGeneric *gen) +{ + asUINT size = gen->GetArgDWord(0); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Reserve(size); +} + +static void ScriptArraySortAsc_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortAsc(); +} + +static void ScriptArrayReverse_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Reverse(); +} + +static void ScriptArrayIsEmpty_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->IsEmpty(); +} + +static void ScriptArraySortAsc2_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + asUINT count = gen->GetArgDWord(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortAsc(index, count); +} + +static void ScriptArraySortDesc_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortDesc(); +} + +static void ScriptArraySortDesc2_Generic(asIScriptGeneric *gen) +{ + asUINT index = gen->GetArgDWord(0); + asUINT count = gen->GetArgDWord(1); + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SortDesc(index, count); +} + +static void ScriptArrayAddRef_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->AddRef(); +} + +static void ScriptArrayRelease_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->Release(); +} + +static void ScriptArrayGetRefCount_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetRefCount(); +} + +static void ScriptArraySetFlag_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + self->SetFlag(); +} + +static void ScriptArrayGetFlag_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = self->GetFlag(); +} + +static void ScriptArrayEnumReferences_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->EnumReferences(engine); +} + +static void ScriptArrayReleaseAllHandles_Generic(asIScriptGeneric *gen) +{ + CScriptArray *self = (CScriptArray*)gen->GetObject(); + asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0); + self->ReleaseAllHandles(engine); +} + +static void RegisterScriptArray_Generic(asIScriptEngine *engine) +{ + int r = 0; + UNUSED_VAR(r); + + engine->SetObjectTypeUserDataCleanupCallback(CleanupObjectTypeArrayCache, ARRAY_CACHE); + + r = engine->RegisterObjectType("array", 0, asOBJ_REF | asOBJ_GC | asOBJ_TEMPLATE); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_TEMPLATE_CALLBACK, "bool f(int&in, bool&out)", asFUNCTION(ScriptArrayTemplateCallback_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in)", asFUNCTION(ScriptArrayFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint)", asFUNCTION(ScriptArrayFactory2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_FACTORY, "array@ f(int&in, uint, const T &in)", asFUNCTION(ScriptArrayFactoryDefVal_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_LIST_FACTORY, "array@ f(int&in, int&in) {repeat T}", asFUNCTION(ScriptArrayListFactory_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptArrayAddRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptArrayRelease_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "T &opIndex(uint)", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "const T &opIndex(uint) const", asFUNCTION(ScriptArrayAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "array &opAssign(const array&in)", asFUNCTION(ScriptArrayAssignment_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("array", "void insertAt(uint, const T&in)", asFUNCTION(ScriptArrayInsertAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeAt(uint)", asFUNCTION(ScriptArrayRemoveAt_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void insertLast(const T&in)", asFUNCTION(ScriptArrayInsertLast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void removeLast()", asFUNCTION(ScriptArrayRemoveLast_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "uint length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reserve(uint)", asFUNCTION(ScriptArrayReserve_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void resize(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc()", asFUNCTION(ScriptArraySortAsc_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortAsc(uint, uint)", asFUNCTION(ScriptArraySortAsc2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc()", asFUNCTION(ScriptArraySortDesc_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void sortDesc(uint, uint)", asFUNCTION(ScriptArraySortDesc2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void reverse()", asFUNCTION(ScriptArrayReverse_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(const T&in) const", asFUNCTION(ScriptArrayFind_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int find(uint, const T&in) const", asFUNCTION(ScriptArrayFind2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(const T&in) const", asFUNCTION(ScriptArrayFindByRef_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "int findByRef(uint, const T&in) const", asFUNCTION(ScriptArrayFindByRef2_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool opEquals(const array&in) const", asFUNCTION(ScriptArrayEquals_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "bool isEmpty() const", asFUNCTION(ScriptArrayIsEmpty_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "uint get_length() const", asFUNCTION(ScriptArrayLength_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("array", "void set_length(uint)", asFUNCTION(ScriptArrayResize_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptArrayGetRefCount_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptArraySetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptArrayGetFlag_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptArrayEnumReferences_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("array", asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptArrayReleaseAllHandles_Generic), asCALL_GENERIC); assert( r >= 0 ); +} + +END_AS_NAMESPACE diff --git a/src/angelscript/scriptarray/scriptarray.h b/src/angelscript/scriptarray/scriptarray.h new file mode 100644 index 0000000000..86c92911f6 --- /dev/null +++ b/src/angelscript/scriptarray/scriptarray.h @@ -0,0 +1,134 @@ +#ifndef SCRIPTARRAY_H +#define SCRIPTARRAY_H + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + +// Sometimes it may be desired to use the same method names as used by C++ STL. +// This may for example reduce time when converting code from script to C++ or +// back. +// +// 0 = off +// 1 = on + +#ifndef AS_USE_STLNAMES +#define AS_USE_STLNAMES 0 +#endif + +BEGIN_AS_NAMESPACE + +struct SArrayBuffer; +struct SArrayCache; + +class CScriptArray +{ +public: + // Set the memory functions that should be used by all CScriptArrays + static void SetMemoryFunctions(asALLOCFUNC_t allocFunc, asFREEFUNC_t freeFunc); + + // Factory functions + static CScriptArray *Create(asIObjectType *ot); + static CScriptArray *Create(asIObjectType *ot, asUINT length); + static CScriptArray *Create(asIObjectType *ot, asUINT length, void *defaultValue); + static CScriptArray *Create(asIObjectType *ot, void *listBuffer); + + // Memory management + void AddRef() const; + void Release() const; + + // Type information + asIObjectType *GetArrayObjectType() const; + int GetArrayTypeId() const; + int GetElementTypeId() const; + + // Get the current size + asUINT GetSize() const; + + // Returns true if the array is empty + bool IsEmpty() const; + + // Pre-allocates memory for elements + void Reserve(asUINT maxElements); + + // Resize the array + void Resize(asUINT numElements); + + // Get a pointer to an element. Returns 0 if out of bounds + void *At(asUINT index); + const void *At(asUINT index) const; + + // Set value of an element. + // The value arg should be a pointer to the value that will be copied to the element. + // Remember, if the array holds handles the value parameter should be the + // address of the handle. The refCount of the object will also be incremented + void SetValue(asUINT index, void *value); + + // Copy the contents of one array to another (only if the types are the same) + CScriptArray &operator=(const CScriptArray&); + + // Compare two arrays + bool operator==(const CScriptArray &) const; + + // Array manipulation + void InsertAt(asUINT index, void *value); + void RemoveAt(asUINT index); + void InsertLast(void *value); + void RemoveLast(); + void SortAsc(); + void SortDesc(); + void SortAsc(asUINT startAt, asUINT count); + void SortDesc(asUINT startAt, asUINT count); + void Sort(asUINT startAt, asUINT count, bool asc); + void Reverse(); + int Find(void *value) const; + int Find(asUINT startAt, void *value) const; + int FindByRef(void *ref) const; + int FindByRef(asUINT startAt, void *ref) const; + + // Return the address of internal buffer for direct manipulation of elements + void *GetBuffer(); + + // GC methods + int GetRefCount(); + void SetFlag(); + bool GetFlag(); + void EnumReferences(asIScriptEngine *engine); + void ReleaseAllHandles(asIScriptEngine *engine); + +protected: + mutable int refCount; + mutable bool gcFlag; + asIObjectType *objType; + SArrayBuffer *buffer; + int elementSize; + int subTypeId; + + // Constructors + CScriptArray(asIObjectType *ot, void *initBuf); // Called from script when initialized with list + CScriptArray(asUINT length, asIObjectType *ot); + CScriptArray(asUINT length, void *defVal, asIObjectType *ot); + CScriptArray(const CScriptArray &other); + virtual ~CScriptArray(); + + bool Less(const void *a, const void *b, bool asc, asIScriptContext *ctx, SArrayCache *cache); + void *GetArrayItemPointer(int index); + void *GetDataPointer(void *buffer); + void Copy(void *dst, void *src); + void Precache(); + bool CheckMaxSize(asUINT numElements); + void Resize(int delta, asUINT at); + void CreateBuffer(SArrayBuffer **buf, asUINT numElements); + void DeleteBuffer(SArrayBuffer *buf); + void CopyBuffer(SArrayBuffer *dst, SArrayBuffer *src); + void Construct(SArrayBuffer *buf, asUINT start, asUINT end); + void Destruct(SArrayBuffer *buf, asUINT start, asUINT end); + bool Equals(const void *a, const void *b, asIScriptContext *ctx, SArrayCache *cache) const; +}; + +void RegisterScriptArray(asIScriptEngine *engine, bool defaultArray); + +END_AS_NAMESPACE + +#endif diff --git a/src/angelscript/scriptbuilder/scriptbuilder.cpp b/src/angelscript/scriptbuilder/scriptbuilder.cpp new file mode 100644 index 0000000000..e60c955e58 --- /dev/null +++ b/src/angelscript/scriptbuilder/scriptbuilder.cpp @@ -0,0 +1,978 @@ +#include "scriptbuilder.h" +#include +#include +using namespace std; + +#include +#if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(__S3E__) +#include +#endif + + +#if defined(__S3E__) || defined(__APPLE__) || defined(__GNUC__) +#include // For getcwd() +#endif + +BEGIN_AS_NAMESPACE + +// Helper functions +static string GetCurrentDir(); +static string GetAbsolutePath(const string &path); + + +CScriptBuilder::CScriptBuilder() +{ + engine = 0; + module = 0; + + includeCallback = 0; + callbackParam = 0; +} + +void CScriptBuilder::SetIncludeCallback(INCLUDECALLBACK_t callback, void *userParam) +{ + includeCallback = callback; + callbackParam = userParam; +} + +int CScriptBuilder::StartNewModule(asIScriptEngine *engine, const char *moduleName) +{ + if( engine == 0 ) return -1; + + this->engine = engine; + module = engine->GetModule(moduleName, asGM_ALWAYS_CREATE); + if( module == 0 ) + return -1; + + ClearAll(); + + return 0; +} + +asIScriptModule *CScriptBuilder::GetModule() +{ + return module; +} + +unsigned int CScriptBuilder::GetSectionCount() const +{ + return (unsigned int)(includedScripts.size()); +} + +string CScriptBuilder::GetSectionName(unsigned int idx) const +{ + if( idx >= includedScripts.size() ) return ""; + +#ifdef _WIN32 + set::const_iterator it = includedScripts.begin(); +#else + set::const_iterator it = includedScripts.begin(); +#endif + while( idx-- > 0 ) it++; + return *it; +} + +// Returns 1 if the section was included +// Returns 0 if the section was not included because it had already been included before +// Returns <0 if there was an error +int CScriptBuilder::AddSectionFromFile(const char *filename) +{ + // The file name stored in the set should be the fully resolved name because + // it is possible to name the same file in multiple ways using relative paths. + string fullpath = GetAbsolutePath(filename); + + if( IncludeIfNotAlreadyIncluded(fullpath.c_str()) ) + { + int r = LoadScriptSection(fullpath.c_str()); + if( r < 0 ) + return r; + else + return 1; + } + + return 0; +} + +// Returns 1 if the section was included +// Returns 0 if the section was not included because it had already been included before +// Returns <0 if there was an error +int CScriptBuilder::AddSectionFromMemory(const char *sectionName, const char *scriptCode, unsigned int scriptLength, int lineOffset) +{ + if( IncludeIfNotAlreadyIncluded(sectionName) ) + { + int r = ProcessScriptSection(scriptCode, scriptLength, sectionName, lineOffset); + if( r < 0 ) + return r; + else + return 1; + } + + return 0; +} + +int CScriptBuilder::BuildModule() +{ + return Build(); +} + +void CScriptBuilder::DefineWord(const char *word) +{ + string sword = word; + if( definedWords.find(sword) == definedWords.end() ) + { + definedWords.insert(sword); + } +} + +void CScriptBuilder::ClearAll() +{ + includedScripts.clear(); + +#if AS_PROCESS_METADATA == 1 + currentClass = ""; + currentNamespace = ""; + + foundDeclarations.clear(); + typeMetadataMap.clear(); + funcMetadataMap.clear(); + varMetadataMap.clear(); +#endif +} + +bool CScriptBuilder::IncludeIfNotAlreadyIncluded(const char *filename) +{ + string scriptFile = filename; + if( includedScripts.find(scriptFile) != includedScripts.end() ) + { + // Already included + return false; + } + + // Add the file to the set of included sections + includedScripts.insert(scriptFile); + + return true; +} + +int CScriptBuilder::LoadScriptSection(const char *filename) +{ + // Open the script file + string scriptFile = filename; +#if _MSC_VER >= 1500 && !defined(__S3E__) + FILE *f = 0; + fopen_s(&f, scriptFile.c_str(), "rb"); +#else + FILE *f = fopen(scriptFile.c_str(), "rb"); +#endif + if( f == 0 ) + { + // Write a message to the engine's message callback + string msg = "Failed to open script file '" + GetAbsolutePath(scriptFile) + "'"; + engine->WriteMessage(filename, 0, 0, asMSGTYPE_ERROR, msg.c_str()); + + // TODO: Write the file where this one was included from + + return -1; + } + + // Determine size of the file + fseek(f, 0, SEEK_END); + int len = ftell(f); + fseek(f, 0, SEEK_SET); + + // On Win32 it is possible to do the following instead + // int len = _filelength(_fileno(f)); + + // Read the entire file + string code; + size_t c = 0; + if( len > 0 ) + { + code.resize(len); + c = fread(&code[0], len, 1, f); + } + + fclose(f); + + if( c == 0 && len > 0 ) + { + // Write a message to the engine's message callback + string msg = "Failed to load script file '" + GetAbsolutePath(scriptFile) + "'"; + engine->WriteMessage(filename, 0, 0, asMSGTYPE_ERROR, msg.c_str()); + return -1; + } + + // Process the script section even if it is zero length so that the name is registered + return ProcessScriptSection(code.c_str(), (unsigned int)(code.length()), filename, 0); +} + +int CScriptBuilder::ProcessScriptSection(const char *script, unsigned int length, const char *sectionname, int lineOffset) +{ + vector includes; + + // Perform a superficial parsing of the script first to store the metadata + if( length ) + modifiedScript.assign(script, length); + else + modifiedScript = script; + + // First perform the checks for #if directives to exclude code that shouldn't be compiled + unsigned int pos = 0; + int nested = 0; + while( pos < modifiedScript.size() ) + { + asUINT len = 0; + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_UNKNOWN && modifiedScript[pos] == '#' && (pos + 1 < modifiedScript.size()) ) + { + int start = pos++; + + // Is this an #if directive? + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + + string token; + token.assign(&modifiedScript[pos], len); + + pos += len; + + if( token == "if" ) + { + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_WHITESPACE ) + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } + + if( t == asTC_IDENTIFIER ) + { + string word; + word.assign(&modifiedScript[pos], len); + + // Overwrite the #if directive with space characters to avoid compiler error + pos += len; + OverwriteCode(start, pos-start); + + // Has this identifier been defined by the application or not? + if( definedWords.find(word) == definedWords.end() ) + { + // Exclude all the code until and including the #endif + pos = ExcludeCode(pos); + } + else + { + nested++; + } + } + } + else if( token == "endif" ) + { + // Only remove the #endif if there was a matching #if + if( nested > 0 ) + { + OverwriteCode(start, pos-start); + nested--; + } + } + } + else + pos += len; + } + +#if AS_PROCESS_METADATA == 1 + // Preallocate memory + string metadata, declaration; + metadata.reserve(500); + declaration.reserve(100); +#endif + + // Then check for meta data and #include directives + pos = 0; + while( pos < modifiedScript.size() ) + { + asUINT len = 0; + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_COMMENT || t == asTC_WHITESPACE ) + { + pos += len; + continue; + } + +#if AS_PROCESS_METADATA == 1 + // Check if class + if( currentClass == "" && modifiedScript.substr(pos,len) == "class" ) + { + // Get the identifier after "class" + do + { + pos += len; + if( pos >= modifiedScript.size() ) + { + t = asTC_UNKNOWN; + break; + } + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } while(t == asTC_COMMENT || t == asTC_WHITESPACE); + + if( t == asTC_IDENTIFIER ) + { + currentClass = modifiedScript.substr(pos,len); + + // Search until first { is encountered + while( pos < modifiedScript.length() ) + { + engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + + // If start of class section encountered stop + if( modifiedScript[pos] == '{' ) + { + pos += len; + break; + } + + // Check next symbol + pos += len; + } + } + + continue; + } + + // Check if end of class + if( currentClass != "" && modifiedScript[pos] == '}' ) + { + currentClass = ""; + pos += len; + continue; + } + + // Check if namespace + if( modifiedScript.substr(pos,len) == "namespace" ) + { + // Get the identifier after "namespace" + do + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } while(t == asTC_COMMENT || t == asTC_WHITESPACE); + + if( currentNamespace != "" ) + currentNamespace += "::"; + currentNamespace += modifiedScript.substr(pos,len); + + // Search until first { is encountered + while( pos < modifiedScript.length() ) + { + engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + + // If start of namespace section encountered stop + if( modifiedScript[pos] == '{' ) + { + pos += len; + break; + } + + // Check next symbol + pos += len; + } + + continue; + } + + // Check if end of namespace + if( currentNamespace != "" && modifiedScript[pos] == '}' ) + { + size_t found = currentNamespace.rfind( "::" ); + if( found != string::npos ) + { + currentNamespace.erase( found ); + } + else + { + currentNamespace = ""; + } + pos += len; + continue; + } + + // Is this the start of metadata? + if( modifiedScript[pos] == '[' ) + { + // Get the metadata string + pos = ExtractMetadataString(pos, metadata); + + // Determine what this metadata is for + int type; + ExtractDeclaration(pos, declaration, type); + + // Store away the declaration in a map for lookup after the build has completed + if( type > 0 ) + { + SMetadataDecl decl(metadata, declaration, type, currentClass, currentNamespace); + foundDeclarations.push_back(decl); + } + } + else +#endif + // Is this a preprocessor directive? + if( modifiedScript[pos] == '#' && (pos + 1 < modifiedScript.size()) ) + { + int start = pos++; + + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_IDENTIFIER ) + { + string token; + token.assign(&modifiedScript[pos], len); + if( token == "include" ) + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_WHITESPACE ) + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } + + if( t == asTC_VALUE && len > 2 && (modifiedScript[pos] == '"' || modifiedScript[pos] == '\'') ) + { + // Get the include file + string includefile; + includefile.assign(&modifiedScript[pos+1], len-2); + pos += len; + + // Store it for later processing + includes.push_back(includefile); + + // Overwrite the include directive with space characters to avoid compiler error + OverwriteCode(start, pos-start); + } + } + } + } + // Don't search for metadata/includes within statement blocks or between tokens in statements + else + { + pos = SkipStatement(pos); + } + } + + // Build the actual script + engine->SetEngineProperty(asEP_COPY_SCRIPT_SECTIONS, true); + module->AddScriptSection(sectionname, modifiedScript.c_str(), modifiedScript.size(), lineOffset); + + if( includes.size() > 0 ) + { + // If the callback has been set, then call it for each included file + if( includeCallback ) + { + for( int n = 0; n < (int)includes.size(); n++ ) + { + int r = includeCallback(includes[n].c_str(), sectionname, this, callbackParam); + if( r < 0 ) + return r; + } + } + else + { + // By default we try to load the included file from the relative directory of the current file + + // Determine the path of the current script so that we can resolve relative paths for includes + string path = sectionname; + size_t posOfSlash = path.find_last_of("/\\"); + if( posOfSlash != string::npos ) + path.resize(posOfSlash+1); + else + path = ""; + + // Load the included scripts + for( int n = 0; n < (int)includes.size(); n++ ) + { + // If the include is a relative path, then prepend the path of the originating script + if( includes[n].find_first_of("/\\") != 0 && + includes[n].find_first_of(":") == string::npos ) + { + includes[n] = path + includes[n]; + } + + // Include the script section + int r = AddSectionFromFile(includes[n].c_str()); + if( r < 0 ) + return r; + } + } + } + + return 0; +} + +int CScriptBuilder::Build() +{ + int r = module->Build(); + if( r < 0 ) + return r; + +#if AS_PROCESS_METADATA == 1 + // After the script has been built, the metadata strings should be + // stored for later lookup by function id, type id, and variable index + for( int n = 0; n < (int)foundDeclarations.size(); n++ ) + { + SMetadataDecl *decl = &foundDeclarations[n]; + module->SetDefaultNamespace(decl->nameSpace.c_str()); + if( decl->type == 1 ) + { + // Find the type id + int typeId = module->GetTypeIdByDecl(decl->declaration.c_str()); + assert( typeId >= 0 ); + if( typeId >= 0 ) + typeMetadataMap.insert(map::value_type(typeId, decl->metadata)); + } + else if( decl->type == 2 ) + { + if( decl->parentClass == "" ) + { + // Find the function id + asIScriptFunction *func = module->GetFunctionByDecl(decl->declaration.c_str()); + assert( func ); + if( func ) + funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + } + else + { + // Find the method id + int typeId = module->GetTypeIdByDecl(decl->parentClass.c_str()); + assert( typeId > 0 ); + map::iterator it = classMetadataMap.find(typeId); + if( it == classMetadataMap.end() ) + { + classMetadataMap.insert(map::value_type(typeId, SClassMetadata(decl->parentClass))); + it = classMetadataMap.find(typeId); + } + + asIObjectType *type = engine->GetObjectTypeById(typeId); + asIScriptFunction *func = type->GetMethodByDecl(decl->declaration.c_str()); + assert( func ); + if( func ) + it->second.funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + } + } + else if( decl->type == 4 ) + { + if( decl->parentClass == "" ) + { + // Find the global virtual property accessors + asIScriptFunction *func = module->GetFunctionByName(("get_" + decl->declaration).c_str()); + if( func ) + funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + func = module->GetFunctionByName(("set_" + decl->declaration).c_str()); + if( func ) + funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + } + else + { + // Find the method virtual property accessors + int typeId = module->GetTypeIdByDecl(decl->parentClass.c_str()); + assert( typeId > 0 ); + map::iterator it = classMetadataMap.find(typeId); + if( it == classMetadataMap.end() ) + { + classMetadataMap.insert(map::value_type(typeId, SClassMetadata(decl->parentClass))); + it = classMetadataMap.find(typeId); + } + + asIObjectType *type = engine->GetObjectTypeById(typeId); + asIScriptFunction *func = type->GetMethodByName(("get_" + decl->declaration).c_str()); + if( func ) + it->second.funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + func = type->GetMethodByName(("set_" + decl->declaration).c_str()); + if( func ) + it->second.funcMetadataMap.insert(map::value_type(func->GetId(), decl->metadata)); + + } + } + else if( decl->type == 3 ) + { + if( decl->parentClass == "" ) + { + // Find the global variable index + int varIdx = module->GetGlobalVarIndexByName(decl->declaration.c_str()); + assert( varIdx >= 0 ); + if( varIdx >= 0 ) + varMetadataMap.insert(map::value_type(varIdx, decl->metadata)); + } + else + { + int typeId = module->GetTypeIdByDecl(decl->parentClass.c_str()); + assert( typeId > 0 ); + + // Add the classes if needed + map::iterator it = classMetadataMap.find(typeId); + if( it == classMetadataMap.end() ) + { + classMetadataMap.insert(map::value_type(typeId, SClassMetadata(decl->parentClass))); + it = classMetadataMap.find(typeId); + } + + // Add the variable to class + asIObjectType *objectType = engine->GetObjectTypeById(typeId); + int idx = -1; + + // Search through all properties to get proper declaration + for( asUINT i = 0; i < (asUINT)objectType->GetPropertyCount(); ++i ) + { + const char *name; + objectType->GetProperty(i, &name); + if( decl->declaration == name ) + { + idx = i; + break; + } + } + + // If found, add it + assert( idx >= 0 ); + if( idx >= 0 ) it->second.varMetadataMap.insert(map::value_type(idx, decl->metadata)); + } + } + } + module->SetDefaultNamespace(""); +#endif + + return 0; +} + +int CScriptBuilder::SkipStatement(int pos) +{ + asUINT len = 0; + + // Skip until ; or { whichever comes first + while( pos < (int)modifiedScript.length() && modifiedScript[pos] != ';' && modifiedScript[pos] != '{' ) + { + engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + pos += len; + } + + // Skip entire statement block + if( pos < (int)modifiedScript.length() && modifiedScript[pos] == '{' ) + { + pos += 1; + + // Find the end of the statement block + int level = 1; + while( level > 0 && pos < (int)modifiedScript.size() ) + { + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_KEYWORD ) + { + if( modifiedScript[pos] == '{' ) + level++; + else if( modifiedScript[pos] == '}' ) + level--; + } + + pos += len; + } + } + else + pos += 1; + + return pos; +} + +// Overwrite all code with blanks until the matching #endif +int CScriptBuilder::ExcludeCode(int pos) +{ + asUINT len = 0; + int nested = 0; + while( pos < (int)modifiedScript.size() ) + { + engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( modifiedScript[pos] == '#' ) + { + modifiedScript[pos] = ' '; + pos++; + + // Is it an #if or #endif directive? + engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + string token; + token.assign(&modifiedScript[pos], len); + OverwriteCode(pos, len); + + if( token == "if" ) + { + nested++; + } + else if( token == "endif" ) + { + if( nested-- == 0 ) + { + pos += len; + break; + } + } + } + else if( modifiedScript[pos] != '\n' ) + { + OverwriteCode(pos, len); + } + pos += len; + } + + return pos; +} + +// Overwrite all characters except line breaks with blanks +void CScriptBuilder::OverwriteCode(int start, int len) +{ + char *code = &modifiedScript[start]; + for( int n = 0; n < len; n++ ) + { + if( *code != '\n' ) + *code = ' '; + code++; + } +} + +#if AS_PROCESS_METADATA == 1 +int CScriptBuilder::ExtractMetadataString(int pos, string &metadata) +{ + metadata = ""; + + // Overwrite the metadata with space characters to allow compilation + modifiedScript[pos] = ' '; + + // Skip opening brackets + pos += 1; + + int level = 1; + asUINT len = 0; + while( level > 0 && pos < (int)modifiedScript.size() ) + { + asETokenClass t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_KEYWORD ) + { + if( modifiedScript[pos] == '[' ) + level++; + else if( modifiedScript[pos] == ']' ) + level--; + } + + // Copy the metadata to our buffer + if( level > 0 ) + metadata.append(&modifiedScript[pos], len); + + // Overwrite the metadata with space characters to allow compilation + if( t != asTC_WHITESPACE ) + OverwriteCode(pos, len); + + pos += len; + } + + return pos; +} + +int CScriptBuilder::ExtractDeclaration(int pos, string &declaration, int &type) +{ + declaration = ""; + type = 0; + + int start = pos; + + std::string token; + asUINT len = 0; + asETokenClass t = asTC_WHITESPACE; + + // Skip white spaces and comments + do + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } while ( t == asTC_WHITESPACE || t == asTC_COMMENT ); + + // We're expecting, either a class, interface, function, or variable declaration + if( t == asTC_KEYWORD || t == asTC_IDENTIFIER ) + { + token.assign(&modifiedScript[pos], len); + if( token == "interface" || token == "class" ) + { + // Skip white spaces and comments + do + { + pos += len; + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + } while ( t == asTC_WHITESPACE || t == asTC_COMMENT ); + + if( t == asTC_IDENTIFIER ) + { + type = 1; + declaration.assign(&modifiedScript[pos], len); + pos += len; + return pos; + } + } + else + { + // For function declarations, store everything up to the start of the statement block + + // For variable declaration store just the name as there can only be one + + // We'll only know if the declaration is a variable or function declaration when we see the statement block, or absense of a statement block. + bool hasParenthesis = false; + declaration.append(&modifiedScript[pos], len); + pos += len; + string name; + for(; pos < (int)modifiedScript.size();) + { + t = engine->ParseToken(&modifiedScript[pos], modifiedScript.size() - pos, &len); + if( t == asTC_KEYWORD ) + { + token.assign(&modifiedScript[pos], len); + if( token == "{" ) + { + if( hasParenthesis ) + { + // We've found the end of a function signature + type = 2; + } + else + { + // We've found a virtual property. Just keep the name + declaration = name; + type = 4; + } + return pos; + } + if( token == "=" || token == ";" ) + { + // Substitute the declaration with just the name + declaration = name; + type = 3; + return pos; + } + else if( token == "(" ) + { + // This is the first parenthesis we encounter. If the parenthesis isn't followed + // by a statement block, then this is a variable declaration, in which case we + // should only store the type and name of the variable, not the initialization parameters. + hasParenthesis = true; + } + } + else if( t == asTC_IDENTIFIER ) + { + name.assign(&modifiedScript[pos], len); + } + + declaration.append(&modifiedScript[pos], len); + pos += len; + } + } + } + + return start; +} + +const char *CScriptBuilder::GetMetadataStringForType(int typeId) +{ + map::iterator it = typeMetadataMap.find(typeId); + if( it != typeMetadataMap.end() ) + return it->second.c_str(); + + return ""; +} + +const char *CScriptBuilder::GetMetadataStringForFunc(asIScriptFunction *func) +{ + if( func ) + { + map::iterator it = funcMetadataMap.find(func->GetId()); + if( it != funcMetadataMap.end() ) + return it->second.c_str(); + } + + return ""; +} + +const char *CScriptBuilder::GetMetadataStringForVar(int varIdx) +{ + map::iterator it = varMetadataMap.find(varIdx); + if( it != varMetadataMap.end() ) + return it->second.c_str(); + + return ""; +} + +const char *CScriptBuilder::GetMetadataStringForTypeProperty(int typeId, int varIdx) +{ + map::iterator typeIt = classMetadataMap.find(typeId); + if(typeIt == classMetadataMap.end()) return ""; + + map::iterator propIt = typeIt->second.varMetadataMap.find(varIdx); + if(propIt == typeIt->second.varMetadataMap.end()) return ""; + + return propIt->second.c_str(); +} + +const char *CScriptBuilder::GetMetadataStringForTypeMethod(int typeId, asIScriptFunction *method) +{ + if( method ) + { + map::iterator typeIt = classMetadataMap.find(typeId); + if(typeIt == classMetadataMap.end()) return ""; + + map::iterator methodIt = typeIt->second.funcMetadataMap.find(method->GetId()); + if(methodIt == typeIt->second.funcMetadataMap.end()) return ""; + + return methodIt->second.c_str(); + } + + return ""; +} +#endif + +string GetAbsolutePath(const string &file) +{ + string str = file; + + // If this is a relative path, complement it with the current path + if( !((str.length() > 0 && (str[0] == '/' || str[0] == '\\')) || + str.find(":") != string::npos) ) + { + str = GetCurrentDir() + "/" + str; + } + + // Replace backslashes for forward slashes + size_t pos = 0; + while( (pos = str.find("\\", pos)) != string::npos ) + str[pos] = '/'; + + // Replace /./ with nothing + pos = 0; + while( (pos = str.find("/./", pos)) != string::npos ) + str.erase(pos, 3); + + // For each /../ remove the parent dir and the /../ + pos = 0; + while( (pos = str.find("/../")) != string::npos ) + { + size_t pos2 = str.rfind("/", pos-1); + if( pos2 != string::npos ) + str.erase(pos2, pos+3-pos2); + else + { + // The path is invalid + break; + } + } + + return str; +} + +string GetCurrentDir() +{ + char buffer[1024]; + return getcwd(buffer, 1024); +} + +END_AS_NAMESPACE + + diff --git a/src/angelscript/scriptbuilder/scriptbuilder.h b/src/angelscript/scriptbuilder/scriptbuilder.h new file mode 100644 index 0000000000..3867f8ec04 --- /dev/null +++ b/src/angelscript/scriptbuilder/scriptbuilder.h @@ -0,0 +1,192 @@ +#ifndef SCRIPTBUILDER_H +#define SCRIPTBUILDER_H + +//--------------------------- +// Compilation settings +// + +// Set this flag to turn on/off metadata processing +// 0 = off +// 1 = on +#ifndef AS_PROCESS_METADATA +#define AS_PROCESS_METADATA 1 +#endif + +// TODO: Implement flags for turning on/off include directives and conditional programming + + + +//--------------------------- +// Declaration +// + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + + +#if defined(_MSC_VER) && _MSC_VER <= 1200 +// disable the annoying warnings on MSVC 6 +#pragma warning (disable:4786) +#endif + +#include +#include +#include +#include +#include // _strcmpi + +BEGIN_AS_NAMESPACE + +class CScriptBuilder; + +// This callback will be called for each #include directive encountered by the +// builder. The callback should call the AddSectionFromFile or AddSectionFromMemory +// to add the included section to the script. If the include cannot be resolved +// then the function should return a negative value to abort the compilation. +typedef int (*INCLUDECALLBACK_t)(const char *include, const char *from, CScriptBuilder *builder, void *userParam); + +// Helper class for loading and pre-processing script files to +// support include directives and metadata declarations +class CScriptBuilder +{ +public: + CScriptBuilder(); + + // Start a new module + int StartNewModule(asIScriptEngine *engine, const char *moduleName); + + // Load a script section from a file on disk + // Returns 1 if the file was included + // 0 if the file had already been included before + // <0 on error + int AddSectionFromFile(const char *filename); + + // Load a script section from memory + // Returns 1 if the section was included + // 0 if a section with the same name had already been included before + // <0 on error + int AddSectionFromMemory(const char *sectionName, + const char *scriptCode, + unsigned int scriptLength = 0, + int lineOffset = 0); + + // Build the added script sections + int BuildModule(); + + // Returns the current module + asIScriptModule *GetModule(); + + // Register the callback for resolving include directive + void SetIncludeCallback(INCLUDECALLBACK_t callback, void *userParam); + + // Add a pre-processor define for conditional compilation + void DefineWord(const char *word); + + // Enumerate included script sections + unsigned int GetSectionCount() const; + std::string GetSectionName(unsigned int idx) const; + +#if AS_PROCESS_METADATA == 1 + // Get metadata declared for class types and interfaces + const char *GetMetadataStringForType(int typeId); + + // Get metadata declared for functions + const char *GetMetadataStringForFunc(asIScriptFunction *func); + + // Get metadata declared for global variables + const char *GetMetadataStringForVar(int varIdx); + + // Get metadata declared for class variables + const char *GetMetadataStringForTypeProperty(int typeId, int varIdx); + + // Get metadata declared for class functions + const char *GetMetadataStringForTypeMethod(int typeId, asIScriptFunction *method); +#endif + +protected: + void ClearAll(); + int Build(); + int ProcessScriptSection(const char *script, unsigned int length, const char *sectionname, int lineOffset); + int LoadScriptSection(const char *filename); + bool IncludeIfNotAlreadyIncluded(const char *filename); + + int SkipStatement(int pos); + + int ExcludeCode(int start); + void OverwriteCode(int start, int len); + + asIScriptEngine *engine; + asIScriptModule *module; + std::string modifiedScript; + + INCLUDECALLBACK_t includeCallback; + void *callbackParam; + +#if AS_PROCESS_METADATA == 1 + int ExtractMetadataString(int pos, std::string &outMetadata); + int ExtractDeclaration(int pos, std::string &outDeclaration, int &outType); + + // Temporary structure for storing metadata and declaration + struct SMetadataDecl + { + SMetadataDecl(std::string m, std::string d, int t, std::string c, std::string ns) : metadata(m), declaration(d), type(t), parentClass(c), nameSpace(ns) {} + std::string metadata; + std::string declaration; + int type; + std::string parentClass; + std::string nameSpace; + }; + std::vector foundDeclarations; + std::string currentClass; + std::string currentNamespace; + + // Storage of metadata for global declarations + std::map typeMetadataMap; + std::map funcMetadataMap; + std::map varMetadataMap; + + // Storage of metadata for class member declarations + struct SClassMetadata + { + SClassMetadata(const std::string& aName) : className(aName) {} + std::string className; + std::map funcMetadataMap; + std::map varMetadataMap; + }; + std::map classMetadataMap; + +#endif + +#ifdef _WIN32 + // On Windows the filenames are case insensitive so the comparisons to + // avoid duplicate includes must also be case insensitive. True case insensitive + // is not easy as it must be language aware, but a simple implementation such + // as strcmpi should suffice in almost all cases. + // + // ref: http://www.gotw.ca/gotw/029.htm + // ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317761(v=vs.85).aspx + // ref: http://site.icu-project.org/ + + // TODO: Strings by default are treated as UTF8 encoded. If the application choses to + // use a different encoding, the comparison algorithm should be adjusted as well + + struct ci_less + { + bool operator()(const std::string &a, const std::string &b) const + { + return _strcmpi(a.c_str(), b.c_str()) < 0; + } + }; + std::set includedScripts; +#else + std::set includedScripts; +#endif + + std::set definedWords; +}; + +END_AS_NAMESPACE + +#endif diff --git a/src/angelscript/scriptmath/scriptmath.cpp b/src/angelscript/scriptmath/scriptmath.cpp new file mode 100644 index 0000000000..df36d20274 --- /dev/null +++ b/src/angelscript/scriptmath/scriptmath.cpp @@ -0,0 +1,347 @@ +#include +#include +#include +#include +#include "scriptmath.h" + +#ifdef __BORLANDC__ +#include + +// The C++Builder RTL doesn't pull the *f functions into the global namespace per default. +using namespace std; + +#if __BORLANDC__ < 0x580 +// C++Builder 6 and earlier don't come with any *f variants of the math functions at all. +inline float cosf (float arg) { return std::cos (arg); } +inline float sinf (float arg) { return std::sin (arg); } +inline float tanf (float arg) { return std::tan (arg); } +inline float atan2f (float y, float x) { return std::atan2 (y, x); } +inline float logf (float arg) { return std::log (arg); } +inline float powf (float x, float y) { return std::pow (x, y); } +inline float sqrtf (float arg) { return std::sqrt (arg); } +#endif + +// C++Builder doesn't define most of the non-standard float-specific math functions with +// "*f" suffix; instead it provides overloads for the standard math functions which take +// "float" arguments. +inline float acosf (float arg) { return std::acos (arg); } +inline float asinf (float arg) { return std::asin (arg); } +inline float atanf (float arg) { return std::atan (arg); } +inline float coshf (float arg) { return std::cosh (arg); } +inline float sinhf (float arg) { return std::sinh (arg); } +inline float tanhf (float arg) { return std::tanh (arg); } +inline float log10f (float arg) { return std::log10 (arg); } +inline float ceilf (float arg) { return std::ceil (arg); } +inline float fabsf (float arg) { return std::fabs (arg); } +inline float floorf (float arg) { return std::floor (arg); } + +// C++Builder doesn't define a non-standard "modff" function but rather an overload of "modf" +// for float arguments. However, BCC's float overload of fmod() is broken (QC #74816; fixed +// in C++Builder 2010). +inline float modff (float x, float *y) +{ + double d; + float f = (float) modf((double) x, &d); + *y = (float) d; + return f; +} +#endif + +BEGIN_AS_NAMESPACE + +// Determine whether the float version should be registered, or the double version +#ifndef AS_USE_FLOAT +#if !defined(_WIN32_WCE) // WinCE doesn't have the float versions of the math functions +#define AS_USE_FLOAT 1 +#endif +#endif + +// The modf function doesn't seem very intuitive, so I'm writing this +// function that simply returns the fractional part of the float value +#if AS_USE_FLOAT +float fractionf(float v) +{ + float intPart; + return modff(v, &intPart); +} +#else +double fraction(double v) +{ + double intPart; + return modf(v, &intPart); +} +#endif + +// As AngelScript doesn't allow bitwise manipulation of float types we'll provide a couple of +// functions for converting float values to IEEE 754 formatted values etc. This also allow us to +// provide a platform agnostic representation to the script so the scripts don't have to worry +// about whether the CPU uses IEEE 754 floats or some other representation +float fpFromIEEE(asUINT raw) +{ + // TODO: Identify CPU family to provide proper conversion + // if the CPU doesn't natively use IEEE style floats + return *reinterpret_cast(&raw); +} +asUINT fpToIEEE(float fp) +{ + return *reinterpret_cast(&fp); +} +double fpFromIEEE(asQWORD raw) +{ + return *reinterpret_cast(&raw); +} +asQWORD fpToIEEE(double fp) +{ + return *reinterpret_cast(&fp); +} + +// closeTo() is used to determine if the binary representation of two numbers are +// relatively close to each other. Numerical errors due to rounding errors build +// up over many operations, so it is almost impossible to get exact numbers and +// this is where closeTo() comes in. +// +// It shouldn't be used to determine if two numbers are mathematically close to +// each other. +// +// ref: http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm +// ref: http://www.gamedev.net/topic/653449-scriptmath-and-closeto/ +bool closeTo(float a, float b, float epsilon) +{ + // Equal numbers and infinity will return immediately + if( a == b ) return true; + + // When very close to 0, we can use the absolute comparison + float diff = fabs(a - b); + if( (a == 0 || b == 0) && (diff < epsilon) ) + return true; + + // Otherwise we need to use relative comparison to account for precision + return diff / (fabs(a) + fabs(b)) < epsilon; +} + +bool closeTo(double a, double b, double epsilon) +{ + if( a == b ) return true; + + double diff = fabs(a - b); + if( (a == 0 || b == 0) && (diff < epsilon) ) + return true; + + return diff / (fabs(a) + fabs(b)) < epsilon; +} + +void RegisterScriptMath_Native(asIScriptEngine *engine) +{ + int r; + + // Conversion between floating point and IEEE bits representations + r = engine->RegisterGlobalFunction("float fpFromIEEE(uint)", asFUNCTIONPR(fpFromIEEE, (asUINT), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("uint fpToIEEE(float)", asFUNCTIONPR(fpToIEEE, (float), asUINT), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double fpFromIEEE(uint64)", asFUNCTIONPR(fpFromIEEE, (asQWORD), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("uint64 fpToIEEE(double)", asFUNCTIONPR(fpToIEEE, (double), asQWORD), asCALL_CDECL); assert( r >= 0 ); + + // Close to comparison with epsilon + r = engine->RegisterGlobalFunction("bool closeTo(float, float, float = 0.00001f)", asFUNCTIONPR(closeTo, (float, float, float), bool), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("bool closeTo(double, double, double = 0.0000000001)", asFUNCTIONPR(closeTo, (double, double, double), bool), asCALL_CDECL); assert( r >= 0 ); + +#if AS_USE_FLOAT + // Trigonometric functions + r = engine->RegisterGlobalFunction("float cos(float)", asFUNCTIONPR(cosf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sin(float)", asFUNCTIONPR(sinf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float tan(float)", asFUNCTIONPR(tanf, (float), float), asCALL_CDECL); assert( r >= 0 ); + + r = engine->RegisterGlobalFunction("float acos(float)", asFUNCTIONPR(acosf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float asin(float)", asFUNCTIONPR(asinf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float atan(float)", asFUNCTIONPR(atanf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float atan2(float,float)", asFUNCTIONPR(atan2f, (float, float), float), asCALL_CDECL); assert( r >= 0 ); + + // Hyberbolic functions + r = engine->RegisterGlobalFunction("float cosh(float)", asFUNCTIONPR(coshf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sinh(float)", asFUNCTIONPR(sinhf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float tanh(float)", asFUNCTIONPR(tanhf, (float), float), asCALL_CDECL); assert( r >= 0 ); + + // Exponential and logarithmic functions + r = engine->RegisterGlobalFunction("float log(float)", asFUNCTIONPR(logf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float log10(float)", asFUNCTIONPR(log10f, (float), float), asCALL_CDECL); assert( r >= 0 ); + + // Power functions + r = engine->RegisterGlobalFunction("float pow(float, float)", asFUNCTIONPR(powf, (float, float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sqrt(float)", asFUNCTIONPR(sqrtf, (float), float), asCALL_CDECL); assert( r >= 0 ); + + // Nearest integer, absolute value, and remainder functions + r = engine->RegisterGlobalFunction("float ceil(float)", asFUNCTIONPR(ceilf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float abs(float)", asFUNCTIONPR(fabsf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float floor(float)", asFUNCTIONPR(floorf, (float), float), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float fraction(float)", asFUNCTIONPR(fractionf, (float), float), asCALL_CDECL); assert( r >= 0 ); + + // Don't register modf because AngelScript already supports the % operator +#else + // double versions of the same + r = engine->RegisterGlobalFunction("double cos(double)", asFUNCTIONPR(cos, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sin(double)", asFUNCTIONPR(sin, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double tan(double)", asFUNCTIONPR(tan, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double acos(double)", asFUNCTIONPR(acos, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double asin(double)", asFUNCTIONPR(asin, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double atan(double)", asFUNCTIONPR(atan, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double atan2(double,double)", asFUNCTIONPR(atan2, (double, double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double cosh(double)", asFUNCTIONPR(cosh, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sinh(double)", asFUNCTIONPR(sinh, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double tanh(double)", asFUNCTIONPR(tanh, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double log(double)", asFUNCTIONPR(log, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double log10(double)", asFUNCTIONPR(log10, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double pow(double, double)", asFUNCTIONPR(pow, (double, double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sqrt(double)", asFUNCTIONPR(sqrt, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double ceil(double)", asFUNCTIONPR(ceil, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double abs(double)", asFUNCTIONPR(fabs, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double floor(double)", asFUNCTIONPR(floor, (double), double), asCALL_CDECL); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double fraction(double)", asFUNCTIONPR(fraction, (double), double), asCALL_CDECL); assert( r >= 0 ); +#endif +} + +#if AS_USE_FLOAT +// This macro creates simple generic wrappers for functions of type 'float func(float)' +#define GENERICff(x) \ +void x##_generic(asIScriptGeneric *gen) \ +{ \ + float f = *(float*)gen->GetAddressOfArg(0); \ + *(float*)gen->GetAddressOfReturnLocation() = x(f); \ +} + +GENERICff(cosf) +GENERICff(sinf) +GENERICff(tanf) +GENERICff(acosf) +GENERICff(asinf) +GENERICff(atanf) +GENERICff(coshf) +GENERICff(sinhf) +GENERICff(tanhf) +GENERICff(logf) +GENERICff(log10f) +GENERICff(sqrtf) +GENERICff(ceilf) +GENERICff(fabsf) +GENERICff(floorf) +GENERICff(fractionf) + +void powf_generic(asIScriptGeneric *gen) +{ + float f1 = *(float*)gen->GetAddressOfArg(0); + float f2 = *(float*)gen->GetAddressOfArg(1); + *(float*)gen->GetAddressOfReturnLocation() = powf(f1, f2); +} +void atan2f_generic(asIScriptGeneric *gen) +{ + float f1 = *(float*)gen->GetAddressOfArg(0); + float f2 = *(float*)gen->GetAddressOfArg(1); + *(float*)gen->GetAddressOfReturnLocation() = atan2f(f1, f2); +} + +#else +// This macro creates simple generic wrappers for functions of type 'double func(double)' +#define GENERICdd(x) \ +void x##_generic(asIScriptGeneric *gen) \ +{ \ + double f = *(double*)gen->GetAddressOfArg(0); \ + *(double*)gen->GetAddressOfReturnLocation() = x(f); \ +} + +GENERICdd(cos) +GENERICdd(sin) +GENERICdd(tan) +GENERICdd(acos) +GENERICdd(asin) +GENERICdd(atan) +GENERICdd(cosh) +GENERICdd(sinh) +GENERICdd(tanh) +GENERICdd(log) +GENERICdd(log10) +GENERICdd(sqrt) +GENERICdd(ceil) +GENERICdd(fabs) +GENERICdd(floor) +GENERICdd(fraction) + +void pow_generic(asIScriptGeneric *gen) +{ + double f1 = *(double*)gen->GetAddressOfArg(0); + double f2 = *(double*)gen->GetAddressOfArg(1); + *(double*)gen->GetAddressOfReturnLocation() = pow(f1, f2); +} +void atan2_generic(asIScriptGeneric *gen) +{ + double f1 = *(double*)gen->GetAddressOfArg(0); + double f2 = *(double*)gen->GetAddressOfArg(1); + *(double*)gen->GetAddressOfReturnLocation() = atan2(f1, f2); +} +#endif +void RegisterScriptMath_Generic(asIScriptEngine *engine) +{ + int r; + +#if AS_USE_FLOAT + // Trigonometric functions + r = engine->RegisterGlobalFunction("float cos(float)", asFUNCTION(cosf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sin(float)", asFUNCTION(sinf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float tan(float)", asFUNCTION(tanf_generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterGlobalFunction("float acos(float)", asFUNCTION(acosf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float asin(float)", asFUNCTION(asinf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float atan(float)", asFUNCTION(atanf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float atan2(float,float)", asFUNCTION(atan2f_generic), asCALL_GENERIC); assert( r >= 0 ); + + // Hyberbolic functions + r = engine->RegisterGlobalFunction("float cosh(float)", asFUNCTION(coshf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sinh(float)", asFUNCTION(sinhf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float tanh(float)", asFUNCTION(tanhf_generic), asCALL_GENERIC); assert( r >= 0 ); + + // Exponential and logarithmic functions + r = engine->RegisterGlobalFunction("float log(float)", asFUNCTION(logf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float log10(float)", asFUNCTION(log10f_generic), asCALL_GENERIC); assert( r >= 0 ); + + // Power functions + r = engine->RegisterGlobalFunction("float pow(float, float)", asFUNCTION(powf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float sqrt(float)", asFUNCTION(sqrtf_generic), asCALL_GENERIC); assert( r >= 0 ); + + // Nearest integer, absolute value, and remainder functions + r = engine->RegisterGlobalFunction("float ceil(float)", asFUNCTION(ceilf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float abs(float)", asFUNCTION(fabsf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float floor(float)", asFUNCTION(floorf_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("float fraction(float)", asFUNCTION(fractionf_generic), asCALL_GENERIC); assert( r >= 0 ); + + // Don't register modf because AngelScript already supports the % operator +#else + // double versions of the same + r = engine->RegisterGlobalFunction("double cos(double)", asFUNCTION(cos_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sin(double)", asFUNCTION(sin_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double tan(double)", asFUNCTION(tan_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double acos(double)", asFUNCTION(acos_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double asin(double)", asFUNCTION(asin_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double atan(double)", asFUNCTION(atan_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double atan2(double,double)", asFUNCTION(atan2_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double cosh(double)", asFUNCTION(cosh_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sinh(double)", asFUNCTION(sinh_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double tanh(double)", asFUNCTION(tanh_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double log(double)", asFUNCTION(log_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double log10(double)", asFUNCTION(log10_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double pow(double, double)", asFUNCTION(pow_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double sqrt(double)", asFUNCTION(sqrt_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double ceil(double)", asFUNCTION(ceil_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double abs(double)", asFUNCTION(fabs_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double floor(double)", asFUNCTION(floor_generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterGlobalFunction("double fraction(double)", asFUNCTION(fraction_generic), asCALL_GENERIC); assert( r >= 0 ); +#endif +} + +void RegisterScriptMath(asIScriptEngine *engine) +{ + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + RegisterScriptMath_Generic(engine); + else + RegisterScriptMath_Native(engine); +} + +END_AS_NAMESPACE + + diff --git a/src/angelscript/scriptmath/scriptmath.h b/src/angelscript/scriptmath/scriptmath.h new file mode 100644 index 0000000000..a239e38d7c --- /dev/null +++ b/src/angelscript/scriptmath/scriptmath.h @@ -0,0 +1,26 @@ +#ifndef SCRIPTMATH_H +#define SCRIPTMATH_H + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + + +BEGIN_AS_NAMESPACE + +// This function will determine the configuration of the engine +// and use one of the two functions below to register the math functions +void RegisterScriptMath(asIScriptEngine *engine); + +// Call this function to register the math functions +// using native calling conventions +void RegisterScriptMath_Native(asIScriptEngine *engine); + +// Use this one instead if native calling conventions +// are not supported on the target platform +void RegisterScriptMath_Generic(asIScriptEngine *engine); + +END_AS_NAMESPACE + +#endif diff --git a/src/angelscript/scriptstdstring/scriptstdstring.cpp b/src/angelscript/scriptstdstring/scriptstdstring.cpp new file mode 100644 index 0000000000..9d15225120 --- /dev/null +++ b/src/angelscript/scriptstdstring/scriptstdstring.cpp @@ -0,0 +1,1204 @@ +#include "scriptstdstring.h" +#include // assert() +#include // std::stringstream +#include // strstr() +#include // sprintf() +#include // strtod() +#ifndef __psp2__ + #include // setlocale() +#endif + +using namespace std; + +BEGIN_AS_NAMESPACE + +// This macro is used to avoid warnings about unused variables. +// Usually where the variables are only used in debug mode. +#define UNUSED_VAR(x) (void)(x) + +#if AS_USE_STRINGPOOL == 1 + +#ifdef AS_CAN_USE_CPP11 + // The string pool doesn't need to keep a specific order in the + // pool, so the unordered_map is faster than the ordinary map + #include // std::unordered_map + typedef unordered_map map_t; +#else + #include // std::map + typedef map map_t; +#endif + +// By keeping the literal strings in a pool the application +// performance is improved as there are less string copies created. + +// The string pool will be kept as user data in the engine. We'll +// need a specific type to identify the string pool user data. +// We just define a number here that we assume nobody else is using for +// object type user data. The add-ons have reserved the numbers 1000 +// through 1999 for this purpose, so we should be fine. +const asPWORD STRING_POOL = 1001; + +// This global static variable is placed here rather than locally within the +// StringFactory, due to memory leak detectors that don't see the deallocation +// of global variables. By placing the variable globally it will be initialized +// before the memory leak detector starts, thus it won't report the missing +// deallocation. An example of this the Marmalade leak detector initialized with +// IwGxInit() and finished with IwGxTerminate(). +static const string emptyString; + +static const string &StringFactory(asUINT length, const char *s) +{ + // Each engine instance has its own string pool + asIScriptContext *ctx = asGetActiveContext(); + if( ctx == 0 ) + { + // The string factory can only be called from a script + assert( ctx ); + return emptyString; + } + asIScriptEngine *engine = ctx->GetEngine(); + + map_t *pool = reinterpret_cast< map_t* >(engine->GetUserData(STRING_POOL)); + if( !pool ) + { + // The string pool hasn't been created yet, so we'll create it now + asAcquireExclusiveLock(); + + // Make sure the string pool wasn't created while we were waiting for the lock + pool = reinterpret_cast< map_t* >(engine->GetUserData(STRING_POOL)); + if( !pool ) + { + #if defined(__S3E__) + pool = new map_t; + #else + pool = new (nothrow) map_t; + #endif + if( pool == 0 ) + { + ctx->SetException("Out of memory"); + asReleaseExclusiveLock(); + return emptyString; + } + engine->SetUserData(pool, STRING_POOL); + } + + asReleaseExclusiveLock(); + } + + // We can't let other threads modify the pool while we query it + asAcquireSharedLock(); + + // First check if a string object hasn't been created already + map_t::iterator it; + it = pool->find(s); + if( it != pool->end() ) + { + asReleaseSharedLock(); + return it->second; + } + + asReleaseSharedLock(); + + // Acquire an exclusive lock so we can add the new string to the pool + asAcquireExclusiveLock(); + + // Make sure the string wasn't created while we were waiting for the exclusive lock + it = pool->find(s); + if( it == pool->end() ) + { + // Create a new string object + it = pool->insert(map_t::value_type(s, string(s, length))).first; + } + + asReleaseExclusiveLock(); + return it->second; +} + +static void CleanupEngineStringPool(asIScriptEngine *engine) +{ + map_t *pool = reinterpret_cast< map_t* >(engine->GetUserData(STRING_POOL)); + if( pool ) + delete pool; +} + +#else +static string StringFactory(asUINT length, const char *s) +{ + return string(s, length); +} +#endif + +static void ConstructString(string *thisPointer) +{ + new(thisPointer) string(); +} + +static void CopyConstructString(const string &other, string *thisPointer) +{ + new(thisPointer) string(other); +} + +static void DestructString(string *thisPointer) +{ + thisPointer->~string(); +} + +static string &AddAssignStringToString(const string &str, string &dest) +{ + // We don't register the method directly because some compilers + // and standard libraries inline the definition, resulting in the + // linker being unable to find the declaration. + // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 + dest += str; + return dest; +} + +// bool string::isEmpty() +// bool string::empty() // if AS_USE_STLNAMES == 1 +static bool StringIsEmpty(const string &str) +{ + // We don't register the method directly because some compilers + // and standard libraries inline the definition, resulting in the + // linker being unable to find the declaration + // Example: CLang/LLVM with XCode 4.3 on OSX 10.7 + return str.empty(); +} + +static string &AssignUInt64ToString(asQWORD i, string &dest) +{ + ostringstream stream; + stream << i; + dest = stream.str(); + return dest; +} + +static string &AddAssignUInt64ToString(asQWORD i, string &dest) +{ + ostringstream stream; + stream << i; + dest += stream.str(); + return dest; +} + +static string AddStringUInt64(const string &str, asQWORD i) +{ + ostringstream stream; + stream << i; + return str + stream.str(); +} + +static string AddInt64String(asINT64 i, const string &str) +{ + ostringstream stream; + stream << i; + return stream.str() + str; +} + +static string &AssignInt64ToString(asINT64 i, string &dest) +{ + ostringstream stream; + stream << i; + dest = stream.str(); + return dest; +} + +static string &AddAssignInt64ToString(asINT64 i, string &dest) +{ + ostringstream stream; + stream << i; + dest += stream.str(); + return dest; +} + +static string AddStringInt64(const string &str, asINT64 i) +{ + ostringstream stream; + stream << i; + return str + stream.str(); +} + +static string AddUInt64String(asQWORD i, const string &str) +{ + ostringstream stream; + stream << i; + return stream.str() + str; +} + +static string &AssignDoubleToString(double f, string &dest) +{ + ostringstream stream; + stream << f; + dest = stream.str(); + return dest; +} + +static string &AddAssignDoubleToString(double f, string &dest) +{ + ostringstream stream; + stream << f; + dest += stream.str(); + return dest; +} + +static string &AssignFloatToString(float f, string &dest) +{ + ostringstream stream; + stream << f; + dest = stream.str(); + return dest; +} + +static string &AddAssignFloatToString(float f, string &dest) +{ + ostringstream stream; + stream << f; + dest += stream.str(); + return dest; +} + +static string &AssignBoolToString(bool b, string &dest) +{ + ostringstream stream; + stream << (b ? "true" : "false"); + dest = stream.str(); + return dest; +} + +static string &AddAssignBoolToString(bool b, string &dest) +{ + ostringstream stream; + stream << (b ? "true" : "false"); + dest += stream.str(); + return dest; +} + +static string AddStringDouble(const string &str, double f) +{ + ostringstream stream; + stream << f; + return str + stream.str(); +} + +static string AddDoubleString(double f, const string &str) +{ + ostringstream stream; + stream << f; + return stream.str() + str; +} + +static string AddStringFloat(const string &str, float f) +{ + ostringstream stream; + stream << f; + return str + stream.str(); +} + +static string AddFloatString(float f, const string &str) +{ + ostringstream stream; + stream << f; + return stream.str() + str; +} + +static string AddStringBool(const string &str, bool b) +{ + ostringstream stream; + stream << (b ? "true" : "false"); + return str + stream.str(); +} + +static string AddBoolString(bool b, const string &str) +{ + ostringstream stream; + stream << (b ? "true" : "false"); + return stream.str() + str; +} + +static char *StringCharAt(unsigned int i, string &str) +{ + if( i >= str.size() ) + { + // Set a script exception + asIScriptContext *ctx = asGetActiveContext(); + ctx->SetException("Out of range"); + + // Return a null pointer + return 0; + } + + return &str[i]; +} + +// AngelScript signature: +// int string::opCmp(const string &in) const +static int StringCmp(const string &a, const string &b) +{ + int cmp = 0; + if( a < b ) cmp = -1; + else if( a > b ) cmp = 1; + return cmp; +} + +// This function returns the index of the first position where the substring +// exists in the input string. If the substring doesn't exist in the input +// string -1 is returned. +// +// AngelScript signature: +// int string::findFirst(const string &in sub, uint start = 0) const +static int StringFindFirst(const string &sub, asUINT start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.find(sub, start); +} + +// This function returns the index of the last position where the substring +// exists in the input string. If the substring doesn't exist in the input +// string -1 is returned. +// +// AngelScript signature: +// int string::findLast(const string &in sub, int start = -1) const +static int StringFindLast(const string &sub, int start, const string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + return (int)str.rfind(sub, (size_t)start); +} + +// AngelScript signature: +// uint string::length() const +static asUINT StringLength(const string &str) +{ + // We don't register the method directly because the return type changes between 32bit and 64bit platforms + return (asUINT)str.length(); +} + + +// AngelScript signature: +// void string::resize(uint l) +static void StringResize(asUINT l, string &str) +{ + // We don't register the method directly because the argument types change between 32bit and 64bit platforms + str.resize(l); +} + +// AngelScript signature: +// string formatInt(int64 val, const string &in options, uint width) +static string formatInt(asINT64 value, const string &options, asUINT width) +{ + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; + + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; + +#ifdef _WIN32 + fmt += "*I64"; +#else +#ifdef _LP64 + fmt += "*l"; +#else + fmt += "*ll"; +#endif +#endif + + if( hexSmall ) fmt += "x"; + else if( hexLarge ) fmt += "X"; + else fmt += "d"; + + string buf; + buf.resize(width+30); +#if _MSC_VER >= 1400 && !defined(__S3E__) + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value); +#else + sprintf(&buf[0], fmt.c_str(), width, value); +#endif + buf.resize(strlen(&buf[0])); + + return buf; +} + +// AngelScript signature: +// string formatUInt(uint64 val, const string &in options, uint width) +static string formatUInt(asQWORD value, const string &options, asUINT width) +{ + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool hexSmall = options.find("h") != string::npos; + bool hexLarge = options.find("H") != string::npos; + + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; + +#ifdef _WIN32 + fmt += "*I64"; +#else +#ifdef _LP64 + fmt += "*l"; +#else + fmt += "*ll"; +#endif +#endif + + if( hexSmall ) fmt += "x"; + else if( hexLarge ) fmt += "X"; + else fmt += "u"; + + string buf; + buf.resize(width+30); +#if _MSC_VER >= 1400 && !defined(__S3E__) + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, value); +#else + sprintf(&buf[0], fmt.c_str(), width, value); +#endif + buf.resize(strlen(&buf[0])); + + return buf; +} + +// AngelScript signature: +// string formatFloat(double val, const string &in options, uint width, uint precision) +static string formatFloat(double value, const string &options, asUINT width, asUINT precision) +{ + bool leftJustify = options.find("l") != string::npos; + bool padWithZero = options.find("0") != string::npos; + bool alwaysSign = options.find("+") != string::npos; + bool spaceOnSign = options.find(" ") != string::npos; + bool expSmall = options.find("e") != string::npos; + bool expLarge = options.find("E") != string::npos; + + string fmt = "%"; + if( leftJustify ) fmt += "-"; + if( alwaysSign ) fmt += "+"; + if( spaceOnSign ) fmt += " "; + if( padWithZero ) fmt += "0"; + + fmt += "*.*"; + + if( expSmall ) fmt += "e"; + else if( expLarge ) fmt += "E"; + else fmt += "f"; + + string buf; + buf.resize(width+precision+50); +#if _MSC_VER >= 1400 && !defined(__S3E__) + // MSVC 8.0 / 2005 or newer + sprintf_s(&buf[0], buf.size(), fmt.c_str(), width, precision, value); +#else + sprintf(&buf[0], fmt.c_str(), width, precision, value); +#endif + buf.resize(strlen(&buf[0])); + + return buf; +} + +// AngelScript signature: +// int64 parseInt(const string &in val, uint base = 10, uint &out byteCount = 0) +static asINT64 parseInt(const string &val, asUINT base, asUINT *byteCount) +{ + // Only accept base 10 and 16 + if( base != 10 && base != 16 ) + { + if( byteCount ) *byteCount = 0; + return 0; + } + + const char *end = &val[0]; + + // Determine the sign + bool sign = false; + if( *end == '-' ) + { + sign = true; + end++; + } + else if( *end == '+' ) + end++; + + asINT64 res = 0; + if( base == 10 ) + { + while( *end >= '0' && *end <= '9' ) + { + res *= 10; + res += *end++ - '0'; + } + } + else if( base == 16 ) + { + while( (*end >= '0' && *end <= '9') || + (*end >= 'a' && *end <= 'f') || + (*end >= 'A' && *end <= 'F') ) + { + res *= 16; + if( *end >= '0' && *end <= '9' ) + res += *end++ - '0'; + else if( *end >= 'a' && *end <= 'f' ) + res += *end++ - 'a' + 10; + else if( *end >= 'A' && *end <= 'F' ) + res += *end++ - 'A' + 10; + } + } + + if( byteCount ) + *byteCount = asUINT(size_t(end - val.c_str())); + + if( sign ) + res = -res; + + return res; +} + +// AngelScript signature: +// double parseFloat(const string &in val, uint &out byteCount = 0) +double parseFloat(const string &val, asUINT *byteCount) +{ + char *end; + + // WinCE doesn't have setlocale. Some quick testing on my current platform + // still manages to parse the numbers such as "3.14" even if the decimal for the + // locale is ",". +#if !defined(_WIN32_WCE) && !defined(ANDROID) && !defined(__psp2__) + // Set the locale to C so that we are guaranteed to parse the float value correctly + char *orig = setlocale(LC_NUMERIC, 0); + setlocale(LC_NUMERIC, "C"); +#endif + + double res = strtod(val.c_str(), &end); + +#if !defined(_WIN32_WCE) && !defined(ANDROID) && !defined(__psp2__) + // Restore the locale + setlocale(LC_NUMERIC, orig); +#endif + + if( byteCount ) + *byteCount = asUINT(size_t(end - val.c_str())); + + return res; +} + +// This function returns a string containing the substring of the input string +// determined by the starting index and count of characters. +// +// AngelScript signature: +// string string::substr(uint start = 0, int count = -1) const +static string StringSubString(asUINT start, int count, const string &str) +{ + // Check for out-of-bounds + string ret; + if( start < str.length() && count != 0 ) + ret = str.substr(start, count); + + return ret; +} + +// String equality comparison. +// Returns true iff lhs is equal to rhs. +// +// For some reason gcc 4.7 has difficulties resolving the +// asFUNCTIONPR(operator==, (const string &, const string &) +// makro, so this wrapper was introduced as work around. +static bool StringEquals(const std::string& lhs, const std::string& rhs) +{ + return lhs == rhs; +} + +void RegisterStdString_Native(asIScriptEngine *engine) +{ + int r = 0; + UNUSED_VAR(r); + + // Register the string type +#if AS_CAN_USE_CPP11 + // With C++11 it is possible to use asGetTypeTraits to automatically determine the correct flags to use + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asGetTypeTraits()); assert( r >= 0 ); +#else + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); +#endif + +#if AS_USE_STRINGPOOL == 1 + // Register the string factory + r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 ); + + // Register the cleanup callback for the string pool + engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL); +#else + // Register the string factory + r = engine->RegisterStringFactory("string", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 ); +#endif + + // Register the object operator overloads + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asMETHODPR(string, operator =, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); + // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails + r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); +// r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asMETHODPR(string, operator+=, (const string&), string&), asCALL_THISCALL); assert( r >= 0 ); + + // Need to use a wrapper for operator== otherwise gcc 4.7 fails to compile + r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTIONPR(StringEquals, (const string &, const string &), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTIONPR(operator +, (const string &, const string &), string), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + + // The string length can be accessed through methods or through virtual property + r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResize), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM, otherwise the linker fails +// r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asMETHOD(string, empty), asCALL_THISCALL); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + // Register the index operator, both as a mutator and as an inspector + // Note that we don't register the operator[] directly, as it doesn't do bounds checking + r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + // Automatic conversion from values + r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddStringDouble), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDoubleString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddStringFloat), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloatString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddStringInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt64ToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddStringUInt64), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt64String), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBoolToString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddStringBool), asCALL_CDECL_OBJFIRST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBoolString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + // Utilities + r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + + r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat), asCALL_CDECL); assert(r >= 0); + +#if AS_USE_STLNAMES == 1 + // Same as length + r = engine->RegisterObjectMethod("string", "uint size() const", asFUNCTION(StringLength), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as isEmpty + r = engine->RegisterObjectMethod("string", "bool empty() const", asFUNCTION(StringIsEmpty), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as findFirst + r = engine->RegisterObjectMethod("string", "int find(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST); assert( r >= 0 ); + // Same as findLast + r = engine->RegisterObjectMethod("string", "int rfind(const string &in, int start = -1) const", asFUNCTION(StringFindLast), asCALL_CDECL_OBJLAST); assert( r >= 0 ); +#endif + + // TODO: Implement the following + // findFirstOf + // findLastOf + // findFirstNotOf + // findLastNotOf + // findAndReplace - replaces a text found in the string + // replaceRange - replaces a range of bytes in the string + // trim/trimLeft/trimRight + // multiply/times/opMul/opMul_r - takes the string and multiplies it n times, e.g. "-".multiply(5) returns "-----" + // parseUInt +} + +#if AS_USE_STRINGPOOL == 1 +static void StringFactoryGeneric(asIScriptGeneric *gen) +{ + asUINT length = gen->GetArgDWord(0); + const char *s = (const char*)gen->GetArgAddress(1); + + // Return a reference to a string + gen->SetReturnAddress(const_cast(&StringFactory(length, s))); +} +#else +static void StringFactoryGeneric(asIScriptGeneric *gen) +{ + asUINT length = gen->GetArgDWord(0); + const char *s = (const char*)gen->GetArgAddress(1); + + // Return a string value + new (gen->GetAddressOfReturnLocation()) string(StringFactory(length, s)); +} +#endif + +static void ConstructStringGeneric(asIScriptGeneric * gen) +{ + new (gen->GetObject()) string(); +} + +static void CopyConstructStringGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetArgObject(0)); + new (gen->GetObject()) string(*a); +} + +static void DestructStringGeneric(asIScriptGeneric * gen) +{ + string * ptr = static_cast(gen->GetObject()); + ptr->~string(); +} + +static void AssignStringGeneric(asIScriptGeneric *gen) +{ + string * a = static_cast(gen->GetArgObject(0)); + string * self = static_cast(gen->GetObject()); + *self = *a; + gen->SetReturnAddress(self); +} + +static void AddAssignStringGeneric(asIScriptGeneric *gen) +{ + string * a = static_cast(gen->GetArgObject(0)); + string * self = static_cast(gen->GetObject()); + *self += *a; + gen->SetReturnAddress(self); +} + +static void StringEqualsGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); + *(bool*)gen->GetAddressOfReturnLocation() = (*a == *b); +} + +static void StringCmpGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); + + int cmp = 0; + if( *a < *b ) cmp = -1; + else if( *a > *b ) cmp = 1; + + *(int*)gen->GetAddressOfReturnLocation() = cmp; +} + +static void StringAddGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + string * b = static_cast(gen->GetArgAddress(0)); + string ret_val = *a + *b; + gen->SetReturnObject(&ret_val); +} + +static void StringLengthGeneric(asIScriptGeneric * gen) +{ + string * self = static_cast(gen->GetObject()); + *static_cast(gen->GetAddressOfReturnLocation()) = (asUINT)self->length(); +} + +static void StringIsEmptyGeneric(asIScriptGeneric * gen) +{ + string * self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringIsEmpty(*self); +} + +static void StringResizeGeneric(asIScriptGeneric * gen) +{ + string * self = static_cast(gen->GetObject()); + self->resize(*static_cast(gen->GetAddressOfArg(0))); +} + +static void StringFindFirst_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindFirst(*find, start, *self); +} + +static void StringFindLast_Generic(asIScriptGeneric * gen) +{ + string *find = reinterpret_cast(gen->GetArgAddress(0)); + asUINT start = gen->GetArgDWord(1); + string *self = reinterpret_cast(gen->GetObject()); + *reinterpret_cast(gen->GetAddressOfReturnLocation()) = StringFindLast(*find, start, *self); +} + +static void formatInt_Generic(asIScriptGeneric * gen) +{ + asINT64 val = gen->GetArgQWord(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + new(gen->GetAddressOfReturnLocation()) string(formatInt(val, *options, width)); +} + +static void formatUInt_Generic(asIScriptGeneric * gen) +{ + asQWORD val = gen->GetArgQWord(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + new(gen->GetAddressOfReturnLocation()) string(formatUInt(val, *options, width)); +} + +static void formatFloat_Generic(asIScriptGeneric *gen) +{ + double val = gen->GetArgDouble(0); + string *options = reinterpret_cast(gen->GetArgAddress(1)); + asUINT width = gen->GetArgDWord(2); + asUINT precision = gen->GetArgDWord(3); + new(gen->GetAddressOfReturnLocation()) string(formatFloat(val, *options, width, precision)); +} + +static void parseInt_Generic(asIScriptGeneric *gen) +{ + string *str = reinterpret_cast(gen->GetArgAddress(0)); + asUINT base = gen->GetArgDWord(1); + asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(2)); + gen->SetReturnQWord(parseInt(*str,base,byteCount)); +} + +static void parseFloat_Generic(asIScriptGeneric *gen) +{ + string *str = reinterpret_cast(gen->GetArgAddress(0)); + asUINT *byteCount = reinterpret_cast(gen->GetArgAddress(1)); + gen->SetReturnDouble(parseFloat(*str,byteCount)); +} + +static void StringCharAtGeneric(asIScriptGeneric * gen) +{ + unsigned int index = gen->GetArgDWord(0); + string * self = static_cast(gen->GetObject()); + + if (index >= self->size()) + { + // Set a script exception + asIScriptContext *ctx = asGetActiveContext(); + ctx->SetException("Out of range"); + + gen->SetReturnAddress(0); + } + else + { + gen->SetReturnAddress(&(self->operator [](index))); + } +} + +static void AssignInt2StringGeneric(asIScriptGeneric *gen) +{ + asINT64 *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); +} + +static void AssignUInt2StringGeneric(asIScriptGeneric *gen) +{ + asQWORD *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); +} + +static void AssignDouble2StringGeneric(asIScriptGeneric *gen) +{ + double *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); +} + +static void AssignFloat2StringGeneric(asIScriptGeneric *gen) +{ + float *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self = sstr.str(); + gen->SetReturnAddress(self); +} + +static void AssignBool2StringGeneric(asIScriptGeneric *gen) +{ + bool *a = static_cast(gen->GetAddressOfArg(0)); + string *self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false"); + *self = sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddAssignDouble2StringGeneric(asIScriptGeneric * gen) +{ + double * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddAssignFloat2StringGeneric(asIScriptGeneric * gen) +{ + float * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddAssignInt2StringGeneric(asIScriptGeneric * gen) +{ + asINT64 * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddAssignUInt2StringGeneric(asIScriptGeneric * gen) +{ + asQWORD * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a; + *self += sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddAssignBool2StringGeneric(asIScriptGeneric * gen) +{ + bool * a = static_cast(gen->GetAddressOfArg(0)); + string * self = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false"); + *self += sstr.str(); + gen->SetReturnAddress(self); +} + +static void AddString2DoubleGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + double * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddString2FloatGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + float * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddString2IntGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + asINT64 * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddString2UIntGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + asQWORD * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddString2BoolGeneric(asIScriptGeneric * gen) +{ + string * a = static_cast(gen->GetObject()); + bool * b = static_cast(gen->GetAddressOfArg(0)); + std::stringstream sstr; + sstr << *a << (*b ? "true" : "false"); + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddDouble2StringGeneric(asIScriptGeneric * gen) +{ + double* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddFloat2StringGeneric(asIScriptGeneric * gen) +{ + float* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddInt2StringGeneric(asIScriptGeneric * gen) +{ + asINT64* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddUInt2StringGeneric(asIScriptGeneric * gen) +{ + asQWORD* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << *a << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void AddBool2StringGeneric(asIScriptGeneric * gen) +{ + bool* a = static_cast(gen->GetAddressOfArg(0)); + string * b = static_cast(gen->GetObject()); + std::stringstream sstr; + sstr << (*a ? "true" : "false") << *b; + std::string ret_val = sstr.str(); + gen->SetReturnObject(&ret_val); +} + +static void StringSubString_Generic(asIScriptGeneric *gen) +{ + // Get the arguments + string *str = (string*)gen->GetObject(); + asUINT start = *(int*)gen->GetAddressOfArg(0); + int count = *(int*)gen->GetAddressOfArg(1); + + // Return the substring + new(gen->GetAddressOfReturnLocation()) string(StringSubString(start, count, *str)); +} + +void RegisterStdString_Generic(asIScriptEngine *engine) +{ + int r = 0; + UNUSED_VAR(r); + + // Register the string type + r = engine->RegisterObjectType("string", sizeof(string), asOBJ_VALUE | asOBJ_APP_CLASS_CDAK); assert( r >= 0 ); + +#if AS_USE_STRINGPOOL == 1 + // Register the string factory + r = engine->RegisterStringFactory("const string &", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 ); + + // Register the cleanup callback for the string pool + engine->SetEngineUserDataCleanupCallback(CleanupEngineStringPool, STRING_POOL); +#else + // Register the string factory + r = engine->RegisterStringFactory("string", asFUNCTION(StringFactoryGeneric), asCALL_GENERIC); assert( r >= 0 ); +#endif + + // Register the object operator overloads + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT, "void f(const string &in)", asFUNCTION(CopyConstructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asFUNCTION(AssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignStringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTION(StringEqualsGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmpGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(const string &in) const", asFUNCTION(StringAddGeneric), asCALL_GENERIC); assert( r >= 0 ); + + // Register the object methods + r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "uint get_length() const", asFUNCTION(StringLengthGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "void set_length(uint)", asFUNCTION(StringResizeGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "bool isEmpty() const", asFUNCTION(StringIsEmptyGeneric), asCALL_GENERIC); assert( r >= 0 ); + + // Register the index operator, both as a mutator and as an inspector + r = engine->RegisterObjectMethod("string", "uint8 &opIndex(uint)", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "const uint8 &opIndex(uint) const", asFUNCTION(StringCharAtGeneric), asCALL_GENERIC); assert( r >= 0 ); + + // Automatic conversion from values + r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(double) const", asFUNCTION(AddString2DoubleGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const", asFUNCTION(AddDouble2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(float) const", asFUNCTION(AddString2FloatGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const", asFUNCTION(AddFloat2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(int64)", asFUNCTION(AssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)", asFUNCTION(AddAssignInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(int64) const", asFUNCTION(AddString2IntGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const", asFUNCTION(AddInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)", asFUNCTION(AssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)", asFUNCTION(AddAssignUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const", asFUNCTION(AddString2UIntGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const", asFUNCTION(AddUInt2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string &opAssign(bool)", asFUNCTION(AssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)", asFUNCTION(AddAssignBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd(bool) const", asFUNCTION(AddString2BoolGeneric), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const", asFUNCTION(AddBool2StringGeneric), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterObjectMethod("string", "string substr(uint start = 0, int count = -1) const", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findFirst(const string &in, uint start = 0) const", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert( r >= 0 ); + r = engine->RegisterObjectMethod("string", "int findLast(const string &in, int start = -1) const", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert( r >= 0 ); + + r = engine->RegisterGlobalFunction("string formatInt(int64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatUInt(uint64 val, const string &in options = \"\", uint width = 0)", asFUNCTION(formatUInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string formatFloat(double val, const string &in options = \"\", uint width = 0, uint precision = 0)", asFUNCTION(formatFloat_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint base = 10, uint &out byteCount = 0)", asFUNCTION(parseInt_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("double parseFloat(const string &in, uint &out byteCount = 0)", asFUNCTION(parseFloat_Generic), asCALL_GENERIC); assert(r >= 0); +} + +void RegisterStdString(asIScriptEngine * engine) +{ + if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) + RegisterStdString_Generic(engine); + else + RegisterStdString_Native(engine); +} + +END_AS_NAMESPACE + + + + diff --git a/src/angelscript/scriptstdstring/scriptstdstring.h b/src/angelscript/scriptstdstring/scriptstdstring.h new file mode 100644 index 0000000000..11181a0fba --- /dev/null +++ b/src/angelscript/scriptstdstring/scriptstdstring.h @@ -0,0 +1,53 @@ +// +// Script std::string +// +// This function registers the std::string type with AngelScript to be used as the default string type. +// +// The string type is registered as a value type, thus may have performance issues if a lot of +// string operations are performed in the script. However, for relatively few operations, this should +// not cause any problem for most applications. +// + +#ifndef SCRIPTSTDSTRING_H +#define SCRIPTSTDSTRING_H + +#ifndef ANGELSCRIPT_H +// Avoid having to inform include path if header is already include before +#include +#endif + +#include + +//--------------------------- +// Compilation settings +// + +// The use of the string pool can improve performance quite drastically +// for scripts that work with a lot of literal string constants. +// +// 1 = on +// 0 = off + +#ifndef AS_USE_STRINGPOOL +#define AS_USE_STRINGPOOL 1 +#endif + +// Sometimes it may be desired to use the same method names as used by C++ STL. +// This may for example reduce time when converting code from script to C++ or +// back. +// +// 0 = off +// 1 = on + +#ifndef AS_USE_STLNAMES +#define AS_USE_STLNAMES 0 +#endif + +BEGIN_AS_NAMESPACE + +void RegisterStdString(asIScriptEngine *engine); +void RegisterStdStringUtils(asIScriptEngine *engine); + +END_AS_NAMESPACE + +#endif diff --git a/src/angelscript/scriptstdstring/scriptstdstring_utils.cpp b/src/angelscript/scriptstdstring/scriptstdstring_utils.cpp new file mode 100644 index 0000000000..7b5b91950a --- /dev/null +++ b/src/angelscript/scriptstdstring/scriptstdstring_utils.cpp @@ -0,0 +1,129 @@ +#include +#include "scriptstdstring.h" +#include "../scriptarray/scriptarray.h" +#include +#include + +using namespace std; + +BEGIN_AS_NAMESPACE + +// This function takes an input string and splits it into parts by looking +// for a specified delimiter. Example: +// +// string str = "A|B||D"; +// array@ array = str.split("|"); +// +// The resulting array has the following elements: +// +// {"A", "B", "", "D"} +// +// AngelScript signature: +// array@ string::split(const string &in delim) const +static CScriptArray *StringSplit(const string &delim, const string &str) +{ + // Obtain a pointer to the engine + asIScriptContext *ctx = asGetActiveContext(); + asIScriptEngine *engine = ctx->GetEngine(); + + // TODO: This should only be done once + // TODO: This assumes that CScriptArray was already registered + asIObjectType *arrayType = engine->GetObjectTypeByDecl("array"); + + // Create the array object + CScriptArray *array = CScriptArray::Create(arrayType); + + // Find the existence of the delimiter in the input string + int pos = 0, prev = 0, count = 0; + while( (pos = (int)str.find(delim, prev)) != (int)string::npos ) + { + // Add the part to the array + array->Resize(array->GetSize()+1); + ((string*)array->At(count))->assign(&str[prev], pos-prev); + + // Find the next part + count++; + prev = pos + (int)delim.length(); + } + + // Add the remaining part + array->Resize(array->GetSize()+1); + ((string*)array->At(count))->assign(&str[prev]); + + return array; +} + +static void StringSplit_Generic(asIScriptGeneric *gen) +{ + // Get the arguments + string *str = (string*)gen->GetObject(); + string *delim = *(string**)gen->GetAddressOfArg(0); + + // Return the array by handle + *(CScriptArray**)gen->GetAddressOfReturnLocation() = StringSplit(*delim, *str); +} + + + +// This function takes as input an array of string handles as well as a +// delimiter and concatenates the array elements into one delimited string. +// Example: +// +// array array = {"A", "B", "", "D"}; +// string str = join(array, "|"); +// +// The resulting string is: +// +// "A|B||D" +// +// AngelScript signature: +// string join(const array &in array, const string &in delim) +static string StringJoin(const CScriptArray &array, const string &delim) +{ + // Create the new string + string str = ""; + if( array.GetSize() ) + { + int n; + for( n = 0; n < (int)array.GetSize() - 1; n++ ) + { + str += *(string*)array.At(n); + str += delim; + } + + // Add the last part + str += *(string*)array.At(n); + } + + return str; +} + +static void StringJoin_Generic(asIScriptGeneric *gen) +{ + // Get the arguments + CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(0); + string *delim = *(string**)gen->GetAddressOfArg(1); + + // Return the string + new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim)); +} + +// This is where the utility functions are registered. +// The string type must have been registered first. +void RegisterStdStringUtils(asIScriptEngine *engine) +{ + int r; + + if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") ) + { + r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0); + r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0); + } + else + { + r = engine->RegisterObjectMethod("string", "array@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0); + r = engine->RegisterGlobalFunction("string join(const array &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0); + } +} + +END_AS_NAMESPACE diff --git a/src/angelscript/util.cpp b/src/angelscript/util.cpp new file mode 100644 index 0000000000..1480da3c7b --- /dev/null +++ b/src/angelscript/util.cpp @@ -0,0 +1,533 @@ +#include +#include "util.h" +#include "aszc.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void asSFX(int sound, int x) +{ + sfx(sound, pan(x)); +} + +void asStopSFX(int sound) +{ + stop_sfx(sound); +} + +bool asQuestRuleEnabled(int rule) +{ + return get_bit(quest_rules, rule); +} + +int getSpriteTile(int spr) +{ + return wpnsbuf[spr].tile; +} + +bool asIsWater(int pos) +{ + return iswater(tmpscr->data[pos]); +} + +// guygrid[] tracks how long it's been since a combo spawned an enemy, I think +void asSetGuyGridAt(int x, int y, int value) +{ + guygrid[(y&0xF0)+(x>>4)]=value; +} + +void asChangeCounter(int id, short value) +{ + game->change_counter(value, id); +} + +void asChangeDCounter(int id, short value) +{ + game->change_dcounter(value, id); +} + +int asGetGeneric(int id) +{ + return game->get_generic(id); +} + +void asSetLevelItem(int level, int item) +{ + game->lvlitems[level]|=item; +} + +int asGetGravity() +{ + return zinit.gravity; +} + +int asGetTerminalVelocity() +{ + return zinit.terminalv; +} + +void asDecGuyCount(int screen) +{ + game->guys[screen]-=1; +} + + +mapscr* asGetTmpscr(int idx) +{ + return &tmpscr[idx]; +} + +mapscr* asGetTmpscr2(int idx) +{ + return &tmpscr2[idx]; +} + +mapscr* asGetTmpscr3(int idx) +{ + return &tmpscr3[idx]; +} + + +enum +{ + WPNPROP_TILE, WPNPROP_CSETS, WPNPROP_FRAMES +}; + +int asGetWeaponProp(int id, int prop) +{ + wpndata& data=wpnsbuf[id]; + + switch(prop) + { + case WPNPROP_TILE: + return data.tile; + case WPNPROP_CSETS: + return data.csets; + case WPNPROP_FRAMES: + return data.frames; + default: + return 0; + } +} + +enum +{ + COMBOPROP_TYPE +}; + +int asGetComboProp(int id, int prop) +{ + newcombo& combo=combobuf[id]; + + switch(prop) + { + case COMBOPROP_TYPE: + return combo.type; + default: + return 0; + } +} + +enum +{ + CCPROP_BLOCK_ENEMIES +}; + +int asGetComboClassProp(int type, int prop) +{ + comboclass& cc=combo_class_buf[type]; + + switch(prop) + { + case CCPROP_BLOCK_ENEMIES: + return cc.block_enemies; + default: + return 0; + } +} + +enum +{ + ITEMPROP_FAMILY, ITEMPROP_LEVEL, ITEMPROP_POWER, ITEMPROP_MAGIC, + ITEMPROP_TILE, ITEMPROP_CSETS, ITEMPROP_SOUND, ITEMPROP_FLAGS, + ITEMPROP_MISC1, ITEMPROP_WPN2, ITEMPROP_PICKUP_SCRIPT +}; + +int asGetItemProp(int id, int prop) +{ + itemdata& data=itemsbuf[id]; + + switch(prop) + { + case ITEMPROP_FAMILY: + return data.family; + case ITEMPROP_LEVEL: + return data.fam_type; + case ITEMPROP_POWER: + return data.power; + case ITEMPROP_MAGIC: + return data.magic; + case ITEMPROP_TILE: + return data.tile; + case ITEMPROP_CSETS: + return data.csets; + case ITEMPROP_SOUND: + return data.usesound; + case ITEMPROP_FLAGS: + return data.flags; + case ITEMPROP_MISC1: + return data.misc1; + case ITEMPROP_WPN2: + return data.wpn2; + case ITEMPROP_PICKUP_SCRIPT: + return data.collect_script; + default: + return 0; + } +} + +void asSetItem(int id, bool value) +{ + game->set_item(id, value); +} + + + +asIScriptObject* asGetGuyObject(int index) +{ + asIScriptObject* obj=guys.spr(index)->getScriptObject(); + obj->AddRef(); + return obj; +} + +int asNumGuys() +{ + return guys.Count(); +} + +#define GUYPROP_FAMILY 0 +#define GUYPROP_HP 1 +#define GUYPROP_STEP 2 +#define GUYPROP_MISC2 3 +#define GUYPROP_MISC9 4 +#define GUYPROP_MISC10 5 +#define GUYPROP_FLAGS2 6 +#define GUYPROP_BOSSPAL 7 + +int asGetGuyProp(int id, int prop) +{ + const guydata& gd=guysbuf[id&0xFFF]; + + switch(prop) + { + case GUYPROP_FAMILY: + return gd.family; + case GUYPROP_HP: + return gd.hp; + case GUYPROP_STEP: + return gd.step; + case GUYPROP_MISC2: + return gd.misc2; + case GUYPROP_MISC9: + return gd.misc9; + case GUYPROP_MISC10: + return gd.misc10; + case GUYPROP_FLAGS2: + return gd.flags2; + case GUYPROP_BOSSPAL: + return gd.bosspal; + default: + return 0; + } +} + +void asSwapGuys(int index1, int index2) +{ + guys.swap(index1, index2); +} + + +asIScriptObject* asGetItemObject(int index) +{ + asIScriptObject* obj=items.spr(index)->getScriptObject(); + obj->AddRef(); + return obj; +} + +int asNumItems() +{ + return items.Count(); +} + +void asDeleteItem(int index) +{ + items.del(index); +} + + +asIScriptObject* asGetLwpnObject(int index) +{ + asIScriptObject* obj=Lwpns.spr(index)->getScriptObject(); + obj->AddRef(); + return obj; +} + +int asNumLwpns() +{ + return Lwpns.Count(); +} + + +asIScriptObject* asGetEwpnObject(int index) +{ + asIScriptObject* obj=Ewpns.spr(index)->getScriptObject(); + obj->AddRef(); + return obj; +} + +int asNumEwpns() +{ + return Ewpns.Count(); +} + +void asDeleteEwpn(int index) +{ + Ewpns.del(index); +} + + +void asPlaceItem(int x, int y, int id, int pickupFlags, int clk) +{ + // Not the same as additem() - doesn't check qr_NOITEMOFFSET + items.add(new item(fix(x), fix(y), fix(0), id, pickupFlags, clk)); +} + + +void asAddDecoration(int type, int x, int y) +{ + switch(type) + { + case dBUSHLEAVES: + decorations.add(new dBushLeaves(fix(x), fix(y), dBUSHLEAVES, 0)); + break; + + case dFLOWERCLIPPINGS: + decorations.add(new dFlowerClippings(fix(x), fix(y), dFLOWERCLIPPINGS, 0)); + break; + + case dGRASSCLIPPINGS: + decorations.add(new dGrassClippings(fix(x), fix(y), dGRASSCLIPPINGS, 0)); + break; + + case dHAMMERSMACK: + decorations.add(new dHammerSmack(fix(x), fix(y), dHAMMERSMACK, 0)); + break; + } +} + + +void asMoveChainLinks(int dx, int dy) +{ + for(int i=0; ix+=dx; + chainlinks.spr(i)->y+=dy; + } +} + +bool asInputUp() +{ + return control_state[0]; +} + +bool asInputDown() +{ + return control_state[1]; +} + +bool asInputLeft() +{ + return control_state[2]; +} + +bool asInputRight() +{ + return control_state[3]; +} + +bool asCAbtn() +{ + return control_state[4]; +} + +bool asCBbtn() +{ + return control_state[5]; +} + +bool asCSbtn() +{ + return control_state[6]; +} + +bool asCMbtn() +{ + return key[KEY_ESC]||joybtn(Mbtn); +} + +bool asCLbtn() +{ + return control_state[7]; +} + +bool asCRbtn() +{ + return control_state[8]; +} + +bool asCPbtn() +{ + return control_state[9]; +} + +bool asCEx1btn() +{ + return control_state[10]; +} + +bool asCEx2btn() +{ + return control_state[11]; +} + +bool asCEx3btn() +{ + return control_state[12]; +} + +bool asCEx4btn() +{ + return control_state[13]; +} + +bool asInputAxisUp() +{ + return control_state[14]; +} + +bool asInputAxisDown() +{ + return control_state[15]; +} + +bool asInputAxisLeft() +{ + return control_state[16]; +} + +bool asInputAxisRight() +{ + return control_state[17]; +} + +bool asRUp() +{ + return rButton(Up,Udown); +} + +bool asRDown() +{ + return rButton(Down,Ddown); +} + +bool asRLeft() +{ + return rButton(Left,Ldown); +} + +bool asRRight() +{ + return rButton(Right,Rdown); +} + +bool asRAbtn() +{ + return rButton(cAbtn,Adown); +} + +bool asRBbtn() +{ + return rButton(cBbtn,Bdown); +} + +bool asRSbtn() +{ + return rButton(cSbtn,Sdown); +} + +bool asRMbtn() +{ + return rButton(cMbtn,Mdown); +} + +bool asRLbtn() +{ + return rButton(cLbtn,LBdown); +} + +bool asRRbtn() +{ + return rButton(cRbtn,RBdown); +} + +bool asRPbtn() +{ + return rButton(cPbtn,Pdown); +} + +bool asREx1btn() +{ + return rButton(cEx1btn,Ex1down); +} + +bool asREx2btn() +{ + return rButton(cEx2btn,Ex2down); +} + +bool asREx3btn() +{ + return rButton(cEx3btn,Ex3down); +} + +bool asREx4btn() +{ + return rButton(cEx4btn,Ex4down); +} + +bool asRAxisUp() +{ + return rButton(AxisUp,AUdown); +} + +bool asRAxisDown() +{ + return rButton(AxisDown,ADdown); +} + +bool asRAxisLeft() +{ + return rButton(AxisLeft,ALdown); +} + +bool asRAxisRight() +{ + return rButton(AxisRight,ARdown); +} diff --git a/src/angelscript/util.h b/src/angelscript/util.h new file mode 100644 index 0000000000..2531161fa1 --- /dev/null +++ b/src/angelscript/util.h @@ -0,0 +1,105 @@ +#ifndef _ZC_ANGELSCRIPT_UTIL_H_ +#define _ZC_ANGELSCRIPT_UTIL_H_ + +#include +class asIScriptObject; +class enemy; +struct mapscr; + +// Various functions for scripts. + +void asSFX(int sound, int x); +void asStopSFX(int sound); +bool asQuestRuleEnabled(int rule); +int getSpriteTile(int spr); +bool asIsWater(int pos); +void asSetGuyGridAt(int x, int y, int value); +void asChangeCounter(int id, short value); +void asChangeDCounter(int id, short value); +int asGetGeneric(int id); +void asSetLevelItem(int level, int item); +int asGetGravity(); +int asGetTerminalVelocity(); +void asDecGuyCount(int screen); + +// mapscr access +mapscr* asGetTmpscr(int idx); +mapscr* asGetTmpscr2(int idx); +mapscr* asGetTmpscr3(int idx); + +// Item stuff +int asGetItemProp(int id, int prop); +void asSetItem(int id, bool value); + +// Weapon stuff +int asGetWeaponProp(int id, int prop); + +// Combo stuff +int asGetComboProp(int id, int prop); +int asGetComboClassProp(int type, int prop); + +// Sprite list access +asIScriptObject* asGetGuyObject(int index); +int asNumGuys(); +int asGetGuyProp(int id, int prop); +void asSwapGuys(int index1, int index2); + +asIScriptObject* asGetItemObject(int index); +int asNumItems(); +void asDeleteItem(int index); + +asIScriptObject* asGetLwpnObject(int index); +int asNumLwpns(); + +asIScriptObject* asGetEwpnObject(int index); +int asNumEwpns(); +void asDeleteEwpn(int index); + +void asPlaceItem(int x, int y, int id, int pickupFlags, int clk); + +void asAddDecoration(int type, int x, int y); + +void asMoveChainLinks(int dx, int dy); + +// Input +bool asInputUp(); +bool asInputDown(); +bool asInputLeft(); +bool asInputRight(); +bool asCAbtn(); +bool asCBbtn(); +bool asCSbtn(); +bool asCMbtn(); +bool asCLbtn(); +bool asCRbtn(); +bool asCPbtn(); +bool asCEx1btn(); +bool asCEx2btn(); +bool asCEx3btn(); +bool asCEx4btn(); +bool asInputAxisUp(); +bool asInputAxisDown(); +bool asInputAxisLeft(); +bool asInputAxisRight(); + +bool asRUp(); +bool asRDown(); +bool asRLeft(); +bool asRRight(); +bool asRAbtn(); +bool asRBbtn(); +bool asRSbtn(); +bool asRMbtn(); +bool asRLbtn(); +bool asRRbtn(); +bool asRPbtn(); +bool asREx1btn(); +bool asREx2btn(); +bool asREx3btn(); +bool asREx4btn(); +bool asRAxisUp(); +bool asRAxisDown(); +bool asRAxisLeft(); +bool asRAxisRight(); + +#endif diff --git a/src/build_modules/gui_module.cpp b/src/build_modules/gui_module.cpp new file mode 100644 index 0000000000..4c84246d7c --- /dev/null +++ b/src/build_modules/gui_module.cpp @@ -0,0 +1,44 @@ + +#include "precompiled.h" + + +#define BOOST_FUNCTION_MAX_ARGS 4 +#include +#include + +#include "gui/alert.cpp" +#include "gui/contents.cpp" +#include "gui/controller.cpp" +#include "gui/dialog.cpp" +#include "gui/manager.cpp" + +#include "gui/allegro/bitmap.cpp" +#include "gui/allegro/button.cpp" +#include "gui/allegro/checkbox.cpp" +#include "gui/allegro/column.cpp" +#include "gui/allegro/comboBox.cpp" +#include "gui/allegro/controller.cpp" +#include "gui/allegro/dummy.cpp" +#include "gui/allegro/editableText.cpp" +#include "gui/allegro/factory.cpp" +#include "gui/allegro/frame.cpp" +#include "gui/allegro/list.cpp" +#include "gui/allegro/renderer.cpp" +#include "gui/allegro/row.cpp" +#include "gui/allegro/scrollbar.cpp" +#include "gui/allegro/scrollingPane.cpp" +#include "gui/allegro/serialContainer.cpp" +#include "gui/allegro/standardWidget.cpp" +#include "gui/allegro/tab.cpp" +#include "gui/allegro/tabBar.cpp" +#include "gui/allegro/tabPanel.cpp" +#include "gui/allegro/text.cpp" +#include "gui/allegro/textField.cpp" +#include "gui/allegro/common.cpp" +#include "gui/allegro/window.cpp" + + + + + + diff --git a/src/build_modules/zc_as_module.cpp b/src/build_modules/zc_as_module.cpp new file mode 100644 index 0000000000..9bbacfb22f --- /dev/null +++ b/src/build_modules/zc_as_module.cpp @@ -0,0 +1,11 @@ + + +#include "angelscript/aszc.cpp" +#include "angelscript/scriptData.cpp" +#include "angelscript/util.cpp" + +#include "angelscript/scriptbuilder/scriptbuilder.cpp" +#include "angelscript/scriptmath/scriptmath.cpp" +#include "angelscript/scriptstdstring/scriptstdstring.cpp" +#include "angelscript/scriptarray/scriptarray.cpp" + diff --git a/src/build_modules/zc_gui_module.cpp b/src/build_modules/zc_gui_module.cpp new file mode 100644 index 0000000000..406c88eeee --- /dev/null +++ b/src/build_modules/zc_gui_module.cpp @@ -0,0 +1,25 @@ + +#include "precompiled.h" + + +// gui +#include "zsys.cpp" +#include "precompiled.cpp" +#include "aglogo.cpp" +#include "colors.cpp" +#include "debug.cpp" +#include "decorations.cpp" +#include "editbox.cpp" +#include "EditboxModel.cpp" +#include "EditboxView.cpp" +#include "ending.cpp" +#include "matrix.cpp" +#include "pal.cpp" +#include "jwin.cpp" +#include "jwinfsel.cpp" +#include "tab_ctl.cpp" +#include "title.cpp" +#include "zc_custom.cpp" +#include "guiBitmapRenderer.cpp" + + diff --git a/src/build_modules/zc_module.cpp b/src/build_modules/zc_module.cpp new file mode 100644 index 0000000000..a5915cfd3d --- /dev/null +++ b/src/build_modules/zc_module.cpp @@ -0,0 +1,36 @@ + +#include "precompiled.h" + +#define BOOST_FUNCTION_MAX_ARGS 4 +#include +#include + +#define NOMINMAX + + +#include "zscriptversion.cpp" +#include "ffscript.cpp" +#include "ffc.cpp" +#include "refInfo.cpp" +#include "fontClass.cpp" +#include "gamedata.cpp" +#include "zelda.cpp" +#include "defdata.cpp" + +#include "qst.cpp" +#include "room.cpp" +#include "sound.cpp" + +#include "zc_init.cpp" +#include "zc_items.cpp" +#include "init.cpp" +#include "message.cpp" +#include "messageManager.cpp" +#include "messageRenderer.cpp" +#include "messageStream.cpp" +#include "messageList.cpp" +#include "screenFreezeState.cpp" +#include "screenWipe.cpp" + +#include "win32.cpp" + diff --git a/src/build_modules/zc_objects_module.cpp b/src/build_modules/zc_objects_module.cpp new file mode 100644 index 0000000000..9b364bca56 --- /dev/null +++ b/src/build_modules/zc_objects_module.cpp @@ -0,0 +1,24 @@ + + + +#include "sequence/sequence.cpp" +#include "sequence/gameOver.cpp" +#include "sequence/ganonIntro.cpp" +#include "sequence/getBigTriforce.cpp" +#include "sequence/getTriforce.cpp" +#include "sequence/potion.cpp" +#include "sequence/whistle.cpp" + + +#include "item/clock.cpp" +#include "item/dinsFire.cpp" +#include "item/faroresWind.cpp" +#include "item/hookshot.cpp" +#include "item/itemEffect.cpp" +#include "item/nayrusLove.cpp" + + + + + + diff --git a/src/build_modules/zc_sprite_module.cpp b/src/build_modules/zc_sprite_module.cpp new file mode 100644 index 0000000000..27ff6ef313 --- /dev/null +++ b/src/build_modules/zc_sprite_module.cpp @@ -0,0 +1,25 @@ + +#include "precompiled.h" + +#define BOOST_FUNCTION_MAX_ARGS 4 +#include +#include + + +// sprite +#include "zc_sprite.cpp" +#include "guys.cpp" +#include "weapons.cpp" +#include "link.cpp" +#include "linkZScriptInterface.cpp" +#include "linkHandler.cpp" +#include "particles.cpp" +#include "items.cpp" +#include "sprite.cpp" +#include "tiles.cpp" +#include "maps.cpp" +#include "script_drawing.cpp" +#include "enemyAttack.cpp" + + + diff --git a/src/build_modules/zc_subscreen_module.cpp b/src/build_modules/zc_subscreen_module.cpp new file mode 100644 index 0000000000..8cec332b7c --- /dev/null +++ b/src/build_modules/zc_subscreen_module.cpp @@ -0,0 +1,29 @@ + +#include "precompiled.h" + +#define USE_ENCRYPTION +//misc +//#include "callback.cpp" +#include "encryptionEnabled.cpp" +//#include "encryptionDisabled.cpp" + + +//subscreen +#include "subscr.cpp" +#include "zc_subscr.cpp" +#include "md5.cpp" + + +//sound +#include "midi.cpp" +#include "sfxAllegro.cpp" +#include "sfxClass.cpp" +#include "sfxManager.cpp" + + +// Some zc files requires zquest headers and that causes problems when unity building, +// so we keep them chained up in here and just feed them fish heads. +#include "gui.cpp" +#include "zc_sys.cpp" + +int zcmusic_bufsz = 64; \ No newline at end of file diff --git a/src/build_modules/zq_as_module.cpp b/src/build_modules/zq_as_module.cpp new file mode 100644 index 0000000000..933d3d27e1 --- /dev/null +++ b/src/build_modules/zq_as_module.cpp @@ -0,0 +1,17 @@ + + +#include "angelscript/scriptData.cpp" + + +#include "angelscript/scriptmath/scriptmath.cpp" + +#ifdef GetObject +#undef GetObject +#endif + +#include "angelscript/scriptstdstring/scriptstdstring.cpp" +#include "angelscript/scriptarray/scriptarray.cpp" + + +#include "angelscript/scriptbuilder/scriptbuilder.cpp" + diff --git a/src/build_modules/zq_dialog_module.cpp b/src/build_modules/zq_dialog_module.cpp new file mode 100644 index 0000000000..72560c50d2 --- /dev/null +++ b/src/build_modules/zq_dialog_module.cpp @@ -0,0 +1,22 @@ + +#include "precompiled.h" + +#define BOOST_FUNCTION_MAX_ARGS 4 +#include +#include + +#include "guiBitmapRenderer.cpp" +#include "messageList.cpp" + +#include "dialog/bitmap/tilePreview.cpp" +#include "dialog/bitmap/tileSelector.cpp" +#include "dialog/zquest/cheatEditor.cpp" +#include "dialog/zquest/paletteViewer.cpp" +#include "dialog/zquest/questRules.cpp" +#include "dialog/zquest/shopEditor.cpp" +#include "dialog/zquest/infoShopEditor.cpp" +#include "dialog/zquest/simpleListSelector.cpp" +#include "dialog/zquest/tileSelector.cpp" +#include "dialog/zquest/tileSelectorBackend.cpp" +#include "dialog/zquest/zscriptEditor.cpp" +#include "dialog/zquest/zscriptMain.cpp" diff --git a/src/build_modules/zq_gui_module.cpp b/src/build_modules/zq_gui_module.cpp new file mode 100644 index 0000000000..a40acbc601 --- /dev/null +++ b/src/build_modules/zq_gui_module.cpp @@ -0,0 +1,24 @@ + +#include "precompiled.h" + + +#define NOMINMAX + +#include "zq_class.cpp" +#include "zq_cset.cpp" +#include "zq_custom.cpp" +#include "zq_doors.cpp" +#include "zq_files.cpp" +#include "zq_init.cpp" +#include "zq_items.cpp" +#include "zq_misc.cpp" +//#include "zq_rules.cpp" +#include "zq_sprite.cpp" +#include "zq_subscr.cpp" +#include "zq_strings.cpp" +#include "zq_tiles.cpp" +#include "zqscale.cpp" +#include "zsys.cpp" + +//#include "ffc.cpp" + diff --git a/src/build_modules/zq_misc_module.cpp b/src/build_modules/zq_misc_module.cpp new file mode 100644 index 0000000000..9cc062fbb5 --- /dev/null +++ b/src/build_modules/zq_misc_module.cpp @@ -0,0 +1,32 @@ + +#include "precompiled.h" + +#define BOOST_FUNCTION_MAX_ARGS 4 +#include +#include + +#define NOMINMAX + + +#include "items.cpp" +#include "questReport.cpp" + +#include "ffasm.cpp" + +#include "zquest.cpp" +#include "jwin.cpp" + +#include "gui.cpp" +#include "jwinfsel.cpp" +#include "tab_ctl.cpp" +#include "tiles.cpp" + +#include "load_gif.cpp" +#include "win32.cpp" + + + + + + + diff --git a/src/build_modules/zq_module.cpp b/src/build_modules/zq_module.cpp new file mode 100644 index 0000000000..87a925a24e --- /dev/null +++ b/src/build_modules/zq_module.cpp @@ -0,0 +1,29 @@ + +//#include "precompiled.h" + +#define NOMINMAX + + +//#include "callback.cpp" +#include "colors.cpp" +#include "defdata.cpp" +#include "encryptionDisabled.cpp" +#include "editbox.cpp" +#include "EditboxModel.cpp" +#include "EditboxView.cpp" +#include "gamedata.cpp" + + +#include "midi.cpp" +#include "md5.cpp" +#include "particles.cpp" +#include "qst.cpp" +#include "save_gif.cpp" +#include "sprite.cpp" + +#include "Subscr.cpp" + +#include "zc_custom.cpp" + +#include "init.cpp" + diff --git a/src/build_modules/zq_script_module.cpp b/src/build_modules/zq_script_module.cpp new file mode 100644 index 0000000000..b17e0ad62d --- /dev/null +++ b/src/build_modules/zq_script_module.cpp @@ -0,0 +1,21 @@ + + + +#include "parser/AST.cpp" +#include "parser/BuildVisitors.cpp" +#include "parser/ByteCode.cpp" +#include "parser/DataStructs.cpp" +#include "parser/GlobalSymbols.cpp" +#include "parser/lex.yy.cpp" +#include "parser/ParseError.cpp" +#include "parser/ScriptParser.cpp" +#include "parser/SymbolVisitors.cpp" +#include "parser/TypeChecker.cpp" +#include "parser/UtilVisitors.cpp" +#include "parser/y.tab.cpp" + + + + + + diff --git a/src/colors.cpp b/src/colors.cpp new file mode 100644 index 0000000000..9a759196b9 --- /dev/null +++ b/src/colors.cpp @@ -0,0 +1,485 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// colors.cc +// +// Palette data for Zelda Classic. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "zc_alleg.h" +#include "colors.h" + +byte nes_pal[] = +{ + 31,31,31, // 0 + 0, 0,63, // 1 + 0, 0,47, // 2 + 17,10,47, // 3 + 37, 0,33, // 4 + 42, 0, 8, // 5 + 42, 4, 0, // 6 + 34, 5, 0, // 7 + 20,12, 0, // 8 + 0,30, 0, // 9 + 0,26, 0, // 10 + 0,22, 0, // 11 + 0,16,22, // 12 + 0, 0, 0, // 13 0D + 0, 0, 0, // 14 0E + 0, 0, 0, // 15 0F + 47,47,47, // 16 + 0,30,62, // 17 + 0,22,62, // 18 + 26,17,63, // 19 + 54, 0,51, // 20 + 57, 0,22, // 21 + 62,14, 0, // 22 + 57,23, 4, // 23 + 43,31, 0, // 24 + 0,46, 0, // 25 + 0,42, 0, // 26 + 0,42,17, // 27 + 0,34,34, // 28 + 0, 0, 0, // 29 + 0, 0, 0, // 30 + 0, 0, 0, // 31 + 62,62,62, // 32 + 15,47,63, // 33 + 26,34,63, // 34 + 38,30,62, // 35 + 62,30,62, // 36 + 62,22,38, // 37 + 62,30,22, // 38 + 63,40,17, // 39 + 62,46, 0, // 40 + 46,62, 6, // 41 + 22,54,21, // 42 + 22,62,38, // 43 + 0,58,54, // 44 + 30,30,30, // 45 + 0, 0, 0, // 46 + 0, 0, 0, // 47 + 63,63,63, // 48 ! + 41,57,63, // 49 + 52,52,62, // 50 + 54,46,62, // 51 + 62,46,62, // 52 + 62,41,48, // 53 + 60,52,44, // 54 + 63,56,42, // 55 + 62,54,30, // 56 + 54,62,30, // 57 + 46,62,46, // 58 + 46,62,54, // 59 + 0,63,63, // 60 + 62,54,62, // 61 + 0,54,50, // 62 + 31,63,63 // 63 +}; + +byte nes_colors[] = +{ + + // ---=== Main Palette ===--- + + // background + + 0x0F,0x30,0x00,0x12,0x0F, // cset 0 system colors (always the same) + 0x0F,0x16,0x27,0x36,0x0F, // cset 1 `' + + 0x0F,0x1A,0x37,0x12,0x0F, // cset 2 level colors + 0x0F,0x17,0x37,0x12,0x0F, // cset 3 `' + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 4 `' + + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 5 extra + + // foreground + + 0x0F,0x29,0x27,0x17,0x0F, // cset 6 system (6 = Link's colors) + 0x0F,0x02,0x22,0x30,0x0F, // cset 7 `' + 0x0F,0x16,0x27,0x30,0x0F, // cset 8 `' + 0x0F,0x0F,0x1C,0x16,0x0F, // cset 9 level sprites + + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 10 extras + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 11 `' + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 12 `' + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 13 `' + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 14 `' + + // ---=== Level Palettes ===--- + + // overworld (level 0) + 0x0F,0x1A,0x37,0x12,0x0F, // cset 2 normal + 0x0F,0x17,0x37,0x12,0x0F, // cset 3 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 4 + 0x0F,0x0F,0x1C,0x16,0x0F, // cset 9 + + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 2 fading #1 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 3 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 4 + + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 2 fading #2 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 3 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 4 + + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 2 fading #3 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 3 + 0x0F,0x0F,0x0F,0x0F,0x0F, // cset 4 + + // level 1 + 0x0F,0x0C,0x1C,0x2C,0x0F, + 0x0F,0x12,0x1C,0x2C,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0C,0x1C,0x2C,0x0F, + + 0x0F,0x0C,0x0C,0x1C,0x0F, + 0x0F,0x11,0x0C,0x1C,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0C,0x0C,0x0F, + 0x0F,0x02,0x0C,0x0C,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0C,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 2 + 0x0F,0x02,0x12,0x22,0x0F, + 0x0F,0x16,0x12,0x22,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x02,0x12,0x22,0x0F, + + 0x0F,0x02,0x02,0x12,0x0F, + 0x0F,0x17,0x02,0x12,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x02,0x02,0x0F, + 0x0F,0x07,0x02,0x02,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x02,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 3 + 0x0F,0x0B,0x1B,0x2B,0x0F, + 0x0F,0x16,0x1B,0x2B,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0B,0x1B,0x2B,0x0F, + + 0x0F,0x0B,0x0B,0x1B,0x0F, + 0x0F,0x17,0x0B,0x1B,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0B,0x0B,0x0F, + 0x0F,0x07,0x0B,0x0B,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0B,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 4 + 0x0F,0x08,0x18,0x28,0x0F, + 0x0F,0x12,0x18,0x28,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x18,0x28,0x0F, + + 0x0F,0x08,0x08,0x18,0x0F, + 0x0F,0x11,0x08,0x18,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x08,0x08,0x0F, + 0x0F,0x02,0x08,0x08,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x08,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 5 + 0x0F,0x0A,0x1A,0x2A,0x0F, + 0x0F,0x16,0x1A,0x2A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0A,0x1A,0x2A,0x0F, + + 0x0F,0x0A,0x0A,0x1A,0x0F, + 0x0F,0x17,0x0A,0x1A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0A,0x0A,0x0F, + 0x0F,0x07,0x0A,0x0A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 6 + 0x0F,0x08,0x18,0x28,0x0F, + 0x0F,0x16,0x18,0x28,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x08,0x18,0x28,0x0F, + + 0x0F,0x08,0x08,0x18,0x0F, + 0x0F,0x17,0x08,0x18,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x08,0x08,0x0F, + 0x0F,0x07,0x08,0x08,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x08,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 7 + 0x0F,0x0A,0x1A,0x2A,0x0F, + 0x0F,0x12,0x1A,0x2A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0A,0x1A,0x2A,0x0F, + + 0x0F,0x0A,0x0A,0x1A,0x0F, + 0x0F,0x11,0x0A,0x1A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0A,0x0A,0x0F, + 0x0F,0x02,0x0A,0x0A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0A,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 8 + 0x0F,0x00,0x10,0x20,0x0F, + 0x0F,0x22,0x10,0x20,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x00,0x10,0x30,0x0F, + + 0x0F,0x00,0x00,0x10,0x0F, + 0x0F,0x11,0x00,0x10,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x00,0x00,0x0F, + 0x0F,0x02,0x00,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // level 9 + 0x0F,0x00,0x10,0x20,0x0F, + 0x0F,0x16,0x10,0x20,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x10,0x30,0x0F, + + 0x0F,0x00,0x00,0x10,0x0F, + 0x0F,0x17,0x00,0x10,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x00,0x00,0x0F, + 0x0F,0x07,0x00,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // cave (10) + 0x0F,0x1A,0x37,0x12,0x0F, + 0x0F,0x07,0x0F,0x17,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x1C,0x16,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // passage way (11) + 0x0F,0x00,0x10,0x20,0x0F, + 0x0F,0x00,0x10,0x20,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x00,0x10,0x30,0x0F, + + 0x0F,0x00,0x00,0x10,0x0F, + 0x0F,0x00,0x00,0x10,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x00,0x00,0x0F, + 0x0F,0x0F,0x00,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x00,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // extra 1 (12) + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // extra 2 (13) + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // extra 3 (14) + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + // ---=== 30 Extra Sprite Palettes ===--- + + 0x0F,0x0A,0x29,0x30,0x0F, // aquamentus + 0x0F,0x2A,0x1A,0x0C,0x0F, // gleeok + 0x0F,0x17,0x27,0x30,0x0F, // digdogger + 0x0F,0x16,0x3E,0x3F,0x0F, // teal Ganon + 0x0F,0x07,0x17,0x30,0x0F, // brown Ganon + + 0x0F,0x27,0x06,0x16,0x0F, // dead Ganon + 0x0F,0x32,0x27,0x17,0x0F, // Link w/ blue ring + 0x0F,0x16,0x27,0x17,0x0F, // Link w/ red ring + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F, + 0x0F,0x0F,0x0F,0x0F,0x0F +}; + +// Global pointer to current color data used by "pal.cc" routines. +// Must be allocated to pdTOTAL*16 bytes before calling init_colordata(). +extern byte *colordata; + +/* create_zc_trans_table: + * Constructs a translucency color table for the specified palette. The + * r, g, and b parameters specifiy the solidity of each color component, + * ranging from 0 (totally transparent) to 255 (totally solid). If the + * callback function is not NULL, it will be called 256 times during the + * calculation, allowing you to display a progress indicator. + */ +void create_zc_trans_table(COLOR_MAP *table, AL_CONST PALETTE pal, int r, int g, int b) +{ + int tmp[768], *q; + int x, y, i, j, k; + unsigned char *p; + RGB c; + + for(x=0; x<256; x++) + { + tmp[x*3] = pal[x].r * (255-r) / 255; + tmp[x*3+1] = pal[x].g * (255-g) / 255; + tmp[x*3+2] = pal[x].b * (255-b) / 255; + } + + for(x=0; xdata[x]; + q = tmp; + + if(rgb_map) + { + for(y=0; ydata[c.r>>1][c.g>>1][c.b>>1]; + } + } + else + { + for(y=0; y +#include +#include "zc_alleg.h" + +static int trace_y=0; + +void trace_reset() +{ + trace_y=0; +} + +void trace(char *format,...) +{ + char buf[256]; + + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + + textout_ex(screen,font,buf,0,trace_y,1,0); + trace_y+=8; + + if(trace_y>=200) + trace_y=0; + + readkey(); +} + diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000000..6ccb2009cc --- /dev/null +++ b/src/debug.h @@ -0,0 +1,27 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// debug.h +// +// Misc debugging tools. +// +//-------------------------------------------------------- + +#ifndef _ZC_DEBUG_H_ +#define _ZC_DEBUG_H_ + +#include "zc_malloc.h" + +#ifdef _DEBUG + #include + #define ZCASSERT(x) assert(x) +#else + #define ZCASSERT(X) +#endif + +void trace_reset(); +void trace(char *format,...); + +#endif + diff --git a/src/decorations.cpp b/src/decorations.cpp new file mode 100644 index 0000000000..53f5b9ef8d --- /dev/null +++ b/src/decorations.cpp @@ -0,0 +1,666 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "sprite.h" +#include "decorations.h" +#include "zc_custom.h" +#include "zelda.h" +#include "zc_sys.h" +#include "maps.h" +#include "zsys.h" + +/***************************************/ +/******* Decoration Base Class *******/ +/***************************************/ + +decoration::decoration(fix X,fix Y,int Id,int Clk) : sprite() +{ + x=X; + y=Y; + id=Id; + clk=Clk; + misc = 0; + yofs = playing_field_offset - 2; + +} + +decoration::~decoration() {} + +/*******************************/ +/******* Decorations *******/ +/*******************************/ + +int dBushLeaves::ft[4][8][3]; +int dFlowerClippings::ft[4][8][3]; +int dGrassClippings::ft[3][4][4]; +int dHammerSmack::ft[2][4][3]; + +dBushLeaves::dBushLeaves(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ + ox=X; + oy=Y; + id=Id; + clk=Clk; + static bool initialized=false; + if(!initialized) + { + initialized=true; + + ft[0][0][0]=6; + ft[0][0][1]=6; + ft[0][0][2]=0; + ft[0][1][0]=6; + ft[0][1][1]=9; + ft[0][1][2]=0; + ft[0][2][0]=7; + ft[0][2][1]=11; + ft[0][2][2]=1; + ft[0][3][0]=7; + ft[0][3][1]=13; + ft[0][3][2]=0; + ft[0][4][0]=9; + ft[0][4][1]=15; + ft[0][4][2]=0; + ft[0][5][0]=10; + ft[0][5][1]=16; + ft[0][5][2]=0; + ft[0][6][0]=11; + ft[0][6][1]=18; + ft[0][6][2]=0; + ft[0][7][0]=4; + ft[0][7][1]=19; + ft[0][7][2]=1; + + ft[1][0][0]=-4; + ft[1][0][1]=3; + ft[1][0][2]=0; + ft[1][1][0]=-1; + ft[1][1][1]=4; + ft[1][1][2]=0; + ft[1][2][0]=0; + ft[1][2][1]=5; + ft[1][2][2]=0; + ft[1][3][0]=1; + ft[1][3][1]=5; + ft[1][3][2]=1; + ft[1][4][0]=-2; + ft[1][4][1]=5; + ft[1][4][2]=1; + ft[1][5][0]=-6; + ft[1][5][1]=5; + ft[1][5][2]=0; + ft[1][6][0]=-7; + ft[1][6][1]=4; + ft[1][6][2]=0; + ft[1][7][0]=-9; + ft[1][7][1]=2; + ft[1][7][2]=1; + + ft[2][0][0]=10; + ft[2][0][1]=2; + ft[2][0][2]=1; + ft[2][1][0]=7; + ft[2][1][1]=3; + ft[2][1][2]=1; + ft[2][2][0]=4; + ft[2][2][1]=5; + ft[2][2][2]=1; + ft[2][3][0]=5; + ft[2][3][1]=5; + ft[2][3][2]=0; + ft[2][4][0]=8; + ft[2][4][1]=9; + ft[2][4][2]=0; + ft[2][5][0]=9; + ft[2][5][1]=9; + ft[2][5][2]=0; + ft[2][6][0]=12; + ft[2][6][1]=9; + ft[2][6][2]=1; + ft[2][7][0]=6; + ft[2][7][1]=16; + ft[2][7][2]=0; + + ft[3][0][0]=4; + ft[3][0][1]=-4; + ft[3][0][2]=0; + ft[3][1][0]=4; + ft[3][1][1]=-6; + ft[3][1][2]=0; + ft[3][2][0]=2; + ft[3][2][1]=-7; + ft[3][2][2]=0; + ft[3][3][0]=1; + ft[3][3][1]=-8; + ft[3][3][2]=3; + ft[3][4][0]=0; + ft[3][4][1]=-9; + ft[3][4][2]=0; + ft[3][5][0]=-1; + ft[3][5][1]=-11; + ft[3][5][2]=0; + ft[3][6][0]=-2; + ft[3][6][1]=-14; + ft[3][6][2]=0; + ft[3][7][0]=-3; + ft[3][7][1]=-16; + ft[3][7][2]=0; + } +} + +bool dBushLeaves::animate(int index) +{ + index=index; //this is here to bypass compiler warnings about unused arguments + return (clk++>=24); +} + +void dBushLeaves::draw(BITMAP *dest) +{ + if(screenscrolling) + { + clk=128; + return; + } + + int t=wpnsbuf[iwBushLeaves].tile; + cs=wpnsbuf[iwBushLeaves].csets&15; + + for(int i=0; i<4; ++i) + { + x=ox+ft[i][int(float(clk-1)/3)][0]; + y=oy+ft[i][int(float(clk-1)/3)][1]; + flip=ft[i][int(float(clk-1)/3)][2]; + tile=t*4+i; + decoration::draw8(dest); + } +} + +dFlowerClippings::dFlowerClippings(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ + ox=X; + oy=Y; + id=Id; + clk=Clk; + static bool initialized=false; + if(!initialized) + { + initialized=true; + + ft[0][0][0]=6; + ft[0][0][1]=6; + ft[0][0][2]=0; + ft[0][1][0]=6; + ft[0][1][1]=9; + ft[0][1][2]=0; + ft[0][2][0]=7; + ft[0][2][1]=11; + ft[0][2][2]=1; + ft[0][3][0]=7; + ft[0][3][1]=13; + ft[0][3][2]=0; + ft[0][4][0]=9; + ft[0][4][1]=15; + ft[0][4][2]=0; + ft[0][5][0]=10; + ft[0][5][1]=16; + ft[0][5][2]=0; + ft[0][6][0]=11; + ft[0][6][1]=18; + ft[0][6][2]=0; + ft[0][7][0]=4; + ft[0][7][1]=19; + ft[0][7][2]=1; + + ft[1][0][0]=-4; + ft[1][0][1]=3; + ft[1][0][2]=0; + ft[1][1][0]=-1; + ft[1][1][1]=4; + ft[1][1][2]=0; + ft[1][2][0]=0; + ft[1][2][1]=5; + ft[1][2][2]=0; + ft[1][3][0]=1; + ft[1][3][1]=5; + ft[1][3][2]=1; + ft[1][4][0]=-2; + ft[1][4][1]=5; + ft[1][4][2]=1; + ft[1][5][0]=-6; + ft[1][5][1]=5; + ft[1][5][2]=0; + ft[1][6][0]=-7; + ft[1][6][1]=4; + ft[1][6][2]=0; + ft[1][7][0]=-9; + ft[1][7][1]=2; + ft[1][7][2]=1; + + ft[2][0][0]=10; + ft[2][0][1]=2; + ft[2][0][2]=1; + ft[2][1][0]=7; + ft[2][1][1]=3; + ft[2][1][2]=1; + ft[2][2][0]=4; + ft[2][2][1]=5; + ft[2][2][2]=1; + ft[2][3][0]=5; + ft[2][3][1]=5; + ft[2][3][2]=0; + ft[2][4][0]=8; + ft[2][4][1]=9; + ft[2][4][2]=0; + ft[2][5][0]=9; + ft[2][5][1]=9; + ft[2][5][2]=0; + ft[2][6][0]=12; + ft[2][6][1]=9; + ft[2][6][2]=1; + ft[2][7][0]=6; + ft[2][7][1]=16; + ft[2][7][2]=0; + + ft[3][0][0]=4; + ft[3][0][1]=-4; + ft[3][0][2]=0; + ft[3][1][0]=4; + ft[3][1][1]=-6; + ft[3][1][2]=0; + ft[3][2][0]=2; + ft[3][2][1]=-7; + ft[3][2][2]=0; + ft[3][3][0]=1; + ft[3][3][1]=-8; + ft[3][3][2]=3; + ft[3][4][0]=0; + ft[3][4][1]=-9; + ft[3][4][2]=0; + ft[3][5][0]=-1; + ft[3][5][1]=-11; + ft[3][5][2]=0; + ft[3][6][0]=-2; + ft[3][6][1]=-14; + ft[3][6][2]=0; + ft[3][7][0]=-3; + ft[3][7][1]=-16; + ft[3][7][2]=0; + } +} + +bool dFlowerClippings::animate(int index) +{ + index=index; //this is here to bypass compiler warnings about unused arguments + return (clk++>=24); +} + +void dFlowerClippings::draw(BITMAP *dest) +{ + if(screenscrolling) + { + clk=128; + return; + } + + int t=wpnsbuf[iwFlowerClippings].tile; + cs=wpnsbuf[iwFlowerClippings].csets&15; + + for(int i=0; i<4; ++i) + { + x=ox+ft[i][int(float(clk-1)/3)][0]; + y=oy+ft[i][int(float(clk-1)/3)][1]; + flip=ft[i][int(float(clk-1)/3)][2]; + tile=t*4+i; + decoration::draw8(dest); + } +} + +dGrassClippings::dGrassClippings(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ + ox=X; + oy=Y; + id=Id; + clk=Clk; + + static bool initialized=false; + if(!initialized) + { + initialized=true; + + ft[0][0][0]=1; + ft[0][0][1]=0; + ft[0][0][2]=1; + ft[0][0][3]=0; + ft[0][1][0]=-1; + ft[0][1][1]=4; + ft[0][1][2]=1; + ft[0][1][3]=0; + ft[0][2][0]=-5; + ft[0][2][1]=2; + ft[0][2][2]=0; + ft[0][2][3]=1; + ft[0][3][0]=-8; + ft[0][3][1]=0; + ft[0][3][2]=0; + ft[0][3][3]=1; + + ft[1][0][0]=3; + ft[1][0][1]=-4; + ft[1][0][2]=0; + ft[1][0][3]=1; + ft[1][1][0]=8; + ft[1][1][1]=-5; + ft[1][1][2]=3; + ft[1][1][3]=1; + ft[1][2][0]=8; + ft[1][2][1]=-5; + ft[1][2][2]=3; + ft[1][2][3]=0; + ft[1][3][0]=8; + ft[1][3][1]=-5; + ft[1][3][2]=0; + ft[1][3][3]=1; + + ft[2][0][0]=8; + ft[2][0][1]=1; + ft[2][0][2]=0; + ft[2][0][3]=1; + ft[2][1][0]=10; + ft[2][1][1]=4; + ft[2][1][2]=1; + ft[2][1][3]=1; + ft[2][2][0]=15; + ft[2][2][1]=3; + ft[2][2][2]=0; + ft[2][2][3]=0; + ft[2][3][0]=16; + ft[2][3][1]=5; + ft[2][3][2]=0; + ft[2][3][3]=1; + } +} + +bool dGrassClippings::animate(int index) +{ + index=index; //this is here to bypass compiler warnings about unused arguments + return (clk++>=12); +} + +void dGrassClippings::draw(BITMAP *dest) +{ + if(screenscrolling) + { + clk=128; + return; + } + + int t=wpnsbuf[iwGrassClippings].tile; + cs=wpnsbuf[iwGrassClippings].csets&15; + + for(int i=0; i<3; ++i) + { + x=ox+ft[i][int(float(clk-1)/3)][0]; + y=oy+ft[i][int(float(clk-1)/3)][1]; + flip=ft[i][int(float(clk-1)/3)][2]; + tile=(t+(ft[i][int(float(clk-1)/3)][3]))*4+i; + decoration::draw8(dest); + } +} + +dHammerSmack::dHammerSmack(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ + ox=X; + oy=Y; + id=Id; + clk=Clk; + + static bool initialized=false; + if(!initialized) + { + initialized=true; + + ft[0][0][0]=-5; + ft[0][0][1]=-4; + ft[0][0][2]=0; + ft[0][1][0]=-4; + ft[0][1][1]=-3; + ft[0][1][2]=1; + ft[0][2][0]=-5; + ft[0][2][1]=-4; + ft[0][2][2]=1; + ft[0][3][0]=-8; + ft[0][3][1]=-7; + ft[0][3][2]=1; + + ft[1][0][0]=3; + ft[1][0][1]=-4; + ft[1][0][2]=0; + ft[1][1][0]=5; + ft[1][1][1]=-3; + ft[1][1][2]=1; + ft[1][2][0]=6; + ft[1][2][1]=-4; + ft[1][2][2]=1; + ft[1][3][0]=9; + ft[1][3][1]=-7; + ft[1][3][2]=1; + } + + wpnid=itemsbuf[current_item_id(itype_hammer)].wpn2; +} + +bool dHammerSmack::animate(int index) +{ + index=index; //this is here to bypass compiler warnings about unused arguments + return (clk++>=12); +} + +void dHammerSmack::draw(BITMAP *dest) +{ + if(screenscrolling) + { + clk=128; + return; + } + + int t=wpnsbuf[wpnid].tile; + cs=wpnsbuf[wpnid].csets&15; + flip=0; + + for(int i=0; i<2; ++i) + { + x=ox+ft[i][int(float(clk-1)/3)][0]; + y=oy+ft[i][int(float(clk-1)/3)][1]; + tile=t*4+i+(ft[i][int(float(clk-1)/3)][2]*2); + decoration::draw8(dest); + } +} + +dTallGrass::dTallGrass(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ +} + +bool dTallGrass::animate(int) +{ + return false; +} + +void dTallGrass::draw(BITMAP *dest) +{ + if(LinkGetDontDraw()) + return; + + int t=wpnsbuf[iwTallGrass].tile*4; + cs=wpnsbuf[iwTallGrass].csets&15; + flip=0; + x=LinkX(); + y=LinkY()+10; + +// if (BSZ) + if(zinit.linkanimationstyle==las_bszelda) + { + tile=t+(anim_3_4(LinkLStep(),7)*2); + } + else + { + tile=t+((LinkLStep()>=6)?2:0); + } + + decoration::draw8(dest); + x+=8; + ++tile; + decoration::draw8(dest); +} + +dRipples::dRipples(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ +} + +bool dRipples::animate(int) +{ + clk++; + return false; +} + +void dRipples::draw(BITMAP *dest) +{ + if(LinkGetDontDraw()) + return; + + int t=wpnsbuf[iwRipples].tile*4; + cs=wpnsbuf[iwRipples].csets&15; + flip=0; + x=LinkX(); + y=LinkY()+10; + tile=t+(((clk/8)%3)*2); + decoration::draw8(dest); + x+=8; + ++tile; + decoration::draw8(dest); +} + +dHover::dHover(fix X,fix Y,int Id,int Clk) : decoration(X,Y,Id,Clk) +{ + wpnid = itemsbuf[current_item_id(itype_hoverboots)].wpn; +} + +void dHover::draw(BITMAP *dest) +{ + int t=wpnsbuf[wpnid].tile*4; + cs=wpnsbuf[wpnid].csets&15; + flip=0; + x=LinkX(); + y=LinkY()+10-LinkZ(); + tile=t+(((clk/8)%3)*2); + decoration::draw8(dest); + x+=8; + ++tile; + decoration::draw8(dest); +} + +bool dHover::animate(int) +{ + clk++; + return false; +} + +dNayrusLoveShield::dNayrusLoveShield(fix X,fix Y, const int& t): + decoration(X, Y, dNAYRUSLOVESHIELD, 0), + flickering((itemsbuf[current_item_id(itype_nayruslove)].flags & ITEM_FLAG4) != 0), + translucent((itemsbuf[current_item_id(itype_nayruslove)].flags & ITEM_FLAG3) != 0), + timer(t) +{ +} + +bool dNayrusLoveShield::animate(int) +{ + clk++; + return false; +} + +void dNayrusLoveShield::realdraw(BITMAP *dest, int draw_what) +{ + if(misc!=draw_what) + { + return; + } + + bool doDraw=true; + if(timer<256 && (timer&0x20)==0) + doDraw=false; + if(flickering) + { + if(misc==1) + doDraw=(frame&1)==0; + else + doDraw=(frame&1)==1; + } + if(!doDraw) + return; + + int fb=(misc==0? + (itemsbuf[current_item_id(itype_nayruslove)].wpn5 ? + itemsbuf[current_item_id(itype_nayruslove)].wpn5 : (byte) iwNayrusLoveShieldFront) : + (itemsbuf[current_item_id(itype_nayruslove)].wpn10 ? + itemsbuf[current_item_id(itype_nayruslove)].wpn10 : (byte) iwNayrusLoveShieldBack)); + int t=wpnsbuf[fb].tile; + int fr=wpnsbuf[fb].frames; + int spd=wpnsbuf[fb].speed; + cs=wpnsbuf[fb].csets&15; + flip=0; + + //if(((LinkNayrusLoveShieldClk()&0x20)||(LinkNayrusLoveShieldClk()&0xF00))&&(!flickering ||((misc==1)?(frame&1):(!(frame&1))))) + { + drawstyle=translucent?1:0; + x=LinkX()-8; + y=LinkY()-8-LinkZ(); + tile=t; + + if(fr>0&&spd>0) + { + tile+=((clk/spd)%fr); + } + + decoration::draw(dest); + x+=16; + tile+=fr; + decoration::draw(dest); + x-=16; + y+=16; + tile+=fr; + decoration::draw(dest); + x+=16; + tile+=fr; + decoration::draw(dest); + } +} + +void dNayrusLoveShield::draw(BITMAP *dest) +{ + realdraw(dest,0); +} + +void dNayrusLoveShield::draw2(BITMAP *dest) +{ + realdraw(dest,1); +} + + +/*** end of sprite.cc ***/ + diff --git a/src/decorations.h b/src/decorations.h new file mode 100644 index 0000000000..cbe64ca68b --- /dev/null +++ b/src/decorations.h @@ -0,0 +1,116 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- + +#ifndef _DECORATIONS_H_ +#define _DECORATIONS_H_ + +#include "sprite.h" + +/***************************************/ +/******* Decoration Base Class *******/ +/***************************************/ + +class decoration : public sprite +{ +public: + decoration(fix X,fix Y,int Id,int Clk); + virtual ~decoration(); +}; + +/*******************************/ +/******* Decorations *******/ +/*******************************/ + +class dBushLeaves : public decoration +{ +public: + static int ft[4][8][3]; //[leaf][frame][x/y/flip] + int ox, oy; + dBushLeaves(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dFlowerClippings : public decoration +{ +public: + static int ft[4][8][3]; //[leaf][frame][x/y/flip] + int ox, oy; + dFlowerClippings(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dGrassClippings : public decoration +{ +public: + static int ft[3][4][4]; //[leaf][frame][x/y/flip/size(0=large, 1=small)] + int ox, oy; + dGrassClippings(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dHammerSmack : public decoration +{ +public: + static int ft[2][4][3]; //[leaf][frame][x/y/icon(0=spark, 1=star)] + int ox, oy, wpnid; + dHammerSmack(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dTallGrass : public decoration +{ +public: + dTallGrass(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dRipples : public decoration +{ +public: + dRipples(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dHover : public decoration +{ + int wpnid; +public: + dHover(fix X,fix Y,int Id,int Clk); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class dNayrusLoveShield : public decoration +{ +public: + dNayrusLoveShield(fix X,fix Y, const int& timer); + virtual bool animate(int index); + virtual void realdraw(BITMAP *dest, int draw_what); + virtual void draw(BITMAP *dest); + virtual void draw2(BITMAP *dest); + +private: + bool flickering; + bool translucent; + const int& timer; +}; +#endif +/*** end of sprite.cc ***/ + diff --git a/src/defdata.cpp b/src/defdata.cpp new file mode 100644 index 0000000000..6a86c140d7 --- /dev/null +++ b/src/defdata.cpp @@ -0,0 +1,703 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// defdata.cc +// +// Default item, weapon, and enemy data for Zelda Classic. +// +// This data was originally hard coded in the item class, +// enemy classes, etc. I exctracted it to make generic +// classes, thus allowing custom items and enemies. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "defdata.h" +#include "sfx.h" + +/* + + combo_class_buf[combo_type].variable + + combo types left to do: + + cNONE, cSTAIR, cCAVE, cARMOS, cGRAVE, + cUNDEF, cPUSH_WAIT, cPUSH_HEAVY, cPUSH_HW, cL_STATUE, cR_STATUE, + cSWIMWARP, cDIVEWARP, + cLADDERHOOKSHOT, cTRIGNOFLAG, cTRIGFLAG, cZELDA, cSLASH, cSLASHITEM, + cPUSH_HEAVY2, cPUSH_HW2, cPOUND, cHSGRAB, cHSBRIDGE, cC_STATUE, cTRAP_H, cTRAP_V, cTRAP_4, + cTRAP_LR, cTRAP_UD, cPIT, cHOOKSHOTONLY, cNOFLYZONE, cMIRROR, + cMIRRORSLASH, cMIRRORBACKSLASH, cMAGICPRISM, cMAGICPRISM4, + cCAVE2, cNOJUMPZONE, cBUSH, + cFLOWERS, cTALLGRASS, cSHALLOWWATER, cLOCKBLOCK, cLOCKBLOCK2, + cBOSSLOCKBLOCK, cBOSSLOCKBLOCK2, cLADDERONLY, cBSGRAVE, + cCHEST, cCHEST2, cLOCKEDCHEST, cLOCKEDCHEST2, cBOSSCHEST, cBOSSCHEST2, + cRESET, cSAVE, cSAVE2, cCAVEB, cCAVEC, cCAVED, + cSTAIRB, cSTAIRC, cSTAIRD, cPITB, cPITC, cPITD, + cCAVE2B, cCAVE2C, cCAVE2D, cSWIMWARPB, cSWIMWARPC, cSWIMWARPD, + cDIVEWARPB, cDIVEWARPC, cDIVEWARPD, cSTAIRR, cPITR, + cAWARPA, cAWARPB, cAWARPC, cAWARPD, cAWARPR, + cSWARPA, cSWARPB, cSWARPC, cSWARPD, cSWARPR, cSTRIGNOFLAG, cSTRIGFLAG, + cSTEP, cSTEPSAME, cSTEPALL, cSTEPCOPY, cNOENEMY, + cCHANGE, cSPINTILE1, cSPINTILE2, + cSCREENFREEZE, cSCREENFREEZEFF, cICE, cSLASHNEXT, cSLASHNEXTITEM, cBUSHNEXT, + cSLASHTOUCHY, cSLASHITEMTOUCHY, cBUSHTOUCHY, cFLOWERSTOUCHY, cTALLGRASSTOUCHY, + cSLASHNEXTTOUCHY, cSLASHNEXTITEMTOUCHY, cBUSHNEXTTOUCHY, cMAX + + + finished: + cDAMAGE1, cDAMAGE2, cDAMAGE3, cDAMAGE4, cDAMAGE5, cDAMAGE6, cDAMAGE7, + cWATER, cDOCK, cCVUP, cCVDOWN, cCVLEFT, cCVRIGHT, cWALKSLOW, cOVERHEAD, + cEYEBALL_A, cEYEBALL_B, cBLOCKARROW1, cBLOCKARROW2, cBLOCKARROW3, cBLOCKBRANG1, + cBLOCKBRANG2, cBLOCKBRANG3, cBLOCKSBEAM, cMAGICSPONGE, cBLOCKFIREBALL, + cBLOCKALL, + +*/ + +comboclass default_combo_classes[cMAX] = +{ +// name a b c d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at01 at02 at03 at04 at05 at06 at07 at08 at09 at10 at11 at12 at13 at14 at15 at16 at17 at18 at19 at20 at21 at22 at23 at24 at25 at26 at27 at28 at29 at30 at31 at32 au av aw ax ay az ba bb bc bd be bf bg bh bi + { "(None)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Stairs [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Down) [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Water", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Armos", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Grave", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Dock", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "-Unused", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Push (Wait)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Push (Heavy)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Push (Heavy, Wait)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Left Statue", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Right Statue", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slow Walk", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Conveyor Up", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Conveyor Down", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Conveyor Left", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Conveyor Right", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Swim Warp [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Dive Warp [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Ladder or Hookshot", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Secrets (Temporary)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Secrets (Permanent)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "-Unused", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }, + { "Slash", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash (Item)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Push (Very Heavy)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Push (Very Heavy, Wait)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Pound", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Hookshot Grab", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +// name a b c d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at01 at02 at03 at04 at05 at06 at07 at08 at09 at10 at11 at12 at13 at14 at15 at16 at17 at18 at19 at20 at21 at22 at23 at24 at25 at26 at27 at28 at29 at30 at31 at32 au av aw ax ay az ba bb bc bd be bf bg bh bi + { "-Hookshot Bridge", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (1/2 Heart)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (1 Heart)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (2 hearts)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (4 Hearts)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Center Statue", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Trap (Horizontal, Line of Sight)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Trap (Vertical, Line of Sight)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Trap (4-Way)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Trap (Horizontal, Constant)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Trap (Vertical, Constant)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Direct Warp [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Hookshot Only", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Overhead", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "No Flying Enemies", 4, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Magic Mirror (4-Way)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Magic Mirror (Up-Left, Down-Right)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Magic Mirror (Up-Right, Down-Left)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Magic Prism (3-Way)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Magic Prism (4-Way)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Block Magic", 0, 0, 0, { 0, 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, + { "Cave (Walk Up) [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Eyeball (8-Way A)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Eyeball (8-Way B)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "No Jumping Enemies", 2, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Bush", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Flowers", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Tall Grass", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Shallow Water", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Lock Block (Normal)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +// name a b c d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at01 at02 at03 at04 at05 at06 at07 at08 at09 at10 at11 at12 at13 at14 at15 at16 at17 at18 at19 at20 at21 at22 at23 at24 at25 at26 at27 at28 at29 at30 at31 at32 au av aw ax ay az ba bb bc bd be bf bg bh bi + { "Lock Block (Normal, Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Lock Block (Boss)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Lock Block (Boss, Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Ladder Only", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "BS Grave", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Normal)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Normal, Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Locked)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Locked, Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Boss)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Treasure Chest (Boss, Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Reset Room", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Save Point", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Save-Quit Point", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Down) [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Down) [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Down) [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Stairs [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Stairs [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Stairs [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Direct Warp [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Direct Warp [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Direct Warp [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Up) [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Up) [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Cave (Walk Up) [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Swim Warp [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Swim Warp [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Swim Warp [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Dive Warp [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, +// name a b c d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at01 at02 at03 at04 at05 at06 at07 at08 at09 at10 at11 at12 at13 at14 at15 at16 at17 at18 at19 at20 at21 at22 at23 at24 at25 at26 at27 at28 at29 at30 at31 at32 au av aw ax ay az ba bb bc bd be bf bg bh bi + { "Dive Warp [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Dive Warp [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, + { "Stairs [Random]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Direct Warp [Random]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Auto Side Warp [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Auto Side Warp [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Auto Side Warp [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Auto Side Warp [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Auto Side Warp [Random]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Sensitive Warp [A]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Sensitive Warp [B]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Sensitive Warp [C]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Sensitive Warp [D]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Sensitive Warp [Random]", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Secrets (Sensitive, Temp)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Secrets (Sensitive, Perm.)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Next", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Next (Same)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Next (All)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Step->Next (Copycat)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "No Enemies", 7, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Block Arrow (L1)", 0, 0, 0, { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { "Block Arrow (L1, L2)", 0, 0, 0, { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, + { "Block Arrow (All)", 0, 0, 0, { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, + { "Block Brang (L1)", 0, 0, 0, { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { "Block Brang (L1, L2)", 0, 0, 0, { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, + { "Block Brang (All)", 0, 0, 0, { 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, + { "Block Sword Beam", 0, 0, 0, { 4, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, + { "Block All", 0, 0, 0, { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, + { "Block Fireball", 0, 0, 0, { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255 }, +// name a b c d01 d02 d03 d04 d05 d06 d07 d08 d09 d10 d11 d12 d13 d14 d15 d16 d17 d18 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 d29 d30 d31 d32 e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah ai aj ak al am an ao ap aq ar as at01 at02 at03 at04 at05 at06 at07 at08 at09 at10 at11 at12 at13 at14 at15 at16 at17 at18 at19 at20 at21 at22 at23 at24 at25 at26 at27 at28 at29 at30 at31 at32 au av aw ax ay az ba bb bc bd be bf bg bh bi + { "Damage (8 hearts)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (16 hearts)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Damage (32 hearts)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "-Unused", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Spinning Tile (Immediate)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "-Unused", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Screen Freeze (Except FFCs)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Screen Freeze (FFCs Only)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "No Ground Enemies", 1, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash->Next", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash->Next (Item)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Bush->Next", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash (Item, Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Bush (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Flowers (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Tall Grass (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash->Next (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Slash->Next (Item, Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Bush->Next (Continuous)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Eyeball (4-Way)", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Tall Grass->Next", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Script 1", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Script 2", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Script 3", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Script 4", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "Script 5", 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +itemdata default_items[iLast]= +{ +// The first 7 values should be 0! (Because qst.dat overwrites them.) +// tile/misc etc. family fam_type power flags script count amount setmax max playsound collect_script initiald[8] initiala[2] wpn wpn2 wpn3 wpn4 wpn5 wpn6 wpn7 wpn8 wpn9 wpn10 pickup_hearts misc1 misc2 misc3 misc4 misc5 misc6 misc7 misc8 misc9 misc10 magic usesound + {0,0,0,0,0,0,0, itype_rupee, i_rupee, 0, 0, 0, 1, 1|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rupee, i_5rupee, 0, 0, 0, 1, 5|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_heart, 1, 0, 0, 0, 0, HP_PER_HEART, 0, 0, WAV_PLINK, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bomb, i_bomb, 4, ITEM_GAMEDATA, 0, 2, 4, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wBOMB, wBOOM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, WAV_BOMB }, + {0,0,0,0,0,0,0, itype_clock, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_sword, i_sword, 1, ITEM_FLAG1|ITEM_FLAG2|ITEM_GAMEDATA|ITEM_FLAG4, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wSWORD, wSWORDSLASH, wSWORD, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SWORD }, + {0,0,0,0,0,0,0, itype_sword, i_wsword, 2, ITEM_FLAG1|ITEM_FLAG2|ITEM_GAMEDATA|ITEM_FLAG4, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wWSWORD, wWSWORDSLASH, wWSWORD, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SWORD }, + {0,0,0,0,0,0,0, itype_sword, i_msword, 4, ITEM_FLAG1|ITEM_FLAG2|ITEM_GAMEDATA|ITEM_FLAG4, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wMSWORD, wMSWORDSLASH, wMSWORD, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SWORD }, + {0,0,0,0,0,0,0, itype_shield, i_largeshield, 0, ITEM_GAMEDATA|ITEM_EDIBLE|ITEM_KEEPOLD, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, shROCK|shARROW|shBRANG|shFIREBALL|shSWORD|shMAGIC|shSCRIPT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_CHINK }, + {0,0,0,0,0,0,0, itype_key, 1, 0, 0, 0, 5, 1, 0, 0, WAV_PLINK, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_candle, i_bcandle, 1, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, wFIRE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_FIRE }, + {0,0,0,0,0,0,0, itype_candle, i_rcandle, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, wFIRE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_FIRE }, + {0,0,0,0,0,0,0, itype_letter, i_letter, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_arrow, i_warrow, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wARROW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ARROW }, + {0,0,0,0,0,0,0, itype_arrow, i_sarrow, 4, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wSARROW, wSSPARKLE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ARROW }, + {0,0,0,0,0,0,0, itype_bow, i_shortbow, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bait, i_bait, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wBAIT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_ring, i_bring, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, spBLUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_ring, i_rring, 4, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, spRED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bracelet, i_bracelet1, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_triforcepiece, 1, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_map, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_compass, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_brang, i_wbrang, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wBRANG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, shBRANG|shROCK|shARROW, 0, 0, 0, 0, 0, 0, 0, 0, WAV_BRANG }, + {0,0,0,0,0,0,0, itype_brang, i_mbrang, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wMBRANG, wMSPARKLE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, shBRANG|shROCK|shARROW|shFIREBALL|shSWORD|shMAGIC, 0, 0, 0, 0, 0, 0, 0, 0, WAV_BRANG }, + {0,0,0,0,0,0,0, itype_wand, i_wand, 2, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wWAND, wSWORDSLASH, wMAGIC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_WAND }, + {0,0,0,0,0,0,0, itype_raft, i_raft, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SECRET }, + {0,0,0,0,0,0,0, itype_ladder, i_ladder, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_heartcontainer, 1, 0, 0, 0, 0, HP_PER_HEART, HP_PER_HEART, 24*HP_PER_HEART, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_potion, i_bpotion, 0, ITEM_GAMEDATA|ITEM_DOWNGRADE|ITEM_COMBINE|ITEM_FLAG1|ITEM_FLAG2, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_potion, i_rpotion, 0, ITEM_GAMEDATA|ITEM_DOWNGRADE|ITEM_KEEPOLD|ITEM_GAINOLD|0x30, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_whistle, i_recorder, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_WHISTLE }, + {0,0,0,0,0,0,0, itype_book, i_book, 2, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wMAGIC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_WAND }, + {0,0,0,0,0,0,0, itype_magickey, i_magickey, 0xFF, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_fairy, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SCALE }, + {0,0,0,0,0,0,0, itype_brang, i_fbrang, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wFBRANG, 0, wFSPARKLE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, shBRANG|shROCK|shARROW|shFIREBALL|shSWORD|shMAGIC, shFIREBALL|shSWORD|shMAGIC, 0, 0, 0, 0, 0, 0, 0, WAV_BRANG }, + {0,0,0,0,0,0,0, itype_sword, i_xsword, 8, ITEM_FLAG1|ITEM_FLAG2|ITEM_GAMEDATA|ITEM_FLAG4, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wXSWORD, wXSWORDSLASH, wXSWORD, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SWORD }, + {0,0,0,0,0,0,0, itype_shield, i_mirrorshield, 0, ITEM_GAMEDATA|ITEM_KEEPOLD, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, shROCK|shARROW|shBRANG|shFIREBALL|shSWORD|shMAGIC|shFLAME|shSCRIPT, shFIREBALL|shMAGIC|shSCRIPT, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_CHINK }, + {0,0,0,0,0,0,0, itype_rupee, i_20rupee, 0, 0, 0, 1, 20|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rupee, i_50rupee, 0, 0, 0, 1, 50|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rupee, i_200rupee, 0, 0, 0, 1, 200|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wallet, i_swallet, 0, ITEM_GAMEDATA, 0, 1, 0, 500, 500, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wallet, i_lwallet, 0, ITEM_GAMEDATA, 0, 1, 0, 999, 999, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_misc, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_triforcepiece, 1, 0, 0, 0, -1, 0, 0, 0, WAV_CLEARED, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_misc, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_misc, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_misc, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_sbomb, i_sbomb, 16, ITEM_GAMEDATA, 0, 6, 1, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wSBOMB, wSBOOM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 1, 8, 0, 0, 0, 0, 0, 0, 0, 0, WAV_BOMB }, + {0,0,0,0,0,0,0, itype_heartpiece, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_amulet, i_amulet1, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_flippers, i_flippers, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_hookshot, i_hookshot, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wHSHEAD, wHSCHAIN_H, wHSCHAIN_V, wHSHANDLE, 0, 0, 0, 0, 0, 0, 0, 8, 100, shBRANG|shROCK|shARROW|shFIREBALL, 0, 0, 0, 0, 0, 0, 0, 0, WAV_HOOKSHOT }, + {0,0,0,0,0,0,0, itype_lens, i_lens, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, WAV_ZN1LENSON }, + {0,0,0,0,0,0,0, itype_hammer, i_hammer, 4, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wHAMMER, iwHammerSmack, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_HAMMER }, + {0,0,0,0,0,0,0, itype_boots, i_boots, 7, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bracelet, i_bracelet2, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_arrow, i_garrow, 8, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wGARROW, wGSPARKLE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ARROW }, + {0,0,0,0,0,0,0, itype_magiccontainer, 1, 0, 0, 0, 4, (MAGICPERBLOCK|0x8000), MAGICPERBLOCK, MAGICPERBLOCK*8, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magic, 1, 0, 0, 0, 4, (MAGICPERBLOCK)|0x8000, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magic, 1, 0, 0, 0, 4, (MAGICPERBLOCK<<3)|0x8000, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_ring, i_gring, 8, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, spGOLD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_killem, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_amulet, i_amulet2, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_dinsfire, i_dinsfire, 8, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wDINSFIRE1A, wDINSFIRE1B, wDINSFIRES1A, wDINSFIRES1B, 0, 0, 0, 0, 0, 0, 0, 32, 200, 0, 0, 0, 0, 0, 0, 0, 0, 32, WAV_ZN1DINSFIRE }, + {0,0,0,0,0,0,0, itype_faroreswind, i_faroreswind, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, WAV_ZN1FARORESWIND }, + {0,0,0,0,0,0,0, itype_nayruslove, i_nayruslove, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wNAYRUSLOVE1A, wNAYRUSLOVE1B,wNAYRUSLOVES1A, wNAYRUSLOVES1B,iwNayrusLoveShieldFront, wNAYRUSLOVE2A, wNAYRUSLOVE2B, wNAYRUSLOVES2A, wNAYRUSLOVES2B, iwNayrusLoveShieldBack, 0, 512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, WAV_ZN1NAYRUSLOVE1 }, + {0,0,0,0,0,0,0, itype_bosskey, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bow, i_longbow, 3, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_fairy, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_SCALE }, + {0,0,0,0,0,0,0, itype_arrowammo, i_arrowa, 0, 0, 0, 3, 1, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_arrowammo, i_5arrowa, 0, 0, 0, 3, 5, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_arrowammo, i_10arrowa, 0, 0, 0, 3, 10, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_arrowammo, i_30arrowa, 0, 0, 0, 3, 30, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_quiver, i_quiver, 0, ITEM_GAMEDATA, 0, 3, 0, 30, 30, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_quiver, i_quiverl2, 0, ITEM_GAMEDATA, 0, 3, 0, 60, 60, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_quiver, i_quiverl3, 0, ITEM_GAMEDATA, 0, 3, 0, 99, 99, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombammo, i_bomba, 0, 0, 0, 2, 1, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombammo, i_4bomba, 0, 0, 0, 2, 4, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombammo, i_8bomba, 0, 0, 0, 2, 8, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombammo, i_30bomba, 0, 0, 0, 2, 30, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombbag, i_bombbag1, 0, ITEM_GAMEDATA, 0, 2, 0, 30, 30, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombbag, i_bombbag2, 0, ITEM_GAMEDATA, 0, 2, 0, 60, 60, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombbag, i_bombbag3, 0, ITEM_GAMEDATA, 0, 2, 0, 99, 99, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_lkey, 1, 0, 0, 0, -1, 0, 0, 0, WAV_PLINK, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_misc, 1, 0, 0, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rupee, i_10rupee, 0, 0, 0, 1, 10|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rupee, i_100rupee, 0, 0, 0, 1, 100|0x8000, 0, 0, WAV_CHIME, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_cbyrna, i_cbyrna, 1, ITEM_GAMEDATA|ITEM_FLAG1|ITEM_FLAG4, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wCBYRNA, wCBYRNASLASH, wCBYRNAORB, 0, 0, 0, 0, 0, 0, 0, 0, 4, 16, 1, 0, 0, 0, 0, 0, 0, 0, 1, WAV_ZN2CANE }, + {0,0,0,0,0,0,0, itype_hookshot, i_longshot, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, wLSHEAD, wLSCHAIN_H, wLSCHAIN_V, wLSHANDLE, 0, 0, 0, 0, 0, 0, 0, 99, 100, shBRANG|shROCK|shARROW|shFIREBALL, 0, 0, 0, 0, 0, 0, 0, 0, WAV_HOOKSHOT }, + {0,0,0,0,0,0,0, itype_letter, i_letter_used, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_rocs, i_rocs, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ZN1JUMP }, + {0,0,0,0,0,0,0, itype_hoverboots, i_hoverboots, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, iwHover, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ZN1HOVER }, + {0,0,0,0,0,0,0, itype_shield, i_smallshield, 0, ITEM_GAMEDATA|ITEM_KEEPOLD, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, shROCK|shARROW|shBRANG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_CHINK }, + {0,0,0,0,0,0,0, itype_spinscroll, i_spinscroll1, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ZN1SPINATTACK }, + {0,0,0,0,0,0,0, itype_crossscroll, i_crossscroll, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_quakescroll, i_quakescroll1, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_BOMB }, + {0,0,0,0,0,0,0, itype_quakescroll2, i_quakescroll2, 3, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x20, 192, 0, 0, 0, 0, 0, 0, 0, 0, 8, WAV_BOMB }, + {0,0,0,0,0,0,0, itype_spinscroll2, i_spinscroll2, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, WAV_ZN1SPINATTACK }, + {0,0,0,0,0,0,0, itype_whispring, i_whispring1, 1, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_whispring, i_whispring2, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_chargering, i_chargering1, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_chargering, i_chargering2, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_perilscroll, i_perilscroll, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wallet, i_mwallet, 1, ITEM_GAMEDATA, 0, 1, 0, 999, 999, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_quiver, i_quiverl4, 1, ITEM_GAMEDATA, 0, 3, 0, 99, 99, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bombbag, i_bombbag4, 1, ITEM_GAMEDATA, 0, 2, 0, 99, 99, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_bracelet, i_oldglove, 1, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_ladder, i_ladder2, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wealthmedal, i_wealthmedal, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wealthmedal, i_wealthmedal2, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_wealthmedal, i_wealthmedal3, 0, ITEM_GAMEDATA|ITEM_FLAG1, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_heartring, i_heartring, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_heartring, i_heartring2, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_heartring, i_heartring3, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magicring, i_magicring, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magicring, i_magicring2, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magicring, i_magicring3, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0x100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_magicring, i_magicring4, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_agony, 1, 0, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_stompboots, 1, 1, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_perilring, 1, 2, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + {0,0,0,0,0,0,0, itype_whimsicalring, 1, 0xFF, ITEM_GAMEDATA, 0, -1, 0, 0, 0, WAV_SCALE, 0, { 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +guydata default_guys[OLDMAXGUYS] = +{ + // flags flags2 tile width, height s_tile s_width s_height etile e_width e_height hp family cset anim e_anim, frate e_frate dp wdp weapon rate hrate step homing grumble item_set misc1 misc2 misc3 misc4 m5 m6 m7 m8 m9 m10 m11 m12 m13 m14 m15 bgsfx bosspal extend + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeNONE, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 84, 1, 0, 0, 0, 0, 84, 1, 1, 2, eeGUY, 8, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 85, 1, 0, 0, 0, 0, 85, 1, 1, 2, eeGUY, 8, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 86, 1, 0, 0, 0, 0, 86, 1, 1, 2, eeGUY, 6, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 116, 1, 0, 0, 0, 0, 116, 1, 1, 2, eeGUY, 8, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000000, 0x00000000, 65, 1, 0, 0, 0, 0, 65, 1, 1, 2, eeGUY, 8, aFLIP, aFLIP, 12, 24, 2, 1, wNone, 0, 0, 0, 0, 0, isNONE, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + { 0x00000000, 0x00000000, 63, 1, 0, 0, 0, 0, 63, 1, 1, 2, eeGUY, 8, a2FRM, a2FRM, 8, 16, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 132, 1, 0, 0, 0, 0, 132, 1, 1, 2, eeGUY, 8, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 35, 1, 0, 0, 0, 0, 35, 1, 1, 2, eeGUY, 6, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 87, 1, 0, 0, 0, 0, 87, 1, 1, 2, eeGUY, 8, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + //10 + { 0x00000001, 0x00000000, 259, 1, 0, 0, 0, 0, 259, 1, 1, 2, eeGUY, 0, aNONE, aNONE, 0, 0, 1, 1, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + //20 eOCTO1S + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 3420, 16, 3, 2, eeWALK, 8, aOCTO, a4FRM4DIRF, 12, 12, 2, 2, ewRock, 4, 3, 50, 64, 1, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO2S + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 3540, 16, 3, 4, eeWALK, 7, aOCTO, a4FRM4DIRF, 12, 12, 2, 2, ewRock, 4, 5, 50, 64, 2, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO1F + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 3480, 16, 3, 2, eeWALK, 8, aOCTO, a4FRM4DIRF, 12, 12, 2, 2, ewRock, 6, 3, 100, 128, 1, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO2F + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 3600, 16, 3, 4, eeWALK, 7, aOCTO, a4FRM4DIRF, 12, 12, 2, 2, ewRock, 6, 5, 100, 128, 2, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eTEK1 + { 0x00000000, 0x00000000, 103, 2, 0, 0, 0, 0, 2340, 16, 2, 2, eeTEK, 8, aTEK, aNEWTEK, 32, 32, 2, 2, wNone, 0, 0, 250, 0, 0, isDEFAULT, 24, 3, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eTEK2 + { 0x00000000, 0x00000000, 103, 2, 0, 0, 0, 0, 2380, 16, 2, 2, eeTEK, 7, aTEK, aNEWTEK, 32, 32, 2, 2, wNone, 0, 0, 250, 0, 0, isMAGICMONEY, 80, 16, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eLEV1 + { 0x00000000, 0x00000000, 96, 5, 0, 0, 0, 0, 3040, 16, 3, 4, eeLEV, 8, aLEV, aNEWLEV, 40, 16, 2, 2, wNone, 0, 0, 50, 0, 0, isMONEY, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,edCHINK,0,0,0 }, 0, WAV_EDEAD, }, + // eLEV2 + { 0x00000000, 0x00000000, 96, 5, 0, 0, 0, 0, 3100, 16, 3, 8, eeLEV, 7, aLEV, aNEWLEV, 40, 16, 4, 2, wNone, 8, 0, 50, 0, 0, isMAGICMONEY, 1, 8, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,edCHINK,0,0,0 }, 0, WAV_EDEAD, }, + // eMOBLIN1 + { 0x00000000, 0x00000000, 114, 4, 0, 0, 0, 0, 3840, 16, 3, 4, eeWALK, 8, aWALK, a4FRM4DIRF, 12, 16, 2, 2, ewArrow, 5, 4, 50, 128, 3, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eMOBLIN2 + { 0x00000000, 0x00000000, 114, 4, 0, 0, 0, 0, 3900, 16, 3, 6, eeWALK, 9, aWALK, a4FRM4DIRF, 12, 16, 2, 2, ewArrow, 8, 6, 50, 128, 4, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 30 eLYNEL1 + { 0x00000000, 0x00000000, 105, 4, 0, 0, 0, 0, 4100, 16, 3, 8, eeWALK, 8, aWALK, a4FRM4DIRF, 12, 16, 4, 8, ewSword, 6, 4, 50, 128, 3, isMAGICMONEY, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eLYNEL2 + { 0x00000000, 0x00000000, 105, 4, 0, 0, 0, 0, 4160, 16, 3, 12, eeWALK, 7, aWALK, a4FRM4DIRF, 12, 16, 8, 8, ewSword, 6, 4, 50, 128, 3, isMAGICBOMBS, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // ePEAHAT + { 0x00000000, 0x00000000, 101, 2, 0, 0, 0, 0, 2300, 16, 2, 4, eePEAHAT, 8, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 4, 8, 62, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNONLY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eZORA + { 0x00000000, 0x00000002, 112, 2, 0, 96, 2, 0, 2460, 16, 6, 4, eeZORA, 9, aZORA, aNEWZORA, 256, 256, 2, 2, ewFireball, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eROCK + { 0x00000008, 0x00000004, 118, 2, 0, 0, 0, 0, 3220, 16, 2, 2, eeROCK, 8, a2FRM, aNEWZORA, 12, 16, 2, 2, wNone, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eGHINI1 + { 0x00000000, 0x00000000, 109, 2, 0, 0, 0, 0, 2200, 16, 1, 18, eeWALK, 7, aGHINI, a4FRMPOS4DIR, 256, 256, 4, 4, wNone, 4, 0, 50, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGHINI2 + { 0x00004000, 0x00001000, 109, 2, 0, 0, 0, 0, 2220, 16, 2, 18, eeGHINI, 7, aGHINI, a4FRMPOS8DIR, 256, 256, 4, 4, wNone, 4, 12, 62, 0, 0, isMONEY, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,0,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eARMOS + { 0x00000010, 0x00000800, 88, 4, 0, 0, 0, 0, 2260, 16, 2, 6, eeWALK, 8, aARMOS, aARMOS4, 16, 16, 4, 4, wNone, 6, 0, 50, 128, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 4, 150, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eKEESE1 + { 0x00000001, 0x00000000, 123, 2, 0, 0, 0, 0, 1580, 16, 2, 1, eeKEESE, 7, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 2, 8, 62, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eKEESE2 + { 0x00000001, 0x00000000, 123, 2, 0, 0, 0, 0, 1620, 16, 2, 1, eeKEESE, 8, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 2, 8, 62, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 40 eKEESE3 + { 0x00000001, 0x00000000, 123, 2, 0, 0, 0, 0, 1660, 16, 2, 1, eeKEESE, 9, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 2, 8, 62, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eSTALFOS + { 0x00000000, 0x00000000, 125, 1, 0, 0, 0, 0, 3960, 16, 1, 4, eeWALK, 8, aFLIP, a4FRM4DIR, 16, 16, 2, 2, wNone, 4, 0, 50, 128, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGEL + { 0x00000001, 0x00000000, 120, 2, 0, 0, 0, 0, 1780, 16, 1, 1, eeWALK, 9, a2FRM, a4FRM4DIR, 4, 8, 2, 2, wNone, 4, 16, 100, 64, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eZOL + { 0x00000000, 0x00000000, 137, 2, 0, 0, 0, 0, 1800, 16, 1, 4, eeWALK, 9, a2FRM, a4FRM4DIR, 16, 16, 4, 4, wNone, 4, 16, 40, 144, 0, isMONEY, 0, e2tSPLITHIT, eGEL, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eROPE + { 0x00000000, 0x00000000, 126, 2, 0, 0, 0, 0, 2420, 16, 1, 2, eeWALK, 8, aROPE, a4FRM4DIR, 16, 16, 2, 2, wNone, 4, 0, 50, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, e9tROPE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGORIYA1 + { 0x00000000, 0x00000000, 130, 4, 0, 0, 0, 0, 3720, 16, 3, 6, eeWALK, 8, aWALK, a4FRM4DIRF, 12, 12, 2, 4, ewBrang, 6, 5, 50, 128, 4, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGORIYA2 + { 0x00000000, 0x00000000, 130, 4, 0, 0, 0, 0, 3780, 16, 3, 10, eeWALK, 7, aWALK, a4FRM4DIRF, 12, 12, 4, 4, ewBrang, 6, 6, 50, 128, 4, isLIFE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eTRAP + { 0x00000008, 0x00000248, 122, 1, 0, 2020, 0, 0, 2000, 16, 3, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eWALLM + { 0x00000000, 0x00000000, 128, 2, 0, 0, 0, 0, 2580, 16, 1, 4, eeWALLM, 7, aWALLM, aNEWWALLM, 16, 16, 2, 2, wNone, 0, 0, 40, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eDKNUT1 + { 0x11000000, 0x00000000, 140, 5, 0, 860, 5, 0, 4220, 16, 1, 8, eeWALK, 8, aDWALK, a4FRM4DIR, 16, 16, 4, 4, wNone, 5, 0, 50, 144, 0, isMAGICBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edCHINK,edIGNORE,0,edCHINK,0,0,0,0,0,0,0,edCHINK,edCHINK,edCHINK,0,0 }, 0, WAV_EDEAD, }, + // 50 eDKNUT2 + { 0x11000000, 0x00000000, 140, 5, 0, 860, 5, 0, 4240, 16, 1, 16, eeWALK, 7, aDWALK, a4FRM4DIR, 16, 16, 8, 4, wNone, 4, 0, 67, 160, 0, isMAGICLIFE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edCHINK,edIGNORE,0,edCHINK,0,0,0,0,0,0,0,edCHINK,edCHINK,edCHINK,0,0 }, 0, WAV_EDEAD, }, + // eBUBBLEST + { 0x00000008, 0x00000001, 111, 1, 0, 0, 0, 0, 1880, 16, 1, 2, eeWALK, 9, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tTEMPJINX, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eVIRE + { 0x00000000, 0x00000000, 165, 4, 0, 0, 0, 0, 1760, 16, 1, 8, eeWALK, 7, aVIRE, a4FRM4DIR, 20, 20, 4, 4, wNone, 4, 0, 50, 64, 0, isBOMBS, 0, e2tSPLITHIT, eKEESE2, 2, 0, 0, 0, 0, e9tVIRE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eLIKE + { 0x00000000, 0x00000000, 162, 3, 0, 0, 0, 0, 1860, 16, 1, 18, eeWALK, 8, a3FRM, a4FRM4DIR, 32, 32, 4, 4, wNone, 4, 0, 50, 64, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tEATITEMS,95, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGIBDO + { 0x00000000, 0x00000000, 136, 1, 0, 0, 0, 0, 2140, 16, 1, 14, eeWALK, 7, aFLIP, a4FRM4DIR, 16, 16, 8, 8, wNone, 4, 0, 50, 128, 0, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // ePOLSV + { 0x00000000, 0x00000000, 134, 2, 0, 2180, 0, 0, 2160, 16, 2, 20, eeWALK, 6, a2FRM, a4FRM4DIR, 16, 16, 8, 8, wNone, 4, 10, 50, 32, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, e9tPOLSVOICE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,edIGNORE,edIGNORE,ed1HKO,edIGNORE,0,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edCHINK,0 }, 0, WAV_EDEAD, }, + // eWIZ1 + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4700, 16, 3, 8, eeWIZZ, 8, aWIZZ, aNEWWIZZ, 256, 256, 4, 16, ewMagic, 0, 0, 0, 0, 0, isBOMBS, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eWIZ2 + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4460, 16, 4, 20, eeWIZZ, 7, aWIZZ, aNEWWIZZ, 16, 16, 8, 8, ewMagic, 4, 0, 50, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eRAQUAM + { 0x00000004, 0x00000000, 226, 4, 2, 0, 0, 0, 7528, 8, 6, 12, eeAQUA, 14, aAQUA, aAQUA, 0, 0, 4, 2, ewFireball2, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ROAR, spAQUA, 0, { edCHINK,0,0,0,edIGNORE,0,0,edCHINK,0,0,0,0,0,0,0,0,0,0,0 }, WAV_GASP, WAV_GASP, }, + // eMOLDORM + { 0x00000004, 0x00000000, 57, 1, 0, 0, 0, 0, 2800, 16, 6, 4, eeMOLD, 8, aNONE, aNONE, 32, 32, 2, 2, wNone, 1, 0, 50, 0, 0, isNONE, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // 60 eDODONGO + { 0x00000000, 0x00000000, 149, 10, 0, 0, 0, 0, 6700, 16, 3, 16, eeDONGO, 8, aDONGO, aNEWDONGO, 0, 0, 4, 2, wNone, 4, 0, 50, 64, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_DODONGO, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eMANHAN + { 0x00000004, 0x00000000, 190, 5, 0, 0, 0, 0, 6260, 16, 8, 8, eeMANHAN, 7, aMANHAN, aMANHAN, 0, 16, 4, 4, ewFireball, 2, 16, 50, 0, 0, isDEFAULT, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,0,0,0,edIGNORE,0,0,edCHINK,0,0,0,0,0,0,0,0,0,0,0 }, WAV_GASP, WAV_GASP, }, + // eGLEEOK1 + { 0x00000004, 0x00000000, 220, 6, 2, 145, 4, 0, 7000, 8, 8, 20, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 4, ewFireball, 2, 9, 89, 0, 0, isDEFAULT, 1, 6, 0, 48, 4, 8, 40, 168, 228, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOK, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGLEEOK2 + { 0x00000004, 0x00000000, 220, 6, 2, 145, 4, 0, 7000, 8, 8, 20, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 4, ewFireball, 2, 9, 89, 0, 0, isDEFAULT, 2, 6, 0, 48, 4, 8, 40, 168, 228, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOK, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGLEEOK3 + { 0x00000004, 0x00000000, 220, 6, 2, 145, 4, 0, 7000, 8, 8, 20, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 4, ewFireball, 2, 9, 89, 0, 0, isDEFAULT, 3, 6, 0, 48, 4, 8, 40, 168, 228, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOK, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGLEEOK4 + { 0x0000004, 0x00000000, 220, 6, 2, 145, 4, 0, 7000, 8, 8, 20, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 4, ewFireball, 2, 9, 89, 0, 0, isDEFAULT, 4, 6, 0, 48, 4, 8, 40, 168, 228, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOK, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eDIG1 + { 0x00000004, 0x00000000, 230, 4, 2, 160, 2, 0, 5580, 16, 8, 12, eeDIG, 14, aDIG, aDIG, 6, 8, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, eDIGPUP1, eDIGPUP2, eDIGPUP3, eDIGPUP4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_VADER, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eDIG3 + { 0x00000004, 0x00000000, 230, 4, 2, 160, 2, 0, 5780, 16, 8, 12, eeDIG, 14, aDIG, aDIG, 6, 8, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, eDIGPUP1, eDIGPUP2, eDIGPUP3, eDIGPUP4, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, WAV_VADER, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eDIGPUP1 + { 0x00000004, 0x00000000, 160, 2, 0, 0, 0, 0, 5740, 16, 2, 16, eeDIG, 14, aDIG, aDIG, 12, 16, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eDIGPUP2 + { 0x00000004, 0x00000000, 160, 2, 0, 0, 0, 0, 5940, 16, 2, 16, eeDIG, 14, aDIG, aDIG, 12, 16, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // 70 eDIGPUP3 + { 0x00000004, 0x00000000, 160, 2, 0, 0, 0, 0, 5980, 16, 2, 16, eeDIG, 14, aDIG, aDIG, 12, 16, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eDIGPUP4 + { 0x00000004, 0x00000000, 160, 2, 0, 0, 0, 0, 6020, 16, 2, 16, eeDIG, 14, aDIG, aDIG, 12, 16, 8, 4, wNone, 2, 16, 25, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eGOHMA1 + { 0x00000004, 0x00000000, 180, 6, 0, 0, 0, 0, 6920, 12, 1, 4, eeGHOMA, 8, aGHOMA, aGHOMA, 0, 0, 8, 4, ewFireball2, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_DODONGO, -1, 0, { edCHINK,edX,edX,0,edX,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK }, WAV_GASP, WAV_GASP, }, + // eGOHMA2 + { 0x00000004, 0x00000000, 180, 6, 0, 0, 0, 0, 6940, 12, 1, 12, eeGHOMA, 7, aGHOMA, aGHOMA, 0, 0, 8, 4, ewFireball2, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_DODONGO, -1, 0, { edCHINK,edX,edX,0,edX,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK }, WAV_GASP, WAV_GASP, }, + // eCENT1 + { 0x00000000, 0x00000000, 173, 2, 0, 0, 0, 0, 2680, 16, 3, 4, eeLANM, 8, aLANM, aLANM, 8, 8, 8, 8, wNone, 8, 0, 100, 0, 0, isDEFAULT, 5, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eCENT2 + { 0x00000000, 0x00000000, 173, 2, 0, 0, 0, 0, 2740, 16, 3, 4, eeLANM, 7, aLANM, aLANM, 4, 4, 8, 8, wNone, 8, 0, 200, 0, 0, isDEFAULT, 5, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // ePATRA1 + { 0x00000004, 0x00000000, 191, 3, 0, 0, 0, 0, 5020, 16, 2, 22, eePATRA, 7, aFLIP, a4FRM8EYE, 4, 4, 8, 8, wNone, 3, 8, 25, 0, 0, isDEFAULT, 8, 0, 12, 0, 0, 6, 3, 40, 8, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // ePATRA2 + { 0x00000004, 0x00000000, 191, 3, 0, 0, 0, 0, 5100, 16, 2, 22, eePATRA, 7, aFLIP, a4FRM8EYE, 4, 4, 8, 8, wNone, 3, 8, 25, 0, 0, isDEFAULT, 8, 0, 12, 1, 0, 8, 4, 40, 8, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGANON + { 0x00000004, 0x00002000, 260, 10, 2, 0, 0, 0, 8360, 16, 2, 32, eeGANON, 14, aGANON, aGANON, 0, 0, 16, 4, ewFireball, 5, 0, 100, 72, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, spGANON, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, WAV_GASP, WAV_GASP, }, + // eSTALFOS2 + { 0x00000000, 0x00000000, 125, 1, 0, 0, 0, 0, 3980, 16, 3, 4, eeWALK, 8, aFLIP, a4FRM4DIRF, 16, 16, 2, 8, ewSword, 4, 4, 50, 128, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 80 eROPE2 + { 0x00000000, 0x00000001, 126, 2, 0, 0, 0, 0, 2440, 16, 1, 8, eeWALK, 8, aROPE, a4FRM4DIR, 16, 16, 2, 2, wNone, 4, 0, 50, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, e9tROPE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eBUBBLESP + { 0x00000008, 0x00000000, 111, 1, 0, 0, 0, 0, 1900, 16, 1, 2, eeWALK, 8, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tPERMJINX,0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eBUBBLESR + { 0x00000008, 0x00000000, 111, 1, 0, 0, 0, 0, 1920, 16, 1, 2, eeWALK, 7, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, e7tUNJINX, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTFBALL + { 0x00000000, 0x00000400, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 2, ewFireball, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eITEMFAIRY + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eeFAIRY, 0, aNONE, aNONE, 256, 256, 0, 0, wNone, 0, 0, 50, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eFIRE + { 0x00000001, 0x00000000, 65, 1, 0, 0, 0, 0, 3160, 16, 2, 2, eeFIRE, 8, aFLIP, a4FRM8EYE, 12, 16, 2, 2, wNone, 0, 0, 0, 0, 0, isNONE, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eCOCTO + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 3660, 16, 3, 40, eeWALK, 9, aOCTO, a4FRM4DIRF, 4, 4, 20, 40, ewMagic, 16, 1, 200, 255, 0, isMAGIC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eDKNUT5 + { 0x11000000, 0x00000000, 140, 5, 0, 860, 5, 0, 4280, 16, 3, 60, eeWALK, 9, aDWALK, a4FRM4DIR, 16, 16, 40, 80, ewSword, 2, 0, 150, 255, 0, isLIFE, e1tCONSTANT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edCHINK,edIGNORE,0,edCHINK,0,0,0,0,0,0,0,edCHINK,edCHINK,edCHINK,0,0 }, 0, WAV_EDEAD, }, + // eGELTRIB + { 0x00000001, 0x00000000, 120, 2, 0, 0, 0, 0, 1820, 16, 1, 1, eeWALK, 9, a2FRM, a4FRM4DIR, 4, 8, 2, 2, wNone, 4, 16, 100, 64, 0, isMAGIC, 0, e2tTRIBBLE, eZOLTRIB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eZOLTRIB + { 0x00000000, 0x00000000, 137, 2, 0, 0, 0, 0, 1840, 16, 1, 8, eeWALK, 9, a2FRM, a4FRM4DIR, 16, 16, 4, 4, wNone, 4, 16, 40, 144, 0, isMAGICMONEY, 0, e2tSPLITHIT, eGELTRIB, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 90 eKEESETRIB + { 0x00000001, 0x00000000, 123, 2, 0, 0, 0, 0, 1700, 16, 2, 1, eeKEESE, 9, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 2, 8, 62, 0, 0, isMAGIC, 0, e2tKEESETRIB, eVIRETRIB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eVIRETRIB + { 0x00000000, 0x00000000, 165, 4, 0, 0, 0, 0, 1740, 16, 1, 16, eeWALK, 9, aVIRE, a4FRM4DIR, 20, 20, 4, 4, wNone, 4, 0, 50, 64, 0, isMAGICBOMBS, 0, e2tSPLITHIT, eKEESETRIB, 2, 0, 0, 0, 0, e9tVIRE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eDKNUT3 + { 0x11000000, 0x00000000, 140, 5, 0, 860, 5, 0, 4260, 16, 1, 32, eeWALK, 9, aDWALK, a4FRM4DIR, 16, 16, 16, 4, wNone, 3, 0, 100, 200, 0, isMAGIC, 0, e2tSPLIT, eDKNUT2, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edCHINK,edIGNORE,0,edCHINK,0,0,0,0,0,0,0,edCHINK,edCHINK,edCHINK,0,0 }, 0, WAV_EDEAD, }, + // eLAQUAM + { 0x00000004, 0x00000000, 226, 4, 2, 0, 0, 0, 7520, 8, 6, 12, eeAQUA, 14, aAQUA, aAQUA, 0, 0, 4, 2, ewFireball2, 0, 0, 0, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_ROAR, spAQUA, 0, { edCHINK,0,0,0,edIGNORE,0,0,edCHINK,0,0,0,0,0,0,0,0,0,0,0 }, WAV_GASP, WAV_GASP, }, + // eMANHAN2 + { 0x00000004, 0x00000000, 190, 5, 0, 0, 0, 0, 6420, 16, 14, 8, eeMANHAN, 8, aMANHAN, aMANHAN, 0, 0, 4, 4, ewFireball, 2, 16, 50, 0, 0, isDEFAULT, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,0,0,0,edIGNORE,0,0,edCHINK,0,0,0,0,0,0,0,0,0,0,0 }, WAV_GASP, WAV_GASP, }, + // eTRAP_H + { 0x00000008, 0x00000010, 122, 1, 0, 0, 0, 0, 2080, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_V + { 0x00000008, 0x00000020, 122, 1, 0, 0, 0, 0, 2060, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_LR + { 0x00000008, 0x00000080, 122, 1, 0, 0, 0, 0, 2120, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_UD + { 0x00000008, 0x00000100, 122, 1, 0, 0, 0, 0, 2100, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eFWIZ + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4540, 16, 4, 24, eeWIZZ, 8, aWIZZ, aNEWWIZZ, 16, 16, 8, 8, ewFlame, 4, 0, 50, 0, 0, isMAGIC, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // 100 eWWIZ + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4760, 16, 3, 28, eeWIZZ, 7, aWIZZ, aNEWWIZZ, 256, 256, 4, 16, ewWind, 0, 0, 0, 0, 0, isMAGICBOMBS, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eCEILINGM + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFLOORM + { 0x00000001, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // ePATRABS + { 0x00000004, 0x00000000, 191, 3, 0, 0, 0, 0, 6060, 16, 10, 22, eePATRA, 7, aFLIP, a4FRM8EYE, 4, 4, 8, 8, wNone, 3, 8, 25, 0, 0, isDEFAULT, 6, 0, 12, 1, 0, 8, 4, 160, 8, 1, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // ePATRAL2 + { 0x00000004, 0x00000000, 191, 3, 0, 0, 0, 0, 5180, 16, 10, 44, eePATRA, 7, aFLIP, a4FRM8EYE, 4, 4, 8, 8, ewFireball, 3, 8, 25, 0, 0, isDEFAULT, 8, 8, 18, 0, 1, 6, 3, 160, 8, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // ePATRAL3 + { 0x00000004, 0x00000000, 191, 3, 0, 0, 0, 0, 5380, 16, 10, 44, eePATRA, 7, aFLIP, a4FRM8EYE, 4, 4, 8, 8, ewFireball, 3, 8, 25, 0, 0, isDEFAULT, 8, 8, 18, 0, 2, 6, 3, 160, 8, 0, 0, 0, 0, 0, 0, WAV_VADER, -1, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eBAT + { 0x00000001, 0x00000000, 123, 2, 0, 0, 0, 0, 4880, 16, 2, 8, eeKEESE, 9, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 6, 6, wNone, 2, 8, 100, 0, 0, isMAGIC, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eBATROBE + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4820, 16, 3, 28, eeWIZZ, 9, aWIZZ, aNEWWIZZ, 256, 256, 4, 16, ewMagic, 0, 0, 0, 0, 0, isMAGICBOMBS, 0, 2, eBAT, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eBATROBEKING + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 0, eeGUY, 0, aNONE, aNONE, 0, 0, 0, 0, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eGLEEOK1F + { 0x00000004, 0x00000000, 220, 6, 2, 145, 0, 0, 7012, 8, 8, 30, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 8, ewFlame, 2, 9, 89, 0, 0, isDEFAULT, 1, 10, 1, 48, 4, 28, 40, 336, 396, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOKF, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // 110 eGLEEOK2F + { 0x00000004, 0x00000000, 220, 6, 2, 145, 0, 0, 7012, 8, 8, 30, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 8, ewFlame, 2, 9, 89, 0, 0, isDEFAULT, 2, 10, 1, 48, 4, 28, 40, 336, 396, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOKF, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGLEEOK3F + { 0x00000004, 0x00000000, 220, 6, 2, 145, 0, 0, 7012, 8, 8, 30, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 8, ewFlame, 2, 9, 89, 0, 0, isDEFAULT, 3, 10, 1, 48, 4, 28, 40, 336, 396, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOKF, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eGLEEOK4F + { 0x00000004, 0x00000000, 220, 6, 2, 145, 0, 0, 7012, 8, 8, 30, eeGLEEOK, 14, aGLEEOK, aGLEEOK, 0, 0, 4, 8, ewFlame, 2, 9, 89, 0, 0, isDEFAULT, 4, 10, 1, 48, 4, 28, 40, 336, 396, 0, 0, 0, 0, 0, 0, WAV_ROAR, spGLEEOKF, 0, { edCHINK,edX,edX,edCHINK,edX,0,edCHINK,edCHINK,0,0,0,0,edCHINK,edX,edX,edX,edX,edX,edX }, WAV_GASP, WAV_GASP, }, + // eMWIZ + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 4620, 16, 4, 192, eeWIZZ, 9, aWIZZ, aNEWWIZZ, 16, 16, 32, 32, ewMagic, 4, 0, 75, 0, 0, isMAGIC, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,0,0,edX,edX,edX,edX,edX,0 }, 0, WAV_EDEAD, }, + // eDODONGOBS + { 0x00000000, 0x00000000, 6760, 16, 4, 0, 0, 0, 6760, 16, 4, 16, eeDONGO, 14, aDONGOBS, aDONGOBS, 0, 0, 4, 2, wNone, 4, 0, 50, 64, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, WAV_DODONGO, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eDODONGOF + { 0x00000000, 0x00000000, 6840, 16, 4, 0, 0, 0, 6840, 16, 4, 16, eeDONGO, 14, aDONGOBS, aDONGOBS, 0, 0, 4, 2, wNone, 4, 0, 50, 64, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, WAV_DODONGO, spDIG, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_GASP, }, + // eTRIGGER + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eeNONE, 8, aNONE, aNONE, 1, 1, 2, 2, wNone, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eBUBBLEIT + { 0x00000008, 0x00000001, 111, 1, 0, 0, 0, 0, 1940, 16, 1, 2, eeWALK, 9, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tTEMPJINX,e8tITEM,0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eBUBBLEIP + { 0x00000008, 0x00000000, 111, 1, 0, 0, 0, 0, 1960, 16, 1, 2, eeWALK, 8, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tPERMJINX,e8tITEM,0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eBUBBLEIR + { 0x00000008, 0x00000000, 111, 1, 0, 0, 0, 0, 1980, 16, 1, 2, eeWALK, 7, aFLIP, a4FRM4DIR, 8, 8, 0, 0, wNone, 4, 0, 100, 0, 0, isNONE, 0, 0, 0, 0, 0, 0,e7tUNJINX, e8tITEM, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORIGNORE,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // 120 eSTALFOS3 + { 0x00000000, 0x00000000, 125, 1, 0, 0, 0, 0, 4040, 16, 3, 12, eeWALK, 9, aFLIP, a4FRM4DIRF, 8, 8, 6, 24, ewSword, 4, 4, 100, 200, 0, isMAGIC, e1t4SHOTS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGOHMA3 + { 0x00000004, 0x00000000, 180, 6, 0, 0, 0, 0, 6960, 12, 1, 24, eeGHOMA, 8, aGHOMA, aGHOMA, 0, 0, 16, 8, ewFireball2, 0, 0, 0, 0, 0, isDEFAULT, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_DODONGO, -1, 0, { edCHINK,edX,edX,edCHINKL4,edX,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK }, WAV_GASP, WAV_GASP, }, + // eGOHMA4 + { 0x00000004, 0x00000000, 180, 6, 0, 0, 0, 0, 6980, 12, 1, 48, eeGHOMA, 7, aGHOMA, aGHOMA, 0, 0, 16, 8, ewFlame, 0, 0, 0, 0, 0, isDEFAULT, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WAV_DODONGO, -1, 0, { edCHINK,edX,edX,edCHINKL8,edX,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK,edCHINK }, WAV_GASP, WAV_GASP, }, + // eNPCSTAND1 + { 0x00000000, 0x00000000, 0, 16, 1, 0, 0, 0, 0, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCSTAND2 + { 0x00000000, 0x00000000, 20, 16, 1, 0, 0, 0, 20, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCSTAND3 + { 0x00000000, 0x00000000, 40, 16, 1, 0, 0, 0, 40, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCSTAND4 + { 0x00000000, 0x00000000, 60, 16, 1, 0, 0, 0, 60, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCSTAND5 + { 0x00000000, 0x00000000, 80, 16, 1, 0, 0, 0, 80, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCSTAND6 + { 0x00000000, 0x00000000, 100, 16, 1, 0, 0, 0, 100, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCWALK1 + { 0x00000000, 0x00000000, 120, 16, 1, 0, 0, 0, 120, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 130 eNPCWALK2 + { 0x00000000, 0x00000000, 140, 16, 1, 0, 0, 0, 140, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCWALK3 + { 0x00000000, 0x00000000, 160, 16, 1, 0, 0, 0, 160, 16, 1, 2, eeGUY, 7, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCWALK4 + { 0x00000000, 0x00000000, 180, 16, 1, 0, 0, 0, 180, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCWALK5 + { 0x00000000, 0x00000000, 200, 16, 1, 0, 0, 0, 200, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eNPCWALK6 + { 0x00000000, 0x00000000, 220, 16, 1, 0, 0, 0, 220, 16, 1, 2, eeGUY, 8, a2FRM4DIR, a4FRM4DIR, 12, 12, 2, 2, wNone, 4, 3, 50, 0, 0, isDEFAULT, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eBOULDER + { 0x00000008, 0x00000000, 3260, 4, 2, 0, 0, 0, 3260, 16, 8, 2, eeROCK, 8, a2FRMB, a4FRM8DIRB, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eGORIYA3 + { 0x00000000, 0x00000000, 130, 4, 0, 0, 0, 0, 8480, 16, 3, 18, eeWALK, 9, aWALK, a4FRM4DIRF, 12, 12, 8, 8, ewBrang, 9, 9, 50, 128, 4, isMAGICBOMBS, e1tHOMINGBRANG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eLEV3 + { 0x00000000, 0x00000000, 96, 5, 0, 0, 0, 0, 8540, 16, 3, 16, eeLEV, 9, aLEV, aNEWLEV, 40, 16, 8, 4, wNone, 8, 0, 300, 0, 0, isMAGICBOMBS, 2, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,edCHINK,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO3S + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 8600, 16, 3, 8, eeWALK, 8, aOCTO, a4FRM4DIRF, 12, 12, 4, 4, ewFlame, 4, 3, 100, 64, 3, isMAGICBOMBS, e1tFIREOCTO, e2tFIREOCTO, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO3F + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 8660, 16, 3, 8, eeWALK, 8, aOCTO, a4FRM4DIRF, 12, 12, 4, 4, ewFlame, 4, 5, 200, 64, 3, isMAGICBOMBS, e1tFIREOCTO, e2tFIREOCTO, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 140 eOCTO4S + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 8720, 16, 3, 20, eeWALK, 10, aOCTO, a4FRM4DIRF, 8, 8, 12, 12, ewLitBomb, 4, 3, 100, 64, 3, isMAGICBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eOCTO4F + { 0x00000000, 0x00000000, 92, 4, 0, 0, 0, 0, 8780, 16, 3, 20, eeWALK, 10, aOCTO, a4FRM4DIRF, 8, 8, 12, 12, ewLitBomb, 4, 5, 200, 64, 3, isMAGICBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eTRAP_8WAY + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8840, 16, 2, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_DIAGONAL + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8880, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_SLASH_C + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8900, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_SLASH_LOS + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8920, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_BACKSLASH_C + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8940, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_BACKSLASH_LOS + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8960, 16, 1, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_CW_C + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 8980, 16, 2, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_CW_LOS + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 9020, 16, 2, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // 150 eTRAP_CCW_C + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 9060, 16, 2, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eTRAP_CCW_LOS + { 0x00000008, 0x00000000, 122, 1, 0, 0, 0, 0, 9100, 16, 2, 2, eeTRAP, 7, aNONE, a4FRM4DIR, 16, 16, 4, 4, wNone, 0, 0, 0, 0, 0, isNONE, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSUMMONER + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 9140, 16, 3, 8, eeWIZZ, 9, aWIZZ, aNEWWIZZ, 256, 256, 4, 16, ewMagic, 0, 0, 0, 0, 0, isBOMBS, 0, 3, 0, 0, 74, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eIWIZ + { 0x00000000, 0x00000000, 169, 4, 0, 0, 0, 0, 9200, 16, 3, 8, eeWIZZ, 9, aWIZZ, aNEWWIZZ, 256, 256, 4, 16, ewMagic, 0, 0, 0, 0, 0, isBOMBS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edIGNORE,edIGNORE,edIGNORE,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edIGNORE,0,0 }, 0, WAV_EDEAD, }, + // eSHOOTMAGIC + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 16, ewMagic, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTROCK + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 2, ewRock, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTSPEAR + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 2, ewArrow, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTSWORD + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 8, ewSword, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTFLAME + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 4, ewFlame, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // eSHOOTFLAME2 + { 0x00000000, 0x00000000, 0, 0, 0, 0, 0, 0, 0, 16, 1, 2, eePROJECTILE, 0, aNONE, aNONE, 0, 0, 0, 12, ewFlame2, 0, 0, 0, 0, 0, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX,edX }, 0, WAV_EDEAD, }, + // 160 eBOMBCHU + { 0x00000000, 0x00000000, 126, 2, 0, 0, 0, 0, 9260, 16, 2, 2, eeWALK, 8, aROPE, a4FRM4DIR, 16, 16, 2, 2, ewBomb, 4, 0, 50, 0, 0, isMONEY, 0, e2tBOMBCHU, 1, 8, 0, 0, 0, 0, e9tROPE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFGEL + { 0x00000000, 0x00000000, 120, 2, 0, 0, 0, 0, 9300, 16, 1, 4, eeWALK, 8, a2FRM, a4FRM4DIR, 4, 8, 4, 4, ewFireTrail, 4, 16, 100, 64, 0, isNONE, e1tEACHTILE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFZOL + { 0x00000000, 0x00000000, 137, 2, 0, 0, 0, 0, 9320, 16, 1, 8, eeWALK, 8, a2FRM, a4FRM4DIR, 16, 16, 8, 8, ewFireTrail, 4, 16, 40, 144, 0, isMONEY, e1tEACHTILE, e2tSPLITHIT, 161, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFGELTRIB + { 0x00000000, 0x00000000, 120, 2, 0, 0, 0, 0, 9340, 16, 1, 4, eeWALK, 8, a2FRM, a4FRM4DIR, 4, 8, 4, 4, ewFireTrail, 4, 16, 100, 64, 0, isMAGIC, e1tEACHTILE, e2tTRIBBLE, eFZOLTRIB, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFZOLTRIB + { 0x00000000, 0x00000000, 137, 2, 0, 0, 0, 0, 9360, 16, 1, 8, eeWALK, 8, a2FRM, a4FRM4DIR, 16, 16, 8, 8, ewFireTrail, 4, 16, 40, 144, 0, isMAGICMONEY, e1tEACHTILE, e2tSPLITHIT, eFGELTRIB, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eTEK3 + { 0x00000000, 0x00000000, 103, 2, 0, 0, 0, 0, 9380, 16, 2, 2, eeTEK, 8, aTEK, aNEWTEK, 32, 32, 2, 2, wNone, 0, 0, 250, 0, 0, isMAGICMONEY, 80, 16, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eSPINTILE1 + { 0x00000000, 0x00000000, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, eeSPINTILE, 8, a4FRMNODIR, a4FRMNODIR, 12, 12, 4, 4, wNone, 4, 3, 200, 64, 1, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eSPINTILE2 + { 0x00000000, 0x00000000, 10080, 4, 0, 0, 0, 0, 10080, 0, 0, 2, eeSPINTILE, 8, a4FRM4DIR, a4FRM4DIR, 12, 12, 4, 4, wNone, 4, 3, 200, 64, 1, isNONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eLYNEL3 + { 0x00000000, 0x00000000, 105, 4, 0, 0, 0, 0, 9420, 16, 3, 12, eeWALK, 8, aWALK, a4FRM4DIRF, 12, 16, 8, 8, ewSword, 6, 4, 50, 128, 3, isMAGICBOMBS, 9, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eFPEAHAT + { 0x00000000, 0x00000000, 101, 2, 0, 0, 0, 0, 9480, 16, 6, 4, eePEAHAT, 8, a2FRMPOS, a4FRMPOS8DIR, 0, 0, 2, 2, wNone, 4, 8, 62, 0, 0, isDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNONLY,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // 170 eMPOLSV + { 0x00000000, 0x00000000, 134, 2, 0, 9620, 0, 0, 9600, 16, 2, 20, eeWALK, 7, a2FRM, a4FRM4DIR, 16, 16, 8, 8, wNone, 4, 10, 50, 32, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, e9tPOLSVOICE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,edIGNORE,edIGNORE,edCHINK,edIGNORE,0,ed1HKO,edSTUNONLY,0,0,0,0,ed1HKO,0,0,0,edCHINK,0 }, 0, WAV_EDEAD, }, + // eWPOLSV + { 0x00000000, 0x00000000, 134, 2, 0, 9660, 0, 0, 9640, 16, 4, 20, eeWALK, 7, a2FRM, a4FRM4DIR, 16, 16, 8, 8, wNone, 4, 10, 50, 32, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, e9tPOLSVOICE, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,edIGNORE,edIGNORE,ed1HKO,edIGNORE,0,edCHINK,edSTUNONLY,0,0,0,0,0,0,0,0,edCHINK,0 }, 0, WAV_EDEAD, }, + // eDKNUT4 + { 0x11000000, 0x00000000, 140, 5, 0, 0, 5, 0, 9720, 16, 1, 32, eeWALK, 8, aDWALK, a4FRM4DIR, 16, 16, 16, 4, wNone, 4, 0, 100, 200, 0, isMAGIC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { edSTUNORCHINK,0,0,edCHINK,edIGNORE,0,edCHINK,0,0,0,0,0,0,0,edCHINK,edCHINK,edCHINK,0,0 }, 0, WAV_EDEAD, }, + // eFGHINI + { 0x00000000, 0x00000000, 109, 2, 0, 0, 0, 0, 9740, 16, 2, 18, eeWALK, 8, aGHINI, a4FRMPOS4DIR, 256, 256, 4, 4, wNone, 4, 0, 50, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eMGHINI + { 0x00000000, 0x00000000, 109, 2, 0, 0, 0, 0, 9780, 16, 2, 18, eeWALK, 7, aGHINI, a4FRMPOS4DIR, 256, 256, 4, 4, wNone, 4, 0, 50, 0, 0, isMONEY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGRAPBUGHP + { 0x00000001, 0x00000000, 65, 1, 0, 0, 0, 0, 9820, 16, 4, 2, eeGUY, 7, aFLIP, a4FRM8EYE, 12, 16, 2, 2, wNone, 0, 0, 0, 0, 0, isNONE, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, }, + // eGRAPBUGMP + { 0x00000001, 0x00000000, 65, 1, 0, 0, 0, 0, 10000, 16, 4, 2, eeGUY, 8, aFLIP, a4FRM8EYE, 12, 16, 2, 2, wNone, 0, 0, 0, 0, 0, isNONE, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, 0, WAV_EDEAD, } +}; + +item_drop_object default_item_drop_sets[isMAX]= +{ + { "None", { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Default", { iFairyMoving, i10Rupies, i5Rupies, i1ArrowAmmo, iHeart, iRupy, 0, 0, 0, 0 }, { 60, 3, 3, 5, 7, 12, 20, 0, 0, 0, 0 } }, + { "Bombs", { iFairyMoving, iClock, i10Rupies, iRupy, i5Rupies, i1ArrowAmmo, iHeart, iBombs, 0, 0 }, { 58, 2, 4, 4, 10, 4, 5, 10, 12, 0, 0 } }, + { "Rupees", { iFairyMoving, i10Rupies, iClock, i1ArrowAmmo, i5Rupies, iHeart, iRupy, 0, 0, 0 }, { 45, 3, 3, 5, 7, 15, 10, 22, 0, 0, 0 } }, + { "Life", { iFairyMoving, iRupy, iHeart, 0, 0, 0, 0, 0, 0, 0 }, { 13, 2, 2, 8, 0, 0, 0, 0, 0, 0, 0 } }, + { "Bombs 100%", { iBombs, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Super Bombs 100%", { iSBomb, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Magic", { iLMagic, iSMagic, 0, 0, 0, 0, 0, 0, 0, 0 }, { 19, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Magic + Bombs", { iFairyMoving, iLMagic, i10Rupies, iSMagic, iClock, iRupy, i5Rupies, iHeart, iBombs, 0 }, { 26, 1, 1, 1, 2, 2, 5, 2, 5, 6, 0 } }, + { "Magic + Rupees", { iFairyMoving, iLMagic, i10Rupies, iSMagic, i1ArrowAmmo, iClock, i5Rupies, iHeart, iRupy, 0 }, { 36, 3, 3, 3, 6, 3, 5, 15, 10, 22, 0 } }, + { "Magic + Life", { iFairyMoving, i10Rupies, iLMagic, i1ArrowAmmo, iSMagic, iRupy, iHeart, 0, 0, 0 }, { 10, 2, 1, 2, 2, 4, 8, 24, 0, 0, 0 } }, + { "Magic 100%", { iLMagic, iSMagic, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { "Tall Grass Combos", { iRupy, iHeart, 0, 0, 0, 0, 0, 0, 0, 0 }, { 65, 20, 15, 0, 0, 0, 0, 0, 0, 0, 0 } }, +}; + diff --git a/src/defdata.h b/src/defdata.h new file mode 100644 index 0000000000..fc2e93cc3a --- /dev/null +++ b/src/defdata.h @@ -0,0 +1,25 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// defdata.cc +// +// Default item, weapon, and enemy data for Zelda Classic. +// +// This data was originally hard coded in the item class, +// enemy classes, etc. I exctracted it to make generic +// classes, thus allowing custom items and enemies. +// +//-------------------------------------------------------- + +#ifndef _DEFDATA_H_ +#define _DEFDATA_H_ + +#include "items.h" +#include "guys.h" +extern comboclass default_combo_classes[cMAX]; +extern itemdata default_items[iLast]; +extern guydata default_guys[OLDMAXGUYS]; +extern item_drop_object default_item_drop_sets[isMAX]; +#endif + diff --git a/src/dialog/bitmap/tilePreview.cpp b/src/dialog/bitmap/tilePreview.cpp new file mode 100644 index 0000000000..2a2145681b --- /dev/null +++ b/src/dialog/bitmap/tilePreview.cpp @@ -0,0 +1,61 @@ +#include "tilePreview.h" + +TilePreviewBitmap::TilePreviewBitmap(): + tile(0), + cset(0), + orientation(0), + needsRedrawn(true) +{ +} + +TilePreviewBitmap::TilePreviewBitmap(int t, int cs, Orientation o): + tile(t), + cset(cs), + orientation(o), + needsRedrawn(true) +{ +} + +void TilePreviewBitmap::initialize() +{ + renderer->initialize(16, 16); +} + +void TilePreviewBitmap::redraw() +{ + if(needsRedrawn) + { + renderer->putTile(tile, cset, orientation, 0, 0); + needsRedrawn=false; + } +} + +void TilePreviewBitmap::setCSet(int cs) +{ + cset=cs; + needsRedrawn=true; +} + +void TilePreviewBitmap::setTile(int t) +{ + tile=t; + needsRedrawn=true; +} + +void TilePreviewBitmap::flipHorizontal() +{ + orientation.flipHorizontal(); + needsRedrawn=true; +} + +void TilePreviewBitmap::flipVertical() +{ + orientation.flipVertical(); + needsRedrawn=true; +} + +void TilePreviewBitmap::rotate(Orientation::rotation rot) +{ + orientation.rotate(rot); + needsRedrawn=true; +} diff --git a/src/dialog/bitmap/tilePreview.h b/src/dialog/bitmap/tilePreview.h new file mode 100644 index 0000000000..b93ffd0f12 --- /dev/null +++ b/src/dialog/bitmap/tilePreview.h @@ -0,0 +1,32 @@ +#ifndef _ZC_DIALOG_BITMAP_TILEPREVIEW_H_ +#define _ZC_DIALOG_BITMAP_TILEPREVIEW_H_ + +#include "../../gui/bitmap.h" + +#include + +class TilePreviewBitmap: public GUI::BitmapBackend +{ +public: + TilePreviewBitmap(); + TilePreviewBitmap(int tile, int cset, Orientation orientation); + void initialize(); + void redraw(); + void setCSet(int cset); + void setTile(int tile); + void flipHorizontal(); + void flipVertical(); + void rotate(Orientation::rotation rot); + + inline int getTile() const { return tile; } + inline int getCSet() const { return cset; } + inline Orientation getOrientation() const { return orientation; } + +private: + int tile; + int cset; + Orientation orientation; + bool needsRedrawn; +}; + +#endif diff --git a/src/dialog/bitmap/tileSelector.cpp b/src/dialog/bitmap/tileSelector.cpp new file mode 100644 index 0000000000..d1169d7973 --- /dev/null +++ b/src/dialog/bitmap/tileSelector.cpp @@ -0,0 +1,58 @@ +#include "tileSelector.h" +#include "../zquest/tileSelectorBackend.h" +#include +#include +#include +#include + +TileSelectorBitmap::TileSelectorBitmap(TileSelectorBackend& be): + backend(be), + cursorTimer(0) +{ +} + +void TileSelectorBitmap::initialize() +{ + renderer->initialize(backend.pageWidth*16, backend.pageHeight*16); + widget->setHandleMouseInput(true); +} + +void TileSelectorBitmap::redraw() +{ + renderer->clear(); + cursorTimer=(cursorTimer+1)%20; + + int startTile=backend.getFirstTileOnPage(); + for(int x=0; xputTile(backend.getTileAt(x, y), backend.getCSet(), + 0, x*16, y*16); + + if(cursorTimer<10 && + backend.tileIsSelected(x, y)) + renderer->drawRect(x*16, y*16, 16, 16, 1); + } + } +} + +void TileSelectorBitmap::onMouseInput(const MouseInput& mouse) +{ + switch(mouse.type) + { + case mouse_LEFTBUTTONDOWN: + backend.selectTile( + backend.getTileAt(mouse.x/16, mouse.y/16), + mouse.shiftPressed); + break; + + case mouse_WHEELUP: + backend.modPage(-1, mouse.shiftPressed); + break; + + case mouse_WHEELDOWN: + backend.modPage(1, mouse.shiftPressed); + break; + } +} diff --git a/src/dialog/bitmap/tileSelector.h b/src/dialog/bitmap/tileSelector.h new file mode 100644 index 0000000000..b3994d835e --- /dev/null +++ b/src/dialog/bitmap/tileSelector.h @@ -0,0 +1,20 @@ +#ifndef _ZC_DIALOG_BITMAP_TILESELECTOR_H_ +#define _ZC_DIALOG_BITMAP_TILESELECTOR_H_ + +#include +class TileSelectorBackend; + +class TileSelectorBitmap: public GUI::BitmapBackend +{ +public: + TileSelectorBitmap(TileSelectorBackend& backend); + void initialize(); + void redraw(); + void onMouseInput(const MouseInput& mouse); + +private: + TileSelectorBackend& backend; + int cursorTimer; +}; + +#endif diff --git a/src/dialog/zquest/cheatEditor.cpp b/src/dialog/zquest/cheatEditor.cpp new file mode 100644 index 0000000000..81dd10e679 --- /dev/null +++ b/src/dialog/zquest/cheatEditor.cpp @@ -0,0 +1,47 @@ +#include "cheatEditor.h" +#include "../../gui/factory.h" +#include "../../zdefs.h" // for ZCHEATS +#include +#include + +extern ZCHEATS zcheats; +extern bool saved; + +#define CB(func) boost::bind(&CheatEditor::func, this) + +GUI::Widget* CheatEditor::createDialog(const GUI::WidgetFactory& f) +{ + GUI::Window* win=f.window("Cheat codes", + f.column(GUI::Contents( + enabledCB=f.checkbox("Cheats &enabled"), + f.row(GUI::Contents(f.text("Level 1"), code1=f.textField(40))), + f.row(GUI::Contents(f.text("Level 2"), code2=f.textField(40))), + f.row(GUI::Contents(f.text("Level 3"), code3=f.textField(40))), + f.row(GUI::Contents(f.text("Level 4"), code4=f.textField(40))), + f.buttonRow(GUI::Contents( + f.button("O&K", CB(onOK)), + f.button("&Cancel", CB(shutDown)) + )) + )) + ); + + enabledCB->setValue((zcheats.flags&1)!=0); + code1->setText(zcheats.codes[0]); + code2->setText(zcheats.codes[1]); + code3->setText(zcheats.codes[2]); + code4->setText(zcheats.codes[3]); + + return win; +} + +void CheatEditor::onOK() +{ + zcheats.flags=enabledCB->getValue() ? 1 : 0; + std::strcpy(zcheats.codes[0], code1->getText().c_str()); + std::strcpy(zcheats.codes[1], code2->getText().c_str()); + std::strcpy(zcheats.codes[2], code3->getText().c_str()); + std::strcpy(zcheats.codes[3], code4->getText().c_str()); + + shutDown(); + saved = false; +} diff --git a/src/dialog/zquest/cheatEditor.h b/src/dialog/zquest/cheatEditor.h new file mode 100644 index 0000000000..8b3583dd61 --- /dev/null +++ b/src/dialog/zquest/cheatEditor.h @@ -0,0 +1,25 @@ +#ifndef _ZC_DIALOG_ZQUEST_CHEATEDITOR_H_ +#define _ZC_DIALOG_ZQUEST_CHEATEDITOR_H_ + +#include "../../gui/dialog.h" + +namespace GUI +{ + class Checkbox; + class TextField; +} + +class CheatEditor: public GUI::Dialog +{ +private: + GUI::Checkbox* enabledCB; + GUI::TextField* code1; + GUI::TextField* code2; + GUI::TextField* code3; + GUI::TextField* code4; + + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + void onOK(); +}; + +#endif diff --git a/src/dialog/zquest/infoShopEditor.cpp b/src/dialog/zquest/infoShopEditor.cpp new file mode 100644 index 0000000000..a335e35879 --- /dev/null +++ b/src/dialog/zquest/infoShopEditor.cpp @@ -0,0 +1,92 @@ +#include "infoShopEditor.h" +#include +#include +#include +#include +#include +#include + +InfoShopEditor::InfoShopEditor(infotype& s, const MessageList& ml): + shop(s), + msgList(ml) +{ +} + +#define CB(func) boost::bind(&InfoShopEditor::func, this) +#define MLCB(func) boost::bind(&MessageList::func, msgList) +#define MLCB1(func) boost::bind(&MessageList::func, msgList, _1) + +GUI::Widget* InfoShopEditor::createDialog(const GUI::WidgetFactory& f) +{ + GUI::Window* win=f.window("Edit info shop", + f.column(GUI::Contents( + f.row(GUI::Contents( + f.text("Name: "), + shopName=f.textField(31) + )), + f.column(GUI::Contents( + f.row(GUI::Contents(f.text("Price"), f.text("Message"))), + f.row(GUI::Contents( + prices[0]=f.textField(5), + messages[0]=f.comboBox(new GUI::ListData(MLCB1(getListMessageText), MLCB(getNumMessages))) + )), + f.row(GUI::Contents( + prices[1]=f.textField(5), + messages[1]=f.comboBox(new GUI::ListData(MLCB1(getListMessageText), MLCB(getNumMessages))) + )), + f.row(GUI::Contents( + prices[2]=f.textField(5), + messages[2]=f.comboBox(new GUI::ListData(MLCB1(getListMessageText), MLCB(getNumMessages))) + )) + )), + f.buttonRow(GUI::Contents( + f.button("O&K", CB(onOK)), + f.button("&Cancel", CB(shutDown)) + )) + )) + ); + + shopName->setText(shop.name); + for(int i=0; i<3; i++) + { + if((shop.str[i])!=0) + { + char buf[6]; + sprintf(buf, "%d", shop.price[i]); + prices[i]->setText(buf); + messages[i]->setSelected(msgList.getMessageListPos(shop.str[i])); + } + else + { + prices[i]->setText("0"); + messages[i]->setSelected(0); + } + } + + return win; +} + +void InfoShopEditor::onOK() +{ + sprintf(shop.name, "%s", shopName->getText().c_str()); + + int j=0; + for(int i=0; i<3; i++) + { + int msg=messages[i]->getSelected(); + if(msg==0) + // Don't put a blank message in the shop + continue; + shop.price[j]=clamp(atoi(prices[i]->getText().c_str()), 0, 65535); + shop.str[j]=msgList.getMessageNum(msg); + j++; + } + + for(; j<3; j++) + { + shop.price[j]=0; + shop.str[j]=0; + } + + shutDown(); +} diff --git a/src/dialog/zquest/infoShopEditor.h b/src/dialog/zquest/infoShopEditor.h new file mode 100644 index 0000000000..ed592a5498 --- /dev/null +++ b/src/dialog/zquest/infoShopEditor.h @@ -0,0 +1,32 @@ +#ifndef _ZC_DIALOG_ZQUEST_INFOSHOPEDITOR_H_ +#define _ZC_DIALOG_ZQUEST_INFOSHOPEDITOR_H_ + + +#include + +struct infotype; +class MessageList; +namespace GUI +{ + class TextField; + class List; +} + +// Edits info shops. +class InfoShopEditor: public GUI::Dialog +{ +public: + InfoShopEditor(infotype& shop, const MessageList& msgList); + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + +private: + infotype& shop; + GUI::TextField* shopName; + GUI::TextField* prices[3]; + GUI::List* messages[3]; + const MessageList& msgList; + + void onOK(); +}; + +#endif diff --git a/src/dialog/zquest/paletteViewer.cpp b/src/dialog/zquest/paletteViewer.cpp new file mode 100644 index 0000000000..fd00a50e22 --- /dev/null +++ b/src/dialog/zquest/paletteViewer.cpp @@ -0,0 +1,45 @@ +#include "paletteViewer.h" +#include "../../gui/factory.h" +#include + +#include "../../gui/bitmap.h" + +namespace +{ + +class PaletteViewerBitmap: public GUI::BitmapBackend +{ +public: + void initialize() + { + // There should be a better way to handle colors... + renderer->initialize(257, 257); + for(int cset=0; cset<16; cset++) + { + for(int color=0; color<16; color++) + { + int x=color*16; + int y=cset*16; + renderer->fillRect(x, y, 17, 17, 241); // 241 is black + renderer->fillRect(x+1, y+1, 15, 15, cset*16+color); + } + } + } + + void redraw() + { + // Never changes - nothing to do + } +}; + +} + +GUI::Widget* PaletteViewer::createDialog(const GUI::WidgetFactory& f) +{ + return f.window("Current palette", + f.column(GUI::Contents( + f.bitmap(new PaletteViewerBitmap(), 1), + f.button("O&K", boost::bind(&PaletteViewer::shutDown, this)) + )) + ); +} diff --git a/src/dialog/zquest/paletteViewer.h b/src/dialog/zquest/paletteViewer.h new file mode 100644 index 0000000000..9ead1bc4c6 --- /dev/null +++ b/src/dialog/zquest/paletteViewer.h @@ -0,0 +1,12 @@ +#ifndef _ZC_DIALOG_ZQUEST_PALETTEVIEWER_H_ +#define _ZC_DIALOG_ZQUEST_PALETTEVIEWER_H_ + +#include "../../gui/dialog.h" + +class PaletteViewer: public GUI::Dialog +{ +private: + GUI::Widget* createDialog(const GUI::WidgetFactory& f); +}; + +#endif diff --git a/src/dialog/zquest/questRules.cpp b/src/dialog/zquest/questRules.cpp new file mode 100644 index 0000000000..a1bc70aa7c --- /dev/null +++ b/src/dialog/zquest/questRules.cpp @@ -0,0 +1,239 @@ +#include "questRules.h" +#include "../../gui/factory.h" +#include "../../zdefs.h" +#include "../../zsys.h" +#include +#include +#include + +extern zinitdata zinit; +extern byte quest_rules[QUESTRULES_SIZE]; + +using namespace GUI; + +namespace +{ + +struct RuleData +{ + int id; + const char* description; +}; + +const RuleData animationRules[]={ + { qr_BSZELDA, "BS-Zelda Animation" }, + { qr_COOLSCROLL, "Circle Opening/Closing Wipes" }, + { qr_OVALWIPE, "Oval Opening/Closing Wipes" }, + { qr_TRIANGLEWIPE, "Triangle Opening/Closing Wipes" }, + { qr_SMASWIPE, "Super Mario All-Stars Opening/Closing Wipes" }, + { qr_EXPANDEDLTM, "Expanded Link Tile Modifiers" }, + { qr_NOSCROLL, "No Screen Scrolling" }, + { qr_FASTDNGN, "Fast Dungeon Scrolling" }, + { qr_VERYFASTSCROLLING, "Very Fast Scrolling" }, + { qr_SMOOTHVERTICALSCROLLING, "Smooth Vertical Scrolling" }, + { qr_FFCSCROLL, "FFCs Are Visible While The Screen Is Scrolling" }, + { qr_FADE, "Interpolated Fading" }, + { qr_FADECS5, "Fade CSet 5" }, + { qr_LINKFLICKER, "Invincible Link Flickers" }, + { qr_HOLDITEMANIMATION, "Items Held Above Link's Head Continue To Animate" }, + { qr_NOBOMBPALFLASH, "Bomb Explosions Don't Flash Palette" }, + { qr_LAYER12UNDERCAVE, "Layers 1 and 2 Are Drawn Under Caves" }, + { -1, "" } +}; + +const RuleData comboRules[]={ + { qr_DROWN, "Link Drowns in Walkable Water" }, + { qr_SMARTSCREENSCROLL, "Smart Screen Scrolling" }, + { qr_SOLIDBLK, "Can't Push Blocks Onto Unwalkable Combos" }, + { qr_HESITANTPUSHBLOCKS, "Push Blocks Don't Move When Bumped" }, + { qr_INSTABURNFLAGS, "Burn Flags Are Triggered Instantly" }, + { qr_SWORDMIRROR, "Magic Mirror/Prism Combos Reflect Sword Beams" }, + { qr_WHIRLWINDMIRROR, "Magic Mirrors Reflect Whistle Whirlwinds" }, + { qr_CMBCYCLELAYERS, "Combo Cycling On Layers" }, + { qr_DMGCOMBOPRI, "Full Priority Damage Combos" }, + { qr_WARPSIGNOREARRIVALPOINT, "Warps Ignore Arrival X/Y Position When Setting Continue Screen" }, + { qr_NOARRIVALPOINT, "Use Warp Return Points Only" }, + { qr_NOSCROLLCONTINUE, "Scrolling Warps Don't Set The Continue Point" }, + { qr_OLDSTYLEWARP, "Use Old-Style Warp Detection (NES Movement Only)" }, + { qr_DMGCOMBOLAYERFIX, "Damage Combos Work On Layers 1 And 2" }, + { qr_HOOKSHOTLAYERFIX, "Hookshot Grab Combos Work On Layers 1 And 2" }, + { -1, "" } +}; + +const RuleData itemRules[]={ + { qr_ENABLEMAGIC, "Enable Magic" }, + { qr_Z3BRANG_HSHOT, "New Boomerang/Hookshot" }, + { qr_TRUEARROWS, "True Arrows" }, + { qr_NODIVING, "No Diving" }, + { qr_TEMPCANDLELIGHT, "Dark Rooms Stay Lit Only While Fire Is On Screen" }, + { qr_FIREPROOFLINK, "Link Isn't Hurt By Own Fire Weapons" }, + { qr_OUCHBOMBS, "Link's Bombs Hurt Link" }, + { qr_RINGAFFECTDAMAGE, "Rings Affect Damage Combos" }, + { qr_QUICKSWORD, "Quick Sword" }, + { qr_SLASHFLIPFIX, "Flip Right-Facing Slash" }, + { qr_NOWANDMELEE, "Wand Can't Be Used As Melee Weapon" }, + { qr_NOITEMMELEE, "Melee Weapons Can't Pick Up Items" }, + { qr_BRANGPICKUP, "Boomerang/Hookshot Grabs All Items" }, + { qr_HEARTSREQUIREDFIX, "'Hearts Required' Affects Non-Special Items" }, + { qr_4TRI, "Big Triforce Pieces" }, + { qr_3TRI, "3 or 6 Triforce Total" }, + { qr_SLOWCHARGINGWALK, "Slow Walk While Charging" }, + { qr_LENSHINTS, "Show Secret Combo Hints When Using The Lens" }, + { qr_RAFTLENS, "Lens Shows Raft Paths" }, + { qr_LENSSEESENEMIES, "Lens Reveals Invisible Enemies" }, + { qr_NONBUBBLEMEDICINE, "Medicine Doesn't Remove Sword Jinxes" }, + { qr_NONBUBBLEFAIRIES, "Fairies Don't Remove Sword Jinxes" }, + { qr_NONBUBBLETRIFORCE, "Triforce Doesn't Remove Sword Jinxes" }, + { qr_ITEMBUBBLE, "Things That Remove Sword Jinxes Also Remove Item Jinxes" }, + { -1, "" } +}; + +const RuleData enemyRules[]={ + { qr_NEWENEMYTILES, "Use New Enemy Tiles" }, + { qr_ENEMIESZAXIS, "Enemies Jump/Fly Through Z-Axis" }, + { qr_HIDECARRIEDITEMS, "Hide Enemy-Carried Items" }, + { qr_ALWAYSRET, "Enemies Always Return" }, + { qr_NOTMPNORET, "Temporary No Return Disabled" }, + { qr_KILLALL, "Must Kill All Bosses To Set 'No Return' Screen State" }, + { qr_MEANTRAPS, "Multi-Directional Traps" }, + { qr_MEANPLACEDTRAPS, "Line-of-Sight Traps Can Move Across Entire Screen" }, + { qr_PHANTOMPLACEDTRAPS, "Constant Traps Can Pass Through Enemies" }, + { qr_WALLFLIERS, "Flying Enemies Can Appear on Unwalkable Combos" }, + { qr_BRKNSHLDTILES, "Broken Enemy Shield Tiles" }, + { qr_NOFLASHDEATH, "Enemies Don't Flash When Dying" }, + { qr_SHADOWS, "Show Shadows" }, + { qr_TRANSSHADOWS, "Translucent Shadows" }, + { qr_SHADOWSFLICKER, "Shadows Flicker" }, + { qr_ENEMIESFLICKER, "Enemies Flicker When Hit" }, + { -1, "" } +}; + +const RuleData nesFixesRules[]={ + { qr_FREEFORM, "Freeform Dungeons" }, + { qr_SAFEENEMYFADE, "Can Safely Trigger Armos/Grave From The South" }, + { qr_ITEMSONEDGES, "Can Use Items/Weapons on Edge of Screen" }, + { qr_LINKDUNGEONPOSFIX, "Fix Link's Position in Dungeons" }, + { qr_RLFIX, "Raft/Ladder Sprite Direction Fix" }, + { qr_NOLEVEL3FIX, "No Palette 3 CSet 6 Fix" }, + { qr_BOMBHOLDFIX, "Link Holds Special Bombs Over His Head" }, + { qr_HOLDNOSTOPMUSIC, "Holding Up Items Doesn't Restart Music" }, + { qr_CAVEEXITNOSTOPMUSIC, "Leaving Item Cellar/Passageway Doesn't Restart Music" }, + { qr_OVERWORLDTUNIC, "Tunic Color Can Change On Overworld" }, + { qr_SWORDWANDFLIPFIX, "Sword/Wand Flip Fix" }, + { qr_PUSHBLOCKCSETFIX, "Push Block CSet Fix" }, + { qr_TRAPPOSFIX, "Trap Position Fix" }, + { qr_NOBORDER, "No Invisible Border on Non-Dungeon Dmaps" }, + { qr_OLDPICKUP, "Items Disappear During Hold-Up" }, + { qr_SUBSCREENOVERSPRITES, "Subscreen Appears Above Sprites" }, + { qr_BOMBDARKNUTFIX, "Correct Bomb/Darknut Interaction" }, + { qr_OFFSETEWPNCOLLISIONFIX, "Correct Offset Enemy Weapon Collision Detection" }, + { qr_ITEMSINPASSAGEWAYS, "Special Items Don't Appear In Passageways" }, + { qr_NOFLICKER, "No NES Sprite Flicker" }, + { qr_FIREPROOFLINK2, "Invincible Link Isn't Hurt By Own Fire Weapons" }, + { qr_NOITEMOFFSET, "No Position Offset Of Screen Items" }, + { qr_LADDERANYWHERE, "Allow Ladder Anywhere" }, + { -1, "" } +}; + +const RuleData miscRules[]={ + { qr_SELECTAWPN, "Can Select A-Button Weapon On Subscreen" }, + { qr_MORESOUNDS, "More Sound Effects" }, + { qr_FASTFILL, "Fast Heart Refill" }, + { qr_QUARTERHEART, "Enable 1/4 Heart Life Bar" }, + { qr_ALLOWFASTMSG, "Messages Can Be Sped Up With The A Button" }, + { qr_ALLOWMSGBYPASS, "Messages Can Be Bypassed With The B Button" }, + { qr_MSGFREEZE, "Messages Freeze All Action" }, + { qr_MSGDISAPPEAR, "Messages Disappear" }, + { qr_TIME, "Show Time On Subscreen" }, + { qr_HEARTRINGFIX, "Healing Fairy Heart Circle Is Centered Around Link" }, + { qr_NOHEARTRING, "No Healing Fairy Heart Circle" }, + { qr_NOSAVE, "No Saving When Continuing" }, + { qr_NOCONTINUE, "Skip Continue Screen" }, + { qr_NOGUYFIRES, "No Fires In Special Rooms" }, + { qr_NOGUYPOOF, "Special Room Guys Don't Create A Puff When Appearing" }, + { qr_LOG, "Log Game Events To Allegro.log" }, + { qr_SCRIPTERRLOG, "Log Script Errors To Allegro.log" }, + { qr_SHOPCHEAT, "Draining Rupees Can Still Be Spent" }, + { -1, "" } +}; + +const RuleData compatRules[]={ + { qr_GOTOLESSNOTEQUAL, "Old GOTOLESS Behavior" }, + { qr_OLDLENSORDER, "Old Lens Drawing Order" }, + { qr_NOFAIRYGUYFIRES, "No Fairy Guy Fires" }, + { qr_TRIGGERSREPEAT, "Continuous Step Triggers" }, + { qr_HOOKSHOTDOWNBUG, "Downward Hookshot Bug" }, + { qr_REPLACEOPENDOORS, "Fix Open Door Solidity" }, + { qr_NOSOLIDDAMAGECOMBOS, "No Solid Damage Combos" }, + { qr_OLDHOOKSHOTGRAB, "Old Hookshot Grab Checking" }, + { qr_PEAHATCLOCKVULN, "Peahats Are Vulnerable When Frozen By Clocks" }, + { qr_OFFSCREENWEAPONS, "Weapons With No Collision Detection Move Offscreen" }, + { -1, "" } +}; + +void addTab(const std::string& name, const RuleData* rules, + const WidgetFactory& f, TabPanel* tp, std::vector& checkboxes) +{ + SerialContainer* column=f.column(); + + for(int i=0; rules[i].id>-1; i++) + { + Checkbox* cb=f.checkbox(rules[i].description); + cb->setValue(get_bit(quest_rules, rules[i].id)!=0); + cb->setUserID(rules[i].id); + column->add(cb); + checkboxes.push_back(cb); + } + + tp->addTab(name, column); +} + +} // namespace + +#define CB(func) boost::bind(&QuestRulesEditor::func, this) + +Widget* QuestRulesEditor::createDialog(const WidgetFactory& f) +{ + TabPanel* tabPanel; + + Window* win=f.window("Quest rules", + f.column(Contents( + tabPanel=f.tabPanel(), + f.buttonRow(Contents( + f.button("O&K", CB(onOK)), + f.button("&Cancel", CB(shutDown)) + )) + )) + ); + + checkboxes.reserve(160); + addTab("&Animation", animationRules, f, tabPanel, checkboxes); + addTab("C&ombos", comboRules, f, tabPanel, checkboxes); + addTab("&Items", itemRules, f, tabPanel, checkboxes); + addTab("&Enemy", enemyRules, f, tabPanel, checkboxes); + addTab("&NES fixes", nesFixesRules, f, tabPanel, checkboxes); + addTab("&Misc.", miscRules, f, tabPanel, checkboxes); + addTab("&Backward compatibility", compatRules, f, tabPanel, checkboxes); + + return win; +} + +void QuestRulesEditor::onOK() +{ + for(int i=0; igetUserID(), cb->getValue()); + } + + shutDown(); + + // For 2.50.0 and 2.50.1. This can be removed when the quest format changes + // (i.e. when those versions can't open new quest files). + if(get_bit(quest_rules, qr_VERYFASTSCROLLING)) + set_bit(quest_rules, qr_FASTDNGN, 1); + + // Left over from zq_rules.cpp: + //this is only here until the subscreen style is selectable by itself + zinit.subscreen_style=get_bit(quest_rules,qr_COOLSCROLL)?1:0; +} diff --git a/src/dialog/zquest/questRules.h b/src/dialog/zquest/questRules.h new file mode 100644 index 0000000000..fe7d53d9b2 --- /dev/null +++ b/src/dialog/zquest/questRules.h @@ -0,0 +1,21 @@ +#ifndef _ZC_DIALOG_ZQUEST_QUESTRULES_H_ +#define _ZC_DIALOG_ZQUEST_QUESTRULES_H_ + +#include "../../gui/dialog.h" +#include + +namespace GUI +{ + class Checkbox; +} + +class QuestRulesEditor: public GUI::Dialog +{ +private: + std::vector checkboxes; + + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + void onOK(); +}; + +#endif diff --git a/src/dialog/zquest/shopEditor.cpp b/src/dialog/zquest/shopEditor.cpp new file mode 100644 index 0000000000..71fabd1db8 --- /dev/null +++ b/src/dialog/zquest/shopEditor.cpp @@ -0,0 +1,135 @@ +#include "shopEditor.h" +#include +#include +#include +#include "../bitmap/tilePreview.h" +#include +#include +#include + +extern bool saved; + +// This one's still pretty ugly. Needs a better interface for the items. + +ShopEditor::ShopEditor(shoptype& s, const item_struct* il): + shop(s), + itemList(il) +{ +} + +#define CB(func) boost::bind(&ShopEditor::func, this) +#define CB1(func) boost::bind(&ShopEditor::func, this, _1) +#define CBID1(func, id) boost::bind(&ShopEditor::func, this, id, _1) + +GUI::Widget* ShopEditor::createDialog(const GUI::WidgetFactory& f) +{ + GUI::Window* win=f.window("Edit shop", + f.column(GUI::Contents( + f.row(GUI::Contents( + f.text("Name: "), + shopName=f.textField(31) + )), + f.column(GUI::Contents( + f.row(GUI::Contents(f.text("Price"), f.text("Item"))), + f.row(GUI::Contents( + prices[0]=f.textField(5), + shopItems[0]=f.comboBox(new GUI::ListData(CB1(getItemText), CB(getNumItems))), + f.bitmap(itemPreview[0]=new TilePreviewBitmap()) + )), + f.row(GUI::Contents( + prices[1]=f.textField(5), + shopItems[1]=f.comboBox(new GUI::ListData(CB1(getItemText), CB(getNumItems))), + f.bitmap(itemPreview[1]=new TilePreviewBitmap()) + )), + f.row(GUI::Contents( + prices[2]=f.textField(5), + shopItems[2]=f.comboBox(new GUI::ListData(CB1(getItemText), CB(getNumItems))), + f.bitmap(itemPreview[2]=new TilePreviewBitmap()) + )) + )), + f.buttonRow(GUI::Contents( + f.button("O&K", CB(onOK)), + f.button("&Cancel", CB(shutDown)) + )) + )) + ); + + shopName->setText(shop.name); + for(int i=0; i<3; i++) + { + shopItems[i]->setOnValueChanged(CBID1(onItemChanged, i)); + + if((shop.hasitem[i])!=0) + { + int it=0; + for(int j=0; j<257; j++) + { + if(itemList[j].i==shop.item[i]) + { + it=j; + break; + } + } + char buf[6]; + sprintf(buf, "%d", shop.price[i]); + prices[i]->setText(buf); + shopItems[i]->setSelected(it); + itemPreview[i]->setTile(itemsbuf[shop.item[i]].tile); + itemPreview[i]->setCSet(itemsbuf[shop.item[i]].csets&15); + } + else + { + prices[i]->setText("0"); + shopItems[i]->setSelected(0); + } + } + + return win; +} + +void ShopEditor::onItemChanged(int id, int newItem) +{ + int sel=shopItems[id]->getSelected(); + int it=itemList[sel].i; + itemPreview[id]->setTile(itemsbuf[it].tile); + itemPreview[id]->setCSet(itemsbuf[it].csets&15); +} + +void ShopEditor::onOK() +{ + sprintf(shop.name, "%s", shopName->getText().c_str()); + + int j=0; + for(int i=0; i<3; i++) + { + int it=shopItems[i]->getSelected(); + if(it==0) + // Don't make nothing buyable... + continue; + shop.hasitem[j]=1; + shop.price[j]=clamp(atoi(prices[i]->getText().c_str()), 0, 65535); + shop.item[j]=itemList[it].i; + j++; + } + + for(; j<3; j++) + { + shop.hasitem[j]=0; + shop.price[j]=0; + shop.item[j]=0; + } + + saved=false; + + shutDown(); +} + +std::string ShopEditor::getItemText(int id) const +{ + return itemList[id].s; +} + +int ShopEditor::getNumItems() const +{ + return 257; // 256 + none +} diff --git a/src/dialog/zquest/shopEditor.h b/src/dialog/zquest/shopEditor.h new file mode 100644 index 0000000000..745b8b23fc --- /dev/null +++ b/src/dialog/zquest/shopEditor.h @@ -0,0 +1,37 @@ +#ifndef _ZC_DIALOG_ZQUEST_SHOPEDITOR_H_ +#define _ZC_DIALOG_ZQUEST_SHOPEDITOR_H_ + +#include +#include + +struct item_struct; +struct shoptype; +class TilePreviewBitmap; +namespace GUI +{ + class TextField; + class List; +} + +// Edits shops. +class ShopEditor: public GUI::Dialog +{ +public: + ShopEditor(shoptype& shop, const item_struct* itemList); + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + +private: + shoptype& shop; + const item_struct* itemList; + GUI::TextField* shopName; + GUI::TextField* prices[3]; + GUI::List* shopItems[3]; + TilePreviewBitmap* itemPreview[3]; + + void onItemChanged(int id, int newItem); + void onOK(); + std::string getItemText(int id) const; + int getNumItems() const; +}; + +#endif diff --git a/src/dialog/zquest/simpleListSelector.cpp b/src/dialog/zquest/simpleListSelector.cpp new file mode 100644 index 0000000000..4796e342a0 --- /dev/null +++ b/src/dialog/zquest/simpleListSelector.cpp @@ -0,0 +1,81 @@ +#include "simpleListSelector.h" +#include +#include + +SimpleListSelector::SimpleListSelector(const std::string& t, + const boost::function& strF, int num, bool em, int init): + editMode(em), + title(t), + stringFunc(strF), + numItems(num), + selected(-1), + list(0), + initialSelection(init) +{ +} + +SimpleListSelector::SimpleListSelector(const std::string& t, + const boost::function& strF, int num, + const boost::function& helpF, bool em, int init): + editMode(em), + title(t), + stringFunc(strF), + helpFunc(helpF), + numItems(num), + selected(-1), + list(0), + initialSelection(init) +{ +} + +#define CB(func) boost::bind(&SimpleListSelector::func, this) +#define CB1(func) boost::bind(&SimpleListSelector::func, this, _1) + +GUI::Widget* SimpleListSelector::createDialog(const GUI::WidgetFactory& f) +{ + GUI::SerialContainer* buttons=f.buttonRow(); + buttons->add(f.button(editMode ? "&Edit" : "O&K", CB(onOK))); + if(helpFunc) + buttons->add(f.button("Help", CB(onHelp))); + buttons->add(f.button(editMode ? "&Done" : "&Cancel", CB(onCancel))); + + GUI::Window* win=f.window(title, + f.column(GUI::Contents( + list=f.list(new GUI::ListData(stringFunc, CB(getNumItems))), + buttons + )) + ); + + list->setSelected(initialSelection); + list->setOnDoubleClick(CB1(onDoubleClick)); + selected=-1; + + return win; +} + +void SimpleListSelector::onDoubleClick(int item) +{ + onOK(); +} + +void SimpleListSelector::onOK() +{ + selected=list->getSelected(); + shutDown(); +} + +void SimpleListSelector::onCancel() +{ + selected=-1; + shutDown(); +} + +void SimpleListSelector::onHelp() +{ + helpFunc(list->getSelected()); +} + +int SimpleListSelector::getNumItems() const +{ + return numItems; +} diff --git a/src/dialog/zquest/simpleListSelector.h b/src/dialog/zquest/simpleListSelector.h new file mode 100644 index 0000000000..91261b4ae8 --- /dev/null +++ b/src/dialog/zquest/simpleListSelector.h @@ -0,0 +1,50 @@ +#ifndef _ZC_DIALOG_ZQUEST_SIMPLELISTSELECTOR_H_ +#define _ZC_DIALOG_ZQUEST_SIMPLELISTSELECTOR_H_ + +#include +#include +#include + +namespace GUI +{ + class List; +} + +class SimpleListSelector: public GUI::Dialog +{ +public: + SimpleListSelector(const std::string& title, + const boost::function& stringFunc, int numItems, + bool editMode, int initialSelection); + SimpleListSelector(const std::string& title, + const boost::function& stringFunc, int numItems, + const boost::function& helpFunc, bool editMode, + int initialSelection); + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + + /// Get the item selected before the dialog was closed. + /** Returns -1 if nothing was selected. */ + inline int getSelected() const { return selected; } + + /// Set the initial selection when the dialog opens. + /** Mainly useful when closing and opening it repeatedly. */ + inline void setInitialSelection(int sel) { initialSelection=sel; } + +private: + const bool editMode; // Show Edit/Done rather than OK/Cancel + const std::string title; + const boost::function stringFunc; + const boost::function helpFunc; + const int numItems; + int selected; + int initialSelection; + GUI::List* list; + + void onDoubleClick(int item); + void onOK(); // Or edit + void onCancel(); // Or done + void onHelp(); + int getNumItems() const; +}; + +#endif diff --git a/src/dialog/zquest/tileSelector.cpp b/src/dialog/zquest/tileSelector.cpp new file mode 100644 index 0000000000..7baabeb832 --- /dev/null +++ b/src/dialog/zquest/tileSelector.cpp @@ -0,0 +1,174 @@ +#include "tileSelector.h" +#include "../bitmap/tileSelector.h" +#include "../bitmap/tilePreview.h" +#include +#include +#include +#include +#include +#include +#include +#include + +TileSelector::TileSelector(int tile, int cset, Orientation orientation): + backend(*this, tile, cset), + tsBmp(new TileSelectorBitmap(backend)), + currTileBmp(new TilePreviewBitmap(tile, cset, orientation)), + tileBmp2(new TilePreviewBitmap(tile, cset, orientation)), + pageSelector(0), + currTileText(0), + currCSetText(0), + cancel(true) +{ + +} + +#define CB(func) boost::bind(&TileSelector::func, this) + +GUI::Widget* TileSelector::createDialog(const GUI::WidgetFactory& f) +{ + char tileBuf[20]; + std::sprintf(tileBuf, "Old tile: %d", tileBmp2->getTile()); + + GUI::SerialContainer* rightColumn=f.column(GUI::Contents( + f.text("Page:"), + pageSelector=f.spinner(0, backend.lastPage), + f.bitmap(currTileBmp), + currTileText=f.text(""), + currCSetText=f.text(""), + f.bitmap(tileBmp2), + f.text(tileBuf) + )); + + GUI::Window* win=f.window("Select tile", + f.column(GUI::Contents( + f.row(GUI::Contents( + f.bitmap(tsBmp), + rightColumn + )), + f.buttonRow(GUI::Contents( + f.button("O&K", CB(onOK)), + f.button("&Cancel", CB(shutDown)) + )) + )) + ); + + pageSelector->setOnValueChanged( + boost::bind(&TileSelectorBackend::setPage, &backend, _1, false)); + + onPageChanged(); + onCSetChanged(); + + return win; +} + +bool TileSelector::onKeyPressed(const KeyInput& key) +{ + bool handled=true; + + switch(key.key) + { + case key_PLUS: + backend.modCSet(1); + break; + + case key_MINUS: + backend.modCSet(-1); + break; + + case key_PAGEUP: + backend.modPage(-1, key.shiftPressed); + break; + + case key_PAGEDOWN: + backend.modPage(1, key.shiftPressed); + break; + + case key_UP: + backend.moveCursor(TileSelectorBackend::cm_UP, key.shiftPressed); + break; + + case key_DOWN: + backend.moveCursor(TileSelectorBackend::cm_DOWN, key.shiftPressed); + break; + + case key_LEFT: + backend.moveCursor(TileSelectorBackend::cm_LEFT, key.shiftPressed); + break; + + case key_RIGHT: + backend.moveCursor(TileSelectorBackend::cm_RIGHT, key.shiftPressed); + break; + + case key_HOME: + if(key.ctrlPressed) + backend.setPage(0, key.shiftPressed); + backend.moveCursor(TileSelectorBackend::cm_START, key.shiftPressed); + break; + + case key_END: + if(key.ctrlPressed) + backend.setPage(backend.lastPage, key.shiftPressed); + backend.moveCursor(TileSelectorBackend::cm_END, key.shiftPressed); + break; + + case key_SPACE: + backend.toggleSelectMode(); + break; + + case key_H: + currTileBmp->flipHorizontal(); + break; + + case key_V: + currTileBmp->flipVertical(); + break; + + case key_R: + if(key.shiftPressed) + currTileBmp->rotate(Orientation::rot_90CCW); + else + currTileBmp->rotate(Orientation::rot_90CW); + break; + + default: + handled=false; + break; + } + + if(handled) + return true; + else + return Dialog::onKeyPressed(key); +} + +void TileSelector::onTileChanged() +{ + int tile=backend.getTile(); + char buf[20]; + std::sprintf(buf, "Tile: %d", tile); + currTileText->setText(buf); + currTileBmp->setTile(tile); +} + +void TileSelector::onCSetChanged() +{ + int cset=backend.getCSet(); + char buf[20]; + std::sprintf(buf, "CSet: %d", cset); + currCSetText->setText(buf); + currTileBmp->setCSet(cset); +} + +void TileSelector::onPageChanged() +{ + int page=backend.getPage(); + pageSelector->setValue(page); + onTileChanged(); +} + +void TileSelector::onOK() +{ + cancel=false; + shutDown(); +} diff --git a/src/dialog/zquest/tileSelector.h b/src/dialog/zquest/tileSelector.h new file mode 100644 index 0000000000..c91f78f8b4 --- /dev/null +++ b/src/dialog/zquest/tileSelector.h @@ -0,0 +1,48 @@ +#ifndef _ZC_DIALOG_ZQUEST_TILESELECTOR_H_ +#define _ZC_DIALOG_ZQUEST_TILESELECTOR_H_ + +#include +#include "tileSelectorBackend.h" + +#include "../bitmap/tilePreview.h" +#include +class TileSelectorBitmap; +//class TilePreviewBitmap; +namespace GUI +{ + class Spinner; + class Text; +} + +class TileSelector: public GUI::Dialog +{ +public: + TileSelector(int tile, int cset, Orientation orientation); + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + bool onKeyPressed(const KeyInput& key); + void onOK(); + + // Used to retrieve the user's selection after the dialog is closed. + inline bool userCanceled() const { return cancel; } + inline int getTile() const { return backend.getTile(); } + inline int getCSet() const { return backend.getCSet(); } + inline int getOrientation() const { return currTileBmp->getOrientation(); } + +private: + TileSelectorBackend backend; + TileSelectorBitmap* tsBmp; + TilePreviewBitmap* currTileBmp; + TilePreviewBitmap* tileBmp2; // Old or copied tile + GUI::Spinner* pageSelector; + GUI::Text* currTileText; + GUI::Text* currCSetText; + bool cancel; + + void onTileChanged(); + void onCSetChanged(); + void onPageChanged(); + + friend class TileSelectorBackend; +}; + +#endif diff --git a/src/dialog/zquest/tileSelectorBackend.cpp b/src/dialog/zquest/tileSelectorBackend.cpp new file mode 100644 index 0000000000..49390879d6 --- /dev/null +++ b/src/dialog/zquest/tileSelectorBackend.cpp @@ -0,0 +1,106 @@ +#include "tileSelectorBackend.h" +#include "tileSelector.h" +#include +#include + +using std::min; +using std::max; + +TileSelectorBackend::TileSelectorBackend(TileSelector& dlg, int t, int cs): + dialog(dlg), + multiSelectEnabled(false), + currentPage(t/pageSize), + cursorPos(t), + selectPos(t), + cset(cs), + selectMode(sm_RECTANGLE) +{ +} + +void TileSelectorBackend::moveCursor(cursorMoveType type, bool multiSelect) +{ + int oldPage=currentPage; + + switch(type) + { + case cm_UP: + cursorPos-=pageWidth; + break; + + case cm_DOWN: + cursorPos+=pageWidth; + break; + + case cm_LEFT: + cursorPos-=1; + break; + + case cm_RIGHT: + cursorPos+=1; + break; + + case cm_START: + cursorPos=currentPage*pageSize; + break; + + case cm_END: + cursorPos=(currentPage+1)*pageSize-1; + break; + } + + cursorPos=vbound(cursorPos, 0, lastTile); + int page=cursorPos/pageSize; + if(page!=oldPage) + { + currentPage=page; + dialog.onPageChanged(); + } + else + dialog.onTileChanged(); + + if(!(multiSelect && multiSelectEnabled)) + selectPos=cursorPos; +} + +bool TileSelectorBackend::tileIsSelected(int x, int y) const +{ + if(selectMode==sm_LINEAR) + { + int tile=getTileAt(x, y); + int start=min(cursorPos, selectPos); + int end=max(cursorPos, selectPos); + return tile>=start && tile<=end; + } + else + { + y+=currentPage*pageHeight; + int left=min(cursorPos%pageWidth, selectPos%pageWidth); + int right=max(cursorPos%pageWidth, selectPos%pageWidth); + int top=min(cursorPos/pageWidth, selectPos/pageWidth); + int bottom=max(cursorPos/pageWidth, selectPos/pageWidth); + return x>=left && x<=right && y>=top && y<=bottom; + } +} + +void TileSelectorBackend::selectTile(int tile, bool multiSelect) +{ + cursorPos=tile; + if(!(multiSelect && multiSelectEnabled)) + selectPos=cursorPos; + dialog.onTileChanged(); +} + +void TileSelectorBackend::setPage(int page, bool multiSelect) +{ + currentPage=clamp(page, 0, lastPage); + cursorPos=currentPage*pageSize+(cursorPos%pageSize); + if(!(multiSelect && multiSelectEnabled)) + selectPos=cursorPos; + dialog.onPageChanged(); +} + +void TileSelectorBackend::modCSet(int amount) +{ + cset=wrap(cset+amount, 0, 11); + dialog.onCSetChanged(); +} diff --git a/src/dialog/zquest/tileSelectorBackend.h b/src/dialog/zquest/tileSelectorBackend.h new file mode 100644 index 0000000000..2b0b8843a8 --- /dev/null +++ b/src/dialog/zquest/tileSelectorBackend.h @@ -0,0 +1,63 @@ +#ifndef _ZC_DIALOG_ZQUEST_TILESELECTORBACKEND_H_ +#define _ZC_DIALOG_ZQUEST_TILESELECTORBACKEND_H_ + +class TileSelector; + +class TileSelectorBackend +{ +public: + enum cursorMoveType + { + cm_UP, cm_DOWN, cm_LEFT, cm_RIGHT, cm_START, cm_END + }; + + static const int pageWidth=20; + static const int pageHeight=13; + static const int pageSize=20*13; + static const int lastPage=251; + static const int lastTile=65519; + + TileSelectorBackend(TileSelector& dialog, int tile, int cset); + void moveCursor(cursorMoveType type, bool multiSelect); + bool tileIsSelected(int x, int y) const; + void selectTile(int tile, bool multiSelect); + + void setPage(int page, bool multiSelect); + inline void modPage(int amount, bool multiSelect) + { + setPage(currentPage+amount, multiSelect); + } + + void modCSet(int amount); + + inline int getCSet() const { return cset; } + inline int getTile() const { return cursorPos; } + inline int getPage() const { return currentPage; } + inline int getFirstTileOnPage() const { return pageSize*currentPage; } + + inline int getTileAt(int x, int y) const + { + return pageSize*currentPage+pageWidth*y+x; + } + + inline void toggleSelectMode() + { + selectMode=(selectMode==sm_LINEAR) ? sm_RECTANGLE : sm_LINEAR; + } + +private: + enum tileSelectMode { sm_LINEAR, sm_RECTANGLE }; + + TileSelector& dialog; + bool multiSelectEnabled; + int currentPage; + int cursorPos; + int selectPos; + int cset; + tileSelectMode selectMode; + + //inline void cursorX() const { return cursorPos%pageWidth; } + //inline void cursorY() const { return cursorPos/pageWidth; } +}; + +#endif diff --git a/src/dialog/zquest/zscriptEditor.cpp b/src/dialog/zquest/zscriptEditor.cpp new file mode 100644 index 0000000000..2b2512f154 --- /dev/null +++ b/src/dialog/zquest/zscriptEditor.cpp @@ -0,0 +1,49 @@ +#include "zscriptEditor.h" +#include +#include +#include +#include +#include +#include +#include + +#define CB(func) boost::bind(&ZScriptEditor::func, this) + +extern std::string zScript; + +ZScriptEditor::ZScriptEditor(GUI::GUIManager& g): + gui(g) +{ +} + +GUI::Widget* ZScriptEditor::createDialog(const GUI::WidgetFactory& f) +{ + GUI::Window* win=f.window("ZScript editor", textBox=f.textBox()); + textBox->setText(zScript); + win->setOnClose(CB(onClose)); + + return win; +} + +bool ZScriptEditor::onKeyPressed(const KeyInput& key) +{ + if(key.key==key_ESCAPE) + { + if(onClose()) + shutDown(); + return true; + } + return Dialog::onKeyPressed(key); +} + +bool ZScriptEditor::onClose() +{ + int ret=gui.alert("ZScript buffer", + "Save changes to buffer?", + "&Yes", "&No", "&Cancel", 1); + if(ret==3) + return false; + if(ret==1) + zScript=textBox->getText(); + return true; +} diff --git a/src/dialog/zquest/zscriptEditor.h b/src/dialog/zquest/zscriptEditor.h new file mode 100644 index 0000000000..547341442a --- /dev/null +++ b/src/dialog/zquest/zscriptEditor.h @@ -0,0 +1,26 @@ +#ifndef _ZC_DIALOG_ZQUEST_ZSCRIPTEDITOR_H_ +#define _ZC_DIALOG_ZQUEST_ZSCRIPTEDITOR_H_ + +#include + +namespace GUI +{ + class GUIManager; + class TextBox; +} + +class ZScriptEditor: public GUI::Dialog +{ +public: + ZScriptEditor(GUI::GUIManager& gui); + +private: + GUI::GUIManager& gui; + GUI::TextBox* textBox; + + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + bool onKeyPressed(const KeyInput& key); + bool onClose(); +}; + +#endif diff --git a/src/dialog/zquest/zscriptMain.cpp b/src/dialog/zquest/zscriptMain.cpp new file mode 100644 index 0000000000..3fb8a8ff08 --- /dev/null +++ b/src/dialog/zquest/zscriptMain.cpp @@ -0,0 +1,125 @@ +#include "zscriptMain.h" +#include "zscriptEditor.h" +#include "../../gui/factory.h" +#include "../../gui/manager.h" +#include "../../gui/text.h" +#include "../../zquest.h" +#include +#include +#include + +#define CB(func) boost::bind(&ZScriptMainDialog::func, this) + +extern std::string zScript; + +ZScriptMainDialog::ZScriptMainDialog(GUI::GUIManager& g): + gui(g) +{ +} + +GUI::Widget* ZScriptMainDialog::createDialog(const GUI::WidgetFactory& f) +{ + GUI::Window* win= + f.window("Compile ZScript", + f.column(GUI::Contents( + sizeText=f.text(""), + f.buttonRow(GUI::Contents( + f.button("&Edit", CB(onEdit)), + f.button("&Compile", CB(onCompile)) + )), + f.buttonRow(GUI::Contents( + f.button("&Import", CB(onImport)), + f.button("E&xport", CB(onExport)) + )), + f.button("C&lose", CB(shutDown)) + )) + ); + + setSizeText(); + + return win; +} + +void ZScriptMainDialog::onEdit() +{ + ZScriptEditor editor(gui); + gui.showDialog(editor); + setSizeText(); +} + +void ZScriptMainDialog::onCompile() +{ + shutDown(); + compileZScript(); +} + +void ZScriptMainDialog::onImport() +{ + int ret=gui.alert( + "Confirm overwrite", + "Loading will erase the current contents of the script buffer. Continue anyway?", + "&Yes", "&No", 2); + + if(ret==2) + return; + + if(!getname("Load ZScript (.z)","z",NULL,datapath,false)) + return; + + std::FILE *newScript = std::fopen(temppath,"r"); + if(!newScript) + { + gui.alert("Error", "An error occurred importing the script."); + return; + } + + zScript.clear(); + + while(!std::feof(newScript)) + { + char c = std::fgetc(newScript); + zScript += c; + } + + std::fclose(newScript); + setSizeText(); + saved = false; +} + +void ZScriptMainDialog::onExport() +{ + if(!getname("Save ZScript (.z)", "z", NULL,datapath,false)) + return; + + if(exists(temppath)) + { + int ret=gui.alert( + "Confirm overwrite", + "File already exists. Overwrite?", + "&Yes", "&No", 2); + if(ret==2) + return; + } + + std::FILE* output = std::fopen(temppath,"w"); + + if(!output) + { + gui.alert("Error", "Unable to open file"); + return; + } + + size_t written=std::fwrite(zScript.c_str(), sizeof(char), zScript.size(), output); + + if(written!=zScript.size()) + gui.alert("Error", "An error occurred while writing the file."); + + std::fclose(output); +} + +void ZScriptMainDialog::setSizeText() +{ + char buf[32]; + sprintf(buf, "%lu bytes in buffer", zScript.size()); + sizeText->setText(buf); +} diff --git a/src/dialog/zquest/zscriptMain.h b/src/dialog/zquest/zscriptMain.h new file mode 100644 index 0000000000..bef02f8965 --- /dev/null +++ b/src/dialog/zquest/zscriptMain.h @@ -0,0 +1,29 @@ +#ifndef _ZC_DIALOG_ZQUEST_ZSCRIPTMAIN_H_ +#define _ZC_DIALOG_ZQUEST_ZSCRIPTMAIN_H_ + +#include "../../gui/dialog.h" + +namespace GUI +{ + class GUIManager; + class Text; +} + +class ZScriptMainDialog: public GUI::Dialog +{ +public: + ZScriptMainDialog(GUI::GUIManager& gui); + +private: + GUI::GUIManager& gui; + GUI::Text* sizeText; + + GUI::Widget* createDialog(const GUI::WidgetFactory& f); + void onEdit(); + void onCompile(); + void onImport(); + void onExport(); + void setSizeText(); +}; + +#endif diff --git a/src/dummyZQ.cpp b/src/dummyZQ.cpp new file mode 100644 index 0000000000..e732b7fb93 --- /dev/null +++ b/src/dummyZQ.cpp @@ -0,0 +1,13 @@ +// This file contains only empty functions and unused variables. +// ZQuest requires these in order to compile, but it never uses them. + +class ASEnemy; +struct BITMAP; +class item; + +BITMAP* scriptDrawingTarget; + +void initializeAngelScript() {} +void shutDownAngelScript() {} +void assignEnemyScript(ASEnemy*, const char*) {} +void assignItemScript(item*, const char*) {} diff --git a/src/editbox.cpp b/src/editbox.cpp new file mode 100644 index 0000000000..b839d25783 --- /dev/null +++ b/src/editbox.cpp @@ -0,0 +1,335 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.c + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +/* This code is not fully tested */ + +#include "precompiled.h" //always first + +#include +#include "zc_alleg.h" +#include "jwin.h" +#include + +#include "EditboxNew.h" + +//#ifndef _MSC_VER +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) +//#endif + +extern int scheme[]; +/* d_editbox_proc: + * A text box object. The dp field points to a char * which is the text + * to be displayed in the text box. If the text is long, there will be + * a vertical scrollbar on the right hand side of the object which can + * be used to scroll through the text. The default is to print the text + * with word wrapping, but if the D_SELECTED flag is set, the text will + * be printed with character wrapping. The d1 field is used internally + * to store the number of lines of text, and d2 is used to store how far + * it has scrolled through the text. + */ +int d_editbox_proc(int msg, DIALOG *d, int c) +{ + EditboxModel *model= (EditboxModel *)d->dp; + int ret = D_O_K; + + static clock_t ticks; + bool dontredraw=false; + + switch(msg) + { + case MSG_START: + { + model->getSelection().clearSelection(); + model->getView()->initialize(model); + break; + } + + case MSG_IDLE: + { + if((d->flags & D_GOTFOCUS)&&(clock()>ticks)) + { + d->flags |= D_DIRTY; + ticks=clock()+(CLOCKS_PER_SEC/2); + model->getCursor().invertVisibility(); + } + + break; + } + + case MSG_DRAW: + { + model->getView()->draw(); + break; + } + + case MSG_WANTFOCUS: + { + ret = D_WANTFOCUS; + break; + } + + case MSG_CHAR: + { + //handle selecting (bah) + + switch(c>>8) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_HOME: + case KEY_END: + case KEY_PGUP: + case KEY_PGDN: + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + model->getSelection().ensureSelecting(model->getCursor()); + } + else + { + model->getSelection().clearSelection(); + } + } + + //normal event handling + switch(c>>8) + { + case KEY_LEFT: + model->getCursor()--; + ret = D_USED_CHAR; + break; + + case KEY_RIGHT: + model->getCursor()++; + ret = D_USED_CHAR; + break; + + case KEY_UP: + model->getView()->lineUp(); + ret = D_USED_CHAR; + break; + + case KEY_DOWN: + model->getView()->lineDown(); + ret = D_USED_CHAR; + break; + + case KEY_HOME: + model->getView()->lineHome(); + ret = D_USED_CHAR; + break; + + case KEY_END: + model->getView()->lineEnd(); + ret = D_USED_CHAR; + break; + + case KEY_PGDN: + model->getView()->pageDown(); + ret = D_USED_CHAR; + break; + + case KEY_PGUP: + model->getView()->pageUp(); + ret = D_USED_CHAR; + break; + + case KEY_ENTER: + case KEY_ENTER_PAD: + model->clear(); + model->getCursor().insertNewline(); + ret = D_USED_CHAR; + break; + + case KEY_TAB: + { + model->clear(); + int ch = Unicode::getCharAtOffset(uconvert_ascii("\t",NULL),0); + model->getCursor().insertChar(ch); + ret = D_USED_CHAR; + break; + } + + case KEY_DEL: + case KEY_DEL_PAD: + if(model->getSelection().hasSelection()) + model->clear(); + else + model->getCursor().deleteChar(); + + ret = D_USED_CHAR; + break; + + case KEY_BACKSPACE: + if(model->getSelection().hasSelection()) + model->clear(); + else if(model->getCursor().getPosition() != 0) + { + model->getCursor()--; + model->getCursor().deleteChar(); + } + + ret = D_USED_CHAR; + break; + + case KEY_C: + if(key[KEY_LCONTROL]||key[KEY_RCONTROL]) + { + model->copy(); + ret = D_USED_CHAR; + break; + } + + ret = D_O_K; + break; + + case KEY_X: + if(key[KEY_LCONTROL]||key[KEY_RCONTROL]) + { + model->cut(); + ret = D_USED_CHAR; + break; + } + + ret = D_O_K; + break; + + case KEY_V: + if(key[KEY_LCONTROL]||key[KEY_RCONTROL]) + { + model->clear(); + model->paste(); + ret = D_USED_CHAR; + break; + } + + ret = D_O_K; + break; + + case KEY_ESC: + return D_EXIT; + + case KEY_F1: + model->doHelp(); + ret = D_USED_CHAR; + dontredraw=true; + break; + } + + //selection post-processing + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + switch(c>>8) + { + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_HOME: + case KEY_END: + case KEY_PGUP: + case KEY_PGDN: + model->getSelection().adjustSelection(model->getCursor()); + } + } + + break; + } + + case MSG_UCHAR: + { + ret = D_USED_CHAR; + + if((c >= ' ') && (uisok(c))) + { + model->clear(); + model->getCursor().insertChar(c); + } + } + break; + + case MSG_CLICK: + { + bool redraw = model->getView()->mouseClick(gui_mouse_x(), gui_mouse_y()); + + if(model->getCursor().isVisible()) + model->getCursor().invertVisibility(); + + if(redraw) + { + object_message(d, MSG_DRAW, 0); + } + + while(gui_mouse_b()) + { + + if(model->getView()->mouseDrag(gui_mouse_x(), gui_mouse_y())) + { + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + } + } + + model->getView()->mouseRelease(gui_mouse_x(), gui_mouse_y()); + + if(!model->getCursor().isVisible()) + model->getCursor().invertVisibility(); + + d->flags |= D_DIRTY; + break; + } + + case MSG_WHEEL: + { + if(c>0) + model->getView()->scrollUp(); + else + model->getView()->scrollDown(); + + d->flags |= D_DIRTY; + break; + } + + } + + if(ret == D_USED_CHAR && !dontredraw) + { + //redraw + if(!model->getCursor().isVisible()) + model->getCursor().invertVisibility(); + + ticks=clock()+(CLOCKS_PER_SEC/2); + model->getView()->ensureCursorOnScreen(); + d->flags |= D_DIRTY; + } + + return ret; +} + diff --git a/src/editbox.h b/src/editbox.h new file mode 100644 index 0000000000..3ed41d586a --- /dev/null +++ b/src/editbox.h @@ -0,0 +1,86 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.c + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ + +#ifndef _EDITBOX_H_ +#define _EDITBOX_H_ + +#include "zc_alleg.h" +#include +//#ifdef __cplusplus +//extern "C" +//{ +//#endif + +enum {eb_wrap_none, eb_wrap_char, eb_wrap_word}; +enum {eb_crlf_n, eb_crlf_nr, eb_crlf_r, eb_crlf_rn, eb_crlf_any}; +enum {eb_scrollbar_optional, eb_scrollbar_on, eb_scrollbar_off}; +enum {eb_handle_vscroll, eb_handle_hscroll}; + +int d_editbox_proc(int msg, DIALOG *d, int c); + +typedef struct editbox_data +{ + // char **text; + std::string text; + int showcursor; + int lines; + int currtextline; + int list_width; + int currxpos; + int fakexpos; + int xofs; + int yofs; + int maxchars; + int maxlines; + int wrapping; + int insertmode; + int currchar; + int tabdisplaystyle; + int crlfdisplaystyle; + int newcrlftype; + int vsbarstyle; + int hsbarstyle; + FONT *font; + //char *clipboard; + //int clipboardsize; + std::string clipboard; + int defaulttabsize; + int tabunits; + int customtabs; + int *customtabpos; + int numchars; + int selstart; + int selend; + int selfg; + int selbg; + int postpaste_dontmove; +} editbox_data; + +//#ifdef __cplusplus +//} +//#endif +#endif + +/*** The End ***/ + diff --git a/src/encryption.h b/src/encryption.h new file mode 100644 index 0000000000..a8c5379a77 --- /dev/null +++ b/src/encryption.h @@ -0,0 +1,7 @@ +#ifndef _ENCRYPTION_H_ +#define _ENCRYPTION_H_ + +int encode_file_007(const char *srcfile, const char *destfile, int key, const char *header, int method); +int decode_file_007(const char *srcfile, const char *destfile, const char *header, int method, bool packed, const char *password); + +#endif diff --git a/src/encryptionDisabled.cpp b/src/encryptionDisabled.cpp new file mode 100644 index 0000000000..51247927d6 --- /dev/null +++ b/src/encryptionDisabled.cpp @@ -0,0 +1,201 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifdef USE_ENCRYPTION + #error "USE_ENCRYPTION is defined; use encryptionEnabled.cpp" +#else + +#include "encryption.h" +#include "zdefs.h" +#include "zsys.h" +#include + +// +// RETURNS: +// 0 - OK +// 1 - srcfile not opened +// 2 - destfile not opened +// +int encode_file_007(const char *srcfile, const char *destfile, int key2, const char *header, int method) +{ + FILE *src, *dest; + int c; + src = fopen(srcfile, "rb"); + + if(!src) + return 1; + + dest = fopen(destfile, "wb"); + + if(!dest) + { + fclose(src); + return 2; + } + + + // write the header + if(header) + { + for(c=0; header[c]; c++) + fputc(header[c], dest); + } + + // encode the data + while((c=fgetc(src)) != EOF) + { + fputc(c, dest); + } + + fclose(src); + fclose(dest); + return 0; +} + +// +// RETURNS: +// 0 - OK +// 1 - srcfile not opened +// 2 - destfile not opened +// 3 - scrfile too small +// 4 - srcfile EOF +// 5 - checksum mismatch +// 6 - header mismatch +// +int decode_file_007(const char *srcfile, const char *destfile, const char *header, int method, bool packed, const char *password) +{ + FILE *normal_src=NULL, *dest=NULL; + PACKFILE *packed_src=NULL; + int i, c, size, err; + + // open files + size = file_size_ex_password(srcfile, password); + + if(size < 1) + { + return 1; + } + + if(!packed) + { + normal_src = fopen(srcfile, "rb"); + + if(!normal_src) + { + return 1; + } + } + else + { + packed_src = pack_fopen_password(srcfile, F_READ_PACKED,password); + + if(errno==EDOM) + { + packed_src = pack_fopen_password(srcfile, F_READ,password); + } + + if(!packed_src) + { + return 1; + } + } + + dest = fopen(destfile, "wb"); + + if(!dest) + { + if(packed) + { + pack_fclose(packed_src); + } + else + { + fclose(normal_src); + } + + return 2; + } + + // read the header + err = 4; + + if(header) + { + for(i=0; header[i]; i++) + { + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + if((c&255) != header[i]) + { + err = 6; + goto error; + } + + --size; + } + } + + // decode the data + for(i=0; i + +//#define MASK 0x4C358938 +static int seed = 0; +//#define MASK 0x91B2A2D1 +//static int seed = 7351962; +static int enc_mask[ENC_METHOD_MAX]= {0x4C358938,0x91B2A2D1,0x4A7C1B87,0xF93941E6,0xFD095E94}; +static int pvalue[ENC_METHOD_MAX]= {0x62E9,0x7D14,0x1A82,0x02BB,0xE09C}; +static int qvalue[ENC_METHOD_MAX]= {0x3619,0xA26B,0xF03C,0x7B12,0x4E8F}; + +static int rand_007(int method) +{ + short BX = seed >> 8; + short CX = (seed & 0xFF) << 8; + signed char AL = seed >> 24; + signed char C = AL >> 7; + signed char D = BX >> 15; + AL <<= 1; + BX = (BX << 1) | C; + CX = (CX << 1) | D; + CX += seed & 0xFFFF; + BX += (seed >> 16) + C; + // CX += 0x62E9; + // BX += 0x3619 + D; + CX += pvalue[method]; + BX += qvalue[method] + D; + seed = (BX << 16) + CX; + return (CX << 16) + BX; +} + +void encode_007(byte *buf, dword size, dword key2, word *check1, word *check2, int method) +{ + dword i; + byte *p; + + *check1 = 0; + *check2 = 0; + + p = buf; + + for(i=0; i> 12) + *p; + ++p; + } + + p = buf; + seed = key2; + + for(i=0; i> 12) + *p; + ++p; + } + + return (c1 == check1) && (c2 == check2); +} + +// +// RETURNS: +// 0 - OK +// 1 - srcfile not opened +// 2 - destfile not opened +// +int encode_file_007(const char *srcfile, const char *destfile, int key2, const char *header, int method) +{ + FILE *src, *dest; + int tog = 0, c, r=0; + short c1 = 0, c2 = 0; + + seed = key2; + src = fopen(srcfile, "rb"); + + if(!src) + return 1; + + dest = fopen(destfile, "wb"); + + if(!dest) + { + fclose(src); + return 2; + } + + + // write the header + if(header) + { + for(c=0; header[c]; c++) + fputc(header[c], dest); + } + + // write the key, XORed with MASK + key2 ^= enc_mask[method]; + fputc(key2>>24, dest); + fputc((key2>>16)&255, dest); + fputc((key2>>8)&255, dest); + fputc(key2&255, dest); + + // encode the data + while((c=fgetc(src)) != EOF) + { + c1 += c; + c2 = (c2 << 4) + (c2 >> 12) + c; + + if(tog) + c += r; + else + { + r = rand_007(method); + c ^= r; + } + + tog ^= 1; + + fputc(c, dest); + } + + // write the checksums + r = rand_007(method); + c1 ^= r; + c2 += r; + fputc(c1>>8, dest); + fputc(c1&255, dest); + fputc(c2>>8, dest); + fputc(c2&255, dest); + + fclose(src); + fclose(dest); + return 0; +} + +// +// RETURNS: +// 0 - OK +// 1 - srcfile not opened +// 2 - destfile not opened +// 3 - scrfile too small +// 4 - srcfile EOF +// 5 - checksum mismatch +// 6 - header mismatch +// +int decode_file_007(const char *srcfile, const char *destfile, const char *header, int method, bool packed, const char *password) +{ + FILE *normal_src=NULL, *dest=NULL; + PACKFILE *packed_src=NULL; + int tog = 0, c, r=0, err; + long size, i; + short c1 = 0, c2 = 0, check1, check2; + + // open files + size = file_size_ex_password(srcfile, password); + + if(size < 1) + { + return 1; + } + + size -= 8; // get actual data size, minus key and checksums + + if(size < 1) + { + return 3; + } + + if(!packed) + { + normal_src = fopen(srcfile, "rb"); + + if(!normal_src) + { + return 1; + } + } + else + { + packed_src = pack_fopen_password(srcfile, F_READ_PACKED,password); + + if(errno==EDOM) + { + packed_src = pack_fopen_password(srcfile, F_READ,password); + } + + if(!packed_src) + { + return 1; + } + } + + dest = fopen(destfile, "wb"); + + if(!dest) + { + if(packed) + { + pack_fclose(packed_src); + } + else + { + fclose(normal_src); + } + + return 2; + } + + // read the header + err = 4; + + if(header) + { + for(i=0; header[i]; i++) + { + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + if((c&255) != header[i]) + { + err = 6; + goto error; + } + + --size; + } + } + + // read the key + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + seed = c << 24; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + seed += (c & 255) << 16; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + seed += (c & 255) << 8; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + seed += c & 255; + seed ^= enc_mask[method]; + + // decode the data + for(i=0; i> 12) + c; + + fputc(c, dest); + } + + // read checksums + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + check1 = c << 8; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + check1 += c & 255; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + check2 = c << 8; + + if(packed) + { + if((c=pack_getc(packed_src)) == EOF) + { + goto error; + } + } + else + { + if((c=fgetc(normal_src)) == EOF) + { + goto error; + } + } + + check2 += c & 255; + + // verify checksums + r = rand_007(method); + check1 ^= r; + check2 -= r; + check1 &= 0xFFFF; + check2 &= 0xFFFF; + + if(check1 != c1 || check2 != c2) + { + err = 5; + goto error; + } + + if(packed) + { + pack_fclose(packed_src); + } + else + { + fclose(normal_src); + } + + fclose(dest); + return 0; + +error: + + if(packed) + { + pack_fclose(packed_src); + } + else + { + fclose(normal_src); + } + + fclose(dest); + delete_file(destfile); + return err; +} + +#endif diff --git a/src/ending.cpp b/src/ending.cpp new file mode 100644 index 0000000000..dfe48aae12 --- /dev/null +++ b/src/ending.cpp @@ -0,0 +1,653 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// ending.cc +// +// Ending code for Zelda Classic. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include + +#include "ending.h" +#include "zelda.h" +#include "zc_sys.h" +#include "zsys.h" +#include "sprite.h" +#include "items.h" +#include "pal.h" +#include "link.h" +#include "guys.h" +#include "title.h" +#include "subscr.h" +#include "init.h" +#include "gamedata.h" +#include "sound.h" + +extern LinkClass Link; +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations; +extern int draw_screen_clip_rect_x1; +extern int draw_screen_clip_rect_x2; +extern int draw_screen_clip_rect_y1; +extern int draw_screen_clip_rect_y2; +//extern bool draw_screen_clip_rect_show_link; +//extern bool draw_screen_clip_rect_show_guys; + +namespace +{ + const int white = WHITE; + const int red = CSET(csBOSS)+4; + const int blue = CSET(csBOSS)+5; + const int green = CSET(csBOSS)+6; + + struct EndingTextLine + { + const char* text; + int xPos, yPos; // yPos determines when this line appears + int color; + }; + + const int numCreditsLines = 12; + const EndingTextLine credits[]={ + { " STAFF ", 104, 240, white }, + { "EXECUTIVE", 40, 272, blue }, + { "PRODUCER... H.YAMAUCHI", 40, 280, blue }, + { "PRODUCER.... S.MIYAHON", 40, 320, green }, + { "DIRECTOR.... S.MIYAHON", 40, 360, red }, + { " ...... TEN TEN", 40, 384, red }, + { "DESIGNER...... TEN TEN", 40, 424, blue }, + { "PROGRAMMER.. T.NAKAZOO", 40, 464, green }, + { " ..... YACHAN", 40, 488, green }, + { " ... MARUMARU", 40, 512, green }, + { "SOUND", 40, 552, red }, + { "COMPOSER...... KONCHAN", 40, 560, red } + }; + + const int numQuest1EndLines = 4; + const EndingTextLine quest1End[]={ + { "ANOTHER QUEST WILL START", 32, 656, white }, + { "FROM HERE.", 88, 672, white }, + { "PRESS THE START BUTTON.", 40, 696, white }, + { "\2731986 NINTENDO", 72, 760, white } + }; + + const int numQuest2EndLines = 4; + const EndingTextLine quest2End[]={ + { "YOU ARE GREAT.", 72, 768, white }, + /* name - deaths */ + { "YOU HAVE AN AMAZING", 48, 816, white }, + { "WISDOM AND POWER.", 64, 832, white }, + { "\2731986 NINTENDO", 72, 912, blue } + }; + + const int numQuest34EndLines = 6; + const EndingTextLine quest34End[]={ + { "YOU ARE GREAT.", 72, 768, white }, + /* name - deaths */ + { "YOU HAVE AN AMAZING", 48, 816, white }, + { "WISDOM AND POWER.", 64, 832, white }, + { "END OF", 104, 880, white }, + { "\"THE LEGEND OF ZELDA 1\"", 32, 896, white }, + { "\2731986 NINTENDO", 72, 912, blue } + }; + + const int numCustomQuestEndLines = 6; + const EndingTextLine customQuestEnd[]={ + { "Congratulations!", 64, 768, white }, + /* name - deaths */ + /* time */ + { "You finished a", 72, 816, white }, + { "custom quest.", 76, 832, white }, + { "ZELDA CLASSIC", 76, 880, white }, + { "\2741999-2014", 88, 896, white }, + { "Armageddon Games", 64, 912, blue } + }; +} + +void noproc() {} + +void put_triforce() +{ + if(get_bit(quest_rules,qr_HOLDITEMANIMATION)) + { + putitem2(framebuf,120,113-(get_bit(quest_rules, qr_NOITEMOFFSET)),iTriforce,lens_hint_item[iTriforce][0],lens_hint_item[iTriforce][1], 0); + putitem2(framebuf,136,113-(get_bit(quest_rules, qr_NOITEMOFFSET)),iTriforce,lens_hint_item[iTriforce][0],lens_hint_item[iTriforce][1], 0); + } + else + { + putitem(framebuf,120,113-(get_bit(quest_rules, qr_NOITEMOFFSET)),iTriforce); + putitem(framebuf,136,113-(get_bit(quest_rules, qr_NOITEMOFFSET)),iTriforce); + } +} + +void putendmsg(const char *s,int x,int y,int speed,void(proc)()) +{ + int i=0; + int c=(int)strlen(s)*speed; + + for(int f=0; fset_cheat(game->get_cheat() | (cheat>1)?1:0); + + draw_screen_clip_rect_x1=0; + draw_screen_clip_rect_x2=255; + draw_screen_clip_rect_y1=0; + draw_screen_clip_rect_y2=223; + //draw_screen_clip_rect_show_link=true; + //draw_screen_clip_rect_show_guys=false; + + for(int f=0; f<365; f++) + { + if(f==363) + { + //363 WIPE complete, DOT out, A/B items out + QMisc.colors.link_dot = 255; + show_subscreen_items = false; + + for(int i = guys.Count() - 1; i >= 0; i--) + { + if(guys.spr(i)->id > gDUMMY9) + { + guys.del(i); + } + } + + guys.draw(framebuf,true); + Link.draw(framebuf); + } + + if(f>=288 && ((f-288)%5 == 0)) + { + //288 begin WIPE (8px per side per step, each 5 frames) + //TODO:: + draw_screen_clip_rect_x1+=8; + draw_screen_clip_rect_x2-=8; + //draw_screen_clip_rect_show_guys=true; + } + + draw_screen(tmpscr); + advanceframe(true); + + if(Quit) return; + } + + draw_screen(tmpscr); + advanceframe(true); + + draw_screen_clip_rect_x1=0; + draw_screen_clip_rect_x2=255; + //draw_screen_clip_rect_show_guys=false; + + char tmpmsg[6][25]; + + for(int x=0; x<3; x++) + { + sprintf(tmpmsg[x], "%.24s", MsgStrings[QMisc.endstring].s+(24*x)); + // sprintf(tmpmsg[x], "%.24s", MsgStrings[QMisc.endstring].s+(24*x)); + // strncpy(tmpmsg[x], MsgStrings[QMisc.endstring].s+(24*x), 24); + } + + for(int x=0; x<3; x++) + { + sprintf(tmpmsg[x+3], "%.24s", MsgStrings[QMisc.endstring+1].s+(24*x)); + // strncpy(tmpmsg[x+3], MsgStrings[QMisc.endstring+1].s+(24*x), 24); + } + + if(QMisc.endstring==0) + { + putendmsg("THANKS LINK,YOU'RE",32,96,6,noproc); + putendmsg("THE HERO OF HYRULE.",32,112,6,noproc); + } + else + { + putendmsg(tmpmsg[0],32,80,6,noproc); + putendmsg(tmpmsg[1],32,96,6,noproc); + putendmsg(tmpmsg[2],32,112,6,noproc); + } + + for(int f=408; f<927; f++) + { + /* + 668 LINK out, ZELDA out + 669 LINK in (TRIFORCE overhead), ZELDA in (TRIFORCE overhead) + 733 BLUE flash bg + 734 RED + 735 GREEN + 736 BLACK + ... + 860 BLACK, LINK out, ZELDA out + 861 LINK in, ZELDA in + */ + if(f==668) + { + rectfill(framebuf,120,129,152,145,0); + blit(framebuf, tmp_bmp, 120,113, 0,0, 32,32); + } + + if(f==860) + { + blit(tmp_bmp, framebuf, 0,0, 120,113, 32,32); + } + + if(f==669 || f==861) + { + overtile16(framebuf,36,120,129,6,0);//draw Zelda two-handed overhead + overtile16(framebuf,BSZ?32:29,136,129,6,0);//draw Link two-handed overhead + } + + if(f==733) + { + blit(framebuf,scrollbuf,0,playing_field_offset!=0?168:0,0,0,256,passive_subscreen_height); + + for(int y=0; y<224; y++) + { + for(int x=0; x<256; x++) + { + if(!(framebuf->line[y][x]&15)) + { + framebuf->line[y][x]=16; + } + } + } + } + + if(f>=733 && f<861) + { + static byte flash[4] = {0x12,0x16,0x2A,0x0F}; + RAMpal[16] = NESpal(flash[(f-733)&3]); + refreshpal=true; + } + + if(f==861) + { + blit(scrollbuf,framebuf,0,0,0,playing_field_offset!=0?168:0,256,passive_subscreen_height); + try_zcmusic((char*)"zelda.nsf", 1, ZC_MIDI_ENDING); + + for(int y=0; y<224; y++) + { + for(int x=0; x<256; x++) + { + if(framebuf->line[y][x]==16) + { + framebuf->line[y][x]=0; + } + } + } + } + + if(f>668 && f!=860) + { + put_triforce(); + } + + advanceframe(true); + + if(Quit) + { + return; + } + } + + if(QMisc.endstring==0) + { + putendmsg("FINALLY,",96,160,8,put_triforce); + putendmsg("PEACE RETURNS TO HYRULE.",32,176,8,put_triforce); + putendmsg("THIS ENDS THE STORY.",48,200,8,put_triforce); + } + else + { + putendmsg(tmpmsg[3],32,160,6,noproc); + putendmsg(tmpmsg[4],32,176,6,noproc); + putendmsg(tmpmsg[5],32,200,6,noproc); + } + + for(int f=1336; f<1492; f++) + { + if(f<1461) + { + put_triforce(); + } + + if(f==1461) + { + blit(tmp_bmp,framebuf,0,0,120,113,32,32); + } + + advanceframe(true); + + if(Quit) + { + return; + } + } + + clear_bitmap(scrollbuf); + blit(framebuf,scrollbuf,0,0,0,0,256,224); + endingpal(); + // draw the brick + puttile16(scrollbuf,3,256,0,csBOSS,0); + + int len=600*2; + + if(game->get_quest()>1) + { + len=720*2; + } + + int creditsLine=0; + int endTextLine=0; + + const EndingTextLine* endText; + int numEndTextLines=0; + int deathsYPos=-1; + int timeYPos=-1; + + switch(game->get_quest()) + { + case 1: + endText=quest1End; + numEndTextLines=numQuest1EndLines; + break; + + case 2: + endText=quest2End; + numEndTextLines=numQuest2EndLines; + deathsYPos=792; + break; + + case 3: + case 4: + case 5: + endText=quest34End; + numEndTextLines=numQuest34EndLines; + deathsYPos=792; + break; + + default: + endText=customQuestEnd; + numEndTextLines=numCustomQuestEndLines; + deathsYPos=784; + timeYPos=800; + break; + } + + for(int f=0; f>1)+224; + + if(y>240 && y<584) + { + brick(24,224); + brick(224,224); + } + + if(y==240 || y==584) + { + for(int x=24; x<=224; x+=8) + { + brick(x,224); + } + } + + if(creditsLineget_name(), game->get_deaths()); + else if(y==timeYPos) + { + if(game->get_timevalid() && !game->get_cheat()) + textout_centre_ex(scrollbuf, zfont, time_str_med(game->get_time()), 128, 224, blue, 0); + } + } + } + + if(f==112) // after subscreen has scrolled away + { + init_NES_mode(); + loadpalset(9,pSprite(spPILE)); + endingpal(); + } + + if(f&1) + { + blit(scrollbuf,scrollbuf,0,1,0,0,256,232); + } + + blit(scrollbuf,framebuf,0,0,0,0,256,224); + advanceframe(true); + + if(Quit) + { + return; + } + + load_control_state(); + rSbtn(); + } + + do + { + if(frame&1) + { + overtile16(framebuf,176,120,129,9,0); + } + + overtile16(framebuf,175,120,129,((frame&8)>>3)+7,0); + + if(!(frame&1)) + { + overtile16(framebuf,176,120,129,9,0); + } + + advanceframe(true); + + if(Quit) + { + return; + } + + load_control_state(); + } + while(!rSbtn()); + + if(game->get_quest()>0 && game->get_quest()<3) + { + inc_quest(); + removeItemsOfFamily(game, itemsbuf, itype_ring); + int maxring = getHighestLevelOfFamily(&zinit,itemsbuf,itype_ring); + + if(maxring != -1) + { + getitem(maxring,true); + } + + ringcolor(false); + } + + stop_midi(); + + if(zcmusic != NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + zcmusic = NULL; + } + +// setPackfilePassword(datapwd); + load_quest(game); +// setPackfilePassword(NULL); + saves[currgame] = *game; + load_game_icon_to_buffer(false,currgame); + load_game_icon(game,false,currgame); + + game->set_continue_dmap(zinit.start_dmap); + game->set_continue_scrn(0xFF); + game->set_cont_hearts(zinit.cont_heart); + show_saving(scrollbuf); + save_savedgames(); +} + +void inc_quest() +{ + char name[9]; + strcpy(name,game->get_name()); + // Go to quest 3 if you got some heart containers, + // or quest 4 if you got them all. + int quest; + + if(game->get_quest()==2 && game->get_maxlife()>=HP_PER_HEART*16) + quest = 4; + else + quest = zc_min(game->get_quest()+1,5); + + if(game->get_quest()==3 && game->get_maxlife()>=HP_PER_HEART*16) + quest = 4; + + int deaths = game->get_deaths(); + + // If you beat the 3rd quest without dying skip over the easier 4th and play the 5th quest. + if(game->get_quest()==3 && deaths == 0) + quest = 5; + + // Likewise, if you beat the 5th but died, go back to the 4th. + if(game->get_quest()==5 && deaths > 0) + quest = 4; + + game->Clear(); + + game->set_name(name); + game->set_quest(quest); + game->set_deaths(deaths); + game->set_maxlife(3*HP_PER_HEART); + game->set_life(3*HP_PER_HEART); + game->set_maxbombs(8); + game->set_hasplayed(true); + game->set_continue_dmap(zinit.start_dmap); + game->set_continue_scrn(0x77); + resetItems(game,&zinit,true); + load_quest(game); + load_game_icon_to_buffer(false,currgame); + load_game_icon(game,false,currgame); +} + diff --git a/src/ending.h b/src/ending.h new file mode 100644 index 0000000000..e01bdce8d5 --- /dev/null +++ b/src/ending.h @@ -0,0 +1,22 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// ending.cc +// +// Ending code for Zelda Classic. +// +//-------------------------------------------------------- + +#ifndef _ENDING_H_ +#define _ENDING_H_ + +void inc_quest(); +void noproc(); +void put_triforce(); +void putendmsg(const char *s,int x,int y,int speed,void(proc)()); +void brick(int x,int y); +void endingpal(); +void ending(); +#endif + diff --git a/src/enemyAttack.cpp b/src/enemyAttack.cpp new file mode 100644 index 0000000000..043dd26501 --- /dev/null +++ b/src/enemyAttack.cpp @@ -0,0 +1,380 @@ +#include "enemyAttack.h" + +#include "zdefs.h" +#include "link.h" +#include "guys.h" +#include "zelda.h" + +extern LinkClass Link; +extern mapscr tmpscr[2]; +extern sprite_list guys, Ewpns; + + +// These will have to do for now... +static int count_layer_enemies() +{ + int cnt=0; + + for(int i=0; i<6; i++) + { + if(tmpscr->layermap[i]!=0) + { + const mapscr* layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+ + tmpscr->layerscreen[i]; + + for(int j=0; j<10; j++) + { + if(layerscreen->enemy[j]!=0) + cnt++; + } + } + } + + return cnt; +} + +static int random_layer_enemy() +{ + int cnt=count_layer_enemies(); + + if(cnt==0) + return eNONE; + + int ret=rand()%cnt; + cnt=0; + + for(int i=0; i<6; ++i) + { + if(tmpscr->layermap[i]!=0) + { + const mapscr* layerscreen=&TheMaps[(tmpscr->layermap[i]-1)*MAPSCRS]+ + tmpscr->layerscreen[i]; + + for(int j=0; j<10; ++j) + { + if(layerscreen->enemy[j]!=0) + { + if(cnt==ret) + return layerscreen->enemy[j]; + cnt++; + } + } + } + } + + return eNONE; +} + + +EnemyAttack::EnemyAttack(int wid, int wt, int pow, fireType ft, const SFX& s): + owner(0), + weaponID(wid), + wpnType(wt), + power(pow), + fType(ft), + breathTimer(0), + sfx(s), + xOffset(0), + yOffset(0) +{ +} + +void EnemyAttack::fire(int dir, int type) +{ + weapon* wpn=new weapon( + owner->getX()+xOffset, + owner->getY()+yOffset, + owner->getZ(), + weaponID, + type, + power, + dir, + -1, + owner->getUID()); + Ewpns.add(wpn); +} + +weapon* EnemyAttack::fireFront(int dir, int type) +{ + weapon* wpn=new weapon( + owner->getX()+xOffset, + owner->getY()+yOffset, + owner->getZ(), + weaponID, + type, + power, + dir, + -1, + owner->getUID()); + Ewpns.addAtFront(wpn); + return wpn; +} + +weapon* EnemyAttack::fireBreath() +{ + bool seeklink=false; + + float fire_angle=0.0; + int wdir=owner->getDir(); + + int oldXOffset=xOffset; + int oldYOffset=yOffset; + + switch(wdir) + { + case -1: + case up: + fire_angle=PI*((rand()%20)+50)/40; + yOffset-=8; + break; + + case down: + fire_angle=PI*((rand()%20)+10)/40; + yOffset+=8; + break; + + case left: + fire_angle=PI*((rand()%20)+30)/40; + xOffset-=8; + break; + + case right: + fire_angle=PI*((rand()%20)+70)/40; + xOffset+=8; + break; + } + + if(weaponID==ewFlame || weaponID==ewFlame2) + { + if(fire_angle==-PI || fire_angle==PI) wdir=left; + else if(fire_angle==-PI/2) wdir=up; + else if(fire_angle==PI/2) wdir=down; + else if(fire_angle==0) wdir=right; + else if(fire_angle<-PI/2) wdir=l_up; + else if(fire_angle<0) wdir=r_up; + else if(fire_angle<(PI/2)) wdir=r_down; + else if(fire_anglegetX()); + + xOffset=oldXOffset; + yOffset=oldYOffset; + + if((rand()&4)!=0) + { + ew->angular=true; + ew->angle=fire_angle; + } + + if(weaponID==ewFlame && wpnsbuf[ewFLAME].frames>1) + { + ew->aframe=rand()%wpnsbuf[ewFLAME].frames; + ew->tile+=ew->aframe; + } + + return 0; +} + +weapon* EnemyAttack::fireAimedBreath() +{ + fireFront(0xFF, 2); + sfx.play(owner->getX()); + + weapon *ew = (weapon*)(Ewpns.spr(0)); + + if(weaponID==ewFlame && wpnsbuf[ewFLAME].frames>1) + { + ew->aframe=rand()%wpnsbuf[ewFLAME].frames; + ew->tile+=ew->aframe; + } + + return 0; +} + +void EnemyAttack::activate() +{ + int dir=owner->getDir(); + fix x=owner->getX(); + fix y=owner->getY(); + fix z=owner->getZ(); + int wpn=owner->wpn; + short wdp=owner->wdp; + + switch(fType) + { + case ft_5Shots: + fire(dir, wpnType+(((dir^left)+5)<<3)); + fire(dir, wpnType+(((dir^right)+5)<<3)); + // Fall through + + case ft_3Shots: + fire(dir, wpnType+(((dir^left)+1)<<3)); + fire(dir, wpnType+(((dir^right)+1)<<3)); + // Fall through + + case ft_1Shot: + fire(dir, wpnType); + sfx.play(owner->getX()); + break; + + case ft_1ShotSlanted: + { + int dx=Link.getX()-owner->getY(); + int dy=Link.getY()-owner->getY(); + int slant=0; + switch(dir) + { + case up: + if(dx<-8) slant=left; + else if(dx>8) slant=right; + break; + case down: + if(dx>8) slant=left; + else if(dx<-8) slant=right; + break; + case left: + if(dy<-8) slant=left; + else if(dy>8) slant=right; + break; + case right: + if(dy>8) slant=left; + else if(dy<-8) slant=right; + break; + } + + fire((weaponID==ewFireball2 || weaponID==ewFireball) ? 0 : dir, // Is this necessary? Won't they set their direction automatically? + wpnType+(((dir^slant)+1)<<3)); + sfx.play(owner->getX()); + break; + } + + case ft_8Shots: + fire(l_up, wpnType); + fire(l_down, wpnType); + fire(r_up, wpnType); + fire(r_down, wpnType); + // Fall through + + case ft_4Shots: + fire(up, wpnType); + fire(down, wpnType); + fire(left, wpnType); + fire(right, wpnType); + sfx.play(owner->getX()); + break; + + case ft_aquamentus: + fire(up, wpnType); + fire(8, wpnType); // Sure, why not. + fire(down, wpnType); + sfx.play(owner->getX()); + break; + + case ft_gohma3Shots: + fire(left, wpnType); + fire(right, wpnType); + // Fall through + + case ft_gohma1Shot: + fire(8, wpnType); + sfx.play(owner->getX()); + break; + + case ft_breath: + case ft_breathAimed: + breathTimer=rand()%50+50; + break; + + case ft_summon: + { + int currentNum=0; + + for(int i=0; iid)==weaponID) + currentNum++; + } + + if(currentNum<=40) + { + int guyCount=guys.Count(); + int numToSummon=(rand()%power)+1; + + for(int i=0; icount_enemy = false; + } + + sfx.play(x); + } + } + break; + + case ft_summonLayer: + { + // This should probably be checked elsewhere... + if(count_layer_enemies()==0) + return; + + int kids = guys.Count(); + + if(kids<200) + { + int numToSummon=(rand()%power)+1; + bool summoned=false; + + for(int i=0; i=32 || abs(y2-Link.getY())>=32)) + { + if(addenemy(x2,y2,get_bit(quest_rules,qr_ENEMIESZAXIS) ? 64 : 0,id2,-10)) + ((enemy*)guys.spr(kids+i))->count_enemy = false; + + summoned=true; + break; + } + } + } + + if(summoned) + sfx.play(x); + } + } + break; + } +} + +void EnemyAttack::update() +{ + if(fType==ft_breath) + { + if((breathTimer&3)==0) // Fires every 4 frames + fireBreath(); + } + else // Aimed + { + if((breathTimer&7)==0) // Fires every 8 frames + fireAimedBreath(); + } + + breathTimer--; +} + +bool EnemyAttack::isActive() +{ + if(!(fType==ft_breath || fType==ft_breathAimed)) + return false; + return breathTimer>0; +} diff --git a/src/enemyAttack.h b/src/enemyAttack.h new file mode 100644 index 0000000000..4006868ebd --- /dev/null +++ b/src/enemyAttack.h @@ -0,0 +1,65 @@ +#ifndef _ZC_ENEMYATTACK_H_ +#define _ZC_ENEMYATTACK_H_ + +#include "sfxClass.h" +class enemy; +class weapon; + +enum fireType +{ + ft_1Shot, ft_1ShotSlanted, ft_3Shots,ft_4Shots, + ft_5Shots, ft_8Shots, ft_aquamentus, ft_gohma1Shot, + ft_gohma3Shots, ft_breath, ft_breathAimed, ft_summon, + ft_summonLayer +}; + +class EnemyAttack +{ +public: + EnemyAttack(int weaponID, int type, int power, fireType fType, const SFX& sfx); + + /// Fire the weapon or begin the breath attack. + void activate(); + + /// Activate breath attack with a specified duration. + inline void setBreathTimer(int value) { breathTimer=value; } + + /// Update the active breath attack. isActive() should be checked first. + void update(); + + /// Returns true if this is a breath attack and it's currently firing. + // Maybe it should also be true if a boomerang is out... + bool isActive(); + + /// Set the enemy associated with this attack. + inline void setOwner(enemy* o) { owner=o; } + + inline void setXOffset(int x) { xOffset=x; } + + inline void setYOffset(int y) { yOffset=y; } + +private: + enemy* owner; + int weaponID; // Doubles as summoned enemy ID + int wpnType; + int power; // Doubles as max number of enemies to summon + fireType fType; + int breathTimer; + SFX sfx; + int xOffset, yOffset; + + /// Creates a single enemy weapon. + void fire(int dir, int type); + + /// Creates an enemy weapon at the beginning of Ewpns. + weapon* fireFront(int dir, int type); + + /// Updates fire breath attack. + weapon* fireBreath(); + + /// Updates aimed breath attack. + weapon* fireAimedBreath(); +}; + +#endif + diff --git a/src/entityPtr.h b/src/entityPtr.h new file mode 100644 index 0000000000..ed95c20aac --- /dev/null +++ b/src/entityPtr.h @@ -0,0 +1,98 @@ +#ifndef _ZC_ENTITYPTR_H_ +#define _ZC_ENTITYPTR_H_ + +#include "debug.h" + +/** Used to track the number of EntityPtrs to a given sprite and + * whether the sprite has been deleted. + */ +class EntityRef +{ +public: + EntityRef(): refCount(0), deleted(false) {} + inline void inc() { refCount++; } + inline void dec() { ZCASSERT(refCount>=1); if(--refCount==0 && deleted) delete this; } + inline void onEntityDelete() { if(refCount<=0) delete this; else deleted=true; } + + int refCount; + bool deleted; +}; + +/** A smart pointer class for sprites. When cast to bool, it evaluates to false + * if no sprite is set or if the sprite has been deleted. + */ +template +class EntityPtr +{ +public: + EntityPtr(): + spr(0), + ref(0) + { + } + + EntityPtr(T* s): + spr(s), + ref(s->ref) + { + ref->inc(); + } + + EntityPtr(EntityPtr& other): + spr(other.spr), + ref(other.ref) + { + ref->inc(); + } + + ~EntityPtr() + { + if(ref) ref->dec(); + } + + inline EntityPtr& operator=(const EntityPtr& other) + { + reset(other.spr); + return *this; + } + + void clear() + { + if(ref) ref->dec(); + spr=0; + ref=0; + } + + void reset(T* newT) + { + if(spr==newT) + return; + if(ref) ref->dec(); + spr=newT; + ref=newT->ref; + if(ref) ref->inc(); + } + + void del() + { + // Should this set ref->deleted? Currently, that's handled by ~sprite(), + // so pointers don't consider it deleted until the next frame. + if(spr && !ref->deleted) + spr->markForDeletion(); + clear(); + } + + inline operator bool() const { return spr && !ref->deleted; } + inline T& operator*() { return *spr; } + inline T* operator->() { return spr; } + inline T* get() { return spr; } + inline const T& operator*() const { return *spr; } + inline const T* operator->() const { return spr; } + inline const T* get() const { return spr; } + +private: + T* spr; + EntityRef* ref; +}; + +#endif diff --git a/src/ffasm.cpp b/src/ffasm.cpp new file mode 100644 index 0000000000..32eff0e7be --- /dev/null +++ b/src/ffasm.cpp @@ -0,0 +1,1116 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include + +#include "zc_malloc.h" +#include "ffasm.h" +#include "zquest.h" +#include "zsys.h" +#ifdef ALLEGRO_MACOSX +#define strnicmp strncasecmp +#endif + +#ifdef ALLEGRO_MACOSX +#define strnicmp strncasecmp +#endif + +#ifdef ALLEGRO_LINUX +#define strnicmp strncasecmp +#endif + +#ifdef _MSC_VER +#define stricmp _stricmp +#define strnicmp _strnicmp +#endif + +extern char *datapath, *temppath; + +script_command command_list[NUMCOMMANDS+1]= +{ + //name args arg1 arg2 more + { "SETV", 2, 0, 1, 0}, + { "SETR", 2, 0, 0, 0}, + { "ADDR", 2, 0, 0, 0}, + { "ADDV", 2, 0, 1, 0}, + { "SUBR", 2, 0, 0, 0}, + { "SUBV", 2, 0, 1, 0}, + { "MULTR", 2, 0, 0, 0}, + { "MULTV", 2, 0, 1, 0}, + { "DIVR", 2, 0, 0, 0}, + { "DIVV", 2, 0, 1, 0}, + { "WAITFRAME", 0, 0, 0, 0}, + { "GOTO", 1, 1, 0, 0}, + { "CHECKTRIG", 0, 0, 0, 0}, + { "WARP", 2, 1, 1, 0}, + { "COMPARER", 2, 0, 0, 0}, + { "COMPAREV", 2, 0, 1, 0}, + { "GOTOTRUE", 2, 0, 0, 0}, + { "GOTOFALSE", 2, 0, 0, 0}, + { "GOTOLESS", 2, 0, 0, 0}, + { "GOTOMORE", 2, 0, 0, 0}, + { "LOAD1", 2, 0, 0, 0}, + { "LOAD2", 2, 0, 0, 0}, + { "SETA1", 2, 0, 0, 0}, + { "SETA2", 2, 0, 0, 0}, + { "QUIT", 0, 0, 0, 0}, + { "SINR", 2, 0, 0, 0}, + { "SINV", 2, 0, 1, 0}, + { "COSR", 2, 0, 0, 0}, + { "COSV", 2, 0, 1, 0}, + { "TANR", 2, 0, 0, 0}, + { "TANV", 2, 0, 1, 0}, + { "MODR", 2, 0, 0, 0}, + { "MODV", 2, 0, 1, 0}, + { "ABS", 1, 0, 0, 0}, + { "MINR", 2, 0, 0, 0}, + { "MINV", 2, 0, 1, 0}, + { "MAXR", 2, 0, 0, 0}, + { "MAXV", 2, 0, 1, 0}, + { "RNDR", 2, 0, 0, 0}, + { "RNDV", 2, 0, 1, 0}, + { "FACTORIAL", 1, 0, 0, 0}, + { "POWERR", 2, 0, 0, 0}, + { "POWERV", 2, 0, 1, 0}, + { "IPOWERR", 2, 0, 0, 0}, + { "IPOWERV", 2, 0, 1, 0}, + { "ANDR", 2, 0, 0, 0}, + { "ANDV", 2, 0, 1, 0}, + { "ORR", 2, 0, 0, 0}, + { "ORV", 2, 0, 1, 0}, + { "XORR", 2, 0, 0, 0}, + { "XORV", 2, 0, 1, 0}, + { "NANDR", 2, 0, 0, 0}, + { "NANDV", 2, 0, 1, 0}, + { "NORR", 2, 0, 0, 0}, + { "NORV", 2, 0, 1, 0}, + { "XNORR", 2, 0, 0, 0}, + { "XNORV", 2, 0, 1, 0}, + { "NOT", 1, 0, 0, 0}, + { "LSHIFTR", 2, 0, 0, 0}, + { "LSHIFTV", 2, 0, 1, 0}, + { "RSHIFTR", 2, 0, 0, 0}, + { "RSHIFTV", 2, 0, 1, 0}, + { "TRACER", 1, 0, 0, 0}, + { "TRACEV", 1, 1, 0, 0}, + { "TRACE3", 0, 0, 0, 0}, + { "LOOP", 2, 1, 0, 0}, + { "PUSHR", 1, 0, 0, 0}, + { "PUSHV", 1, 1, 0, 0}, + { "POP", 1, 0, 0, 0}, + { "ENQUEUER", 2, 0, 0, 0}, + { "ENQUEUEV", 2, 0, 1, 0}, + { "DEQUEUE", 1, 0, 0, 0}, + { "PLAYSOUNDR", 1, 0, 0, 0}, + { "PLAYSOUNDV", 1, 1, 0, 0}, + { "LOADLWEAPONR", 1, 0, 0, 0}, + { "LOADLWEAPONV", 1, 1, 0, 0}, + { "LOADITEMR", 1, 0, 0, 0}, + { "LOADITEMV", 1, 1, 0, 0}, + { "LOADNPCR", 1, 0, 0, 0}, + { "LOADNPCV", 1, 1, 0, 0}, + { "CREATELWEAPONR", 1, 0, 0, 0}, + { "CREATELWEAPONV", 1, 1, 0, 0}, + { "CREATEITEMR", 1, 0, 0, 0}, + { "CREATEITEMV", 1, 1, 0, 0}, + { "CREATENPCR", 1, 0, 0, 0}, + { "CREATENPCV", 1, 1, 0, 0}, + { "LOADI", 2, 0, 0, 0}, + { "STOREI", 2, 0, 0, 0}, + { "GOTOR", 1, 0, 0, 0}, + { "SQROOTV", 2, 0, 1, 0}, + { "SQROOTR", 2, 0, 0, 0}, + { "CREATEEWEAPONR", 1, 0, 0, 0}, + { "CREATEEWEAPONV", 1, 1, 0, 0}, + { "PITWARP", 2, 1, 1, 0}, + { "WARPR", 2, 0, 0, 0}, + { "PITWARPR", 2, 0, 0, 0}, + { "CLEARSPRITESR", 1, 0, 0, 0}, + { "CLEARSPRITESV", 1, 1, 0, 0}, + { "RECT", 0, 0, 0, 0}, + { "CIRCLE", 0, 0, 0, 0}, + { "ARC", 0, 0, 0, 0}, + { "ELLIPSE", 0, 0, 0, 0}, + { "LINE", 0, 0, 0, 0}, + { "PUTPIXEL", 0, 0, 0, 0}, + { "DRAWTILE", 0, 0, 0, 0}, + { "DRAWCOMBO", 0, 0, 0, 0}, + { "ELLIPSE2", 0, 0, 0, 0}, + { "SPLINE", 0, 0, 0, 0}, + { "FLOODFILL", 0, 0, 0, 0}, + { "COMPOUNDR", 1, 0, 0, 0}, + { "COMPOUNDV", 1, 1, 0, 0}, + { "MSGSTRR", 1, 0, 0, 0}, + { "MSGSTRV", 1, 1, 0, 0}, + { "ISVALIDITEM", 1, 0, 0, 0}, + { "ISVALIDNPC", 1, 0, 0, 0}, + { "PLAYMIDIR", 1, 0, 0, 0}, + { "PLAYMIDIV", 1, 1, 0, 0}, + { "COPYTILEVV", 2, 1, 1, 0}, + { "COPYTILEVR", 2, 1, 0, 0}, + { "COPYTILERV", 2, 0, 1, 0}, + { "COPYTILERR", 2, 0, 0, 0}, + { "SWAPTILEVV", 2, 1, 1, 0}, + { "SWAPTILEVR", 2, 1, 0, 0}, + { "SWAPTILERV", 2, 0, 1, 0}, + { "SWAPTILERR", 2, 0, 0, 0}, + { "CLEARTILEV", 1, 1, 0, 0}, + { "CLEARTILER", 1, 0, 0, 0}, + { "OVERLAYTILEVV", 2, 1, 1, 0}, + { "OVERLAYTILEVR", 2, 1, 0, 0}, + { "OVERLAYTILERV", 2, 0, 1, 0}, + { "OVERLAYTILERR", 2, 0, 0, 0}, + { "FLIPROTTILEVV", 2, 1, 1, 0}, + { "FLIPROTTILEVR", 2, 1, 0, 0}, + { "FLIPROTTILERV", 2, 0, 1, 0}, + { "FLIPROTTILERR", 2, 0, 0, 0}, + { "GETTILEPIXELV", 1, 1, 0, 0}, + { "GETTILEPIXELR", 1, 0, 0, 0}, + { "SETTILEPIXELV", 1, 1, 0, 0}, + { "SETTILEPIXELR", 1, 0, 0, 0}, + { "SHIFTTILEVV", 2, 1, 1, 0}, + { "SHIFTTILEVR", 2, 1, 0, 0}, + { "SHIFTTILERV", 2, 0, 1, 0}, + { "SHIFTTILERR", 2, 0, 0, 0}, + { "ISVALIDLWPN", 1, 0, 0, 0}, + { "ISVALIDEWPN", 1, 0, 0, 0}, + { "LOADEWEAPONR", 1, 0, 0, 0}, + { "LOADEWEAPONV", 1, 1, 0, 0}, + { "ALLOCATEMEMR", 2, 0, 0, 0}, + { "ALLOCATEMEMV", 2, 0, 1, 0}, + { "ALLOCATEGMEMV", 2, 0, 1, 0}, + { "DEALLOCATEMEMR", 1, 0, 0, 0}, + { "DEALLOCATEMEMV", 1, 1, 0, 0}, + { "WAITDRAW", 0, 0, 0, 0}, + { "ARCTANR", 1, 0, 0, 0}, + { "LWPNUSESPRITER", 1, 0, 0, 0}, + { "LWPNUSESPRITEV", 1, 1, 0, 0}, + { "EWPNUSESPRITER", 1, 0, 0, 0}, + { "EWPNUSESPRITEV", 1, 1, 0, 0}, + { "LOADITEMDATAR", 1, 0, 0, 0}, + { "LOADITEMDATAV", 1, 1, 0, 0}, + { "BITNOT", 1, 0, 0, 0}, + { "LOG10", 1, 0, 0, 0}, + { "LOGE", 1, 0, 0, 0}, + { "ISSOLID", 1, 0, 0, 0}, + { "LAYERSCREEN", 2, 0, 0, 0}, + { "LAYERMAP", 2, 0, 0, 0}, + { "TRACE2R", 1, 0, 0, 0}, + { "TRACE2V", 1, 1, 0, 0}, + { "TRACE4", 0, 0, 0, 0}, + { "TRACE5", 0, 0, 0, 0}, + { "SECRETS", 0, 0, 0, 0}, + { "DRAWCHAR", 0, 0, 0, 0}, + { "GETSCREENFLAGS", 1, 0, 0, 0}, + { "QUAD", 0, 0, 0, 0}, + { "TRIANGLE", 0, 0, 0, 0}, + { "ARCSINR", 2, 0, 0, 0}, + { "ARCSINV", 2, 1, 0, 0}, + { "ARCCOSR", 2, 0, 0, 0}, + { "ARCCOSV", 2, 1, 0, 0}, + { "GAMEEND", 0, 0, 0, 0}, + { "DRAWINT", 0, 0, 0, 0}, + { "SETTRUE", 1, 0, 0, 0}, + { "SETFALSE", 1, 0, 0, 0}, + { "SETMORE", 1, 0, 0, 0}, + { "SETLESS", 1, 0, 0, 0}, + { "FASTTILE", 0, 0, 0, 0}, + { "FASTCOMBO", 0, 0, 0, 0}, + { "DRAWSTRING", 0, 0, 0, 0}, + { "SETSIDEWARP", 0, 0, 0, 0}, + { "SAVE", 0, 0, 0, 0}, + { "TRACE6", 0, 0, 0, 0}, + { "DEPRECATED", 1, 0, 0, 0}, + { "QUAD3D", 0, 0, 0, 0}, + { "TRIANGLE3D", 0, 0, 0, 0}, + { "SETCOLORB", 0, 0, 0, 0}, + { "SETDEPTHB", 0, 0, 0, 0}, + { "GETCOLORB", 0, 0, 0, 0}, + { "GETDEPTHB", 0, 0, 0, 0}, + { "COMBOTILE", 2, 0, 0, 0}, + { "SETTILEWARP", 0, 0, 0, 0}, + { "GETSCREENEFLAGS", 1, 0, 0, 0}, + { "GETSAVENAME", 1, 0, 0, 0}, + { "ARRAYSIZE", 1, 0, 0, 0}, + { "ITEMNAME", 1, 0, 0, 0}, + { "SETSAVENAME", 1, 0, 0, 0}, + { "NPCNAME", 1, 0, 0, 0}, + { "GETMESSAGE", 2, 0, 0, 0}, + { "GETDMAPNAME", 2, 0, 0, 0}, + { "GETDMAPTITLE", 2, 0, 0, 0}, + { "GETDMAPINTRO", 2, 0, 0, 0}, + { "ALLOCATEGMEMR", 2, 0, 0, 0}, + { "DRAWBITMAP", 0, 0, 0, 0}, + { "SETRENDERTARGET", 0, 0, 0, 0}, + { "PLAYENHMUSIC", 2, 0, 0, 0}, + { "GETMUSICFILE", 2, 0, 0, 0}, + { "GETMUSICTRACK", 1, 0, 0, 0}, + { "SETDMAPENHMUSIC", 0, 0, 0, 0}, + { "DRAWLAYER", 0, 0, 0, 0}, + { "DRAWSCREEN", 0, 0, 0, 0}, + { "BREAKSHIELD", 1, 0, 0, 0}, + { "SAVESCREEN", 1, 0, 0, 0}, + { "SAVEQUITSCREEN", 0, 0, 0, 0}, + { "SELECTAWPNR", 1, 0, 0, 0}, + { "SELECTAWPNV", 1, 1, 0, 0}, + { "SELECTBWPNR", 1, 0, 0, 0}, + { "SELECTBWPNV", 1, 1, 0, 0}, + { "GETSIDEWARPDMAP", 1, 0, 0, 0}, + { "GETSIDEWARPSCR", 1, 0, 0, 0}, + { "GETSIDEWARPTYPE", 1, 0, 0, 0}, + { "GETTILEWARPDMAP", 1, 0, 0, 0}, + { "GETTILEWARPSCR", 1, 0, 0, 0}, + { "GETTILEWARPTYPE", 1, 0, 0, 0}, + { "GETFFCSCRIPT", 1, 0, 0, 0}, + { "", 0, 0, 0, 0} +}; + + +script_variable variable_list[]= +{ + //name id maxcount multiple + { "D", REG_D(0), 8, 0 }, + { "A", REG_A(0), 2, 0 }, + { "DATA", DATA, 0, 0 }, + { "CSET", FCSET, 0, 0 }, + { "DELAY", DELAY, 0, 0 }, + { "X", FX, 0, 0 }, + { "Y", FY, 0, 0 }, + { "XD", XD, 0, 0 }, + { "YD", YD, 0, 0 }, + { "XD2", XD2, 0, 0 }, + { "YD2", YD2, 0, 0 }, + { "FLAG", FLAG, 0, 0 }, + { "WIDTH", WIDTH, 0, 0 }, + { "HEIGHT", HEIGHT, 0, 0 }, + { "LINK", LINK, 0, 0 }, + { "FFFLAGSD", FFFLAGSD, 0, 0 }, + { "FFCWIDTH", FFCWIDTH, 0, 0 }, + { "FFCHEIGHT", FFCHEIGHT, 0, 0 }, + { "FFTWIDTH", FFTWIDTH, 0, 0 }, + { "FFTHEIGHT", FFTHEIGHT, 0, 0 }, + { "FFLINK", FFLINK, 0, 0 }, + //{ "COMBOD", COMBOD(0), 176, 3 }, + //{ "COMBOC", COMBOC(0), 176, 3 }, + //{ "COMBOF", COMBOF(0), 176, 3 }, + { "INPUTSTART", INPUTSTART, 0, 0 }, + { "INPUTUP", INPUTUP, 0, 0 }, + { "INPUTDOWN", INPUTDOWN, 0, 0 }, + { "INPUTLEFT", INPUTLEFT, 0, 0 }, + { "INPUTRIGHT", INPUTRIGHT, 0, 0 }, + { "INPUTA", INPUTA, 0, 0 }, + { "INPUTB", INPUTB, 0, 0 }, + { "INPUTL", INPUTL, 0, 0 }, + { "INPUTR", INPUTR, 0, 0 }, + { "INPUTMOUSEX", INPUTMOUSEX, 0, 0 }, + { "INPUTMOUSEY", INPUTMOUSEY, 0, 0 }, + { "LINKX", LINKX, 0, 0 }, + { "LINKY", LINKY, 0, 0 }, + { "LINKZ", LINKZ, 0, 0 }, + { "LINKJUMP", LINKJUMP, 0, 0 }, + { "LINKDIR", LINKDIR, 0, 0 }, + { "LINKHITDIR", LINKHITDIR, 0, 0 }, + { "LINKHP", LINKHP, 0, 0 }, + { "LINKMP", LINKMP, 0, 0 }, + { "LINKMAXHP", LINKMAXHP, 0, 0 }, + { "LINKMAXMP", LINKMAXMP, 0, 0 }, + { "LINKACTION", LINKACTION, 0, 0 }, + { "LINKHELD", LINKHELD, 0, 0 }, + { "LINKITEMD", LINKITEMD, 0, 0 }, + { "LINKSWORDJINX", LINKSWORDJINX, 0, 0 }, + { "LINKITEMJINX", LINKITEMJINX, 0, 0 }, + { "LINKDRUNK", LINKDRUNK, 0, 0 }, + { "ITEMX", ITEMX, 0, 0 }, + { "ITEMY", ITEMY, 0, 0 }, + { "ITEMZ", ITEMZ, 0, 0 }, + { "ITEMJUMP", ITEMJUMP, 0, 0 }, + { "ITEMDRAWTYPE", ITEMDRAWTYPE, 0, 0 }, + { "ITEMID", ITEMID, 0, 0 }, + { "ITEMTILE", ITEMTILE, 0, 0 }, + { "ITEMOTILE", ITEMOTILE, 0, 0 }, + { "ITEMCSET", ITEMCSET, 0, 0 }, + { "ITEMFLASHCSET", ITEMFLASHCSET, 0, 0 }, + { "ITEMFRAMES", ITEMFRAMES, 0, 0 }, + { "ITEMFRAME", ITEMFRAME, 0, 0 }, + { "ITEMASPEED", ITEMASPEED, 0, 0 }, + { "ITEMDELAY", ITEMDELAY, 0, 0 }, + { "ITEMFLASH", ITEMFLASH, 0, 0 }, + { "ITEMFLIP", ITEMFLIP, 0, 0 }, + { "ITEMCOUNT", ITEMCOUNT, 0, 0 }, + { "IDATAFAMILY", IDATAFAMILY, 0, 0 }, + { "IDATALEVEL", IDATALEVEL, 0, 0 }, + { "IDATAKEEP", IDATAKEEP, 0, 0 }, + { "IDATAAMOUNT", IDATAAMOUNT, 0, 0 }, + { "IDATASETMAX", IDATASETMAX, 0, 0 }, + { "IDATAMAX", IDATAMAX, 0, 0 }, + { "IDATACOUNTER", IDATACOUNTER, 0, 0 }, + { "ITEMEXTEND", ITEMEXTEND, 0, 0 }, + { "NPCX", NPCX, 0, 0 }, + { "NPCY", NPCY, 0, 0 }, + { "NPCZ", NPCZ, 0, 0 }, + { "NPCJUMP", NPCJUMP, 0, 0 }, + { "NPCDIR", NPCDIR, 0, 0 }, + { "NPCRATE", NPCRATE, 0, 0 }, + { "NPCSTEP", NPCSTEP, 0, 0 }, + { "NPCFRAMERATE", NPCFRAMERATE, 0, 0 }, + { "NPCHALTRATE", NPCHALTRATE, 0, 0 }, + { "NPCDRAWTYPE", NPCDRAWTYPE, 0, 0 }, + { "NPCHP", NPCHP, 0, 0 }, + { "NPCID", NPCID, 0, 0 }, + { "NPCDP", NPCDP, 0, 0 }, + { "NPCWDP", NPCWDP, 0, 0 }, + { "NPCOTILE", NPCOTILE, 0, 0 }, + { "NPCENEMY", NPCENEMY, 0, 0 }, + { "NPCWEAPON", NPCWEAPON, 0, 0 }, + { "NPCITEMSET", NPCITEMSET, 0, 0 }, + { "NPCCSET", NPCCSET, 0, 0 }, + { "NPCBOSSPAL", NPCBOSSPAL, 0, 0 }, + { "NPCBGSFX", NPCBGSFX, 0, 0 }, + { "NPCCOUNT", NPCCOUNT, 0, 0 }, + { "GD", GD(0), 256, 0 }, + { "SDD", SDD, 0, 0 }, + { "GDD", GDD, 0, 0 }, + { "SDDD", SDDD, 0, 0 }, + { "SCRDOORD", SCRDOORD, 0, 0 }, + { "GAMEDEATHS", GAMEDEATHS, 0, 0 }, + { "GAMECHEAT", GAMECHEAT, 0, 0 }, + { "GAMETIME", GAMETIME, 0, 0 }, + { "GAMEHASPLAYED", GAMEHASPLAYED, 0, 0 }, + { "GAMETIMEVALID", GAMETIMEVALID, 0, 0 }, + { "GAMEGUYCOUNT", GAMEGUYCOUNT, 0, 0 }, + { "GAMECONTSCR", GAMECONTSCR, 0, 0 }, + { "GAMECONTDMAP", GAMECONTDMAP, 0, 0 }, + { "GAMECOUNTERD", GAMECOUNTERD, 0, 0 }, + { "GAMEMCOUNTERD", GAMEMCOUNTERD, 0, 0 }, + { "GAMEDCOUNTERD", GAMEDCOUNTERD, 0, 0 }, + { "GAMEGENERICD", GAMEGENERICD, 0, 0 }, + { "GAMEITEMSD", GAMEITEMSD, 0, 0 }, + { "GAMELITEMSD", GAMELITEMSD, 0, 0 }, + { "GAMELKEYSD", GAMELKEYSD, 0, 0 }, + { "SCREENSTATED", SCREENSTATED, 0, 0 }, + { "SCREENSTATEDD", SCREENSTATEDD, 0, 0 }, + { "GAMEGUYCOUNTD", GAMEGUYCOUNTD, 0, 0 }, + { "CURMAP", CURMAP, 0, 0 }, + { "CURSCR", CURSCR, 0, 0 }, + { "CURDSCR", CURDSCR, 0, 0 }, + { "CURDMAP", CURDMAP, 0, 0 }, + { "COMBODD", COMBODD, 0, 0 }, + { "COMBOCD", COMBOCD, 0, 0 }, + { "COMBOFD", COMBOFD, 0, 0 }, + { "COMBOTD", COMBOTD, 0, 0 }, + { "COMBOID", COMBOID, 0, 0 }, + { "COMBOSD", COMBOSD, 0, 0 }, + { "REFITEMCLASS", REFITEMCLASS, 0, 0 }, + { "REFITEM", REFITEM, 0, 0 }, + { "REFFFC", REFFFC, 0, 0 }, + { "REFLWPN", REFLWPN, 0, 0 }, + { "REFEWPN", REFEWPN, 0, 0 }, + { "REFLWPNCLASS", REFLWPNCLASS, 0, 0 }, + { "REFEWPNCLASS", REFEWPNCLASS, 0, 0 }, + { "REFNPC", REFNPC, 0, 0 }, + { "REFNPCCLASS", REFNPCCLASS, 0, 0 }, + { "LWPNX", LWPNX, 0, 0 }, + { "LWPNY", LWPNY, 0, 0 }, + { "LWPNZ", LWPNZ, 0, 0 }, + { "LWPNJUMP", LWPNJUMP, 0, 0 }, + { "LWPNDIR", LWPNDIR, 0, 0 }, + { "LWPNSTEP", LWPNSTEP, 0, 0 }, + { "LWPNANGULAR", LWPNANGULAR, 0, 0 }, + { "LWPNANGLE", LWPNANGLE, 0, 0 }, + { "LWPNDRAWTYPE", LWPNDRAWTYPE, 0, 0 }, + { "LWPNPOWER", LWPNPOWER, 0, 0 }, + { "LWPNDEAD", LWPNDEAD, 0, 0 }, + { "LWPNID", LWPNID, 0, 0 }, + { "LWPNTILE", LWPNTILE, 0, 0 }, + { "LWPNCSET", LWPNCSET, 0, 0 }, + { "LWPNFLASHCSET", LWPNFLASHCSET, 0, 0 }, + { "LWPNFRAMES", LWPNFRAMES, 0, 0 }, + { "LWPNFRAME", LWPNFRAME, 0, 0 }, + { "LWPNASPEED", LWPNASPEED, 0, 0 }, + { "LWPNFLASH", LWPNFLASH, 0, 0 }, + { "LWPNFLIP", LWPNFLIP, 0, 0 }, + { "LWPNCOUNT", LWPNCOUNT, 0, 0 }, + { "LWPNEXTEND", LWPNEXTEND, 0, 0 }, + { "LWPNOTILE", LWPNOTILE, 0, 0 }, + { "LWPNOCSET", LWPNOCSET, 0, 0 }, + { "EWPNX", EWPNX, 0, 0 }, + { "EWPNY", EWPNY, 0, 0 }, + { "EWPNZ", EWPNZ, 0, 0 }, + { "EWPNJUMP", EWPNJUMP, 0, 0 }, + { "EWPNDIR", EWPNDIR, 0, 0 }, + { "EWPNSTEP", EWPNSTEP, 0, 0 }, + { "EWPNANGULAR", EWPNANGULAR, 0, 0 }, + { "EWPNANGLE", EWPNANGLE, 0, 0 }, + { "EWPNDRAWTYPE", EWPNDRAWTYPE, 0, 0 }, + { "EWPNPOWER", EWPNPOWER, 0, 0 }, + { "EWPNDEAD", EWPNDEAD, 0, 0 }, + { "EWPNID", EWPNID, 0, 0 }, + { "EWPNTILE", EWPNTILE, 0, 0 }, + { "EWPNCSET", EWPNCSET, 0, 0 }, + { "EWPNFLASHCSET", EWPNFLASHCSET, 0, 0 }, + { "EWPNFRAMES", EWPNFRAMES, 0, 0 }, + { "EWPNFRAME", EWPNFRAME, 0, 0 }, + { "EWPNASPEED", EWPNASPEED, 0, 0 }, + { "EWPNFLASH", EWPNFLASH, 0, 0 }, + { "EWPNFLIP", EWPNFLIP, 0, 0 }, + { "EWPNCOUNT", EWPNCOUNT, 0, 0 }, + { "EWPNEXTEND", EWPNEXTEND, 0, 0 }, + { "EWPNOTILE", EWPNOTILE, 0, 0 }, + { "EWPNOCSET", EWPNOCSET, 0, 0 }, + { "NPCEXTEND", NPCEXTEND, 0, 0 }, + { "SP", SP, 0, 0 }, + { "SP", SP, 0, 0 }, + { "WAVY", WAVY, 0, 0 }, + { "QUAKE", QUAKE, 0, 0 }, + { "IDATAUSESOUND", IDATAUSESOUND, 0, 0 }, + { "INPUTMOUSEZ", INPUTMOUSEZ, 0, 0 }, + { "INPUTMOUSEB", INPUTMOUSEB, 0, 0 }, + { "COMBODDM", COMBODDM, 0, 0 }, + { "COMBOCDM", COMBOCDM, 0, 0 }, + { "COMBOFDM", COMBOFDM, 0, 0 }, + { "COMBOTDM", COMBOTDM, 0, 0 }, + { "COMBOIDM", COMBOIDM, 0, 0 }, + { "COMBOSDM", COMBOSDM, 0, 0 }, + { "SCRIPTRAM", SCRIPTRAM, 0, 0 }, + { "GLOBALRAM", GLOBALRAM, 0, 0 }, + { "SCRIPTRAMD", SCRIPTRAMD, 0, 0 }, + { "GLOBALRAMD", GLOBALRAMD, 0, 0 }, + { "LWPNHXOFS", LWPNHXOFS, 0, 0 }, + { "LWPNHYOFS", LWPNHYOFS, 0, 0 }, + { "LWPNXOFS", LWPNXOFS, 0, 0 }, + { "LWPNYOFS", LWPNYOFS, 0, 0 }, + { "LWPNZOFS", LWPNZOFS, 0, 0 }, + { "LWPNHXSZ", LWPNHXSZ, 0, 0 }, + { "LWPNHYSZ", LWPNHYSZ, 0, 0 }, + { "LWPNHZSZ", LWPNHZSZ, 0, 0 }, + { "EWPNHXOFS", EWPNHXOFS, 0, 0 }, + { "EWPNHYOFS", EWPNHYOFS, 0, 0 }, + { "EWPNXOFS", EWPNXOFS, 0, 0 }, + { "EWPNYOFS", EWPNYOFS, 0, 0 }, + { "EWPNZOFS", EWPNZOFS, 0, 0 }, + { "EWPNHXSZ", EWPNHXSZ, 0, 0 }, + { "EWPNHYSZ", EWPNHYSZ, 0, 0 }, + { "EWPNHZSZ", EWPNHZSZ, 0, 0 }, + { "NPCHXOFS", NPCHXOFS, 0, 0 }, + { "NPCHYOFS", NPCHYOFS, 0, 0 }, + { "NPCXOFS", NPCXOFS, 0, 0 }, + { "NPCYOFS", NPCYOFS, 0, 0 }, + { "NPCZOFS", NPCZOFS, 0, 0 }, + { "NPCHXSZ", NPCHXSZ, 0, 0 }, + { "NPCHYSZ", NPCHYSZ, 0, 0 }, + { "NPCHZSZ", NPCHZSZ, 0, 0 }, + { "ITEMHXOFS", ITEMHXOFS, 0, 0 }, + { "ITEMHYOFS", ITEMHYOFS, 0, 0 }, + { "ITEMXOFS", ITEMXOFS, 0, 0 }, + { "ITEMYOFS", ITEMYOFS, 0, 0 }, + { "ITEMZOFS", ITEMZOFS, 0, 0 }, + { "ITEMHXSZ", ITEMHXSZ, 0, 0 }, + { "ITEMHYSZ", ITEMHYSZ, 0, 0 }, + { "ITEMHZSZ", ITEMHZSZ, 0, 0 }, + { "LWPNTXSZ", LWPNTXSZ, 0, 0 }, + { "LWPNTYSZ", LWPNTYSZ, 0, 0 }, + { "EWPNTXSZ", EWPNTXSZ, 0, 0 }, + { "EWPNTYSZ", EWPNTYSZ, 0, 0 }, + { "NPCTXSZ", NPCTXSZ, 0, 0 }, + { "NPCTYSZ", NPCTYSZ, 0, 0 }, + { "ITEMTXSZ", ITEMTXSZ, 0, 0 }, + { "ITEMTYSZ", ITEMTYSZ, 0, 0 }, + { "LINKHXOFS", LINKHXOFS, 0, 0 }, + { "LINKHYOFS", LINKHYOFS, 0, 0 }, + { "LINKXOFS", LINKXOFS, 0, 0 }, + { "LINKYOFS", LINKYOFS, 0, 0 }, + { "LINKZOFS", LINKZOFS, 0, 0 }, + { "LINKHXSZ", LINKHXSZ, 0, 0 }, + { "LINKHYSZ", LINKHYSZ, 0, 0 }, + { "LINKHZSZ", LINKHZSZ, 0, 0 }, + { "LINKTXSZ", LINKTXSZ, 0, 0 }, + { "LINKTYSZ", LINKTYSZ, 0, 0 }, + { "NPCTILE", NPCTILE, 0, 0 }, + { "LWPNBEHIND", LWPNBEHIND, 0, 0 }, + { "EWPNBEHIND", EWPNBEHIND, 0, 0 }, + { "SDDDD", SDDDD, 0, 0 }, + { "CURLEVEL", CURLEVEL, 0, 0 }, + { "ITEMPICKUP", ITEMPICKUP, 0, 0 }, + { "INPUTMAP", INPUTMAP, 0, 0 }, + { "LIT", LIT, 0, 0 }, + { "INPUTEX1", INPUTEX1, 0, 0 }, + { "INPUTEX2", INPUTEX2, 0, 0 }, + { "INPUTEX3", INPUTEX3, 0, 0 }, + { "INPUTEX4", INPUTEX4, 0, 0 }, + { "INPUTPRESSSTART", INPUTPRESSSTART, 0, 0 }, + { "INPUTPRESSUP", INPUTPRESSUP, 0, 0 }, + { "INPUTPRESSDOWN", INPUTPRESSDOWN, 0, 0 }, + { "INPUTPRESSLEFT", INPUTPRESSLEFT, 0, 0 }, + { "INPUTPRESSRIGHT", INPUTPRESSRIGHT, 0, 0 }, + { "INPUTPRESSA", INPUTPRESSA, 0, 0 }, + { "INPUTPRESSB", INPUTPRESSB, 0, 0 }, + { "INPUTPRESSL", INPUTPRESSL, 0, 0 }, + { "INPUTPRESSR", INPUTPRESSR, 0, 0 }, + { "INPUTPRESSEX1", INPUTPRESSEX1, 0, 0 }, + { "INPUTPRESSEX2", INPUTPRESSEX2, 0, 0 }, + { "INPUTPRESSEX3", INPUTPRESSEX3, 0, 0 }, + { "INPUTPRESSEX4", INPUTPRESSEX4, 0, 0 }, + { "LWPNMISCD", LWPNMISCD, 0, 0 }, + { "EWPNMISCD", EWPNMISCD, 0, 0 }, + { "NPCMISCD", NPCMISCD, 0, 0 }, + { "ITEMMISCD", ITEMMISCD, 0, 0 }, + { "FFMISCD", FFMISCD, 0, 0 }, + { "GETMIDI", GETMIDI, 0, 0 }, + { "NPCHOMING", NPCHOMING, 0, 0 }, + { "NPCDD", NPCDD, 0, 0 }, + { "LINKEQUIP", LINKEQUIP, 0, 0 }, + { "INPUTAXISUP", INPUTAXISUP, 0, 0 }, + { "INPUTAXISDOWN", INPUTAXISDOWN, 0, 0 }, + { "INPUTAXISLEFT", INPUTAXISLEFT, 0, 0 }, + { "INPUTAXISRIGHT", INPUTAXISRIGHT, 0, 0 }, + { "PRESSAXISUP", INPUTPRESSAXISUP, 0, 0 }, + { "PRESSAXISDOWN", INPUTPRESSAXISDOWN, 0, 0 }, + { "PRESSAXISLEFT", INPUTPRESSAXISLEFT, 0, 0 }, + { "PRESSAXISRIGHT", INPUTPRESSAXISRIGHT, 0, 0 }, + { "NPCTYPE", NPCTYPE, 0, 0 }, + { "FFSCRIPT", FFSCRIPT, 0, 0 }, + { "SCREENFLAGSD", SCREENFLAGSD, 0, 0 }, + { "LINKINVIS", LINKINVIS, 0, 0 }, + { "LINKINVINC", LINKINVINC, 0, 0 }, + { "SCREENEFLAGSD", SCREENEFLAGSD, 0, 0 }, + { "NPCMFLAGS", NPCMFLAGS, 0, 0 }, + { "FFINITDD", FFINITDD, 0, 0 }, + { "LINKMISCD", LINKMISCD, 0, 0 }, + { "DMAPFLAGSD", DMAPFLAGSD, 0, 0 }, + { "LWPNCOLLDET", LWPNCOLLDET, 0, 0 }, + { "EWPNCOLLDET", EWPNCOLLDET, 0, 0 }, + { "NPCCOLLDET", NPCCOLLDET, 0, 0 }, + { "LINKLADDERX", LINKLADDERX, 0, 0 }, + { "LINKLADDERY", LINKLADDERY, 0, 0 }, + { "NPCSTUN", NPCSTUN, 0, 0 }, + { "NPCDEFENSED", NPCDEFENSED, 0, 0 }, + { "IDATAPOWER", IDATAPOWER, 0, 0 }, + { "DMAPLEVELD", DMAPLEVELD, 0, 0 }, + { "DMAPCOMPASSD", DMAPCOMPASSD, 0, 0 }, + { "DMAPCONTINUED", DMAPCONTINUED, 0, 0 }, + { "DMAPMIDID", DMAPMIDID, 0, 0 }, + { "IDATAINITDD", IDATAINITDD, 0, 0 }, + { "ROOMTYPE", ROOMTYPE, 0, 0 }, + { "ROOMDATA", ROOMDATA, 0, 0 }, + { "LINKTILE", LINKTILE, 0, 0 }, + { "LINKFLIP", LINKFLIP, 0, 0 }, + { "INPUTPRESSMAP", INPUTPRESSMAP, 0, 0 }, + { "NPCHUNGER", NPCHUNGER, 0, 0 }, + { "GAMESTANDALONE", GAMESTANDALONE, 0, 0 }, + { "GAMEENTRSCR", GAMEENTRSCR, 0, 0 }, + { "GAMEENTRDMAP", GAMEENTRDMAP, 0, 0 }, + { "GAMECLICKFREEZE", GAMECLICKFREEZE, 0, 0 }, + { "PUSHBLOCKX", PUSHBLOCKX, 0, 0 }, + { "PUSHBLOCKY", PUSHBLOCKY, 0, 0 }, + { "PUSHBLOCKCOMBO", PUSHBLOCKCOMBO, 0, 0 }, + { "PUSHBLOCKCSET", PUSHBLOCKCSET, 0, 0 }, + { "UNDERCOMBO", UNDERCOMBO, 0, 0 }, + { "UNDERCSET", UNDERCSET, 0, 0 }, + { "DMAPOFFSET", DMAPOFFSET, 0, 0 }, + { "DMAPMAP", DMAPMAP, 0, 0 }, + { " ", -1, 0, 0 } +}; + +long ffparse(char *string) +{ + //return int(atof(string)*10000); + + //this function below isn't working too well yet + //clean_numeric_string(string); + double negcheck = atof(string); + + //if no decimal point, ascii to int conversion + char *ptr=strchr(string, '.'); + + if(!ptr) + { + return atoi(string)*10000; + } + + long ret=0; + char *tempstring1; + tempstring1=(char *)zc_malloc(strlen(string)+5); + sprintf(tempstring1, string); + + for(int i=0; i<4; ++i) + { + tempstring1[strlen(string)+i]='0'; + } + + ptr=strchr(tempstring1, '.'); + *ptr=0; + ret=atoi(tempstring1)*10000; + + ++ptr; + char *ptr2=ptr; + ptr2+=4; + *ptr2=0; + + if(negcheck<0) + ret-=atoi(ptr); + else ret+=atoi(ptr); + + zc_free(tempstring1); + return ret; +} + +bool ffcheck(char *arg) +{ + + for(int i=0; i<0x100; i++) + { + if(arg[i]!='\0') + { + if(i==0) + { + if(arg[i]!='-' && arg[i]!='.' && !(arg[i] >= '0' && arg[i] <='9')) + return false; + } + else + { + if(arg[i]!='.' && !(arg[i] >= '0' && arg[i] <='9')) + return false; + } + } + else + { + i=0x100; + } + } + + return true; +} + +char labels[65536][80]; +int lines[65536]; +int numlines; + +int parse_script(ffscript **script) +{ + if(!getname("Import Script (.txt)","txt",NULL,datapath,false)) + return D_CLOSE; + + return parse_script_file(script,temppath, true); +} + +int parse_script_file(ffscript **script, const char *path, bool report_success) +{ + saved=false; + FILE *fscript = fopen(path,"rb"); + char *buffer = new char[0x400]; + char *combuf = new char[0x100]; + char *arg1buf = new char[0x100]; + char *arg2buf = new char[0x100]; + bool stop=false; + bool success=true; + numlines = 0; + int num_commands; + + for(int i=0;; i++) + { + buffer[0]=0; + + if(stop) + { + num_commands=i+1; + break; + } + + for(int j=0; j<0x400; j++) + { + char temp; + temp = getc(fscript); + + if(feof(fscript)) + { + stop=true; + buffer[j]='\0'; + j=0x400; + ungetc(temp,fscript); + } + else + { + ungetc(temp,fscript); + buffer[j] = getc(fscript); + + if(buffer[j] == ';' || buffer[j] == '\n' || buffer[j] == 13) + { + if(buffer[j] == '\n') + { + buffer[j] = '\0'; + j=0x400; + } + else + { + while(getc(fscript)!='\n') + { + if(feof(fscript)) + { + stop=true; + break; + } + } + + buffer[j] = '\0'; + j=0x400; + } + } + } + } + + int k=0; + + while(buffer[k] == ' ' || buffer[k] == '\t') k++; + + if(buffer[k] == '\0') + { + i--; + continue; + } + + k=0; + + if(buffer[k] != ' ' && buffer[k] !='\t' && buffer[k] != '\0') + { + while(buffer[k] != ' ' && buffer[k] !='\t' && buffer[k] != '\0') + { + labels[numlines][k] = buffer[k]; + k++; + } + + labels[numlines][k] = '\0'; + lines[numlines] = i; + numlines++; + } + } + + fseek(fscript, 0, SEEK_SET); + stop = false; + + if((*script)!=NULL) delete [](*script); + + (*script) = new ffscript[num_commands]; + + for(int i=0; i-1) + { + if(variable_list[i].maxcount>1) + { + for(int j=0; j0) + { + if(command_list[i].arg1_type==1) + { + if(!ffcheck(arg1buf)) + { + retcode=ERR_PARAM1; + return 0; + } + + (*script)[com].arg1 = ffparse(arg1buf); + } + else + { + if(!set_argument(arg1buf, script, com, 0)) + { + retcode=ERR_PARAM1; + return 0; + } + } + + if(command_list[i].args>1) + { + if(command_list[i].arg2_type==1) + { + if(!ffcheck(arg2buf)) + { + retcode=ERR_PARAM2; + return 0; + } + + (*script)[com].arg2 = ffparse(arg2buf); + } + else + { + if(!set_argument(arg2buf, script, com, 1)) + { + retcode=ERR_PARAM2; + return 0; + } + } + } + } + } + } + } + + if(found_command) + { + return 1; + } + + retcode=ERR_INSTRUCTION; + return 0; +} + diff --git a/src/ffasm.h b/src/ffasm.h new file mode 100644 index 0000000000..a3c0111507 --- /dev/null +++ b/src/ffasm.h @@ -0,0 +1,13 @@ +# include "ffscript.h" + +#ifndef _FFASM_H_ +#define _FFASM_H_ + +int set_argument(char *argbuf, ffscript **script, int com, int argument); +int parse_script_section(char *combuf, char *arg1buf, char *arg2buf, ffscript **script, int com, int &retcode); +int parse_script(ffscript **script); +int parse_script_file(ffscript **script, const char *path, bool report_success); +long ffparse(char *string); + +#endif + diff --git a/src/ffc.cpp b/src/ffc.cpp new file mode 100644 index 0000000000..5d806dc1fc --- /dev/null +++ b/src/ffc.cpp @@ -0,0 +1,327 @@ +#include "ffc.h" +#include "tiles.h" // isonline() is in tiles for some reason... +#include "zdefs.h" // mapscr + +FFC::FFC() +{ + clear(); +} + +bool FFC::isVisible(bool lensActive) const +{ + if(data==0 || (flags&ffCHANGER)!=0) + return false; + + if((flags&ffLENSVIS)!=0) + return lensActive; + + return true; +} + +bool FFC::isUnderPoint(int px, int py) const +{ + int fx=x/10000; + if(pxfx+(width&63)) + return false; + + int fy=y/10000; + if(pyfy+(height&63)) + return false; + + if((flags&(ffCHANGER|ffETHEREAL))!=0) + return false; + + return true; +} + +void FFC::clear() +{ + data=0; + cset=0; + delay=0; + x=0; + y=0; + xVel=0; + yVel=0; + xAccel=0; + yAccel=0; + width=15; + height=15; + flags=0; + link=0; + lastChangerX=-1000; + lastChangerY=-1000; + prevX=-10000000; + prevY=-10000000; + + script=0; + scriptData.Clear(); + for(int i=0; i<16; i++) + misc[i]=0; + for(int i=0; i<8; i++) + initd[i]=0; + inita[0]=10000; // Should these be 0? They get reset + inita[1]=10000; // to 10000 everywhere else, so... + + initialized=false; +} + +void FFC::copy(const FFC& other, copyType type) +{ + // This is wrong. Redo it. + + // This stuff is always copied... + data=other.data; + cset=other.cset; + delay=other.delay; + xVel=other.xVel; + yVel=other.yVel; + xAccel=other.xAccel; + yAccel=other.yAccel; + flags=other.flags; + width=other.width; + height=other.height; + link=other.link; + + // loadscr() used to copy script both conditionally and unconditionally + // on carry over. I think unconditional is correct, but maybe not... + script=other.script; + + scriptData=other.scriptData; // I think? + + for(int i=0; i<16; i++) + misc[i]=other.misc[i]; + for(int i=0; i<8; i++) + initd[i]=other.initd[i]; + inita[0]=other.inita[0]; + inita[1]=other.inita[1]; + + if(type==copy_pasteSingle) + return; + + x=other.x; + y=other.y; + + if(type==copy_full) + { + initialized=other.initialized; + lastChangerX=other.lastChangerX; + lastChangerY=other.lastChangerY; + prevX=other.prevX; + prevY=other.prevY; + } + else // Carry over + { + if((flags&ffSCRIPTRESET)==0) + initialized=other.initialized; + else // Script resets + { + initialized=false; + scriptData.pc=0; + scriptData.sp=0; + scriptData.ffcref=0; + } + } +} + +void FFC::applyChanger(FFC& changer) +{ + if((changer.flags&ffCHANGETHIS)!=0) + { + data=changer.data; + cset=changer.cset; + } + + if((changer.flags&ffCHANGENEXT)!=0) + data++; + + if((changer.flags&ffCHANGEPREV)!=0) + data--; + + delay=changer.delay; + x=changer.x; + y=changer.y; + width=changer.width; + height=changer.height; + xVel=changer.xVel; + yVel=changer.yVel; + xAccel=changer.xAccel; + yAccel=changer.yAccel; + link=changer.link; + + dword newFlags=changer.flags; + newFlags&=~ffCHANGER; + if((flags&ffCARRYOVER)!=0) // Keep carry-over flag if it's set. + newFlags|=ffCARRYOVER; // (it can still be taken from the changer. + flags=newFlags; // It's always been that way.) +} + +void FFC::checkScreenEdges(bool wrap) +{ + if(wrap) + { + bool wrappedX=false, wrappedY=false; + if(x<-320000) + { + x=2880000+(x+320000); + wrappedX=true; + } + else if(x>=2880000) + { + x = x-2880000-320000; + wrappedX=true; + } + + if(y<-320000) + { + y=2080000+(y+320000); + wrappedY=true; + } + else if(y>=2080000) + { + y=y-2080000-320000; + wrappedY=true; + } + + if(wrappedX || wrappedY) + { + if(wrappedX) + prevY=y; + if(wrappedY) + prevX=x; + lastChangerX=-1000; + lastChangerY=-1000; + } + } + else if(x<-640000 || x>=2880000 || y<-640000 || y>=2080000) + { + data=0; + flags&=~ffCARRYOVER; + } +} + +void FFC::updateMovement(FFC* linked) +{ + if((linked ? linked->delay : delay)==0) + { + if(linked && linked!=this) + { + prevX=x; + prevY=y; + x+=linked->xVel; + y+=linked->yVel; + } + else + { + prevX=x; + prevY=y; + x+=xVel; + y+=yVel; + xVel+=xAccel; + yVel+=yAccel; + + if(xVel>1280000) + xVel=1280000; + else if(xVel<-1280000) + xVel=-1280000; + + if(yVel>1280000) + yVel=1280000; + else if(yVel<-1280000) + yVel=-1280000; + } + } + else + { + if(!linked || linked==this) + delay--; + } +} + +bool FFC::canMove() +{ + // Not stationary or a changer, has a combo set + return data!=0 && (flags&(ffCHANGER|ffSTATIONARY))==0; +} + + + + +FFCSet::FFCSet() +{ + clear(); +} + +void FFCSet::updateMovement(mapscr* tmpscr, bool holdingItem) +{ + for(int i=0; i<32; i++) + { + FFC& curr=ffcs[i]; + + if(!curr.canMove()) + continue; + + // Frozen because Link's holding up an item? + if(holdingItem && (curr.flags&ffIGNOREHOLDUP)==0) + continue; + + // Check for changers + if(curr.link==0) + { + for(int j=0; j<32; j++) + { + FFC& changer=ffcs[j]; + + // Not a functioning changer? + if((changer.flags&ffCHANGER)==0 || changer.data==0) + continue; + + // Ignore this changer if it's in the same place as the last one + if(changer.x/10000==curr.lastChangerX && + changer.y/10000==curr.lastChangerY) + continue; + + if((isonline(curr.x, curr.y, curr.prevX, curr.prevY, changer.x, changer.y) || // Along the line, or... + (curr.x==changer.x && curr.y==changer.y)) && // At exactly the same position, and... + (curr.prevX>-10000000 && curr.prevY>-10000000)) // Whatever this means + { + curr.applyChanger(changer); + + curr.lastChangerX=(short)(changer.x/10000); + curr.lastChangerY=(short)(changer.y/10000); + + // This switches to a secret combo, I guess? Sure is ugly. + if(combobuf[changer.data].flag>15 && combobuf[changer.data].flag<32) + changer.data=tmpscr->secretcombo[combobuf[changer.data].flag-16+4]; + + if((changer.flags&ffSWAPPREV)!=0) + swapData(changer, ffcs[(j>0) ? j-1 : 31]); + else if((changer.flags&ffSWAPPREV)!=0) + swapData(changer, ffcs[(j<31) ? j+1 : 0]); + + break; + } + } + } + + curr.updateMovement((curr.link!=0) ? &ffcs[curr.link-1] : 0); + curr.checkScreenEdges((tmpscr->flags6&fWRAPAROUNDFF)!=0); + } +} + +void FFCSet::swapData(FFC& f1, FFC& f2) +{ + // The flag checkboxes just say "swap speed"... + // Should all this stuff really be swapped + zc_swap(f1.data, f2.data); + zc_swap(f1.cset, f2.cset); + zc_swap(f1.delay, f2.delay); + zc_swap(f1.xVel, f2.xVel); + zc_swap(f1.yVel, f2.yVel); + zc_swap(f1.xAccel, f2.xAccel); + zc_swap(f1.yAccel, f2.yAccel); + zc_swap(f1.link, f2.link); + zc_swap(f1.width, f2.width); + zc_swap(f1.height, f2.height); + zc_swap(f1.flags, f2.flags); +} diff --git a/src/ffc.h b/src/ffc.h new file mode 100644 index 0000000000..9a656d67a2 --- /dev/null +++ b/src/ffc.h @@ -0,0 +1,161 @@ +#ifndef _ZC_FFC_H_ +#define _ZC_FFC_H_ + +#include "refInfo.h" +#include "types.h" + +//FF combo flags +#define ffOVERLAY 0x00000001 +#define ffTRANS 0x00000002 +#define ffSOLID 0x00000004 +#define ffCARRYOVER 0x00000008 +#define ffSTATIONARY 0x00000010 +#define ffCHANGER 0x00000020 //Is a changer +#define ffPRELOAD 0x00000040 //Script is run before screen appears. +#define ffLENSVIS 0x00000080 //Invisible, but not to the Lens of Truth. +#define ffSCRIPTRESET 0x00000100 //Script resets when carried over. +#define ffETHEREAL 0x00000200 //Does not occlude combo and flags on the screen +#define ffIGNOREHOLDUP 0x00000400 //Updated even while Link is holding an item + +//FF combo changer flags +#define ffSWAPNEXT 0x80000000 //Swap speed with next FFC +#define ffSWAPPREV 0x40000000 //Swap speed with prev. FFC +#define ffCHANGENEXT 0x20000000 //Increase combo ID +#define ffCHANGEPREV 0x10000000 //Decrease combo ID +#define ffCHANGETHIS 0x08000000 //Change combo/cset to this +#define ffCHANGESPEED 0x04000000 //Change speed to this (default, not implemented yet) + +struct FFC +{ + enum copyType { copy_full, copy_pasteSingle, copy_carryOver }; + + FFC(); + bool isVisible(bool lensActive) const; + bool isUnderPoint(int px, int py) const; + void clear(); + void copy(const FFC& other, copyType type); + void applyChanger(FFC& changer); + inline bool overlay() const { return (flags&ffOVERLAY)!=0; } + inline bool carriesOver() const { return (flags&ffCARRYOVER)!=0; } + + inline int getXInt() const { return x/10000; } + inline int getYInt() const { return y/10000; } + + inline word getCombo() const { return data; } + inline void setCombo(word c) { data=c; } + inline void modCombo(short amt) { data+=amt; } + inline word getCSet() const { return cset; } + inline void setCSet(word c) { cset=c; } + + inline dword getFlags() const { return flags; } + + // This sort of thing is why bit fields exist. :p + inline void setEffectWidth(int w) { width=(width&0xC0)|(w-1); } + inline void setEffectHeight(int h) { height=(height&0xC0)|(h-1); } + inline byte getEffectWidth() const { return (width&0x3F)+1; } + inline byte getEffectHeight() const { return (height&0x3F)+1; } + + inline void setTileWidth(int w) { width=((w-1)<<6)|(width&0x3F); } + inline void setTileHeight(int h) { height=((h-1)<<6)|(height&0x3F); } + inline byte getTileWidth() const { return (width>>6)+1; } + inline byte getTileHeight() const { return (height>>6)+1; } + + inline word getScript() const { return script; } + +//private: // Too much trouble. Probably will be for a while. + word data; + byte cset; + word delay; + long x, y; + long xVel, yVel; + long xAccel, yAccel; + byte width, height; + dword flags; + byte link; + + word script; + long misc[16]; + refInfo scriptData; + long initd[8], inita[2]; + bool initialized; + +private: + short lastChangerX, lastChangerY; + long prevX, prevY; + + bool canMove(); + void updateMovement(FFC* linked); + + /// Called when moving to see if the FFC has gone of the edge of the screen. + void checkScreenEdges(bool wrap); + + friend class FFCSet; +}; + +/// The set of 32 FFCs on a single screen. +class FFCSet +{ +public: + FFCSet(); + + void updateMovement(struct mapscr* tmpscr, bool holdingItem); + inline void clear() + { + for(int i=0; i<32; i++) + ffcs[i].clear(); + } + + inline FFC& operator[](int index) { return ffcs[index]; } + inline const FFC& operator[](int index) const { return ffcs[index]; } + + // For AngelScript + inline FFC* getPtr(int index) { return ffcs+index; } + +private: + FFC ffcs[32]; + + /// Called when a changer with a swap flag is triggered. + void swapData(FFC& f1, FFC& f2); +}; + + +class SparseFFCSetArray +{ +public: + enum { MAX_SCREENS = 65535 }; + + /// Gets a screen ffcset. Can be null. + FFCSet* GetFFCSet(int screenIndex) + { + //assert(screenIndex < MAX_SCREENS); + return screenFFCSets[screenIndex]; + } + + /// Gets a screen ffcset. If it does not exist a new ffcset is created. + FFCSet* GetOrCreateFFCSet(int screenIndex) + { + //assert(screenIndex < MAX_SCREENS); + if(screenFFCSets[screenIndex] == 0) + screenFFCSets[screenIndex] = new FFCSet(); + + return screenFFCSets[screenIndex]; + } + + void Clear() + { + for(int i(0); i < MAX_SCREENS; ++i) + { + if(screenFFCSets[i]) + { + delete screenFFCSets[i]; + screenFFCSets[i] = 0; + } + } + } + + FFCSet blankFFCSet; + FFCSet* screenFFCSets[MAX_SCREENS]; +}; + + +#endif diff --git a/src/ffdebug.cpp b/src/ffdebug.cpp new file mode 100644 index 0000000000..d150982bdd --- /dev/null +++ b/src/ffdebug.cpp @@ -0,0 +1,1244 @@ +#include "ffdebug.h" + +extern long sarg1; +extern long sarg2; + +namespace ffdebug +{ +char varToStringTemp[40]; +const char * const varToString(int ID) +{ + switch(ID) + { + case SP: + return "SP"; + + case DATA: + return "DATA"; + + case FFSCRIPT: + return "FFSCRIPT"; + + case FCSET: + return "CSET"; + + case DELAY: + return "DELAY"; + + case FX: + return "X"; + + case FY: + return "Y"; + + case XD: + return "XD"; + + case YD: + return "YD"; + + case XD2: + return "XD2"; + + case YD2: + return "YD2"; + + case LINKX: + return "LINKX"; + + case LINKY: + return "LINKY"; + + case LINKZ: + return "LINKZ"; + + case LINKJUMP: + return "LINKJUMP"; + + case LINKDIR: + return "LINKDIR"; + + case LINKSWORDJINX: + return "LINKSWORDJINX"; + + case LINKITEMJINX: + return "LINKITEMJINX"; + + case LINKHP: + return "LINKHP"; + + case LINKMP: + return "LINKMP"; + + case LINKMAXHP: + return "LINKMAXHP"; + + case LINKMAXMP: + return "LINKMAXMP"; + + case LINKACTION: + return "LINKACTION"; + + case LINKHELD: + return "LINKHELD"; + + case LINKINVIS: + return "LINKINVIS"; + + case LINKINVINC: + return "LINKINVINC"; + + case LINKMISCD: + return "LINKMISCD"; + + case INPUTSTART: + return "INPUTSTART"; + + case INPUTMAP: + return "INPUTMAP"; + + case INPUTUP: + return "INPUTUP"; + + case INPUTDOWN: + return "INPUTDOWN"; + + case INPUTLEFT: + return "INPUTLEFT"; + + case INPUTRIGHT: + return "INPUTRIGHT"; + + case INPUTA: + return "INPUTA"; + + case INPUTB: + return "INPUTB"; + + case INPUTL: + return "INPUTL"; + + case INPUTR: + return "INPUTR"; + + case INPUTEX1: + return "INPUTEX1"; + + case INPUTEX2: + return "INPUTEX2"; + + case INPUTEX3: + return "INPUTEX3"; + + case INPUTEX4: + return "INPUTEX4"; + + case INPUTAXISUP: + return "INPUTAXISUP"; + + case INPUTAXISDOWN: + return "INPUTAXISDOWN"; + + case INPUTAXISLEFT: + return "INPUTAXISLEFT"; + + case INPUTAXISRIGHT: + return "INPUTAXISRIGHT"; + + case INPUTPRESSSTART: + return "INPUTPRESSSTART"; + + case INPUTPRESSUP: + return "INPUTPRESSUP"; + + case INPUTPRESSDOWN: + return "INPUTPRESSDOWN"; + + case INPUTPRESSLEFT: + return "INPUTPRESSLEFT"; + + case INPUTPRESSRIGHT: + return "INPUTPRESSRIGHT"; + + case INPUTPRESSA: + return "INPUTPRESSA"; + + case INPUTPRESSB: + return "INPUTPRESSB"; + + case INPUTPRESSL: + return "INPUTPRESSL"; + + case INPUTPRESSR: + return "INPUTPRESSR"; + + case INPUTPRESSEX1: + return "INPUTPRESSEX1"; + + case INPUTPRESSEX2: + return "INPUTPRESSEX2"; + + case INPUTPRESSEX3: + return "INPUTPRESSEX3"; + + case INPUTPRESSEX4: + return "INPUTPRESSEX4"; + + case INPUTPRESSAXISUP: + return "PRESSAXISUP"; + + case INPUTPRESSAXISDOWN: + return "PRESSAXISDOWN"; + + case INPUTPRESSAXISLEFT: + return "PRESSAXISLEFT"; + + case INPUTPRESSAXISRIGHT: + return "PRESSAXISRIGHT"; + + case INPUTMOUSEX: + return "INPUTMOUSEX"; + + case INPUTMOUSEY: + return "INPUTMOUSEY"; + + case INPUTMOUSEZ: + return "INPUTMOUSEZ"; + + case INPUTMOUSEB: + return "INPUTMOUSEB"; + + case SDD: + return "SDD"; + + case SCREENFLAGSD: + return "SCREENFLAGSD"; + + case SCREENEFLAGSD: + return "SCREENEFLAGSD"; + + case COMBODD: + return "COMBODD"; + + case COMBOCD: + return "COMBOCD"; + + case COMBOFD: + return "COMBOFD"; + + case COMBODDM: + return "COMBODDM"; + + case COMBOCDM: + return "COMBOCDM"; + + case COMBOFDM: + return "COMBOFDM"; + + case REFFFC: + return "REFFFC"; + + case REFITEM: + return "REFITEM"; + + case ITEMCOUNT: + return "ITEMCOUNT"; + + case ITEMX: + return "ITEMX"; + + case ITEMY: + return "ITEMY"; + + case ITEMZ: + return "ITEMZ"; + + case ITEMJUMP: + return "ITEMJUMP"; + + case ITEMDRAWTYPE: + return "ITEMDRAWTYPE"; + + case ITEMID: + return "ITEMID"; + + case ITEMTILE: + return "ITEMTILE"; + + case ITEMCSET: + return "ITEMCSET"; + + case ITEMFLASHCSET: + return "ITEMFLASHCSET"; + + case ITEMFRAMES: + return "ITEMFRAMES"; + + case ITEMFRAME: + return "ITEMFRAME"; + + case ITEMASPEED: + return "ITEMASPEED"; + + case ITEMDELAY: + return "ITEMDELAY"; + + case ITEMFLASH: + return "ITEMFLASH"; + + case ITEMFLIP: + return "ITEMFLIP"; + + case ITEMEXTEND: + return "ITEMEXTEND"; + + case ITEMPICKUP: + return "ITEMPICKUP"; + + case ITEMMISCD: + return "ITEMMISCD"; + + case IDATAFAMILY: + return "IDATAFAMILY"; + + case IDATALEVEL: + return "IDATALEVEL"; + + case IDATAAMOUNT: + return "IDATAAMOUNT"; + + case IDATAMAX: + return "IDATAMAX"; + + case IDATASETMAX: + return "IDATAKEEP"; + + case IDATACOUNTER: + return "IDATACOUNTER"; + + case IDATAUSESOUND: + return "IDATAUSESOUND"; + + case IDATAPOWER: + return "IDATAPOWER"; + + case IDATAINITDD: + return "IDATAINITDD"; + + case REFITEMCLASS: + return "REFITEMCLASS"; + + case COMBOID: + return "COMBOID"; + + case COMBOTD: + return "COMBOTD"; + + case COMBOSD: + return "COMBOSD"; + + case COMBOIDM: + return "COMBOIDM"; + + case COMBOTDM: + return "COMBOTDM"; + + case COMBOSDM: + return "COMBOSDM"; + + case GETMIDI: + return "GETMIDI"; + + case CURSCR: + return "CURSCR"; + + case CURDSCR: + return "CURDSCR"; + + case CURMAP: + return "CURMAP"; + + case CURDMAP: + return "CURDMAP"; + + case CURLEVEL: + return "CURLEVEL"; + + case GAMEDEATHS: + return "GAMEDEATHS"; + + case GAMECHEAT: + return "GAMECHEAT"; + + case GAMETIME: + return "GAMETIME"; + + case GAMEHASPLAYED: + return "GAMEHASPLAYED"; + + case GAMETIMEVALID: + return "GAMETIMEVALID"; + + case GAMEGUYCOUNT: + return "GAMEGUYCOUNT"; + + case GAMECONTSCR: + return "GAMECONTSCR"; + + case GAMECONTDMAP: + return "GAMECONTDMAP"; + + case GAMECOUNTERD: + return "GAMECOUNTERD"; + + case GAMEMCOUNTERD: + return "GAMEMCOUNTERD"; + + case GAMEDCOUNTERD: + return "GAMEDCOUNTERD"; + + case GAMEGENERICD: + return "GAMEGENERICD"; + + case GAMEITEMSD: + return "GAMEITEMSD"; + + case GAMELITEMSD: + return "GAMELITEMSD"; + + case GAMELKEYSD: + return "GAMELKEYSD"; + + case SCREENSTATED: + return "SCREENSTATED"; + + case SCREENSTATEDD: + return "SCREENSTATEDD"; + + case DMAPFLAGSD: + return "DMAPFLAGSD"; + + case DMAPLEVELD: + return "DMAPLEVELD"; + + case DMAPCOMPASSD: + return "DMAPCOMPASSD"; + + case DMAPCONTINUED: + return "DMAPCONTINUED"; + + case DMAPMIDID: + return "DMAPMIDID"; + + case DMAPOFFSET: + return "DMAPOFFSET"; + + case DMAPMAP: + return "DMAPMAP"; + + case SDDD: + return "SDDD"; + + case SDDDD: + return "SDDDD"; + + case FFFLAGSD: + return "FFFLAGSD"; + + case FFTWIDTH: + return "FFTWIDTH"; + + case FFTHEIGHT: + return "FFTHEIGHT"; + + case FFCWIDTH: + return "FFCWIDTH"; + + case FFCHEIGHT: + return "FFCHEIGHT"; + + case FFLINK: + return "FFLINK"; + + case FFMISCD: + return "FFMISCD"; + + case FFINITDD: + return "FFINITDD"; + + /*case FFDD: + return "FFDD";*/ + case LINKITEMD: + return "LINKITEMD"; + + case REFNPC: + return "REFNPC"; + + case NPCCOUNT: + return "NPCCOUNT"; + + case NPCX: + return "NPCX"; + + case NPCY: + return "NPCY"; + + case NPCZ: + return "NPCZ"; + + case NPCJUMP: + return "NPCJUMP"; + + case NPCDIR: + return "NPCDIR"; + + case NPCRATE: + return "NPCRATE"; + + case NPCHOMING: + return "NPCHOMING"; + + case NPCFRAMERATE: + return "NPCFRAMERATE"; + + case NPCHALTRATE: + return "NPCHALTRATE"; + + case NPCDRAWTYPE: + return "NPCDRAWTYPE"; + + case NPCHP: + return "NPCHP"; + + case NPCID: + return "NPCID"; + + case NPCTYPE: + return "NPCTYPE"; + + case NPCDP: + return "NPCDP"; + + case NPCWDP: + return "NPCWDP"; + + case NPCTILE: + return "NPCTILE"; + + case NPCOTILE: + return "NPCOTILE"; + + case NPCWEAPON: + return "NPCWEAPON"; + + case NPCITEMSET: + return "NPCITEMSET"; + + case NPCCSET: + return "NPCCSET"; + + case NPCBOSSPAL: + return "NPCBOSSPAL"; + + case NPCBGSFX: + return "NPCBGSFX"; + + case NPCEXTEND: + return "NPCEXTEND"; + + case NPCSTEP: + return "NPCSTEP"; + + case NPCDEFENSED: + return "NPCDEFENSED"; + + case NPCMISCD: + return "NPCMISCD"; + + case NPCDD: + return "NPCDD"; + + case NPCMFLAGS: + return "NPCMFLAGS"; + + case NPCCOLLDET: + return "NPCCOLLDET"; + + case NPCSTUN: + return "NPCSTUN"; + + case NPCHUNGER: + return "NPCHUNGER"; + + case SCRDOORD: + return "SCRDOORD"; + + case LIT: + return "LIT"; + + case WAVY: + return "WAVY"; + + case QUAKE: + return "QUAKE"; + + case ITEMOTILE: + return "ITEMOTILE"; + + case REFLWPN: + return "REFLWPN"; + + case LWPNCOUNT: + return "LWPNCOUNT"; + + case LWPNX: + return "LWPNX"; + + case LWPNY: + return "LWPNY"; + + case LWPNZ: + return "LWPNZ"; + + case LWPNJUMP: + return "LWPNJUMP"; + + case LWPNDIR: + return "LWPNDIR"; + + case LWPNANGLE: + return "LWPNANGLE"; + + case LWPNSTEP: + return "LWPNSTEP"; + + case LWPNFRAMES: + return "LWPNFRAMES"; + + case LWPNFRAME: + return "LWPNFRAME"; + + case LWPNDRAWTYPE: + return "LWPNDRAWTYPE"; + + case LWPNPOWER: + return "LWPNPOWER"; + + case LWPNID: + return "LWPNID"; + + case LWPNANGULAR: + return "LWPNANGULAR"; + + case LWPNBEHIND: + return "LWPNBEHIND"; + + case LWPNASPEED: + return "LWPNASPEED"; + + case LWPNTILE: + return "LWPNTILE"; + + case LWPNFLASHCSET: + return "LWPNFLASHCSET"; + + case LWPNDEAD: + return "LWPNDEAD"; + + case LWPNCSET: + return "LWPNCSET"; + + case LWPNFLASH: + return "LWPNFLASH"; + + case LWPNFLIP: + return "LWPNFLIP"; + + case LWPNOTILE: + return "LWPNOTILE"; + + case LWPNOCSET: + return "LWPNOCSET"; + + case LWPNEXTEND: + return "LWPNEXTEND"; + + case LWPNCOLLDET: + return "LWPNCOLLDET"; + + case REFEWPN: + return "REFEWPN"; + + case EWPNCOUNT: + return "EWPNCOUNT"; + + case EWPNX: + return "EWPNX"; + + case EWPNY: + return "EWPNY"; + + case EWPNZ: + return "EWPNZ"; + + case EWPNJUMP: + return "EWPNJUMP"; + + case EWPNDIR: + return "EWPNDIR"; + + case EWPNANGLE: + return "EWPNANGLE"; + + case EWPNSTEP: + return "EWPNSTEP"; + + case EWPNFRAMES: + return "EWPNFRAMES"; + + case EWPNFRAME: + return "EWPNFRAME"; + + case EWPNDRAWTYPE: + return "EWPNDRAWTYPE"; + + case EWPNPOWER: + return "EWPNPOWER"; + + case EWPNID: + return "EWPNID"; + + case EWPNANGULAR: + return "EWPNANGULAR"; + + case EWPNBEHIND: + return "EWPNBEHIND"; + + case EWPNASPEED: + return "EWPNASPEED"; + + case EWPNTILE: + return "EWPNTILE"; + + case EWPNFLASHCSET: + return "EWPNFLASHCSET"; + + case EWPNDEAD: + return "EWPNDEAD"; + + case EWPNCSET: + return "EWPNCSET"; + + case EWPNFLASH: + return "EWPNFLASH"; + + case EWPNFLIP: + return "EWPNFLIP"; + + case EWPNOTILE: + return "EWPNOTILE"; + + case EWPNOCSET: + return "EWPNOCSET"; + + case EWPNEXTEND: + return "EWPNEXTEND"; + + case EWPNCOLLDET: + return "EWPNCOLLDET"; + + case SCRIPTRAM: + return "SCRIPTRAM"; + + case GLOBALRAM: + return "GLOBALRAM"; + + case SCRIPTRAMD: + return "SCRIPTRAMD"; + + case GLOBALRAMD: + return "GLOBALRAMD"; + + case LWPNHXOFS: + return "LWPNHXOFS"; + + case LWPNHYOFS: + return "LWPNHYOFS"; + + case LWPNXOFS: + return "LWPNXOFS"; + + case LWPNYOFS: + return "LWPNYOFS"; + + case LWPNZOFS: + return "LWPNZOFS"; + + case LWPNHXSZ: + return "LWPNHXSZ"; + + case LWPNHYSZ: + return "LWPNHYSZ"; + + case LWPNHZSZ: + return "LWPNHZSZ"; + + case LWPNTXSZ: + return "LWPNTXSZ"; + + case LWPNTYSZ: + return "LWPNTYSZ"; + + case LWPNMISCD: + return "LWPNMISCD"; + + case EWPNHXOFS: + return "EWPNHXOFS"; + + case EWPNHYOFS: + return "EWPNHYOFS"; + + case EWPNXOFS: + return "EWPNXOFS"; + + case EWPNYOFS: + return "EWPNYOFS"; + + case EWPNZOFS: + return "EWPNZOFS"; + + case EWPNHXSZ: + return "EWPNHXSZ"; + + case EWPNHYSZ: + return "EWPNHYSZ"; + + case EWPNHZSZ: + return "EWPNHZSZ"; + + case EWPNTXSZ: + return "EWPNTXSZ"; + + case EWPNTYSZ: + return "EWPNTYSZ"; + + case EWPNMISCD: + return "EWPNMISCD"; + + case NPCHXOFS: + return "NPCHXOFS"; + + case NPCHYOFS: + return "NPCHYOFS"; + + case NPCXOFS: + return "NPCXOFS"; + + case NPCYOFS: + return "NPCYOFS"; + + case NPCZOFS: + return "NPCZOFS"; + + case NPCHXSZ: + return "NPCHXSZ"; + + case NPCHYSZ: + return "NPCHYSZ"; + + case NPCHZSZ: + return "NPCHZSZ"; + + case NPCTXSZ: + return "NPCTXSZ"; + + case NPCTYSZ: + return "NPCTYSZ"; + + case ITEMHXOFS: + return "ITEMHXOFS"; + + case ITEMHYOFS: + return "ITEMHYOFS"; + + case ITEMXOFS: + return "ITEMXOFS"; + + case ITEMYOFS: + return "ITEMYOFS"; + + case ITEMZOFS: + return "ITEMZOFS"; + + case ITEMHXSZ: + return "ITEMHXSZ"; + + case ITEMHYSZ: + return "ITEMHYSZ"; + + case ITEMHZSZ: + return "ITEMHZSZ"; + + case ITEMTXSZ: + return "ITEMTXSZ"; + + case ITEMTYSZ: + return "ITEMTYSZ"; + + case LINKHXOFS: + return "LINKHXOFS"; + + case LINKHYOFS: + return "LINKHYOFS"; + + case LINKXOFS: + return "LINKXOFS"; + + case LINKYOFS: + return "LINKYOFS"; + + case LINKZOFS: + return "LINKZOFS"; + + case LINKHXSZ: + return "LINKHXSZ"; + + case LINKHYSZ: + return "LINKHYSZ"; + + case LINKHZSZ: + return "LINKHZSZ"; + + case LINKTXSZ: + return "LINKTXSZ"; + + case LINKTYSZ: + return "LINKTYSZ"; + + case LINKDRUNK: + return "LINKDRUNK"; + + case LINKEQUIP: + return "LINKEQUIP"; + + case LINKLADDERX: + return "LINKLADDERX"; + + case LINKLADDERY: + return "LINKLADDERY"; + + case ROOMTYPE: + return "ROOMTYPE"; + + case ROOMDATA: + return "ROOMDATA"; + + case LINKTILE: + return "LINKTILE"; + + case LINKFLIP: + return "LINKFLIP"; + + case INPUTPRESSMAP: + return "INPUTPRESSMAP"; + + case GAMESTANDALONE: + return "GAMESTANDALONE"; + + case GAMEENTRSCR: + return "GAMEENTRSCREEN"; + + case GAMEENTRDMAP: + return "GAMEENTRDMAP"; + + case GAMECLICKFREEZE: + return "GAMECLICKFREEZE"; + + case PUSHBLOCKX: + return "PUSHBLOCKX"; + + case PUSHBLOCKY: + return "PUSHBLOCKY"; + + case PUSHBLOCKCOMBO: + return "PUSHBLOCKCOMBO"; + + case PUSHBLOCKCSET: + return "PUSHBLOCKCSET"; + + case UNDERCOMBO: + return "UNDERCOMBO"; + + case UNDERCSET: + return "UNDERCSET"; + + default: + { + sprintf(varToStringTemp, "d%d", ID); + return varToStringTemp; + } + } +} + +script_command command_list[NUMCOMMANDS+1]= +{ + //name args arg1 arg2 more + { "SETV", 2, 0, 1, 0}, + { "SETR", 2, 0, 0, 0}, + { "ADDR", 2, 0, 0, 0}, + { "ADDV", 2, 0, 1, 0}, + { "SUBR", 2, 0, 0, 0}, + { "SUBV", 2, 0, 1, 0}, + { "MULTR", 2, 0, 0, 0}, + { "MULTV", 2, 0, 1, 0}, + { "DIVR", 2, 0, 0, 0}, + { "DIVV", 2, 0, 1, 0}, + { "WAITFRAME", 0, 0, 0, 0}, + { "GOTO", 1, 1, 0, 0}, + { "CHECKTRIG", 0, 0, 0, 0}, + { "WARP", 2, 1, 1, 0}, + { "COMPARER", 2, 0, 0, 0}, + { "COMPAREV", 2, 0, 1, 0}, + { "GOTOTRUE", 2, 0, 0, 0}, + { "GOTOFALSE", 2, 0, 0, 0}, + { "GOTOLESS", 2, 0, 0, 0}, + { "GOTOMORE", 2, 0, 0, 0}, + { "LOAD1", 2, 0, 0, 0}, + { "LOAD2", 2, 0, 0, 0}, + { "SETA1", 2, 0, 0, 0}, + { "SETA2", 2, 0, 0, 0}, + { "QUIT", 0, 0, 0, 0}, + { "SINR", 2, 0, 0, 0}, + { "SINV", 2, 0, 1, 0}, + { "COSR", 2, 0, 0, 0}, + { "COSV", 2, 0, 1, 0}, + { "TANR", 2, 0, 0, 0}, + { "TANV", 2, 0, 1, 0}, + { "MODR", 2, 0, 0, 0}, + { "MODV", 2, 0, 1, 0}, + { "ABS", 1, 0, 0, 0}, + { "MINR", 2, 0, 0, 0}, + { "MINV", 2, 0, 1, 0}, + { "MAXR", 2, 0, 0, 0}, + { "MAXV", 2, 0, 1, 0}, + { "RNDR", 2, 0, 0, 0}, + { "RNDV", 2, 0, 1, 0}, + { "FACTORIAL", 1, 0, 0, 0}, + { "POWERR", 2, 0, 0, 0}, + { "POWERV", 2, 0, 1, 0}, + { "IPOWERR", 2, 0, 0, 0}, + { "IPOWERV", 2, 0, 1, 0}, + { "ANDR", 2, 0, 0, 0}, + { "ANDV", 2, 0, 1, 0}, + { "ORR", 2, 0, 0, 0}, + { "ORV", 2, 0, 1, 0}, + { "XORR", 2, 0, 0, 0}, + { "XORV", 2, 0, 1, 0}, + { "NANDR", 2, 0, 0, 0}, + { "NANDV", 2, 0, 1, 0}, + { "NORR", 2, 0, 0, 0}, + { "NORV", 2, 0, 1, 0}, + { "XNORR", 2, 0, 0, 0}, + { "XNORV", 2, 0, 1, 0}, + { "NOT", 1, 0, 0, 0}, + { "LSHIFTR", 2, 0, 0, 0}, + { "LSHIFTV", 2, 0, 1, 0}, + { "RSHIFTR", 2, 0, 0, 0}, + { "RSHIFTV", 2, 0, 1, 0}, + { "TRACER", 1, 0, 0, 0}, + { "TRACEV", 1, 1, 0, 0}, + { "TRACE3", 0, 0, 0, 0}, + { "LOOP", 2, 1, 0, 0}, + { "PUSHR", 1, 0, 0, 0}, + { "PUSHV", 1, 1, 0, 0}, + { "POP", 1, 0, 0, 0}, + { "ENQUEUER", 2, 0, 0, 0}, + { "ENQUEUEV", 2, 0, 1, 0}, + { "DEQUEUE", 1, 0, 0, 0}, + { "PLAYSOUNDR", 1, 0, 0, 0}, + { "PLAYSOUNDV", 1, 1, 0, 0}, + { "LOADLWEAPONR", 1, 0, 0, 0}, + { "LOADLWEAPONV", 1, 1, 0, 0}, + { "LOADITEMR", 1, 0, 0, 0}, + { "LOADITEMV", 1, 1, 0, 0}, + { "LOADNPCR", 1, 0, 0, 0}, + { "LOADNPCV", 1, 1, 0, 0}, + { "CREATELWEAPONR", 1, 0, 0, 0}, + { "CREATELWEAPONV", 1, 1, 0, 0}, + { "CREATEITEMR", 1, 0, 0, 0}, + { "CREATEITEMV", 1, 1, 0, 0}, + { "CREATENPCR", 1, 0, 0, 0}, + { "CREATENPCV", 1, 1, 0, 0}, + { "LOADI", 2, 0, 0, 0}, + { "STOREI", 2, 0, 0, 0}, + { "GOTOR", 1, 0, 0, 0}, + { "SQROOTV", 2, 0, 1, 0}, + { "SQROOTR", 2, 0, 0, 0}, + { "CREATEEWEAPONR", 1, 0, 0, 0}, + { "CREATEEWEAPONV", 1, 1, 0, 0}, + { "PITWARP", 2, 1, 1, 0}, + { "WARPR", 2, 0, 0, 0}, + { "PITWARPR", 2, 0, 0, 0}, + { "CLEARSPRITESR", 1, 0, 0, 0}, + { "CLEARSPRITESV", 1, 1, 0, 0}, + { "RECT", 0, 0, 0, 0}, + { "CIRCLE", 0, 0, 0, 0}, + { "ARC", 0, 0, 0, 0}, + { "ELLIPSE", 0, 0, 0, 0}, + { "LINE", 0, 0, 0, 0}, + { "PUTPIXEL", 0, 0, 0, 0}, + { "DRAWTILE", 0, 0, 0, 0}, + { "DRAWCOMBO", 0, 0, 0, 0}, + { "ELLIPSE2", 0, 0, 0, 0}, + { "SPLINE", 0, 0, 0, 0}, + { "FLOODFILL", 0, 0, 0, 0}, + { "COMPOUNDR", 1, 0, 0, 0}, + { "COMPOUNDV", 1, 1, 0, 0}, + { "MSGSTRR", 1, 0, 0, 0}, + { "MSGSTRV", 1, 1, 0, 0}, + { "ISVALIDITEM", 1, 0, 0, 0}, + { "ISVALIDNPC", 1, 0, 0, 0}, + { "PLAYMIDIR", 1, 0, 0, 0}, + { "PLAYMIDIV", 1, 1, 0, 0}, + { "COPYTILEVV", 2, 1, 1, 0}, + { "COPYTILEVR", 2, 1, 0, 0}, + { "COPYTILERV", 2, 0, 1, 0}, + { "COPYTILERR", 2, 0, 0, 0}, + { "SWAPTILEVV", 2, 1, 1, 0}, + { "SWAPTILEVR", 2, 1, 0, 0}, + { "SWAPTILERV", 2, 0, 1, 0}, + { "SWAPTILERR", 2, 0, 0, 0}, + { "CLEARTILEV", 1, 1, 0, 0}, + { "CLEARTILER", 1, 0, 0, 0}, + { "OVERLAYTILEVV", 2, 1, 1, 0}, + { "OVERLAYTILEVR", 2, 1, 0, 0}, + { "OVERLAYTILERV", 2, 0, 1, 0}, + { "OVERLAYTILERR", 2, 0, 0, 0}, + { "FLIPROTTILEVV", 2, 1, 1, 0}, + { "FLIPROTTILEVR", 2, 1, 0, 0}, + { "FLIPROTTILERV", 2, 0, 1, 0}, + { "FLIPROTTILERR", 2, 0, 0, 0}, + { "GETTILEPIXELV", 1, 1, 0, 0}, + { "GETTILEPIXELR", 1, 0, 0, 0}, + { "SETTILEPIXELV", 1, 1, 0, 0}, + { "SETTILEPIXELR", 1, 0, 0, 0}, + { "SHIFTTILEVV", 2, 1, 1, 0}, + { "SHIFTTILEVR", 2, 1, 0, 0}, + { "SHIFTTILERV", 2, 0, 1, 0}, + { "SHIFTTILERR", 2, 0, 0, 0}, + { "ISVALIDLWPN", 1, 0, 0, 0}, + { "ISVALIDEWPN", 1, 0, 0, 0}, + { "LOADEWEAPONR", 1, 0, 0, 0}, + { "LOADEWEAPONV", 1, 1, 0, 0}, + { "ALLOCATEMEMR", 2, 0, 0, 0}, + { "ALLOCATEMEMV", 2, 0, 1, 0}, + { "ALLOCATEGMEM", 2, 0, 1, 0}, + { "DEALLOCATEMEMR", 1, 0, 0, 0}, + { "DEALLOCATEMEMV", 1, 1, 0, 0}, + { "WAITDRAW", 0, 0, 0, 0}, + { "ARCTANR", 1, 0, 0, 0}, + { "LWPNUSESPRITER", 1, 0, 0, 0}, + { "LWPNUSESPRITEV", 1, 1, 0, 0}, + { "EWPNUSESPRITER", 1, 0, 0, 0}, + { "EWPNUSESPRITEV", 1, 1, 0, 0}, + { "LOADITEMDATAR", 1, 0, 0, 0}, + { "LOADITEMDATAV", 1, 1, 0, 0}, + { "BITNOT", 1, 0, 0, 0}, + { "LOG10", 1, 0, 0, 0}, + { "LOGE", 1, 0, 0, 0}, + { "ISSOLID", 1, 0, 0, 0}, + { "LAYERSCREEN", 2, 0, 0, 0}, + { "LAYERMAP", 2, 0, 0, 0}, + { "TRACE2R", 1, 0, 0, 0}, + { "TRACE2V", 1, 1, 0, 0}, + { "TRACE4", 0, 0, 0, 0}, + { "TRACE5", 0, 0, 0, 0}, + { "SECRETS", 0, 0, 0, 0}, + { "DRAWCHAR", 0, 0, 0, 0}, + { "GETSCREENFLAGS", 1, 0, 0, 0}, + { "QUAD", 0, 0, 0, 0}, + { "TRIANGLE", 0, 0, 0, 0}, + { "ARCSINR", 2, 0, 0, 0}, + { "ARCSINV", 2, 1, 0, 0}, + { "ARCCOSR", 2, 0, 0, 0}, + { "ARCCOSV", 2, 1, 0, 0}, + { "GAMEEND", 0, 0, 0, 0}, + { "DRAWINT", 0, 0, 0, 0}, + { "SETTRUE", 1, 0, 0, 0}, + { "SETFALSE", 1, 0, 0, 0}, + { "SETMORE", 1, 0, 0, 0}, + { "SETLESS", 1, 0, 0, 0}, + { "FASTTILE", 0, 0, 0, 0}, + { "FASTCOMBO", 0, 0, 0, 0}, + { "DRAWSTRING", 0, 0, 0, 0}, + { "SETSIDEWARP", 0, 0, 0, 0}, + { "SAVE", 0, 0, 0, 0}, + { "TRACE6", 0, 0, 0, 0}, + { "DEPRECATED", 1, 0, 0, 0}, + { "QUAD3D", 0, 0, 0, 0}, + { "TRIANGLE3D", 0, 0, 0, 0}, + { "SETCOLORB", 0, 0, 0, 0}, + { "SETDEPTHB", 0, 0, 0, 0}, + { "GETCOLORB", 0, 0, 0, 0}, + { "GETDEPTHB", 0, 0, 0, 0}, + { "COMBOTILE", 2, 0, 0, 0}, + { "SETTILEWARP", 0, 0, 0, 0}, + { "GETSCREENEFLAGS", 1, 0, 0, 0}, + { "GETSAVENAMER", 1, 0, 0, 0}, + { "ARRAYSIZE", 1, 0, 0, 0}, + { "ITEMNAMER", 1, 0, 0, 0}, + { "SETSAVENAMER", 1, 0, 0, 0}, + { "PLAYENHMUSIC", 2, 0, 0, 0}, + { "GETMUSICFILE", 2, 0, 0, 0}, + { "GETMUSICTRACK", 1, 0, 0, 0}, + { "SETDMAPENHMUSIC", 0, 0, 0, 0}, + { "BREAKSHIELD", 1, 0, 0, 0}, + { "SAVESCREEN", 1, 0, 0, 0}, + { "SAVEQUITSCREEN", 0, 0, 0, 0}, + { "SELECTAWPNR", 1, 0, 0, 0}, + { "SELECTAWPNV", 1, 1, 0, 0}, + { "SELECTBWPNR", 1, 0, 0, 0}, + { "SELECTBWPNV", 1, 1, 0, 0}, + { "GETSIDEWARPDMAP", 1, 0, 0, 0}, + { "GETSIDEWARPSCR", 1, 0, 0, 0}, + { "GETSIDEWARPTYPE", 1, 0, 0, 0}, + { "GETTILEWARPDMAP", 1, 0, 0, 0}, + { "GETTILEWARPSCR", 1, 0, 0, 0}, + { "GETTILEWARPTYPE", 1, 0, 0, 0}, + { "", 0, 0, 0, 0} +}; + + +void print_disassembly(const word scommand) +{ + script_command s_c = command_list[scommand]; + + if(s_c.args == 2) + { + al_trace("%14s: ", s_c.name); + + if(s_c.arg1_type == 0) + al_trace("%10s (val = %9d), ", varToString(sarg1), get_register(sarg1)); + else + al_trace("%10s (val = %9d), ", "immediate", sarg1); + + if(s_c.arg2_type == 0) + al_trace("%10s (val = %9d)\n", varToString(sarg2), get_register(sarg2)); + else + al_trace("%10s (val = %9d)\n", "immediate", sarg2); + } + else if(s_c.args == 1) + { + al_trace("%14s: ", s_c.name); + + if(s_c.arg1_type == 0) + al_trace("%10s (val = %9d)\n", varToString(sarg1), get_register(sarg1)); + else + al_trace("%10s (val = %9d)\n", "immediate", sarg1); + } + else + al_trace("%14s\n", s_c.name); + +} + +} diff --git a/src/ffdebug.h b/src/ffdebug.h new file mode 100644 index 0000000000..34bc9035e8 --- /dev/null +++ b/src/ffdebug.h @@ -0,0 +1,16 @@ +//With _DEBUGPRINTSCOMMAND from zdefs.h enabled, ffdebug.h will print out each ASM command +//processed with the value stored in each register supplied to it before the command acts on those registers +//~Joe123 + +#include "ffscript.h" +#include "zdefs.h" + +#ifndef _FFDEBUG_H +#define _FFDEBUG_H + +namespace ffdebug +{ +void print_disassembly(const word scommand); +} + +#endif diff --git a/src/ffscript.cpp b/src/ffscript.cpp new file mode 100644 index 0000000000..deb3378262 --- /dev/null +++ b/src/ffscript.cpp @@ -0,0 +1,7557 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +//#include +#include +#include +#include +#include + +#include "zc_math.h" +#include "zc_array.h" +#include "ffscript.h" +#include "zelda.h" +#include "zc_sys.h" +#include "link.h" +#include "guys.h" +#include "gamedata.h" +#include "zc_init.h" +#include "zsys.h" +#include "title.h" +#include "mem_debug.h" +#include "zscriptversion.h" +#include "rendertarget.h" +#include "linkZScriptInterface.h" +#include "messageManager.h" +#include "sfxManager.h" +#include "sound.h" + +#ifdef _FFDEBUG +#include "ffdebug.h" +#endif + +#include "debug.h" + +#define zc_max(a,b) ((a)>(b)?(a):(b)) +/*template +T zc_max(T a, T b) +{ + return (a > b) ? a : b; +}*/ + +#define zc_min(a,b) ((a)<(b)?(a):(b)) + +#ifdef _MSC_VER +#pragma warning ( disable : 4800 ) //int to bool town. population: lots. +#endif + + +using std::string; + +extern MessageManager messageMgr; +extern SFXManager sfxMgr; + +extern sprite_list particles; +extern LinkClass Link; +extern char *guy_string[]; +extern int skipcont; +extern std::map > ffcmap; + +//We gain some speed by not passing as arguments +long sarg1 = 0; +long sarg2 = 0; +refInfo *ri = NULL; +ffscript *curscript = NULL; + +static bool scriptCanSave = true; +byte curScriptType; +word curScriptNum; + +//Global script data +refInfo globalScriptData; +word g_doscript = 1; +bool global_wait = false; + +//Item script data +refInfo itemScriptData; + +LinkZScriptInterface linkIF; + +//The stacks +long(*stack)[256] = NULL; +long ffc_stack[32][256]; +long global_stack[256]; +long item_stack[256]; + +void clear_ffc_stack(const byte i) +{ + memset(ffc_stack[i], 0, 256 * sizeof(long)); +} + +void clear_global_stack() +{ + memset(global_stack, 0, 256 * sizeof(long)); +} + +//ScriptHelper +class SH +{ + +///-----------------------------// +// Errors // +///-----------------------------// + +public: + + enum __Error + { + _NoError, //OK! + _Overflow, //script array too small + _InvalidPointer, //passed NULL pointer or similar + _OutOfBounds, //library array out of bounds + _InvalidSpriteUID //bad npc, ffc, etc. + }; + +#define INVALIDARRAY localRAM[0] //localRAM[0] is never used + + //only if the player is messing with their pointers... + static ZScriptArray& InvalidError(const long ptr) + { + Z_scripterrlog("Invalid pointer (%i) passed to array (don't change the values of your array pointers)\n", ptr); + return INVALIDARRAY; + } + + static void write_stack(const int stackoffset, const long value) + { + if(stackoffset == 0) + { + Z_scripterrlog("Stack over or underflow, stack pointer = %ld\n", stackoffset); + return; + } + + (*stack)[stackoffset] = value; + } + + static long read_stack(const int stackoffset) + { + if(stackoffset == 0) + { + Z_scripterrlog("Stack over or underflow, stack pointer = %ld\n", stackoffset); + return -10000; + } + + return (*stack)[stackoffset]; + } + + static INLINE long get_arg(long arg, bool v) + { + return v ? arg : get_register(arg); + } +}; + +///----------------------------// +// Misc. // +///----------------------------// + +//Miscellaneous Helper +class MiscH : public SH +{ + +public: + +}; + +byte flagpos; +int ornextflag(bool flag) +{ + int f = (flag?1:0)<flags6&1) | ornextflag(m->flags6&2) | ornextflag(m->flags7&8); + break; + + case 1: // View + f = ornextflag(m->flags3&8) | ornextflag(m->flags7&16) | ornextflag(m->flags3&16) + | ornextflag(m->flags3&64) | ornextflag(m->flags7&2) | ornextflag(m->flags7&1) + | ornextflag(m->flags&4); + break; + + case 2: // Secrets + f = ornextflag(m->flags&1) | ornextflag(m->flags5&16) | ornextflag(m->flags6&4) + | ornextflag(m->flags6&32); + break; + + case 3: // Warp + f = ornextflag(m->flags5&4) | ornextflag(m->flags5&8) | ornextflag(m->flags&64) + | ornextflag(m->flags8&64) | ornextflag(m->flags3&32); + break; + + case 4: // Item + f = ornextflag(m->flags3&1) | ornextflag(m->flags7&4); + break; + + case 5: // Combo + f = ornextflag((m->flags2>>4)&2)| ornextflag(m->flags3&2)| ornextflag(m->flags5&2) + | ornextflag(m->flags6&64); + break; + + case 6: // Save + f = ornextflag(m->flags4&64) | ornextflag(m->flags4&128) | ornextflag(m->flags6&8) + | ornextflag(m->flags6&16); + break; + + case 7: // FFC + f = ornextflag(m->flags6&128)| ornextflag(m->flags5&128); + break; + + case 8: // Whistle + f = ornextflag(m->flags&16) | ornextflag(m->flags7&64) | ornextflag(m->flags7&128); + break; + + case 9: // Misc + f = ornextflag(m->flags&32) | ornextflag(m->flags5&64) | m->flags8<<2; + break; + } + + return f*10000; +} + +long get_screeneflags(mapscr *m, int flagset) +{ + int f=0; + flagpos = 0; + + switch(flagset) + { + case 0: + f = m->enemyflags&0x1F; + break; + + case 1: + f = ornextflag(m->enemyflags&32) | ornextflag(m->enemyflags&64) | ornextflag(m->flags3&4) + | ornextflag(m->enemyflags&128)| ornextflag((m->flags2>>4)&4); + break; + + case 2: + f = ornextflag(m->flags3&128) | ornextflag(m->flags&2) | ornextflag((m->flags2>>4)&8) + | ornextflag(m->flags4&16); + break; + } + + return f*10000; +} + + +///------------------------------------------------// +// Bounds Checking Functions // +///------------------------------------------------// + +//Bounds Checker +class BC : public SH +{ +public: + + static INLINE int checkMapID(const long ID, const char * const str) + { + //return checkBounds(ID, 0, map_count-1, str); + if(ID < 0 || ID > map_count-1) + { + Z_scripterrlog("Invalid value (%i) passed to '%s'\n", ID+1, str); + return _OutOfBounds; + } + + return _NoError; + } + + static INLINE int checkDMapID(const long ID, const char * const str) + { + return checkBounds(ID, 0, MAXDMAPS-1, str); + } + + static INLINE int checkComboPos(const long pos, const char * const str) + { + return checkBounds(pos, 0, 175, str); + } + + static INLINE int checkTile(const long pos, const char * const str) + { + return checkBounds(pos, 0, NEWMAXTILES-1, str); + } + + static INLINE int checkCombo(const long pos, const char * const str) + { + return checkBounds(pos, 0, MAXCOMBOS-1, str); + } + + static INLINE int checkMisc(const long a, const char * const str) + { + return checkBounds(a, 0, 15, str); + } + + static INLINE int checkMessage(const long ID, const char * const str) + { + return checkBounds(ID, 0, msg_strings_size-1, str); + } + + static INLINE int checkLayer(const long layer, const char * const str) + { + return checkBounds(layer, 0, 6, str); + } + + static INLINE int checkFFC(const long ffc, const char * const str) + { + return checkBounds(ffc, 0, MAXFFCS-1, str); + } + + static INLINE int checkGuyIndex(const long index, const char * const str) + { + return checkBounds(index, 0, guys.Count()-1, str); + } + + static INLINE int checkItemIndex(const long index, const char * const str) + { + return checkBounds(index, 0, items.Count()-1, str); + } + + static INLINE int checkEWeaponIndex(const long index, const char * const str) + { + return checkBounds(index, 0, Ewpns.Count()-1, str); + } + + static INLINE int checkLWeaponIndex(const long index, const char * const str) + { + return checkBounds(index, 0, Lwpns.Count()-1, str); + } + + static INLINE int checkGuyID(const long ID, const char * const str) + { + return checkBounds(ID, 0, MAXGUYS-1, str); + } + + static INLINE int checkItemID(const long ID, const char * const str) + { + return checkBounds(ID, 0, ITEMCNT-1, str); + } + + static INLINE int checkWeaponID(const long ID, const char * const str) + { + return checkBounds(ID, 0, WPNCNT-1, str); + } + + static INLINE int checkWeaponMiscSprite(const long ID, const char * const str) + { + return checkBounds(ID, 0, MAXWPNS-1, str); + } + + static INLINE int checkSFXID(const long ID, const char * const str) + { + return checkBounds(ID, 0, WAV_COUNT-1, str); + } + + static INLINE int checkBounds(const long n, const long boundlow, const long boundup, const char * const funcvar) + { + if(n < boundlow || n > boundup) + { + Z_scripterrlog("Invalid value (%i) passed to '%s'\n", n, funcvar); + return _OutOfBounds; + } + + return _NoError; + } + + static INLINE int checkUserArrayIndex(const long index, const dword size) + { + if(index < 0 || index >= long(size)) + { + Z_scripterrlog("Invalid index (%ld) to local array of size %ld\n", index, size); + return _OutOfBounds; + } + + return _NoError; + } +}; + +///------------------------------------------------// +// Pointer Handling Functions // +///------------------------------------------------// +//MUST call AND check load functions before trying to use other functions + +//Guy Helper +class GuyH : public SH +{ + +public: + static int loadNPC(const long eid, const char * const funcvar) + { + tempenemy = (enemy *) guys.getByUID(eid); + + if(tempenemy == NULL) + { + Z_scripterrlog("Invalid NPC with UID %ld passed to %s\nNPCs on screen have UIDs ", eid, funcvar); + + for(word i = 0; i < guys.Count(); i++) + Z_scripterrlog("%ld ", guys.spr(i)->getUID()); + + Z_scripterrlog("\n"); + return _InvalidSpriteUID; + } + + return _NoError; + } + + static INLINE enemy *getNPC() + { + return tempenemy; + } + + // Currently only used in a context where the enemy is known to be valid, + // so there's no need to print an error + static int getNPCIndex(const long eid) + { + for(word i = 0; i < guys.Count(); i++) + { + if(guys.spr(i)->getUID() == eid) + return i; + } + + return -1; + } + + static long getNPCDMisc(const byte a) + { + switch(a) + { + case 0: + return tempenemy->dmisc1; + + case 1: + return tempenemy->dmisc2; + + case 2: + return tempenemy->dmisc3; + + case 3: + return tempenemy->dmisc4; + + case 4: + return tempenemy->dmisc5; + + case 5: + return tempenemy->dmisc6; + + case 6: + return tempenemy->dmisc7; + + case 7: + return tempenemy->dmisc8; + + case 8: + return tempenemy->dmisc9; + + case 9: + return tempenemy->dmisc10; + + case 10: + return tempenemy->dmisc11; + + case 11: + return tempenemy->dmisc12; + } + + return 0; + } + + static bool hasLink() + { + if(tempenemy->family == eeWALLM || + tempenemy->family == eeWALK) + return ((ASEnemy *) tempenemy)->haslink; + + return false; + } + + static long getMFlags() + { + flagpos = 5; + // Must be in the same order as in the Enemy Editor pane + return (tempenemy->flags&0x1F) + | ornextflag(tempenemy->flags&(lens_only)) + | ornextflag(tempenemy->flags2&(guy_flashing)) + | ornextflag(tempenemy->flags2&(guy_blinking)) + | ornextflag(tempenemy->flags2&(guy_transparent)) + | ornextflag(tempenemy->flags&(inv_front)) + | ornextflag(tempenemy->flags&(inv_left)) + | ornextflag(tempenemy->flags&(inv_right)) + | ornextflag(tempenemy->flags&(inv_back)) + | ornextflag(tempenemy->flags&(guy_bkshield)); + } + + static INLINE void clearTemp() + { + tempenemy = NULL; + } + +private: + + static enemy *tempenemy; +}; + +enemy *GuyH::tempenemy = NULL; + +//Item Helper +class ItemH : public SH +{ + +public: + static int loadItem(const long iid, const char * const funcvar) + { + tempitem = (item *) items.getByUID(iid); + + if(tempitem == NULL) + { + Z_scripterrlog("Invalid item with UID %ld passed to %s\nItems on screen have UIDs ", iid, funcvar); + + for(word i = 0; i < items.Count(); i++) + Z_scripterrlog("%ld ", items.spr(i)->getUID()); + + Z_scripterrlog("\n"); + return _InvalidSpriteUID; + } + + return _NoError; + } + + static INLINE item* getItem() + { + return tempitem; + } + + static INLINE void clearTemp() + { + tempitem = NULL; + } + +private: + + static item *tempitem; +}; + +item *ItemH::tempitem = NULL; + +//LWeapon Helper +class LwpnH : public SH +{ + +public: + static int loadWeapon(const long wid, const char * const funcvar) + { + tempweapon = (weapon *) Lwpns.getByUID(wid); + + if(tempweapon == NULL) + { + Z_scripterrlog("Invalid lweapon with UID %ld passed to %s\nLWeapons on screen have UIDs ", wid, funcvar); + + for(word i = 0; i < Lwpns.Count(); i++) + Z_scripterrlog("%ld ", Lwpns.spr(i)->getUID()); + + Z_scripterrlog("\n"); + return _InvalidSpriteUID; + } + + return _NoError; + } + + static INLINE weapon *getWeapon() + { + return tempweapon; + } + + static INLINE void clearTemp() + { + tempweapon = NULL; + } + +private: + + static weapon *tempweapon; +}; + +weapon *LwpnH::tempweapon = NULL; + +//EWeapon Helper +class EwpnH : public SH +{ + +public: + static int loadWeapon(const long wid, const char * const funcvar) + { + tempweapon = (weapon *) Ewpns.getByUID(wid); + + if(tempweapon == NULL) + { + Z_scripterrlog("Invalid eweapon with UID %ld passed to %s\nEWeapons on screen have UIDs ", wid, funcvar); + + for(word i = 0; i < Ewpns.Count(); i++) + Z_scripterrlog("%ld ", Ewpns.spr(i)->getUID()); + + Z_scripterrlog("\n"); + return _InvalidSpriteUID; + } + + return _NoError; + } + + static INLINE weapon *getWeapon() + { + return tempweapon; + } + + static INLINE void clearTemp() + { + tempweapon = NULL; + } + +private: + + static weapon *tempweapon; +}; + +weapon *EwpnH::tempweapon = NULL; + +void clearScriptHelperData() +{ + GuyH::clearTemp(); + ItemH::clearTemp(); + LwpnH::clearTemp(); + EwpnH::clearTemp(); +} + +///---------------------------------------------// +// Array Helper Functions // +///---------------------------------------------// + +//Array Helper +class ArrayH : public SH +{ +public: + + //Returns a reference to the correct array based on pointer passed + static ZScriptArray& getArray(const long ptr) + { + if(ptr <= 0) + return InvalidError(ptr); + + if(ptr >= MAX_ZCARRAY_SIZE) //Then it's a global + { + dword gptr = ptr - MAX_ZCARRAY_SIZE; + + if(gptr > game->globalRAM.size()) + return InvalidError(ptr); + + return game->globalRAM[gptr]; + } + else + { + if(localRAM[ptr].Size() == 0) + return InvalidError(ptr); + + return localRAM[ptr]; + } + } + + static size_t getSize(const long ptr) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return size_t(-1); + + return a.Size(); + } + + //Can't you get the std::string and then check its length? + static int strlen(const long ptr) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return -1; + + word count; + + for(count = 0; BC::checkUserArrayIndex(count, a.Size()) == _NoError && a[count] != '\0'; count++) ; + + return count; + } + + //Returns values of a zscript array as an std::string. + static void getString(const long ptr, string &str, word num_chars = 256) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + { + str.clear(); + return; + } + + str.clear(); + + for(word i = 0; BC::checkUserArrayIndex(i, a.Size()) == _NoError && a[i] != '\0' && num_chars != 0; i++) + { + str += char(a[i] / 10000); + num_chars--; + } + } + + //Like getString but for an array of longs instead of chars. *(arrayPtr is not checked for validity) + static void getValues(const long ptr, long* arrayPtr, word num_values) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return; + + for(word i = 0; BC::checkUserArrayIndex(i, a.Size()) == _NoError && num_values != 0; i++) + { + arrayPtr[i] = (a[i] / 10000); + num_values--; + } + } + + //Get element from array + static INLINE long getElement(const long ptr, const long offset) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return -10000; + + if(BC::checkUserArrayIndex(offset, a.Size()) == _NoError) + return a[offset]; + else + return -10000; + } + + //Set element in array + static INLINE void setElement(const long ptr, const long offset, const long value) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return; + + if(BC::checkUserArrayIndex(offset, a.Size()) == _NoError) + a[offset] = value; + } + + //Puts values of a zscript array into a client array. returns 0 on success. Overloaded + template + static int getArray(const long ptr, T *refArray) + { + return getArray(ptr, getArray(ptr).Size(), 0, 0, 0, refArray); + } + + template + static int getArray(const long ptr, const word size, T *refArray) + { + return getArray(ptr, size, 0, 0, 0, refArray); + } + + template + static int getArray(const long ptr, const word size, word userOffset, const word userStride, const word refArrayOffset, T *refArray) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return _InvalidPointer; + + word j = 0, k = userStride; + + for(word i = 0; j < size; i++) + { + if(i >= a.Size()) + return _Overflow; + + if(userOffset-- > 0) + continue; + + if(k > 0) + k--; + else if(BC::checkUserArrayIndex(i, a.Size()) == _NoError) + { + refArray[j + refArrayOffset] = T(a[i]); + k = userStride; + j++; + } + } + + return _NoError; + } + + + static int setArray(const long ptr, const string s2) + { + ZScriptArray &a = getArray(ptr); + + if(a == INVALIDARRAY) + return _InvalidPointer; + + word i; + + for(i = 0; i < s2.size(); i++) + { + if(i >= a.Size()) + { + a.Back() = '\0'; + return _Overflow; + } + + if(BC::checkUserArrayIndex(i, a.Size()) == _NoError) + a[i] = s2[i] * 10000; + } + + if(BC::checkUserArrayIndex(i, a.Size()) == _NoError) + a[i] = '\0'; + + return _NoError; + } + + //Puts values of a client array into a zscript array. returns 0 on success. Overloaded + template + static int setArray(const long ptr, const word size, T *refArray) + { + return setArray(ptr, size, 0, 0, 0, refArray); + } + + template + static int setArray(const long ptr, const word size, word userOffset, const word userStride, const word refArrayOffset, T *refArray) + { + ZScriptArray& a = getArray(ptr); + + if(a == INVALIDARRAY) + return _InvalidPointer; + + word j = 0, k = userStride; + + for(word i = 0; j < size; i++) + { + if(i >= a.Size()) + return _Overflow; //Resize? + + if(userOffset-- > 0) + continue; + + if(k > 0) + k--; + else if(BC::checkUserArrayIndex(i, a.Size()) == _NoError) + { + a[i] = long(refArray[j + refArrayOffset]) * 10000; + k = userStride; + j++; + } + } + + return _NoError; + } +}; + +// Called when leaving a screen; deallocate arrays created by FFCs that aren't carried over +void deallocateArray(const long ptrval) +{ + if(ptrval<=0 || ptrval >= MAX_ZCARRAY_SIZE) + Z_scripterrlog("Script tried to deallocate memory at invalid address %ld\n", ptrval); + else + { + arrayOwner[ptrval] = 255; + + if(localRAM[ptrval].Size() == 0) + Z_scripterrlog("Script tried to deallocate memory that was not allocated at address %ld\n", ptrval); + else + localRAM[ptrval].Clear(); + } +} + +item *checkItem(long iid) +{ + item *s = (item *)items.getByUID(iid); + + if(s == NULL) + { + Z_eventlog("Script attempted to reference a nonexistent item!\n"); + Z_eventlog("You were trying to reference an item with UID = %ld; Items on screen are UIDs ", iid); + + for(int i=0; igetUID()); + } + + Z_eventlog("\n"); + return NULL; + } + + return s; +} + +weapon *checkLWpn(long eid, const char *what) +{ + weapon *s = (weapon *)Lwpns.getByUID(eid); + + if(s == NULL) + { + + Z_eventlog("Script attempted to reference a nonexistent LWeapon!\n"); + Z_eventlog("You were trying to reference the %s of an LWeapon with UID = %ld; LWeapons on screen are UIDs ", what, eid); + + for(int i=0; igetUID()); + } + + Z_eventlog("\n"); + return NULL; + } + + return s; +} + +weapon *checkEWpn(long eid, const char *what) +{ + weapon *s = (weapon *)Ewpns.getByUID(eid); + + if(s == NULL) + { + + Z_eventlog("Script attempted to reference a nonexistent EWeapon!\n"); + Z_eventlog("You were trying to reference the %s of an EWeapon with UID = %ld; EWeapons on screen are UIDs ", what, eid); + + for(int i=0; igetUID()); + } + + Z_eventlog("\n"); + return NULL; + } + + return s; +} + + +int get_screen_d(long index1, long index2) +{ + if(index2 < 0 || index2 > 7) + { + Z_scripterrlog("You were trying to reference an out-of-bounds array index for a screen's D[] array (%ld); valid indices are from 0 to 7.\n", index1); + return 0; + } + + return game->screen_d[index1][index2]; +} + +void set_screen_d(long index1, long index2, int val) +{ + if(index2 < 0 || index2 > 7) + { + Z_scripterrlog("You were trying to reference an out-of-bounds array index for a screen's D[] array (%ld); valid indices are from 0 to 7.\n", index1); + return; + } + + game->screen_d[index1][index2] = val; +} + +// If scr is currently being used as a layer, return that layer no. +int whichlayer(long scr) +{ + for(int i = 0; i < 6; i++) + { + if(scr == (tmpscr->layermap[i] - 1) * MAPSCRS + tmpscr->layerscreen[i]) + return i; + } + + return -1; +} + +sprite *s; + + + +long get_register(const long arg) +{ + long ret = 0; + + switch(arg) + { +///----------------------------------------------------------------------------------------------------// +//FFC Variables + case DATA: + ret = tmpscr->ffcs[ri->ffcref].data*10000; + break; + + case FFSCRIPT: + ret = tmpscr->ffcs[ri->ffcref].script*10000; + break; + + case FCSET: + ret = tmpscr->ffcs[ri->ffcref].cset*10000; + break; + + case DELAY: + ret = tmpscr->ffcs[ri->ffcref].delay*10000; + break; + + case FX: + ret = tmpscr->ffcs[ri->ffcref].x; + break; + + case FY: + ret = tmpscr->ffcs[ri->ffcref].y; + break; + + case XD: + ret = tmpscr->ffcs[ri->ffcref].xVel; + break; + + case YD: + ret = tmpscr->ffcs[ri->ffcref].yVel; + break; + + case XD2: + ret = tmpscr->ffcs[ri->ffcref].xAccel; + break; + + case YD2: + ret = tmpscr->ffcs[ri->ffcref].yAccel; + break; + + case FFFLAGSD: + ret=((tmpscr->ffcs[ri->ffcref].flags >> (ri->d[0] / 10000))&1) ? 10000 : 0; + break; + + case FFCWIDTH: + ret=tmpscr->ffcs[ri->ffcref].getEffectWidth()*10000; + break; + + case FFCHEIGHT: + ret=tmpscr->ffcs[ri->ffcref].getEffectHeight()*10000; + break; + + case FFTWIDTH: + ret=(tmpscr->ffcs[ri->ffcref].getTileWidth())*10000; + break; + + case FFTHEIGHT: + ret=(tmpscr->ffcs[ri->ffcref].getTileHeight())*10000; + break; + + case FFLINK: + ret=(tmpscr->ffcs[ri->ffcref].link)*10000; + break; + + case FFMISCD: + { + int a = ri->d[0] / 10000; + + if(BC::checkMisc(a, "ffc->Misc") != SH::_NoError) + ret = -10000; + else + ret = tmpscr->ffcs[ri->ffcref].misc[a]; + } + break; + + case FFINITDD: + { + int a = ri->d[0] / 10000; + + if(BC::checkBounds(a, 0, 7, "ffc->InitD") != SH::_NoError) + ret = -10000; + else + ret = tmpscr->ffcs[ri->ffcref].initd[a]; + } + break; + +///----------------------------------------------------------------------------------------------------// +//Link's Variables + case LINKX: + ret = long(linkIF.getX()) * 10000; + break; + + case LINKY: + ret = long(linkIF.getY()) * 10000; + break; + + case LINKZ: + ret = long(linkIF.getZ()) * 10000; + break; + + case LINKJUMP: + // -fall/100*10000, but doing it that way screwed up the result + ret = long(-Link.getFall()) * 100; + break; + + case LINKDIR: + ret=(int)(linkIF.getDir())*10000; + break; + + case LINKHITDIR: + ret=(int)(Link.getHitDir())*10000; + break; + + case LINKHP: + ret=(int)(game->get_life())*10000; + break; + + case LINKMP: + ret=(int)(game->get_magic())*10000; + break; + + case LINKMAXHP: + ret=(int)(game->get_maxlife())*10000; + break; + + case LINKMAXMP: + ret=(int)(game->get_maxmagic())*10000; + break; + + case LINKACTION: + ret=(int)(Link.getAction())*10000; + break; + + case LINKHELD: + ret = (int)(Link.getHeldItem())*10000; + break; + + case LINKITEMD: + ret = game->item[vbound(ri->d[0]/10000, 0, MAXITEMS-1)] ? 10000 : 0; + break; + + case LINKEQUIP: + ret = ((Awpn&0xFF)|((Bwpn&0xFF)<<8))*10000; + break; + + case LINKINVIS: + ret = (int)(Link.getDontDraw())*10000; + break; + + case LINKINVINC: + ret = (int)(Link.scriptcoldet)*10000; + break; + + case LINKLADDERX: + ret=(int)(linkIF.getLadderX())*10000; + break; + + case LINKLADDERY: + ret=(int)(linkIF.getLadderY())*10000; + break; + + case LINKSWORDJINX: + ret = (int)(Link.getSwordClk())*10000; + break; + + case LINKITEMJINX: + ret = (int)(Link.getItemClk())*10000; + break; + + case LINKDRUNK: + ret = (int)(Link.DrunkClock())*10000; + break; + + case LINKMISCD: + ret = (int)(Link.miscellaneous[vbound(ri->d[0]/10000,0,15)]); + break; + + case LINKHXOFS: + ret = (int)(Link.hxofs)*10000; + break; + + case LINKHYOFS: + ret = (int)(Link.hyofs)*10000; + break; + + case LINKXOFS: + ret = (int)(Link.xofs)*10000; + break; + + case LINKYOFS: + ret = (int)(Link.yofs-playing_field_offset)*10000; + break; + + case LINKZOFS: + ret = (int)(Link.zofs)*10000; + break; + + case LINKHXSZ: + ret = (int)(Link.hxsz)*10000; + break; + + case LINKHYSZ: + ret = (int)(Link.hysz)*10000; + break; + + case LINKHZSZ: + ret = (int)(Link.hzsz)*10000; + break; + + case LINKTXSZ: + ret = (int)(Link.txsz)*10000; + break; + + case LINKTYSZ: + ret = (int)(Link.tysz)*10000; + break; + + case LINKTILE: + ret = (int)(Link.tile)*10000; + break; + + case LINKFLIP: + ret = (int)(Link.flip)*10000; + break; + +///----------------------------------------------------------------------------------------------------// +//Input States + case INPUTSTART: + ret=control_state[6]?10000:0; + break; + + case INPUTMAP: + ret=control_state[9]?10000:0; + break; + + case INPUTUP: + ret=control_state[0]?10000:0; + break; + + case INPUTDOWN: + ret=control_state[1]?10000:0; + break; + + case INPUTLEFT: + ret=control_state[2]?10000:0; + break; + + case INPUTRIGHT: + ret=control_state[3]?10000:0; + break; + + case INPUTA: + ret=control_state[4]?10000:0; + break; + + case INPUTB: + ret=control_state[5]?10000:0; + break; + + case INPUTL: + ret=control_state[7]?10000:0; + break; + + case INPUTR: + ret=control_state[8]?10000:0; + break; + + case INPUTEX1: + ret=control_state[10]?10000:0; + break; + + case INPUTEX2: + ret=control_state[11]?10000:0; + break; + + case INPUTEX3: + ret=control_state[12]?10000:0; + break; + + case INPUTEX4: + ret=control_state[13]?10000:0; + break; + + case INPUTAXISUP: + ret=control_state[14]?10000:0; + break; + + case INPUTAXISDOWN: + ret=control_state[15]?10000:0; + break; + + case INPUTAXISLEFT: + ret=control_state[16]?10000:0; + break; + + case INPUTAXISRIGHT: + ret=control_state[17]?10000:0; + break; + + case INPUTMOUSEX: + { + int leftOffset=(resx/2)-(128*screen_scale); + ret=((gui_mouse_x()-leftOffset)/screen_scale)*10000; + break; + } + + case INPUTMOUSEY: + { + int topOffset=(resy/2)-((112-playing_field_offset)*screen_scale); + ret=((gui_mouse_y()-topOffset)/screen_scale)*10000; + break; + } + + case INPUTMOUSEZ: + ret=(gui_mouse_z())*10000; + break; + + case INPUTMOUSEB: + ret=(gui_mouse_b())*10000; + break; + + case INPUTPRESSSTART: + ret=button_press[6]?10000:0; + break; + + case INPUTPRESSMAP: + ret=button_press[9]?10000:0; + break; + + case INPUTPRESSUP: + ret=button_press[0]?10000:0; + break; + + case INPUTPRESSDOWN: + ret=button_press[1]?10000:0; + break; + + case INPUTPRESSLEFT: + ret=button_press[2]?10000:0; + break; + + case INPUTPRESSRIGHT: + ret=button_press[3]?10000:0; + break; + + case INPUTPRESSA: + ret=button_press[4]?10000:0; + break; + + case INPUTPRESSB: + ret=button_press[5]?10000:0; + break; + + case INPUTPRESSL: + ret=button_press[7]?10000:0; + break; + + case INPUTPRESSR: + ret=button_press[8]?10000:0; + break; + + case INPUTPRESSEX1: + ret=button_press[10]?10000:0; + break; + + case INPUTPRESSEX2: + ret=button_press[11]?10000:0; + break; + + case INPUTPRESSEX3: + ret=button_press[12]?10000:0; + break; + + case INPUTPRESSEX4: + ret=button_press[13]?10000:0; + break; + + case INPUTPRESSAXISUP: + ret=button_press[14]?10000:0; + break; + + case INPUTPRESSAXISDOWN: + ret=button_press[15]?10000:0; + break; + + case INPUTPRESSAXISLEFT: + ret=button_press[16]?10000:0; + break; + + case INPUTPRESSAXISRIGHT: + ret=button_press[17]?10000:0; + break; + + +///----------------------------------------------------------------------------------------------------// +//Item Variables + case ITEMX: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)((item*)(s))->x)*10000; + } + + break; + + case ITEMY: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)((item*)(s))->y)*10000; + } + + break; + + case ITEMZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)((item*)(s))->z)*10000; + } + + break; + + case ITEMJUMP: + if(0!=(s=checkItem(ri->itemref))) + { + ret = long((-((item*)(s))->fall / fix(100.0)) * 10000); + } + + break; + + case ITEMDRAWTYPE: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->drawstyle*10000; + } + + break; + + case ITEMID: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->id*10000; + } + + break; + + case ITEMTILE: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->tile*10000; + } + + break; + + case ITEMOTILE: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->o_tile*10000; + } + + break; + + case ITEMCSET: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->o_cset&15)*10000; + } + + break; + + case ITEMFLASHCSET: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->o_cset>>4)*10000; + } + + break; + + case ITEMFRAMES: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->frames*10000; + } + + break; + + case ITEMFRAME: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->aframe*10000; + } + + break; + + case ITEMASPEED: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->o_speed*10000; + } + + break; + + case ITEMDELAY: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->o_delay*10000; + } + + break; + + case ITEMFLIP: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->flip*10000; + } + + break; + + case ITEMFLASH: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->flash*10000; + } + + break; + + case ITEMHXOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->hxofs)*10000; + } + + break; + + case ITEMHYOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->hyofs)*10000; + } + + break; + + case ITEMXOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)(((item*)(s))->xofs))*10000; + } + + break; + + case ITEMYOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)(((item*)(s))->yofs-playing_field_offset))*10000; + } + + break; + + case ITEMZOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((int)(((item*)(s))->zofs))*10000; + } + + break; + + case ITEMHXSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->hxsz)*10000; + } + + break; + + case ITEMHYSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->hysz)*10000; + } + + break; + + case ITEMHZSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->hzsz)*10000; + } + + break; + + case ITEMTXSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->txsz)*10000; + } + + break; + + case ITEMTYSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ret=(((item*)(s))->tysz)*10000; + } + + break; + + case ITEMCOUNT: + ret=(items.Count())*10000; + break; + + case ITEMEXTEND: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->extend*10000; + } + + break; + + case ITEMPICKUP: + if(0!=(s=checkItem(ri->itemref))) + { + ret=((item*)(s))->pickup*10000; + } + + break; + + case ITEMMISCD: + if(0!=(s=checkItem(ri->itemref))) + { + int a = vbound(ri->d[0]/10000,0,15); + ret=(((item*)(s))->miscellaneous[a]); + break; + } + +///----------------------------------------------------------------------------------------------------// +//Itemdata Variables + case IDATAFAMILY: + ret=(itemsbuf[ri->idata].family)*10000; + break; + + case IDATALEVEL: + ret=(itemsbuf[ri->idata].fam_type)*10000; + break; + + case IDATAKEEP: + ret=(itemsbuf[ri->idata].flags & ITEM_GAMEDATA)?10000:0; + break; + + case IDATAAMOUNT: + ret=(itemsbuf[ri->idata].amount)*10000; + break; + + case IDATASETMAX: + ret=(itemsbuf[ri->idata].setmax)*10000; + break; + + case IDATAMAX: + ret=(itemsbuf[ri->idata].max)*10000; + break; + + case IDATACOUNTER: + ret=(itemsbuf[ri->idata].count)*10000; + break; + + case IDATAUSESOUND: + ret=(itemsbuf[ri->idata].usesound)*10000; + break; + + case IDATAPOWER: + ret=(itemsbuf[ri->idata].power)*10000; + break; + + case IDATAINITDD: + { + int a = ri->d[0] / 10000; + + if(BC::checkBounds(a, 0, 7, "itemdata->InitD") != SH::_NoError) + ret = -10000; + else + ret = itemsbuf[ri->idata].initiald[a]; + } + break; + +///----------------------------------------------------------------------------------------------------// +//NPC Variables + +//Reduces accessing integer members to one line +#define GET_NPC_VAR_INT(member, str) \ +{ \ + if(GuyH::loadNPC(ri->guyref, str) != SH::_NoError) \ + ret = -10000; \ + else \ + ret = GuyH::getNPC()->member * 10000; \ +} + + case NPCDIR: + if(GuyH::loadNPC(ri->guyref, "npc->Dir") != SH::_NoError) + ret = -10000; + else + ret = zc_max(GuyH::getNPC()->dir * 10000, 0); + + break; + + case NPCRATE: + GET_NPC_VAR_INT(rate, "npc->Rate") break; + + case NPCHOMING: + GET_NPC_VAR_INT(homing, "npc->Homing") break; + + case NPCFRAMERATE: + GET_NPC_VAR_INT(frate, "npc->ASpeed") break; + + case NPCHALTRATE: + GET_NPC_VAR_INT(hrate, "npc->HaltRate") break; + + case NPCDRAWTYPE: + GET_NPC_VAR_INT(drawstyle, "npc->DrawStyle") break; + + case NPCHP: + GET_NPC_VAR_INT(hp, "npc->HP") break; + + case NPCCOLLDET: + GET_NPC_VAR_INT(scriptcoldet, "npc->ColDetection") break; + + case NPCSTUN: + GET_NPC_VAR_INT(stunclk, "npc->Stun") break; + + case NPCHUNGER: + GET_NPC_VAR_INT(grumble, "npc->Hunger") break; + + case NPCTYPE: + GET_NPC_VAR_INT(family, "npc->Type") break; + + case NPCDP: + GET_NPC_VAR_INT(dp, "npc->Damage") break; + + case NPCWDP: + GET_NPC_VAR_INT(wdp, "npc->WeaponDamage") break; + + case NPCOTILE: + GET_NPC_VAR_INT(o_tile, "npc->OriginalTile") break; + + case NPCTILE: + GET_NPC_VAR_INT(tile, "npc->Tile") break; + + case NPCWEAPON: + GET_NPC_VAR_INT(wpn, "npc->Weapon") break; + + case NPCITEMSET: + GET_NPC_VAR_INT(item_set, "npc->ItemSet") break; + + case NPCCSET: + GET_NPC_VAR_INT(cs, "npc->CSet") break; + + case NPCBOSSPAL: + GET_NPC_VAR_INT(bosspal, "npc->BossPal") break; + + case NPCBGSFX: + GET_NPC_VAR_INT(bgsfx, "npc->SFX") break; + + case NPCEXTEND: + GET_NPC_VAR_INT(extend, "npc->Extend") break; + + case NPCHXOFS: + GET_NPC_VAR_INT(hxofs, "npc->HitXOffset") break; + + case NPCHYOFS: + GET_NPC_VAR_INT(hyofs, "npc->HitYOffset") break; + + case NPCHXSZ: + GET_NPC_VAR_INT(hxsz, "npc->HitWidth") break; + + case NPCHYSZ: + GET_NPC_VAR_INT(hysz, "npc->HitHeight") break; + + case NPCHZSZ: + GET_NPC_VAR_INT(hzsz, "npc->HitZHeight") break; + + case NPCTXSZ: + GET_NPC_VAR_INT(txsz, "npc->TileWidth") break; + + case NPCTYSZ: + GET_NPC_VAR_INT(tysz, "npc->TileHeight") break; + +//And fix +#define GET_NPC_VAR_FIX(member, str) \ +{ \ + if(GuyH::loadNPC(ri->guyref, str) != SH::_NoError) \ + ret = -10000; \ + else \ + ret = (long(GuyH::getNPC()->member) * 10000); \ +} + + case NPCX: + GET_NPC_VAR_FIX(x, "npc->X") break; + + case NPCY: + GET_NPC_VAR_FIX(y, "npc->Y") break; + + case NPCZ: + GET_NPC_VAR_FIX(z, "npc->Z") break; + + case NPCXOFS: + GET_NPC_VAR_FIX(xofs, "npc->DrawXOffset") break; + + case NPCYOFS: + GET_NPC_VAR_FIX(yofs, "npc->DrawYOffset") ret-=playing_field_offset*10000; + break; + + case NPCZOFS: + GET_NPC_VAR_FIX(zofs, "npc->DrawZOffset") break; + + //These variables are all different to the templates (casting for jump and step is slightly non-standard) + case NPCJUMP: + if(GuyH::loadNPC(ri->guyref, "npc->Jump") != SH::_NoError) + ret = -10000; + else + ret = (long(-GuyH::getNPC()->fall / fix(100.0)) * 10000); + + break; + + case NPCSTEP: + if(GuyH::loadNPC(ri->guyref, "npc->Step") != SH::_NoError) + ret = -10000; + else + ret = long(GuyH::getNPC()->step * fix(100.0)) * 10000; + + break; + + case NPCID: + if(GuyH::loadNPC(ri->guyref, "npc->ID") != SH::_NoError) + ret = -10000; + else + ret = (GuyH::getNPC()->id & 0xFFF) * 10000; + + break; + + case NPCMFLAGS: + if(GuyH::loadNPC(ri->guyref, "npc->MiscFlags") != SH::_NoError) + ret = -10000; + else + ret = GuyH::getMFlags() * 10000; + + break; + + //Indexed (two checks) + case NPCDEFENSED: + { + int a = ri->d[0] / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Defense") != SH::_NoError || + BC::checkBounds(a, 0, edefSCRIPT, "npc->Defense") != SH::_NoError) + ret = -10000; + else + ret = GuyH::getNPC()->defense[a] * 10000; + } + break; + + case NPCMISCD: + { + int a = ri->d[0] / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Misc") != SH::_NoError || + BC::checkMisc(a, "npc->Misc") != SH::_NoError) + ret = -10000; + else + ret = GuyH::getNPC()->miscellaneous[a]; + } + break; + + case NPCDD: + { + int a = ri->d[0] / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Attributes") != SH::_NoError || + BC::checkBounds(a, 0, 11, "npc->Attributes") != SH::_NoError) + ret = -10000; + else + ret = GuyH::getNPCDMisc(a) * 10000; + } + break; + + +///----------------------------------------------------------------------------------------------------// +//LWeapon Variables + case LWPNX: + if(0!=(s=checkLWpn(ri->lwpn,"X"))) + ret=((int)((weapon*)(s))->x)*10000; + + break; + + case LWPNY: + if(0!=(s=checkLWpn(ri->lwpn,"Y"))) + ret=((int)((weapon*)(s))->y)*10000; + + break; + + case LWPNZ: + if(0!=(s=checkLWpn(ri->lwpn,"Z"))) + ret=((int)((weapon*)(s))->z)*10000; + + break; + + case LWPNJUMP: + if(0!=(s=checkLWpn(ri->lwpn,"Jump"))) + ret = long((-((weapon*)(s))->fall / fix(100.0)) * 100000); + + break; + + case LWPNDIR: + if(0!=(s=checkLWpn(ri->lwpn,"Dir"))) + ret=((weapon*)(s))->dir*10000; + + break; + + case LWPNSTEP: + if(0!=(s=checkLWpn(ri->lwpn,"Step"))) + ret=(int)((float)((weapon*)s)->step * 1000000.0); + + break; + + case LWPNANGLE: + if(0!=(s=checkLWpn(ri->lwpn,"Angle"))) + ret=(int)(((weapon*)(s))->angle*10000); + + break; + + case LWPNANGULAR: + if(0!=(s=checkLWpn(ri->lwpn,"Angular"))) + ret=((weapon*)(s))->angular*10000; + + break; + + case LWPNBEHIND: + if(0!=(s=checkLWpn(ri->lwpn,"Behind"))) + ret=((weapon*)(s))->behind*10000; + + break; + + case LWPNDRAWTYPE: + if(0!=(s=checkLWpn(ri->lwpn,"DrawStyle"))) + ret=((weapon*)(s))->drawstyle*10000; + + break; + + case LWPNPOWER: + if(0!=(s=checkLWpn(ri->lwpn,"Damage"))) + ret=((weapon*)(s))->power*10000; + + break; + + case LWPNDEAD: + if(0!=(s=checkLWpn(ri->lwpn,"DeadState"))) + ret=((weapon*)(s))->dead*10000; + + break; + + case LWPNID: + if(0!=(s=checkLWpn(ri->lwpn,"ID"))) + ret=((weapon*)(s))->id*10000; + + break; + + case LWPNTILE: + if(0!=(s=checkLWpn(ri->lwpn,"Tile"))) + ret=((weapon*)(s))->tile*10000; + + break; + + case LWPNCSET: + if(0!=(s=checkLWpn(ri->lwpn,"CSet"))) + ret=((weapon*)(s))->cs*10000; + + break; + + case LWPNFLASHCSET: + if(0!=(s=checkLWpn(ri->lwpn,"FlashCSet"))) + ret=(((weapon*)(s))->o_cset>>4)*10000; + + break; + + case LWPNFRAMES: + if(0!=(s=checkLWpn(ri->lwpn,"NumFrames"))) + ret=((weapon*)(s))->frames*10000; + + break; + + case LWPNFRAME: + if(0!=(s=checkLWpn(ri->lwpn,"Frame"))) + ret=((weapon*)(s))->aframe*10000; + + break; + + case LWPNASPEED: + if(0!=(s=checkLWpn(ri->lwpn,"ASpeed"))) + ret=((weapon*)(s))->o_speed*10000; + + break; + + case LWPNFLASH: + if(0!=(s=checkLWpn(ri->lwpn,"Flash"))) + ret=((weapon*)(s))->flash*10000; + + break; + + case LWPNFLIP: + if(0!=(s=checkLWpn(ri->lwpn,"Flip"))) + ret=((weapon*)(s))->flip*10000; + + break; + + case LWPNCOUNT: + ret=Lwpns.Count()*10000; + break; + + case LWPNEXTEND: + if(0!=(s=checkLWpn(ri->lwpn,"Extend"))) + ret=((weapon*)(s))->extend*10000; + + break; + + case LWPNOTILE: + if(0!=(s=checkLWpn(ri->lwpn,"OriginalTile"))) + ret=((weapon*)(s))->o_tile*10000; + + break; + + case LWPNOCSET: + if(0!=(s=checkLWpn(ri->lwpn,"OriginalCSet"))) + ret=(((weapon*)(s))->o_cset&15)*10000; + + break; + + case LWPNHXOFS: + if(0!=(s=checkLWpn(ri->lwpn,"HitXOffset"))) + ret=(((weapon*)(s))->hxofs)*10000; + + break; + + case LWPNHYOFS: + if(0!=(s=checkLWpn(ri->lwpn,"HitYOffset"))) + ret=(((weapon*)(s))->hyofs)*10000; + + break; + + case LWPNXOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawXOffset"))) + ret=((int)(((weapon*)(s))->xofs))*10000; + + break; + + case LWPNYOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawYOffset"))) + ret=((int)(((weapon*)(s))->yofs-playing_field_offset))*10000; + + break; + + case LWPNZOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawZOffset"))) + ret=((int)(((weapon*)(s))->zofs))*10000; + + break; + + case LWPNHXSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitWidth"))) + ret=(((weapon*)(s))->hxsz)*10000; + + break; + + case LWPNHYSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitHeight"))) + ret=(((weapon*)(s))->hysz)*10000; + + break; + + case LWPNHZSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitZHeight"))) + ret=(((weapon*)(s))->hzsz)*10000; + + break; + + case LWPNTXSZ: + if(0!=(s=checkLWpn(ri->lwpn,"TileWidth"))) + ret=(((weapon*)(s))->txsz)*10000; + + break; + + case LWPNTYSZ: + if(0!=(s=checkLWpn(ri->lwpn,"TileHeight"))) + ret=(((weapon*)(s))->tysz)*10000; + + break; + + case LWPNMISCD: + if(0!=(s=checkLWpn(ri->lwpn,"Misc"))) + { + int a = vbound(ri->d[0]/10000,0,15); + ret=(((weapon*)(s))->miscellaneous[a]); + } + + break; + + case LWPNCOLLDET: + if(0!=(s=checkLWpn(ri->lwpn,"CollDetection"))) + ret=(((weapon*)(s))->scriptcoldet)*10000; + + break; + +///----------------------------------------------------------------------------------------------------// +//EWeapon Variables + case EWPNX: + if(0!=(s=checkEWpn(ri->ewpn, "X"))) + ret=((int)((weapon*)(s))->x)*10000; + + break; + + case EWPNY: + if(0!=(s=checkEWpn(ri->ewpn, "Y"))) + ret=((int)((weapon*)(s))->y)*10000; + + break; + + case EWPNZ: + if(0!=(s=checkEWpn(ri->ewpn, "Z"))) + ret=((int)((weapon*)(s))->z)*10000; + + break; + + case EWPNJUMP: + if(0!=(s=checkEWpn(ri->ewpn, "Jump"))) + ret = long((-((weapon*)(s))->fall / fix(100.0)) * 100000); + + break; + + case EWPNDIR: + if(0!=(s=checkEWpn(ri->ewpn, "Dir"))) + ret=((weapon*)(s))->dir*10000; + + break; + + case EWPNSTEP: + if(0!=(s=checkEWpn(ri->ewpn, "Step"))) + ret=(int)((float)((weapon*)s)->step * 1000000.0); + + break; + + case EWPNANGLE: + if(0!=(s=checkEWpn(ri->ewpn,"Angle"))) + ret=(int)(((weapon*)(s))->angle*10000); + + break; + + case EWPNANGULAR: + if(0!=(s=checkEWpn(ri->ewpn,"Angular"))) + ret=((weapon*)(s))->angular*10000; + + break; + + case EWPNBEHIND: + if(0!=(s=checkEWpn(ri->ewpn,"Behind"))) + ret=((weapon*)(s))->behind*10000; + + break; + + case EWPNDRAWTYPE: + if(0!=(s=checkEWpn(ri->ewpn,"DrawStyle"))) + ret=((weapon*)(s))->drawstyle*10000; + + break; + + case EWPNPOWER: + if(0!=(s=checkEWpn(ri->ewpn,"Damage"))) + ret=((weapon*)(s))->power*10000; + + break; + + case EWPNDEAD: + if(0!=(s=checkEWpn(ri->ewpn,"DeadState"))) + ret=((weapon*)(s))->dead*10000; + + break; + + case EWPNID: + if(0!=(s=checkEWpn(ri->ewpn,"ID"))) + ret=((weapon*)(s))->id*10000; + + break; + + case EWPNTILE: + if(0!=(s=checkEWpn(ri->ewpn,"Tile"))) + ret=((weapon*)(s))->tile*10000; + + break; + + case EWPNCSET: + if(0!=(s=checkEWpn(ri->ewpn,"CSet"))) + ret=((weapon*)(s))->cs*10000; + + break; + + case EWPNFLASHCSET: + if(0!=(s=checkEWpn(ri->ewpn,"FlashCSet"))) + ret=(((weapon*)(s))->o_cset>>4)*10000; + + break; + + case EWPNFRAMES: + if(0!=(s=checkEWpn(ri->ewpn,"NumFrames"))) + ret=((weapon*)(s))->frames*10000; + + break; + + case EWPNFRAME: + if(0!=(s=checkEWpn(ri->ewpn,"Frame"))) + ret=((weapon*)(s))->aframe*10000; + + break; + + case EWPNASPEED: + if(0!=(s=checkEWpn(ri->ewpn,"ASpeed"))) + ret=((weapon*)(s))->o_speed*10000; + + break; + + case EWPNFLASH: + if(0!=(s=checkEWpn(ri->ewpn,"Flash"))) + ret=((weapon*)(s))->flash*10000; + + break; + + case EWPNFLIP: + if(0!=(s=checkEWpn(ri->ewpn,"Flip"))) + ret=((weapon*)(s))->flip*10000; + + break; + + case EWPNCOUNT: + ret=Ewpns.Count()*10000; + break; + + case EWPNEXTEND: + if(0!=(s=checkEWpn(ri->ewpn,"Extend"))) + ret=((weapon*)(s))->extend*10000; + + break; + + case EWPNOTILE: + if(0!=(s=checkEWpn(ri->ewpn,"OriginalTile"))) + ret=((weapon*)(s))->o_tile*10000; + + break; + + case EWPNOCSET: + if(0!=(s=checkEWpn(ri->ewpn,"OriginalCSet"))) + ret=(((weapon*)(s))->o_cset&15)*10000; + + break; + + case EWPNHXOFS: + if(0!=(s=checkEWpn(ri->ewpn,"HitXOffset"))) + ret=(((weapon*)(s))->hxofs)*10000; + + break; + + case EWPNHYOFS: + if(0!=(s=checkEWpn(ri->ewpn,"HitYOffset"))) + ret=(((weapon*)(s))->hyofs)*10000; + + break; + + case EWPNXOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawXOffset"))) + ret=((int)(((weapon*)(s))->xofs))*10000; + + break; + + case EWPNYOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawYOffset"))) + ret=((int)(((weapon*)(s))->yofs-playing_field_offset))*10000; + + break; + + case EWPNZOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawZOffset"))) + ret=((int)(((weapon*)(s))->zofs))*10000; + + break; + + case EWPNHXSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitWidth"))) + ret=(((weapon*)(s))->hxsz)*10000; + + break; + + case EWPNHYSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitHeight"))) + ret=(((weapon*)(s))->hysz)*10000; + + break; + + case EWPNHZSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitZHeight"))) + ret=(((weapon*)(s))->hzsz)*10000; + + break; + + case EWPNTXSZ: + if(0!=(s=checkEWpn(ri->ewpn,"TileWidth"))) + ret=(((weapon*)(s))->txsz)*10000; + + break; + + case EWPNTYSZ: + if(0!=(s=checkEWpn(ri->ewpn,"TileHeight"))) + ret=(((weapon*)(s))->tysz)*10000; + + break; + + case EWPNMISCD: + if(0!=(s=checkEWpn(ri->ewpn,"Misc"))) + { + int a = vbound(ri->d[0]/10000,0,15); + ret=(((weapon*)(s))->miscellaneous[a]); + } + + break; + + case EWPNCOLLDET: + if(0!=(s=checkEWpn(ri->ewpn,"CollDetection"))) + ret=(((weapon*)(s))->scriptcoldet)*10000; + + break; + +///----------------------------------------------------------------------------------------------------// +//Game Info + case GAMEDEATHS: + ret=game->get_deaths()*10000; + break; + + case GAMECHEAT: + ret=game->get_cheat()*10000; + break; + + case GAMETIME: + ret=game->get_time(); + break;// Can't multiply by 10000 or the maximum result is too big + + case GAMETIMEVALID: + ret=game->get_timevalid()?10000:0; + break; + + case GAMEHASPLAYED: + ret=game->get_hasplayed()?10000:0; + break; + + case GAMESTANDALONE: + ret=standalone_mode?10000:0; + break; + + case GAMEGUYCOUNT: + { + int mi = (currmap*MAPSCRSNORMAL)+(ri->d[0]/10000); + ret=game->guys[mi]*10000; + } + break; + + case GAMECONTSCR: + ret=game->get_continue_scrn()*10000; + break; + + case GAMECONTDMAP: + ret=game->get_continue_dmap()*10000; + break; + + case GAMEENTRSCR: + ret=lastentrance*10000; + break; + + case GAMEENTRDMAP: + ret=lastentrance_dmap*10000; + break; + + case GAMECOUNTERD: + ret=game->get_counter((ri->d[0])/10000)*10000; + break; + + case GAMEMCOUNTERD: + ret=game->get_maxcounter((ri->d[0])/10000)*10000; + break; + + case GAMEDCOUNTERD: + ret=game->get_dcounter((ri->d[0])/10000)*10000; + break; + + case GAMEGENERICD: + ret=game->get_generic((ri->d[0])/10000)*10000; + break; + + case GAMEITEMSD: + ret=(game->item[(ri->d[0])/10000] ? 10000 : 0); + break; + + case GAMELITEMSD: + ret=game->lvlitems[(ri->d[0])/10000]*10000; + break; + + case GAMELKEYSD: + ret=game->lvlkeys[(ri->d[0])/10000]*10000; + break; + + case SCREENSTATED: + { + int mi =(currmap*MAPSCRSNORMAL)+currscr; + ret=((game->maps[mi]>>((ri->d[0]/10000)))&1)?10000:0; + } + break; + + case SCREENSTATEDD: + { + // Gah! >:( Screen state is stored in game->maps, which uses 128 screens per map, + // but the compiler multiplies the map number by 136, so it has to be corrected here. + // Yeah, the compiler could be fixed, but that wouldn't cover existing quests... + int mi = ri->d[0] / 10000; + mi -= 8*((ri->d[0] / 10000) / MAPSCRS); + + if(BC::checkMapID(mi>>7, "Game->GetScreenState") == SH::_NoError) + ret=(game->maps[mi] >> (ri->d[1] / 10000) & 1) ? 10000 : 0; + else + ret=0; + + break; + } + + case GAMEGUYCOUNTD: + ret=game->guys[(currmap * MAPSCRSNORMAL) + (ri->d[0] / 10000)]*10000; + break; + + case CURMAP: + ret=(1+currmap)*10000; + break; + + case CURSCR: + ret=currscr*10000; + break; + + case GETMIDI: + ret=(currmidi-(ZC_MIDI_COUNT-1))*10000; + break; + + case CURDSCR: + { + int di = (get_currscr()-DMaps[get_currdmap()].xoff); + ret=(DMaps[get_currdmap()].type==dmOVERW ? currscr : di)*10000; + } + break; + + case CURDMAP: + ret=currdmap*10000; + break; + + case CURLEVEL: + ret=DMaps[get_currdmap()].level*10000; + break; + + case GAMECLICKFREEZE: + ret=disableClickToFreeze?0:10000; + break; + + +///----------------------------------------------------------------------------------------------------// +//DMap Information + +#define GET_DMAP_VAR(member, str) \ +{ \ + int ID = ri->d[0] / 10000; \ + if(BC::checkDMapID(ID, str) != SH::_NoError) \ + ret = -10000; \ + else \ + ret = DMaps[ID].member * 10000; \ +} + + case DMAPFLAGSD: + GET_DMAP_VAR(flags, "Game->DMapFlags") break; + + case DMAPLEVELD: + GET_DMAP_VAR(level, "Game->DMapLevel") break; + + case DMAPCOMPASSD: + GET_DMAP_VAR(compass, "Game->DMapCompass") break; + + case DMAPCONTINUED: + GET_DMAP_VAR(cont, "Game->DMapContinue") break; + + case DMAPOFFSET: + GET_DMAP_VAR(xoff, "Game->DMapOffset") break; + + case DMAPMAP: + { + int ID = ri->d[0] / 10000; + + if(BC::checkDMapID(ID, "Game->DMapMap") != SH::_NoError) + ret = -10000; + else + ret = (DMaps[ID].map+1) * 10000; + + break; + } + + case DMAPMIDID: + { + int ID = ri->d[0] / 10000; + + if(BC::checkDMapID(ID, "Game->DMapMIDI") == SH::_NoError) + { + // Based on play_DmapMusic + switch(DMaps[ID].midi) + { + case 2: + ret = -60000; + break; // Dungeon + + case 3: + ret = -30000; + break; // Level 9 + + case 1: + ret = -20000; + break; // Overworld + + case 0: + ret = 0; + break; // None + + default: + ret = (DMaps[ID].midi - 3) * 10000; + } + } + else + ret = -10000; // Which is valid, but whatever. + + break; + } + +///----------------------------------------------------------------------------------------------------// +//Screen->ComboX +#define GET_COMBO_VAR(member, str) \ +{ \ +int pos = ri->d[0] / 10000; \ +if(BC::checkComboPos(pos, str) != SH::_NoError) \ + ret = -10000; \ +else \ + ret = tmpscr->member[pos]*10000; \ +} + + case COMBODD: + GET_COMBO_VAR(data, "Screen->ComboD") break; + + case COMBOCD: + GET_COMBO_VAR(cset, "Screen->ComboC") break; + + case COMBOFD: + GET_COMBO_VAR(sflag, "Screen->ComboF") break; + +#define GET_COMBO_VAR_BUF(member, str) \ +{ \ + int pos = ri->d[0] / 10000; \ + if(BC::checkComboPos(pos, str) != SH::_NoError) \ + ret = -10000; \ + else \ + ret = combobuf[tmpscr->data[pos]].member * 10000; \ +} + + case COMBOTD: + GET_COMBO_VAR_BUF(type, "Screen->ComboT") break; + + case COMBOID: + GET_COMBO_VAR_BUF(flag, "Screen->ComboI") break; + + case COMBOSD: + { + int pos = ri->d[0] / 10000; + + if(BC::checkComboPos(pos, "Screen->ComboS") != SH::_NoError) + ret = -10000; + else + ret = (combobuf[tmpscr->data[pos]].walk & 0xF) * 10000; + } + break; + +///----------------------------------------------------------------------------------------------------// +//Game->GetComboX + case COMBODDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && mdata[pos]*10000; + else if(layr>-1) + ret=tmpscr2[layr].data[pos]*10000; + else ret=TheMaps[scr].data[pos]*10000; + } + else + ret = 10000; + } + break; + + case COMBOCDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && mcset[pos]*10000; + else if(layr>-1) + ret=tmpscr2[layr].cset[pos]*10000; + else ret=TheMaps[scr].cset[pos]*10000; + } + else + ret = 10000; + } + break; + + case COMBOFDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && msflag[pos]*10000; + else if(layr>-1) + ret=tmpscr2[layr].sflag[pos]*10000; + else ret=TheMaps[scr].sflag[pos]*10000; + } + else + ret = 10000; + } + break; + + case COMBOTDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && mdata[pos]].type*10000; + else if(layr>-1) + ret=combobuf[tmpscr2[layr].data[pos]].type*10000; + else ret=combobuf[ + TheMaps[scr].data[pos]].type*10000; + } + else + ret = 10000; + } + break; + + case COMBOIDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && mdata[pos]].flag*10000; + else if(layr>-1) + ret=combobuf[tmpscr2[layr].data[pos]].flag*10000; + else ret=combobuf[TheMaps[scr].data[pos]].flag*10000; + } + else + ret = 10000; + } + break; + + case COMBOSDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos>=0 && pos<176 && + scr>=0 && scr=0 && mdata[pos]].walk&15)*10000; + else if(layr>-1) + ret=(combobuf[tmpscr2[layr].data[pos]].walk&15)*10000; + else ret=(combobuf[TheMaps[scr].data[pos]].walk&15)*10000; + } + else + ret = 10000; + } + break; + +///----------------------------------------------------------------------------------------------------// +//Screen Information + case SDD: + { + int di = ((get_currdmap())<<7) + get_currscr()-(DMaps[get_currdmap()].type==dmOVERW ? 0 : DMaps[get_currdmap()].xoff); + ret=get_screen_d(di, ri->d[0]/10000); + } + break; + + case SDDD: + ret=get_screen_d((ri->d[0])/10000 + ((get_currdmap())<<7), ri->d[1] / 10000); + break; + + case SDDDD: + ret=get_screen_d(ri->d[1] / 10000 + ((ri->d[0]/10000)<<7), ri->d[2] / 10000); + break; + + case SCRDOORD: + ret=tmpscr->door[ri->d[0]/10000]*10000; + break; + + case LIT: + ret= darkroom ? 0 : 10000; + break; + + case WAVY: + ret = wavy*10000; + break; + + case QUAKE: + ret = quakeclk*10000; + break; + + case SCREENFLAGSD: + ret = get_screenflags(tmpscr,vbound(ri->d[0] / 10000,0,9)); + break; + + case SCREENEFLAGSD: + ret = get_screeneflags(tmpscr,vbound(ri->d[0] / 10000,0,2)); + break; + + case NPCCOUNT: + ret = guys.Count()*10000; + break; + + case ROOMDATA: + ret = tmpscr->catchall*10000; + break; + + case ROOMTYPE: + ret = tmpscr->room*10000; + break; + + case PUSHBLOCKX: + ret = blockmoving ? int(mblock2.x)*10000 : -10000; + break; + + case PUSHBLOCKY: + ret = blockmoving ? int(mblock2.y)*10000 : -10000; + break; + + case PUSHBLOCKCOMBO: + ret = mblock2.bcombo*10000; + break; + + case PUSHBLOCKCSET: + ret = mblock2.cs*10000; + break; + + case UNDERCOMBO: + ret = tmpscr->undercombo*10000; + break; + + case UNDERCSET: + ret = tmpscr->undercset*10000; + break; + +///----------------------------------------------------------------------------------------------------// +//Misc./Internal + case REFFFC: + ret = ri->ffcref * 10000; + break; + + case REFITEM: + ret = ri->itemref; + break; + + case REFITEMCLASS: + ret = ri->idata; + break; + + case REFLWPN: + ret = ri->lwpn; + break; + + case REFEWPN: + ret = ri->ewpn; + break; + + case REFNPC: + ret = ri->guyref; + break; + + case SP: + ret = ri->sp * 10000; + break; + + case SCRIPTRAM: + case GLOBALRAM: + ret = ArrayH::getElement(ri->d[0] / 10000, ri->d[1] / 10000); + break; + + case SCRIPTRAMD: + case GLOBALRAMD: + ret = ArrayH::getElement(ri->d[0] / 10000, 0); + break; + + case GDD://Doesn't work like this =( + ret = game->global_d[ri->d[0] / 10000]; + break; + +///----------------------------------------------------------------------------------------------------// +//Most of this is deprecated I believe ~Joe123 + default: + { + if(arg >= REG_D(0) && arg <= REG_D(7)) ret = ri->d[arg - REG_D(0)]; + else if(arg >= REG_A(0) && arg <= REG_A(1)) ret = ri->a[arg - REG_A(0)]; + else if(arg >= GD(0) && arg <= GD(255)) ret = game->global_d[arg - GD(0)]; + + break; + } + } + + return ret; +} + + + +void set_register(const long arg, const long value) +{ + + switch(arg) + { +///----------------------------------------------------------------------------------------------------// +//FFC Variables + case DATA: + tmpscr->ffcs[ri->ffcref].data = vbound(value/10000,0,MAXCOMBOS-1); + break; + + case FFSCRIPT: + for(long i = 1; i < MAX_ZCARRAY_SIZE; i++) + { + if(arrayOwner[i]==ri->ffcref) + deallocateArray(i); + } + + tmpscr->ffcs[ri->ffcref].script = vbound(value/10000, 0, NUMSCRIPTFFC-1); + + for(int i=0; i<16; i++) + tmpscr->ffcs[ri->ffcref].misc[i] = 0; + + for(int i=0; i<2; i++) + tmpscr->ffcs[ri->ffcref].inita[i] = 0; + + for(int i=0; i<8; i++) + tmpscr->ffcs[ri->ffcref].initd[i] = 0; + + tmpscr->ffcs[ri->ffcref].scriptData.Clear(); + tmpscr->ffcs[ri->ffcref].initialized = false; + break; + + case FCSET: + tmpscr->ffcs[ri->ffcref].cset = (value/10000)&15; + break; + + case DELAY: + tmpscr->ffcs[ri->ffcref].delay = value/10000; + break; + + case FX: + tmpscr->ffcs[ri->ffcref].x = value; + break; + + case FY: + tmpscr->ffcs[ri->ffcref].y=value; + break; + + case XD: + tmpscr->ffcs[ri->ffcref].xVel=value; + break; + + case YD: + tmpscr->ffcs[ri->ffcref].yVel=value; + break; + + case XD2: + tmpscr->ffcs[ri->ffcref].xAccel=value; + break; + + case YD2: + tmpscr->ffcs[ri->ffcref].yAccel=value; + break; + + case FFFLAGSD: + value ? tmpscr->ffcs[ri->ffcref].flags |= 1<<((ri->d[0])/10000) + : tmpscr->ffcs[ri->ffcref].flags &= ~(1<<((ri->d[0])/10000)); + break; + + case FFCWIDTH: + tmpscr->ffcs[ri->ffcref].setEffectWidth(vbound(value/10000, 1, 64)); + break; + + case FFCHEIGHT: + tmpscr->ffcs[ri->ffcref].setEffectHeight(vbound(value/10000, 1, 64)); + break; + + case FFTWIDTH: + tmpscr->ffcs[ri->ffcref].setTileWidth(vbound(value/10000, 1, 4)); + break; + + case FFTHEIGHT: + tmpscr->ffcs[ri->ffcref].setTileHeight(vbound(value/10000, 1, 4)); + break; + + case FFLINK: + (tmpscr->ffcs[ri->ffcref].link)=vbound(value/10000, 1, 32); // Shouldn't 0 be allowed...? + break; + + case FFMISCD: + { + int a = vbound(ri->d[0]/10000,0,15); + (tmpscr->ffcs[ri->ffcref].misc[a])=value; + break; + } + + case FFINITDD: + (tmpscr->ffcs[ri->ffcref].initd[vbound(ri->d[0]/10000,0,7)])=value; + break; + + +///----------------------------------------------------------------------------------------------------// +//Link's Variables + case LINKX: + linkIF.setX(value/10000); + break; + + case LINKY: + linkIF.setY(value/10000); + break; + + case LINKZ: + linkIF.setZ(value/10000); + break; + + case LINKJUMP: + linkIF.setJump(fix((value * (100.0)) / 10000.0)); + break; + + case LINKDIR: + { + //Link.setDir() calls reset_hookshot(), which removes the sword sprite.. O_o + //if(Link.getAction() == attacking) Link.dir = (value/10000); + //else Link.setDir(value/10000); + + // Meh, let it. It'll get fixed later. + linkIF.setDir(value/10000); + + break; + } + + case LINKHITDIR: + Link.setHitDir(value / 10000); + break; + + case LINKHP: + game->set_life(zc_max(0, zc_min(value/10000,game->get_maxlife()))); + break; + + case LINKMP: + game->set_magic(zc_max(0, zc_min(value/10000,game->get_maxmagic()))); + break; + + case LINKMAXHP: + game->set_maxlife(value/10000); + break; + + case LINKMAXMP: + game->set_maxmagic(value/10000); + break; + + case LINKACTION: + linkIF.setAction((actiontype)(value/10000)); + break; + + case LINKHELD: + Link.setHeldItem(vbound(value/10000,0,MAXITEMS-1)); + break; + + case LINKITEMD: + { + int itemID=vbound(ri->d[0]/10000,0,MAXITEMS-1); + + // If the Cane of Byrna is being removed, cancel its effect. + if(value==0 && itemID==current_item_id(itype_cbyrna)) + stopCaneOfByrna(); + + game->set_item(itemID,(value != 0)); + + //resetItems(game); - Is this really necessary? ~Joe123 + if((get_bit(quest_rules,qr_OVERWORLDTUNIC) != 0) || (currscr<128 || dlevel)) ringcolor(false); + } + break; + + /*case LINKEQUIP: + { + + int setb = ((value/10000)&0xFF00)>>8, seta = (value/10000)&0xFF; + if(seta && get_bit(quest_rules,qr_SELECTAWPN) && game->item[seta]){ + + } + if(setb && game->item[setb]){ + } + } + break;*/ + case LINKINVIS: + Link.setDontDraw(value/10000); + break; + + case LINKINVINC: + Link.scriptcoldet=(value/10000); + break; + + case LINKSWORDJINX: + Link.setSwordClk(value/10000); + break; + + case LINKITEMJINX: + Link.setItemClk(value/10000); + break; + + case LINKDRUNK: + Link.setDrunkClock(value/10000); + break; + + case LINKMISCD: + Link.miscellaneous[vbound(ri->d[0]/10000,0,15)] = value; + break; + + case LINKHXOFS: + (Link.hxofs)=(fix)(value/10000); + break; + + case LINKHYOFS: + (Link.hyofs)=(fix)(value/10000); + break; + + case LINKXOFS: + (Link.xofs)=(fix)(value/10000); + break; + + case LINKYOFS: + (Link.yofs)=(fix)(value/10000)+playing_field_offset; + break; + + case LINKZOFS: + (Link.zofs)=(fix)(value/10000); + break; + + case LINKHXSZ: + (Link.hxsz)=(fix)(value/10000); + break; + + case LINKHYSZ: + (Link.hysz)=(fix)(value/10000); + break; + + case LINKHZSZ: + (Link.hzsz)=(fix)(value/10000); + break; + + case LINKTXSZ: + (Link.txsz)=(fix)(value/10000); + break; + + case LINKTYSZ: + (Link.tysz)=(fix)(value/10000); + break; + + case LINKTILE: + (Link.tile)=(fix)(value/10000); + break; + + case LINKFLIP: + (Link.flip)=(fix)(value/10000); + break; + +///----------------------------------------------------------------------------------------------------// +//Input States + case INPUTSTART: + control_state[6]=((value/10000)!=0)?true:false; + break; + + case INPUTMAP: + control_state[9]=((value/10000)!=0)?true:false; + break; + + case INPUTUP: + control_state[0]=((value/10000)!=0)?true:false; + break; + + case INPUTDOWN: + control_state[1]=((value/10000)!=0)?true:false; + break; + + case INPUTLEFT: + control_state[2]=((value/10000)!=0)?true:false; + break; + + case INPUTRIGHT: + control_state[3]=((value/10000)!=0)?true:false; + break; + + case INPUTA: + control_state[4]=((value/10000)!=0)?true:false; + break; + + case INPUTB: + control_state[5]=((value/10000)!=0)?true:false; + break; + + case INPUTL: + control_state[7]=((value/10000)!=0)?true:false; + break; + + case INPUTR: + control_state[8]=((value/10000)!=0)?true:false; + break; + + case INPUTEX1: + control_state[10]=((value/10000)!=0)?true:false; + break; + + case INPUTEX2: + control_state[11]=((value/10000)!=0)?true:false; + break; + + case INPUTEX3: + control_state[12]=((value/10000)!=0)?true:false; + break; + + case INPUTEX4: + control_state[13]=((value/10000)!=0)?true:false; + break; + + case INPUTAXISUP: + control_state[14]=((value/10000)!=0)?true:false; + break; + + case INPUTAXISDOWN: + control_state[15]=((value/10000)!=0)?true:false; + break; + + case INPUTAXISLEFT: + control_state[16]=((value/10000)!=0)?true:false; + break; + + case INPUTAXISRIGHT: + control_state[17]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSSTART: + button_press[6]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSMAP: + button_press[9]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSUP: + button_press[0]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSDOWN: + button_press[1]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSLEFT: + button_press[2]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSRIGHT: + button_press[3]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSA: + button_press[4]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSB: + button_press[5]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSL: + button_press[7]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSR: + button_press[8]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSEX1: + button_press[10]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSEX2: + button_press[11]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSEX3: + button_press[12]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSEX4: + button_press[13]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSAXISUP: + button_press[14]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSAXISDOWN: + button_press[15]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSAXISLEFT: + button_press[16]=((value/10000)!=0)?true:false; + break; + + case INPUTPRESSAXISRIGHT: + button_press[17]=((value/10000)!=0)?true:false; + break; + + case INPUTMOUSEX: + { + int leftOffset=(resx/2)-(128*screen_scale); + position_mouse((value/10000)*screen_scale+leftOffset, gui_mouse_y()); + break; + } + + case INPUTMOUSEY: + { + int topOffset=(resy/2)-((112-playing_field_offset)*screen_scale); + position_mouse(gui_mouse_x(), (value/10000)*screen_scale+topOffset); + break; + } + + case INPUTMOUSEZ: + position_mouse_z(value/10000); + break; + +///----------------------------------------------------------------------------------------------------// +//Item Variables + case ITEMX: + if(0!=(s=checkItem(ri->itemref))) + { + (s->x)=(fix)(value/10000); + + // Move the Fairy enemy as well. + if(itemsbuf[((item*)(s))->id].family==itype_fairy && itemsbuf[((item*)(s))->id].misc3) + movefairy2(((item*)(s))->x,((item*)(s))->y,((item*)(s))->misc); + } + + break; + + case ITEMY: + if(0!=(s=checkItem(ri->itemref))) + { + (s->y)=(fix)(value/10000); + + // Move the Fairy enemy as well. + if(itemsbuf[((item*)(s))->id].family==itype_fairy && itemsbuf[((item*)(s))->id].misc3) + movefairy2(((item*)(s))->x,((item*)(s))->y,((item*)(s))->misc); + } + + break; + + case ITEMZ: + if(0!=(s=checkItem(ri->itemref))) + { + (s->z)=(fix)(value/10000); + + if(s->z < 0) + s->z = 0; + } + + break; + + case ITEMJUMP: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->fall)=-value*100.0/10000.0; + } + + break; + + case ITEMDRAWTYPE: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->drawstyle)=value/10000; + } + + break; + + case ITEMID: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->id)=value/10000; + flushItemCache(); + } + + break; + + case ITEMTILE: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->tile)=vbound(value/10000,0,NEWMAXTILES-1); + } + + break; + + case ITEMOTILE: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->o_tile)=vbound(value/10000,0,NEWMAXTILES-1); + } + + break; + + case ITEMCSET: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->o_cset) = (((item *)s)->o_cset & ~15) | ((value/10000)&15); + (((item *)s)->cs) = (((item *)s)->o_cset & 15); + } + + break; + + case ITEMFLASHCSET: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->o_cset) = ((value/10000)<<4) | (((item *)s)->o_cset & 15); + } + + break; + + case ITEMFRAMES: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->frames)=value/10000; + } + + break; + + case ITEMFRAME: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->aframe)=value/10000; + } + + break; + + case ITEMASPEED: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->o_speed)=value/10000; + } + + break; + + case ITEMDELAY: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->o_delay)=value/10000; + } + + break; + + case ITEMFLIP: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->flip)=value/10000; + } + + break; + + case ITEMFLASH: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->flash)= (value/10000)?1:0; + } + + break; + + case ITEMEXTEND: + if(0!=(s=checkItem(ri->itemref))) + { + (((item *)s)->extend)=value/10000; + } + + break; + + case ITEMHXOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->hxofs=value/10000; + } + + break; + + case ITEMHYOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->hyofs=value/10000; + } + + break; + + case ITEMXOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->xofs=(fix)(value/10000); + } + + break; + + case ITEMYOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->yofs=(fix)(value/10000)+playing_field_offset; + } + + break; + + case ITEMZOFS: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->zofs=(fix)(value/10000); + } + + break; + + case ITEMHXSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->hxsz=value/10000; + } + + break; + + case ITEMHYSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->hysz=value/10000; + } + + break; + + case ITEMHZSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->hzsz=value/10000; + } + + break; + + case ITEMTXSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->txsz=vbound((value/10000),1,20); + } + + break; + + case ITEMTYSZ: + if(0!=(s=checkItem(ri->itemref))) + { + ((item*)(s))->tysz=vbound((value/10000),1,20); + } + + break; + + case ITEMPICKUP: + if(0!=(s=checkItem(ri->itemref))) + { + int newpickup = value/10000; + // Values that the questmaker should not use, ever + newpickup &= ~(ipBIGRANGE | ipCHECK | ipMONEY | ipBIGTRI | ipNODRAW | ipFADE); + + // If making an item timeout, set its timer + if(newpickup & ipFADE) + { + (((item*)(s))->clk2) = 512; + } + + // If making it a carried item, + // alter hasitem and set an itemguy. + if((((item*)(s))->pickup & ipENEMY) < (newpickup & ipENEMY)) + { + hasitem |= 2; + bool hasitemguy = false; + + for(int i=0; iitemguy) + { + hasitemguy = true; + } + } + + if(!hasitemguy && guys.Count()>0) + { + ((enemy*)guys.spr(guys.Count()-1))->itemguy = true; + } + } + // If unmaking it a carried item, + // alter hasitem if there are no more carried items. + else if((((item*)(s))->pickup & ipENEMY) > (newpickup & ipENEMY)) + { + // Move it back onscreen! + if(get_bit(quest_rules,qr_HIDECARRIEDITEMS)) + { + for(int i=0; iitemguy) + { + ((item*)(s))->x = ((enemy*)guys.spr(i))->x; + ((item*)(s))->y = ((enemy*)guys.spr(i))->y; + ((item*)(s))->z = ((enemy*)guys.spr(i))->z; + break; + } + } + } + + if(more_carried_items()<=1) // 1 includes this own item. + { + hasitem &= ~2; + } + } + + ((item*)(s))->pickup=value/10000; + } + + break; + + case ITEMMISCD: + if(0!=(s=checkItem(ri->itemref))) + { + int a = vbound(ri->d[0]/10000,0,15); + (((item*)(s))->miscellaneous[a])=value; + } + + break; + +///----------------------------------------------------------------------------------------------------// +//Itemdata Variables + case IDATAFAMILY: + (itemsbuf[ri->idata].family)=value/10000; + flushItemCache(); + break; + + case IDATALEVEL: + (itemsbuf[ri->idata].fam_type)=value/10000; + flushItemCache(); + break; + + case IDATAKEEP: + (itemsbuf[ri->idata].flags)|=(value/10000)?ITEM_GAMEDATA:0; + break; + + case IDATAAMOUNT: + (itemsbuf[ri->idata].amount)=value/10000; + break; + + case IDATASETMAX: + (itemsbuf[ri->idata].setmax)=value/10000; + break; + + case IDATAMAX: + (itemsbuf[ri->idata].max)=value/10000; + break; + + case IDATAPOWER: + (itemsbuf[ri->idata].power)=value/10000; + break; + + case IDATACOUNTER: + (itemsbuf[ri->idata].count)=value/10000; + break; + + case IDATAUSESOUND: + (itemsbuf[ri->idata].usesound)=value/10000; + break; + + case IDATAINITDD: + { + int a = ri->d[0] / 10000; + + if(BC::checkBounds(a, 0, 7, "itemdata->InitD") == SH::_NoError) + itemsbuf[ri->idata].initiald[a] = value; + } + break; + +///----------------------------------------------------------------------------------------------------// +//LWeapon Variables + case LWPNX: + if(0!=(s=checkLWpn(ri->lwpn,"X"))) + ((weapon*)s)->x=(fix)(value/10000); + + break; + + case LWPNY: + if(0!=(s=checkLWpn(ri->lwpn,"Y"))) + ((weapon*)s)->y=(fix)(value/10000); + + break; + + case LWPNZ: + if(0!=(s=checkLWpn(ri->lwpn,"Z"))) + ((weapon*)s)->z=zc_max((fix)(value/10000),(fix)0); + + break; + + case LWPNJUMP: + if(0!=(s=checkLWpn(ri->lwpn,"Jump"))) + ((weapon*)s)->fall=((-value*100.0)/10000.0); + + break; + + case LWPNDIR: + if(0!=(s=checkLWpn(ri->lwpn,"Dir"))) + ((weapon*)s)->dir=(value/10000); + + break; + + case LWPNSTEP: + if(0!=(s=checkLWpn(ri->lwpn,"Step"))) + ((weapon*)s)->step=(value/10000)/100.0; + + break; + + case LWPNANGLE: + if(0!=(s=checkLWpn(ri->lwpn,"Angle"))) + ((weapon*)s)->angle=(double)(value/10000.0); + + break; + + case LWPNANGULAR: + if(0!=(s=checkLWpn(ri->lwpn,"Angular"))) + ((weapon*)s)->angular=(value/10000) != 0; + + break; + + case LWPNBEHIND: + if(0!=(s=checkLWpn(ri->lwpn,"Behind"))) + ((weapon*)s)->behind=(value/10000) != 0; + + break; + + case LWPNDRAWTYPE: + if(0!=(s=checkLWpn(ri->lwpn,"DrawStyle"))) + ((weapon*)s)->drawstyle=(value/10000); + + break; + + case LWPNPOWER: + if(0!=(s=checkLWpn(ri->lwpn,"Damage"))) + ((weapon*)s)->power=(value/10000); + + break; + + case LWPNDEAD: + if(0!=(s=checkLWpn(ri->lwpn,"DeadState"))) + ((weapon*)s)->dead=(value/10000); + + break; + + case LWPNID: + if(0!=(s=checkLWpn(ri->lwpn,"ID"))) + ((weapon*)s)->id=(value/10000); + + break; + + case LWPNTILE: + if(0!=(s=checkLWpn(ri->lwpn,"Tile"))) + ((weapon*)s)->tile=(value/10000); + + break; + + case LWPNCSET: + if(0!=(s=checkLWpn(ri->lwpn,"CSet"))) + ((weapon*)s)->cs=(value/10000)&15; + + break; + + case LWPNFLASHCSET: + if(0!=(s=checkLWpn(ri->lwpn,"FlashCSet"))) + (((weapon*)s)->o_cset)|=(value/10000)<<4; + + break; + + case LWPNFRAMES: + if(0!=(s=checkLWpn(ri->lwpn,"NumFrames"))) + ((weapon*)s)->frames=(value/10000); + + break; + + case LWPNFRAME: + if(0!=(s=checkLWpn(ri->lwpn,"Frame"))) + ((weapon*)s)->aframe=(value/10000); + + break; + + case LWPNASPEED: + if(0!=(s=checkLWpn(ri->lwpn,"ASpeed"))) + ((weapon*)s)->o_speed=(value/10000); + + break; + + case LWPNFLASH: + if(0!=(s=checkLWpn(ri->lwpn,"Flash"))) + ((weapon*)s)->flash=(value/10000); + + break; + + case LWPNFLIP: + if(0!=(s=checkLWpn(ri->lwpn,"Flip"))) + ((weapon*)s)->flip=(value/10000); + + break; + + case LWPNEXTEND: + if(0!=(s=checkLWpn(ri->lwpn,"Extend"))) + ((weapon*)s)->extend=(value/10000); + + break; + + case LWPNOTILE: + if(0!=(s=checkLWpn(ri->lwpn,"OriginalTile"))) + ((weapon*)s)->o_tile=(value/10000); + + break; + + case LWPNOCSET: + if(0!=(s=checkLWpn(ri->lwpn,"OriginalCSet"))) + (((weapon*)s)->o_cset)|=(value/10000)&15; + + break; + + case LWPNHXOFS: + if(0!=(s=checkLWpn(ri->lwpn,"HitXOffset"))) + (((weapon*)s)->hxofs)=(value/10000); + + break; + + case LWPNHYOFS: + if(0!=(s=checkLWpn(ri->lwpn,"HitYOffset"))) + (((weapon*)s)->hyofs)=(value/10000); + + break; + + case LWPNXOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawXOffset"))) + (((weapon*)s)->xofs)=(fix)(value/10000); + + break; + + case LWPNYOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawYOffset"))) + (((weapon*)s)->yofs)=(fix)(value/10000)+playing_field_offset; + + break; + + case LWPNZOFS: + if(0!=(s=checkLWpn(ri->lwpn,"DrawZOffset"))) + (((weapon*)s)->zofs)=(fix)(value/10000); + + break; + + case LWPNHXSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitWidth"))) + (((weapon*)s)->hxsz)=(value/10000); + + break; + + case LWPNHYSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitHeight"))) + (((weapon*)s)->hysz)=(value/10000); + + break; + + case LWPNHZSZ: + if(0!=(s=checkLWpn(ri->lwpn,"HitZHeight"))) + (((weapon*)s)->hzsz)=(value/10000); + + break; + + case LWPNTXSZ: + if(0!=(s=checkLWpn(ri->lwpn,"TileWidth"))) + (((weapon*)s)->txsz)=vbound((value/10000),1,20); + + break; + + case LWPNTYSZ: + if(0!=(s=checkLWpn(ri->lwpn,"TileHeight"))) + (((weapon*)s)->tysz)=vbound((value/10000),1,20); + + break; + + case LWPNMISCD: + if(0!=(s=checkLWpn(ri->lwpn,"Misc"))) + { + int a = vbound(ri->d[0]/10000,0,15); + (((weapon*)(s))->miscellaneous[a])=value; + } + + break; + + case LWPNCOLLDET: + if(0!=(s=checkLWpn(ri->lwpn,"CollDetection"))) + (((weapon*)(s))->scriptcoldet)=value/10000; + + break; + +///----------------------------------------------------------------------------------------------------// +//EWeapon Variables + case EWPNX: + if(0!=(s=checkEWpn(ri->ewpn,"X"))) + ((weapon*)s)->x=(fix)(value/10000); + + break; + + case EWPNY: + if(0!=(s=checkEWpn(ri->ewpn,"Y"))) + ((weapon*)s)->y=(fix)(value/10000); + + break; + + case EWPNZ: + if(0!=(s=checkEWpn(ri->ewpn,"Z"))) + ((weapon*)s)->z=zc_max((fix)(value/10000),(fix)0); + + break; + + case EWPNJUMP: + if(0!=(s=checkEWpn(ri->ewpn,"Jump"))) + ((weapon*)s)->fall=(-value*100.0/10000.0); + + break; + + case EWPNDIR: + if(0!=(s=checkEWpn(ri->ewpn,"Dir"))) + ((weapon*)s)->dir=(value/10000); + + break; + + case EWPNSTEP: + if(0!=(s=checkEWpn(ri->ewpn,"Step"))) + ((weapon*)s)->step=(value/10000)/100.0; + + break; + + case EWPNANGLE: + if(0!=(s=checkEWpn(ri->ewpn,"Angle"))) + ((weapon*)s)->angle=(double)(value/10000.0); + + break; + + case EWPNANGULAR: + if(0!=(s=checkEWpn(ri->ewpn,"Angular"))) + ((weapon*)s)->angular=(value/10000) != 0; + + break; + + case EWPNBEHIND: + if(0!=(s=checkEWpn(ri->ewpn,"Behind"))) + ((weapon*)s)->behind=(value/10000) != 0; + + break; + + case EWPNDRAWTYPE: + if(0!=(s=checkEWpn(ri->ewpn,"DrawStyle"))) + ((weapon*)s)->drawstyle=(value/10000); + + break; + + case EWPNPOWER: + if(0!=(s=checkEWpn(ri->ewpn,"Damage"))) + ((weapon*)s)->power=(value/10000); + + break; + + case EWPNDEAD: + if(0!=(s=checkEWpn(ri->ewpn,"DeadState"))) + ((weapon*)s)->dead=(value/10000); + + break; + + case EWPNID: + if(0!=(s=checkEWpn(ri->ewpn,"ID"))) + ((weapon*)s)->id=(value/10000); + + break; + + case EWPNTILE: + if(0!=(s=checkEWpn(ri->ewpn,"Tile"))) + ((weapon*)s)->tile=(value/10000); + + break; + + case EWPNCSET: + if(0!=(s=checkEWpn(ri->ewpn,"CSet"))) + ((weapon*)s)->cs=(value/10000)&15; + + break; + + case EWPNFLASHCSET: + if(0!=(s=checkEWpn(ri->ewpn,"FlashCSet"))) + (((weapon*)s)->o_cset)|=(value/10000)<<4; + + break; + + case EWPNFRAMES: + if(0!=(s=checkEWpn(ri->ewpn,"NumFrames"))) + ((weapon*)s)->frames=(value/10000); + + break; + + case EWPNFRAME: + if(0!=(s=checkEWpn(ri->ewpn,"Frame"))) + ((weapon*)s)->aframe=(value/10000); + + break; + + case EWPNASPEED: + if(0!=(s=checkEWpn(ri->ewpn,"ASpeed"))) + ((weapon*)s)->o_speed=(value/10000); + + break; + + case EWPNFLASH: + if(0!=(s=checkEWpn(ri->ewpn,"Flash"))) + ((weapon*)s)->flash=(value/10000); + + break; + + case EWPNFLIP: + if(0!=(s=checkEWpn(ri->ewpn,"Flip"))) + ((weapon*)s)->flip=(value/10000); + + break; + + case EWPNEXTEND: + if(0!=(s=checkEWpn(ri->ewpn,"Extend"))) + ((weapon*)s)->extend=(value/10000); + + break; + + case EWPNOTILE: + if(0!=(s=checkEWpn(ri->ewpn,"OriginalTile"))) + ((weapon*)s)->o_tile=(value/10000); + + break; + + case EWPNOCSET: + if(0!=(s=checkEWpn(ri->ewpn,"OriginalCSet"))) + (((weapon*)s)->o_cset)|=(value/10000)&15; + + break; + + case EWPNHXOFS: + if(0!=(s=checkEWpn(ri->ewpn,"HitXOffset"))) + (((weapon*)s)->hxofs)=(value/10000); + + break; + + case EWPNHYOFS: + if(0!=(s=checkEWpn(ri->ewpn,"HitYOffset"))) + (((weapon*)s)->hyofs)=(value/10000); + + break; + + case EWPNXOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawXOffset"))) + (((weapon*)s)->xofs)=(fix)(value/10000); + + break; + + case EWPNYOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawYOffset"))) + (((weapon*)s)->yofs)=(fix)(value/10000)+playing_field_offset; + + break; + + case EWPNZOFS: + if(0!=(s=checkEWpn(ri->ewpn,"DrawZOffset"))) + (((weapon*)s)->zofs)=(fix)(value/10000); + + break; + + case EWPNHXSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitWidth"))) + (((weapon*)s)->hxsz)=(value/10000); + + break; + + case EWPNHYSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitHeight"))) + (((weapon*)s)->hysz)=(value/10000); + + break; + + case EWPNHZSZ: + if(0!=(s=checkEWpn(ri->ewpn,"HitZHeight"))) + (((weapon*)s)->hzsz)=(value/10000); + + break; + + case EWPNTXSZ: + if(0!=(s=checkEWpn(ri->ewpn,"TileWidth"))) + (((weapon*)s)->txsz)=vbound((value/10000),1,20); + + break; + + case EWPNTYSZ: + if(0!=(s=checkEWpn(ri->ewpn,"TileHeight"))) + (((weapon*)s)->tysz)=vbound((value/10000),1,20); + + break; + + case EWPNMISCD: + if(0!=(s=checkEWpn(ri->ewpn,"Misc"))) + { + int a = vbound(ri->d[0]/10000,0,15); + (((weapon*)(s))->miscellaneous[a])=value; + } + + break; + + case EWPNCOLLDET: + if(0!=(s=checkEWpn(ri->ewpn,"CollDetection"))) + (((weapon*)(s))->scriptcoldet)=value/10000; + + break; + +///----------------------------------------------------------------------------------------------------// +//NPC Variables + +//Fixs are all a bit different + case NPCX: + { + if(GuyH::loadNPC(ri->guyref, "npc->X") == SH::_NoError) + { + GuyH::getNPC()->x = fix(value / 10000); + + if(GuyH::hasLink()) + Link.setX(fix(value / 10000)); + } + } + break; + + case NPCY: + { + if(GuyH::loadNPC(ri->guyref, "npc->Y") == SH::_NoError) + { + fix oldy = GuyH::getNPC()->y; + GuyH::getNPC()->y = fix(value / 10000); + GuyH::getNPC()->floor_y += ((value / 10000) - oldy); + + if(GuyH::hasLink()) + Link.setY(fix(value / 10000)); + } + } + break; + + case NPCZ: + { + if(GuyH::loadNPC(ri->guyref, "npc->Z") == SH::_NoError) + { + if(!never_in_air(GuyH::getNPC()->id)) + { + if(value < 0) + GuyH::getNPC()->z = fix(0); + else + GuyH::getNPC()->z = fix(value / 10000); + + if(GuyH::hasLink()) + Link.setZ(fix(value / 10000)); + } + } + } + break; + + case NPCJUMP: + { + if(GuyH::loadNPC(ri->guyref, "npc->Jump") == SH::_NoError) + { + if(canfall(GuyH::getNPC()->id)) + GuyH::getNPC()->fall = -fix(value * 100.0 / 10000.0); + + if(GuyH::hasLink()) + linkIF.setJump(-value / fix(10000.0)); + } + } + break; + + case NPCSTEP: + { + if(GuyH::loadNPC(ri->guyref, "npc->Step") == SH::_NoError) + GuyH::getNPC()->step = fix(value / 10000) / fix(100.0); + } + break; + + case NPCXOFS: + { + if(GuyH::loadNPC(ri->guyref, "npc->DrawXOffset") == SH::_NoError) + GuyH::getNPC()->xofs = fix(value / 10000); + } + break; + + case NPCYOFS: + { + if(GuyH::loadNPC(ri->guyref, "npc->DrawYOffset") == SH::_NoError) + GuyH::getNPC()->yofs = fix(value / 10000) + playing_field_offset; + } + break; + + case NPCZOFS: + { + if(GuyH::loadNPC(ri->guyref, "npc->DrawZOffset") == SH::_NoError) + GuyH::getNPC()->zofs = fix(value / 10000); + } + break; + +#define SET_NPC_VAR_INT(member, str) \ +{ \ +if(GuyH::loadNPC(ri->guyref, str) == SH::_NoError) \ + GuyH::getNPC()->member = value / 10000; \ +} + + case NPCDIR: + SET_NPC_VAR_INT(dir, "npc->Dir") break; + + case NPCRATE: + SET_NPC_VAR_INT(rate, "npc->Rate") break; + + case NPCHOMING: + SET_NPC_VAR_INT(homing, "npc->Homing") break; + + case NPCFRAMERATE: + SET_NPC_VAR_INT(frate, "npc->ASpeed") break; + + case NPCHALTRATE: + SET_NPC_VAR_INT(hrate, "npc->HaltRate") break; + + case NPCDRAWTYPE: + SET_NPC_VAR_INT(drawstyle, "npc->DrawStyle") break; + + case NPCHP: + SET_NPC_VAR_INT(hp, "npc->HP") break; + + //case NPCID: SET_NPC_VAR_INT(id, "npc->ID") break; ~Disallowed + case NPCDP: + SET_NPC_VAR_INT(dp, "npc->Damage") break; + + case NPCWDP: + SET_NPC_VAR_INT(wdp, "npc->WeaponDamage") break; + + case NPCITEMSET: + SET_NPC_VAR_INT(item_set, "npc->ItemSet") break; + + case NPCBOSSPAL: + SET_NPC_VAR_INT(bosspal, "npc->BossPal") break; + + case NPCBGSFX: + if(GuyH::loadNPC(ri->guyref, "npc->SFX") == SH::_NoError) + { + enemy *en=GuyH::getNPC(); + int newSFX = value / 10000; + en->setBGSFX(sfxMgr.getSFX(newSFX)); + } + + break; + + case NPCEXTEND: + SET_NPC_VAR_INT(extend, "npc->Extend") break; + + case NPCHXOFS: + SET_NPC_VAR_INT(hxofs, "npc->HitXOffset") break; + + case NPCHYOFS: + SET_NPC_VAR_INT(hyofs, "npc->HitYOffset") break; + + case NPCHXSZ: + SET_NPC_VAR_INT(hxsz, "npc->HitWidth") break; + + case NPCHYSZ: + SET_NPC_VAR_INT(hysz, "npc->HitHeight") break; + + case NPCHZSZ: + SET_NPC_VAR_INT(hzsz, "npc->HitZHeight") break; + + case NPCCOLLDET: + SET_NPC_VAR_INT(scriptcoldet, "npc->CollDetection") break; + + case NPCSTUN: + SET_NPC_VAR_INT(stunclk, "npc->Stun") break; + + case NPCHUNGER: + SET_NPC_VAR_INT(grumble, "npc->Hunger") break; + + case NPCCSET: + { + if(GuyH::loadNPC(ri->guyref, "npc->CSet") == SH::_NoError) + GuyH::getNPC()->cs = (value / 10000) & 0xF; + } + break; + +//Bounds on value + case NPCTXSZ: + { + long height = value / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->TileWidth") == SH::_NoError && + BC::checkBounds(height, 0, 20, "npc->TileWidth") == SH::_NoError) + GuyH::getNPC()->txsz = height; + } + break; + + case NPCTYSZ: + { + long width = value / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->TileHeight") == SH::_NoError && + BC::checkBounds(width, 0, 20, "npc->TileHeight") == SH::_NoError) + GuyH::getNPC()->tysz = width; + } + break; + + case NPCOTILE: + { + long tile = value / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->OriginalTile") == SH::_NoError && + BC::checkTile(tile, "npc->OriginalTile") == SH::_NoError) + GuyH::getNPC()->o_tile = tile; + } + break; + + case NPCTILE: + { + long tile = value / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Tile") == SH::_NoError && + BC::checkTile(tile, "npc->Tile") == SH::_NoError) + GuyH::getNPC()->tile = tile; + } + break; + + case NPCWEAPON: + { + long weapon = value / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Weapon") == SH::_NoError && + BC::checkBounds(weapon, 0, MAXWPNS-1, "npc->Weapon") == SH::_NoError) + GuyH::getNPC()->wpn = weapon; + } + break; + +//Indexed + case NPCDEFENSED: + { + long a = ri->d[0] / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Defense") == SH::_NoError && + BC::checkBounds(a, 0, edefSCRIPT, "npc->Defense") == SH::_NoError) + GuyH::getNPC()->defense[a] = value / 10000; + } + break; + + case NPCMISCD: + { + long a = ri->d[0] / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->Misc") == SH::_NoError && + BC::checkMisc(a, "npc->Misc") == SH::_NoError) + GuyH::getNPC()->miscellaneous[a] = value; + + } + + break; + +///----------------------------------------------------------------------------------------------------// +//Game Information + case GAMEDEATHS: + game->set_deaths(value/10000); + break; + + case GAMECHEAT: + game->set_cheat(value/10000); + cheat=(value/10000); + break; + + case GAMETIME: + game->set_time(value); + break; // Can't multiply by 10000 or the maximum result is too big + + case GAMETIMEVALID: + game->set_timevalid((value/10000)?1:0); + break; + + case GAMEHASPLAYED: + game->set_hasplayed((value/10000)?1:0); + break; + + case GAMEGUYCOUNT: + { + int mi2 = (currmap*MAPSCRSNORMAL)+(ri->d[0]/10000); + game->guys[mi2]=value/10000; + } + break; + + case GAMECONTSCR: + game->set_continue_scrn(value/10000); + break; + + case GAMECONTDMAP: + game->set_continue_dmap(value/10000); + break; + + case GAMEENTRSCR: + lastentrance=value/10000; + break; + + case GAMEENTRDMAP: + lastentrance_dmap=value/10000; + break; + + case GAMECOUNTERD: + game->set_counter(value/10000, (ri->d[0])/10000); + break; + + case GAMEMCOUNTERD: + game->set_maxcounter(value/10000, (ri->d[0])/10000); + break; + + case GAMEDCOUNTERD: + game->set_dcounter(value/10000, (ri->d[0])/10000); + break; + + case GAMEGENERICD: + game->set_generic(value/10000, (ri->d[0])/10000); + break; + + case GAMEITEMSD: + game->set_item((ri->d[0])/10000,(value!=0)); + break; + + case GAMELITEMSD: + game->lvlitems[(ri->d[0])/10000]=value/10000; + break; + + case GAMELKEYSD: + game->lvlkeys[(ri->d[0])/10000]=value/10000; + break; + + case SCREENSTATED: + { + int mi2 = (currmap*MAPSCRSNORMAL)+currscr; + (value)?setmapflag(mi2, 1<<((ri->d[0])/10000)) : unsetmapflag(mi2, 1 << ((ri->d[0]) / 10000)); + } + break; + + case SCREENSTATEDD: + { + int mi2 = ri->d[0]/10000; + mi2 -= 8*(mi2/MAPSCRS); + + if(BC::checkMapID(mi2>>7, "Game->SetScreenState") == SH::_NoError) + (value)?setmapflag(mi2, 1<<(ri->d[1]/10000)) : unsetmapflag(mi2, 1 << (ri->d[1] / 10000), true); + } + break; + + case GAMEGUYCOUNTD: + game->guys[(currmap*MAPSCRSNORMAL)+(ri->d[0]/10000)] = value / 10000; + break; + + case GAMECLICKFREEZE: + disableClickToFreeze=value==0; + break; + +///----------------------------------------------------------------------------------------------------// +//DMap Information + +#define SET_DMAP_VAR(member, str) \ +{ \ + int ID = ri->d[0] / 10000; \ + if(BC::checkDMapID(ID, str) == SH::_NoError) \ + DMaps[ID].member = value / 10000; \ +} + + case DMAPFLAGSD: + SET_DMAP_VAR(flags, "Game->DMapFlags") break; + + case DMAPLEVELD: + SET_DMAP_VAR(level, "Game->DMapLevel") break; + + case DMAPCOMPASSD: + SET_DMAP_VAR(compass, "Game->DMapCompass") break; + + case DMAPCONTINUED: + SET_DMAP_VAR(cont, "Game->DMapContinue") break; + + case DMAPMIDID: + { + int ID = ri->d[0] / 10000; + + if(BC::checkDMapID(ID, "Game->DMapMIDI") == SH::_NoError) + { + // Based on play_DmapMusic + switch(value / 10000) + { + case -6: + DMaps[ID].midi = 2; + break; // Dungeon + + case -3: + DMaps[ID].midi = 3; + break; // Level 9 + + case -2: + DMaps[ID].midi = 1; + break; // Overworld + + case 0: + DMaps[ID].midi = 0; + break; // None + + default: + DMaps[ID].midi = value / 10000 + 3; + } + } + + break; + } + +///----------------------------------------------------------------------------------------------------// +//Screen->ComboX + case COMBODD: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + { + screen_combo_modify_preroutine(tmpscr,pos); + tmpscr->data[pos]=(value/10000); + screen_combo_modify_postroutine(tmpscr,pos); + } + } + break; + + case COMBOCD: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + { + screen_combo_modify_preroutine(tmpscr,pos); + tmpscr->cset[pos]=(value/10000)&15; + screen_combo_modify_postroutine(tmpscr,pos); + } + } + break; + + case COMBOFD: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + tmpscr->sflag[pos]=(value/10000); + } + break; + + case COMBOTD: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + { + // Preprocess each instance of the combo on the screen + for(int i = 0; i < 176; i++) + { + if(tmpscr->data[i] == tmpscr->data[pos]) + { + screen_combo_modify_preroutine(tmpscr,i); + } + } + + combobuf[tmpscr->data[pos]].type=value/10000; + + for(int i = 0; i < 176; i++) + { + if(tmpscr->data[i] == tmpscr->data[pos]) + { + screen_combo_modify_postroutine(tmpscr,i); + } + } + } + } + break; + + case COMBOID: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + combobuf[tmpscr->data[pos]].flag=value/10000; + } + break; + + case COMBOSD: + { + int pos = (ri->d[0])/10000; + + if(pos >= 0 && pos < 176) + combobuf[tmpscr->data[pos]].walk=(value/10000)&15; + } + break; + +///----------------------------------------------------------------------------------------------------// +//Game->SetComboX + case COMBODDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + if(scr==(currmap*MAPSCRS+currscr)) + screen_combo_modify_preroutine(tmpscr,pos); + + TheMaps[scr].data[pos]=value/10000; + + if(scr==(currmap*MAPSCRS+currscr)) + { + tmpscr->data[pos] = value/10000; + screen_combo_modify_postroutine(tmpscr,pos); + } + + int layr = whichlayer(scr); + + if(layr>-1) + { + //if (layr==(currmap*MAPSCRS+currscr)) + // screen_combo_modify_preroutine(tmpscr,pos); + tmpscr2[layr].data[pos]=value/10000; + //if (layr==(currmap*MAPSCRS+currscr)) + // screen_combo_modify_postroutine(tmpscr,pos); + } + } + break; + + case COMBOCDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + TheMaps[scr].cset[pos]=(value/10000)&15; + + if(scr==(currmap*MAPSCRS+currscr)) + tmpscr->cset[pos] = value/10000; + + int layr = whichlayer(scr); + + if(layr>-1) + tmpscr2[layr].cset[pos]=(value/10000)&15; + } + break; + + case COMBOFDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + TheMaps[scr].sflag[pos]=value/10000; + + if(scr==(currmap*MAPSCRS+currscr)) + tmpscr->sflag[pos] = value/10000; + + int layr = whichlayer(scr); + + if(layr>-1) + tmpscr2[layr].sflag[pos]=value/10000; + } + break; + + case COMBOTDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + int cdata = TheMaps[scr].data[pos]; + + // Preprocess the screen's combos in case the combo changed is present on the screen. -L + for(int i = 0; i < 176; i++) + { + if(tmpscr->data[i] == cdata) + { + screen_combo_modify_preroutine(tmpscr,i); + } + } + + combobuf[cdata].type=value/10000; + + for(int i = 0; i < 176; i++) + { + if(tmpscr->data[i] == cdata) + { + screen_combo_modify_postroutine(tmpscr,i); + } + } + } + break; + + case COMBOIDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + combobuf[TheMaps[scr].data[pos]].flag=value/10000; + } + break; + + case COMBOSDM: + { + int pos = (ri->d[0])/10000; + int sc = (ri->d[2]/10000); + int m = (ri->d[1]/10000)-1; + long scr = m*MAPSCRS+sc; + + if(pos<0 || pos>=176 || + scr<0 || scr>=MAPSCRS || + m<0 || m>=map_count) + break; + + combobuf[TheMaps[scr].data[pos]].walk=(value/10000)&15; + } + break; + +///----------------------------------------------------------------------------------------------------// +//Screen Variables + case SDD: + { + { + int di2 = ((get_currdmap())<<7) + get_currscr()-(DMaps[get_currdmap()].type==dmOVERW ? 0 : DMaps[get_currdmap()].xoff); + set_screen_d(di2, ri->d[0]/10000, value); + break; + } + } + + case GDD: + al_trace("GDD"); + game->global_d[ri->d[0]/10000]=value; + break; + + case SDDD: + set_screen_d((ri->d[0])/10000 + ((get_currdmap())<<7), ri->d[1]/10000, value); + break; + + case SDDDD: + set_screen_d(ri->d[1]/10000 + ((ri->d[0]/10000)<<7), ri->d[2]/10000, value); + break; + + case SCRDOORD: + tmpscr->door[ri->d[0]/10000]=value/10000; + putdoor(scrollbuf,0,ri->d[0]/10000,value/10000,true,true); + break; + + case LIT: + naturaldark = !value; + lighting(false, false); + break; + + case WAVY: + wavy=value/10000; + break; + + case QUAKE: + quakeclk=value/10000; + break; + + //case ROOMTYPE: + // tmpscr->room=value/10000; break; //this probably doesn't work too well... + case ROOMDATA: + tmpscr->catchall=value/10000; + break; + + case PUSHBLOCKCOMBO: + mblock2.bcombo=value/10000; + break; + + case PUSHBLOCKCSET: + mblock2.cs=value/10000; + mblock2.oldcset=value/10000; + break; + + case UNDERCOMBO: + tmpscr->undercombo=value/10000; + break; + + case UNDERCSET: + tmpscr->undercset=value/10000; + break; + +///----------------------------------------------------------------------------------------------------// +//Misc./Internal + case SP: + ri->sp = value / 10000; + break; + + case SCRIPTRAM: + case GLOBALRAM: + ArrayH::setElement(ri->d[0] / 10000, ri->d[1] / 10000, value); + break; + + case SCRIPTRAMD: + case GLOBALRAMD: + ArrayH::setElement(ri->d[0] / 10000, 0, value); + break; + + case REFFFC: + ri->ffcref = value / 10000; + break; + + case REFITEM: + ri->itemref = value; + break; + + case REFITEMCLASS: + ri->idata = value; + break; + + case REFLWPN: + ri->lwpn = value; + break; + + case REFEWPN: + ri->ewpn = value; + break; + + case REFNPC: + ri->guyref = value; + break; + + default: + { + if(arg >= REG_D(0) && arg <= REG_D(7)) ri->d[arg - REG_D(0)] = value; + else if(arg >= REG_A(0) && arg <= REG_A(1)) ri->a[arg - REG_A(0)] = value; + else if(arg >= GD(0) && arg <= GD(255)) game->global_d[arg-GD(0)] = value; + + break; + } + } +} + +///----------------------------------------------------------------------------------------------------// +// ASM Functions // +///----------------------------------------------------------------------------------------------------// + + +///----------------------------------------------------------------------------------------------------// +//Internal (to ZScript) + +void do_set(const bool v, byte whichFFC) +{ + // Trying to change the current script? + // -Checking for a ffc here is slow. Any way to make this go away? + if(sarg1==FFSCRIPT && ri->ffcref==whichFFC) + return; + + long temp = SH::get_arg(sarg2, v); + set_register(sarg1, temp); +} + +void do_push(const bool v) +{ + const long value = SH::get_arg(sarg1, v); + ri->sp--; + SH::write_stack(ri->sp, value); +} + +void do_pop() +{ + const long value = SH::read_stack(ri->sp); + ri->sp++; + set_register(sarg1, value); +} + +void do_loadi() +{ + const long stackoffset = get_register(sarg2) / 10000; + const long value = SH::read_stack(stackoffset); + set_register(sarg1, value); +} + +void do_storei() +{ + const long stackoffset = get_register(sarg2) / 10000; + const long value = get_register(sarg1); + SH::write_stack(stackoffset, value); +} + +void do_enqueue(const bool) +{ +} +void do_dequeue(const bool) +{ +} + +void do_comp(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + if(temp2 >= temp) ri->scriptflag |= MOREFLAG; + else ri->scriptflag &= ~MOREFLAG; + + if(temp2 == temp) ri->scriptflag |= TRUEFLAG; + else ri->scriptflag &= ~TRUEFLAG; +} + +void do_allocatemem(const bool v, const bool local, const byte i) +{ + const long size = SH::get_arg(sarg2, v) / 10000; + dword ptrval; + + if(size <= 0) + { + Z_scripterrlog("Array initialized to invalid size of %d\n", size); + set_register(sarg1, 0); //Pass back NULL + return; + } + + if(local) + { + //localRAM[0] is used as an invalid container, so 0 can be the NULL pointer in ZScript + for(ptrval = 1; localRAM[ptrval].Size() != 0; ptrval++) ; + + if(ptrval >= MAX_ZCARRAY_SIZE) + { + Z_scripterrlog("%d local arrays already in use, no more can be allocated\n", MAX_ZCARRAY_SIZE-1); + ptrval = 0; + } + else + { + ZScriptArray &a = localRAM[ptrval]; //marginally faster for large arrays if we use a reference + + a.Resize(size); + + for(dword j = 0; j < (dword)size; j++) + a[j] = 0; //initialize array + + // Keep track of which FFC created the array so we know which to deallocate when changing screens + arrayOwner[ptrval]=i; + } + } + else + { + //Globals are only allocated here at first play, otherwise in init_game + for(ptrval = 0; game->globalRAM[ptrval].Size() != 0; ptrval++) ; + + if(ptrval >= game->globalRAM.size()) + { + al_trace("Invalid pointer value of %ld passed to global allocate\n", ptrval); + //this shouldn't happen, unless people are putting ALLOCATEGMEM in their ZASM scripts where they shouldn't be + } + + ZScriptArray &a = game->globalRAM[ptrval]; + + a.Resize(size); + + for(dword j = 0; j < (dword)size; j++) + a[j] = 0; + + ptrval += MAX_ZCARRAY_SIZE; //so each pointer has a unique value + } + + + set_register(sarg1, ptrval * 10000); + + // If this happens once per frame, it can drown out every other message. -L + /*Z_eventlog("Allocated %s array of size %d, pointer address %ld\n", + local ? "local": "global", size, ptrval);*/ +} + +void do_deallocatemem() +{ + const long ptrval = get_register(sarg1) / 10000; + + deallocateArray(ptrval); +} + +void do_loada(const byte a) +{ + if(ri->a[a] == 0) + { + Z_eventlog("Global scripts currently have no A registers\n"); + return; + } + + long ffcref = (ri->a[a] / 10000) - 1; //FFC 2 + + if(BC::checkFFC(ffcref, "LOAD%i") != SH::_NoError) + return; + + long reg = get_register(sarg2); //Register in FFC 2 + + if(reg >= REG_D(0) || reg <= REG_D(7)) + set_register(sarg1, tmpscr->ffcs[ffcref].scriptData.d[reg - REG_D(0)]); //get back the info into *sarg1 + else if(reg == REG_A(0) || reg == REG_A(1)) + set_register(sarg1, tmpscr->ffcs[ffcref].scriptData.a[reg - REG_A(0)]); + else if(reg == SP) + set_register(sarg1, tmpscr->ffcs[ffcref].scriptData.sp * 10000); + + //Can get everything else using REFFFC +} + +void do_seta(const byte a) +{ + if(ri->a[a] == 0) + { + Z_eventlog("Global scripts currently have no A registers\n"); + return; + } + + long ffcref = (ri->a[a] / 10000) - 1; //FFC 2 + + if(BC::checkFFC(ffcref, "SETA%i") != SH::_NoError) + return; + + long reg = get_register(sarg2); //Register in FFC 2 + + if(reg >= REG_D(0) || reg <= REG_D(7)) + tmpscr->ffcs[ffcref].scriptData.d[reg - REG_D(0)] = get_register(sarg1); //Set it to *sarg1 + else if(reg == REG_A(0) || reg == REG_A(1)) + tmpscr->ffcs[ffcref].scriptData.a[reg - REG_A(0)] = get_register(sarg1); + else if(reg == SP) + tmpscr->ffcs[ffcref].scriptData.sp = get_register(sarg1) / 10000; +} + +///----------------------------------------------------------------------------------------------------// +//Mathematical + +void do_add(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + set_register(sarg1, temp2 + temp); +} + +void do_sub(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + set_register(sarg1, temp2 - temp); +} + +void do_mult(const bool v) +{ + long long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + set_register(sarg1, long((temp * temp2) / 10000)); +} + +void do_div(const bool v) +{ + long long temp = SH::get_arg(sarg2, v); + long long temp2 = get_register(sarg1); + + if(temp == 0) + { + Z_scripterrlog("Script attempted to divide %ld by zero!\n", temp2); + set_register(sarg1, long(sign(temp2) * LONG_MAX)); + } + else + { + set_register(sarg1, long((temp2 * 10000) / temp)); + } +} + +void do_mod(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + if(temp == 0) + { + Z_scripterrlog("Script attempted to modulo %ld by zero!\n",temp2); + temp = 1; + } + + set_register(sarg1, temp2 % temp); +} + +void do_trig(const bool v, const byte type) +{ + double rangle = (SH::get_arg(sarg2, v) / 10000.0) * PI / 180.0; + + switch(type) + { + case 0: + set_register(sarg1, long(sin(rangle) * 10000.0)); + break; + + case 1: + set_register(sarg1, long(cos(rangle) * 10000.0)); + break; + + case 2: + set_register(sarg1, long(tan(rangle) * 10000.0)); + break; + } +} + +void do_asin(const bool v) +{ + double temp = double(SH::get_arg(sarg2, v)) / 10000.0; + + if(temp >= -1 && temp <= 1) + set_register(sarg1, long(asin(temp) * 10000.0)); + else + { + Z_scripterrlog("Script attempted to pass %ld into ArcSin!\n",temp); + set_register(sarg1, -10000); + } +} + +void do_acos(const bool v) +{ + double temp = double(SH::get_arg(sarg2, v)) / 10000.0; + + if(temp >= -1 && temp <= 1) + set_register(sarg1, long(acos(temp) * 10000.0)); + else + { + Z_scripterrlog("Script attempted to pass %ld into ArcCos!\n",temp); + set_register(sarg1, -10000); + } +} + +void do_arctan() +{ + double xpos = ri->d[0] / 10000.0; + double ypos = ri->d[1] / 10000.0; + + set_register(sarg1, long(atan2(ypos, xpos) * 10000.0)); +} + +void do_abs(const bool v) +{ + long temp = SH::get_arg(sarg1, v); + set_register(sarg1, abs(temp)); +} + +void do_log10(const bool v) +{ + double temp = double(SH::get_arg(sarg1, v)) / 10000.0; + + if(temp > 0) + set_register(sarg1, long(log10(temp) * 10000.0)); + else if(temp == 0) + { + Z_eventlog("Script tried to calculate log of 0\n"); + set_register(sarg1, -LONG_MAX); + } + else + { + Z_eventlog("Script tried to calculate log of %f\n", temp / 10000.0); + set_register(sarg1, 0); + } +} + +void do_naturallog(const bool v) +{ + double temp = double(SH::get_arg(sarg1, v)) / 10000.0; + + if(temp > 0) + set_register(sarg1, long(log(temp) * 10000.0)); + else if(temp == 0) + { + Z_eventlog("Script tried to calculate ln of 0\n"); + set_register(sarg1, -LONG_MAX); + } + else + { + Z_eventlog("Script tried to calculate ln of %f\n", temp / 10000.0); + set_register(sarg1, 0); + } +} + +void do_min(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + set_register(sarg1, zc_min(temp2, temp)); +} + +void do_max(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + long temp2 = get_register(sarg1); + + set_register(sarg1, zc_max(temp2, temp)); +} + + +void do_rnd(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + + if(temp > 0) + set_register(sarg1, (rand() % temp) * 10000); + else if(temp < 0) + set_register(sarg1, (rand() % (-temp)) * -10000); + else + set_register(sarg1, 0); // Just return 0. (Do not log an error) +} + +void do_factorial(const bool v) +{ + long temp; + + if(v) + return; //must factorial a register, not a value (why is this exactly? ~Joe123) + else + { + temp = get_register(sarg1) / 10000; + + if(temp < 2) + { + set_register(sarg1, temp >= 0 ? 10000 : 00000); + return; + } + } + + long temp2 = 1; + + for(long temp3 = temp; temp > 1; temp--) + temp2 *= temp3; + + set_register(sarg1, temp2 * 10000); +} + +void do_power(const bool v) +{ + double temp = double(SH::get_arg(sarg2, v)) / 10000.0; + double temp2 = double(get_register(sarg1)) / 10000.0; + + if(temp == 0 && temp2 == 0) + { + Z_scripterrlog("Script attempted to calculate 0 to the power 0!\n"); + set_register(sarg1, 1); + return; + } + + set_register(sarg1, long(pow(temp2, temp) * 10000.0)); +} + +void do_ipower(const bool v) +{ + double temp = 10000.0 / double(SH::get_arg(sarg2, v)); + double temp2 = double(get_register(sarg1)) / 10000.0; + + if(temp == 0 && temp2 == 0) + { + Z_scripterrlog("Script attempted to calculate 0 to the power 0!\n"); + set_register(sarg1, 1); + return; + } + + set_register(sarg1, long(pow(temp2, temp) * 10000.0)); +} + +void do_sqroot(const bool v) +{ + double temp = double(SH::get_arg(sarg2, v)) / 10000.0; + + if(temp < 0) + { + Z_scripterrlog("Script attempted to calculate square root of %ld!\n", temp); + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, long(sqrt(temp) * 10000.0)); +} + +///----------------------------------------------------------------------------------------------------// +//Bitwise + +void do_and(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (temp2 & temp) * 10000); +} + +void do_or(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (temp2 | temp) * 10000); +} + +void do_xor(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (temp2 ^ temp) * 10000); +} + +void do_nand(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (~(temp2 & temp)) * 10000); +} + +void do_nor(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (~(temp2 | temp)) * 10000); +} + +void do_xnor(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (~(temp2 ^ temp)) * 10000); +} + +void do_not(const bool v) +{ + long temp = SH::get_arg(sarg2, v); + set_register(sarg1, !temp); +} + +void do_bitwisenot(const bool v) +{ + long temp = SH::get_arg(sarg1, v) / 10000; + set_register(sarg1, (~temp) * 10000); +} + +void do_lshift(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (temp2 << temp) * 10000); +} + +void do_rshift(const bool v) +{ + long temp = SH::get_arg(sarg2, v) / 10000; + long temp2 = get_register(sarg1) / 10000; + set_register(sarg1, (temp2 >> temp) * 10000); +} + +///----------------------------------------------------------------------------------------------------// +//Gameplay functions + +void do_warp(bool v, bool pit) +{ + linkIF.warp(SH::get_arg(sarg1, v)/10000, SH::get_arg(sarg2, v)/10000, pit); +} + +void do_breakshield() +{ + long UID = get_register(sarg1); + + for(int j = 0; j < guys.Count(); j++) + if(guys.spr(j)->getUID() == UID) + { + ((enemy*)guys.spr(j))->break_shield(); + return; + } +} + +void do_showsavescreen() +{ + bool saved = save_game(false, 0); + set_register(sarg1, saved ? 10000 : 0); +} + +void do_selectweapon(bool v, bool Abtn) +{ + if(Abtn && !get_bit(quest_rules,qr_SELECTAWPN)) + return; + + byte dir=(byte)(SH::get_arg(sarg1, v)/10000); + + // Selection directions don't match the normal ones... + switch(dir) + { + case 0: + dir=SEL_UP; + break; + + case 1: + dir=SEL_DOWN; + break; + + case 2: + dir=SEL_LEFT; + break; + + case 3: + dir=SEL_RIGHT; + break; + + default: + return; + } + + if(Abtn) + selectNextAWpn(dir); + else + selectNextBWpn(dir); +} + +///----------------------------------------------------------------------------------------------------// +//Screen Information + +void do_issolid() +{ + int x = int(ri->d[0] / 10000); + int y = int(ri->d[1] / 10000); + + set_register(sarg1, (_walkflag(x, y, 1) ? 10000 : 0)); +} + +void do_setsidewarp() +{ + long warp = SH::read_stack(ri->sp + 3) / 10000; + long scrn = SH::read_stack(ri->sp + 2) / 10000; + long dmap = SH::read_stack(ri->sp + 1) / 10000; + long type = SH::read_stack(ri->sp + 0) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->SetSideWarp") != SH::_NoError || + BC::checkBounds(scrn, -1, 0x87, "Screen->SetSideWarp") != SH::_NoError || + BC::checkBounds(dmap, -1, MAXDMAPS - 1, "Screen->SetSideWarp") != SH::_NoError || + BC::checkBounds(type, -1, wtMAX - 1, "Screen->SetSideWarp") != SH::_NoError) + return; + + if(scrn > -1) + tmpscr->sidewarpscr[warp] = scrn; + + if(dmap > -1) + tmpscr->sidewarpdmap[warp] = dmap; + + if(type > -1) + tmpscr->sidewarptype[warp] = type; +} + +void do_settilewarp() +{ + long warp = SH::read_stack(ri->sp + 3) / 10000; + long scrn = SH::read_stack(ri->sp + 2) / 10000; + long dmap = SH::read_stack(ri->sp + 1) / 10000; + long type = SH::read_stack(ri->sp + 0) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->SetTileWarp") != SH::_NoError || + BC::checkBounds(scrn, -1, 0x87, "Screen->SetTileWarp") != SH::_NoError || + BC::checkBounds(dmap, -1, MAXDMAPS - 1, "Screen->SetTileWarp") != SH::_NoError || + BC::checkBounds(type, -1, wtMAX - 1, "Screen->SetTileWarp") != SH::_NoError) + return; + + if(scrn > -1) + tmpscr->tilewarpscr[warp] = scrn; + + if(dmap > -1) + tmpscr->tilewarpdmap[warp] = dmap; + + if(type > -1) + tmpscr->tilewarptype[warp] = type; +} + +void do_getsidewarpdmap(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetSideWarpDMap") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->sidewarpdmap[warp]*10000); +} + +void do_getsidewarpscr(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetSideWarpScreen") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->sidewarpscr[warp]*10000); +} + +void do_getsidewarptype(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetSideWarpType") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->sidewarptype[warp]*10000); +} + +void do_gettilewarpdmap(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetTileWarpDMap") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->tilewarpdmap[warp]*10000); +} + +void do_gettilewarpscr(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetTileWarpScreen") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->tilewarpscr[warp]*10000); +} + +void do_gettilewarptype(const bool v) +{ + long warp = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(warp, -1, 3, "Screen->GetTileWarpType") != SH::_NoError) + { + set_register(sarg1, -10000); + return; + } + + set_register(sarg1, tmpscr->tilewarptype[warp]*10000); +} + +void do_layerscreen() +{ + long layer = (get_register(sarg2) / 10000) - 1; + + if(BC::checkBounds(layer, 0, 5, "Screen->LayerScreen") != SH::_NoError || + tmpscr->layermap[layer] == 0) + set_register(sarg1, -10000); + else + set_register(sarg1, tmpscr->layerscreen[layer] * 10000); +} + +void do_layermap() +{ + long layer = (get_register(sarg2) / 10000) - 1; + + if(BC::checkBounds(layer, 0, 5, "Screen->LayerMap") != SH::_NoError || + tmpscr->layermap[layer] == 0) + set_register(sarg1, -10000); + else + set_register(sarg1, tmpscr->layermap[layer] * 10000); +} + +void do_triggersecrets() +{ + hidden_entrance(0, true, false, -4); +} + +void do_getscreenflags() +{ + long map = (ri->d[2] / 10000) - 1; + long scrn = ri->d[1] / 10000; + long flagset = ri->d[0] / 10000; + + if(BC::checkMapID(map, "Game->GetScreenFlags") != SH::_NoError || + BC::checkBounds(scrn, 0, 0x87, "Game->GetScreenFlags") != SH::_NoError || + BC::checkBounds(flagset, 0, 9, "Game->GetScreenFlags") != SH::_NoError) + return; + + set_register(sarg1, get_screenflags(&TheMaps[map * MAPSCRS + scrn], flagset)); +} + +void do_getscreeneflags() +{ + long map = (ri->d[2] / 10000) - 1; + long scrn = ri->d[1] / 10000; + long flagset = ri->d[0] / 10000; + + if(BC::checkMapID(map, "Game->GetScreenEFlags") != SH::_NoError || + BC::checkBounds(scrn, 0, 0x87, "Game->GetScreenEFlags") != SH::_NoError || + BC::checkBounds(flagset, 0, 9, "Game->GetScreenEFlags") != SH::_NoError) + return; + + set_register(sarg1, get_screeneflags(&TheMaps[map * MAPSCRS + scrn], flagset)); +} + +///----------------------------------------------------------------------------------------------------// +//Pointer handling + +void do_isvaliditem() +{ + long IID = get_register(sarg1); + + for(int j = 0; j < items.Count(); j++) + if(items.spr(j)->getUID() == IID) + { + set_register(sarg1, 10000); + return; + } + + set_register(sarg1, 0); +} + +void do_isvalidnpc() +{ + long UID = get_register(sarg1); + + for(int j = 0; j < guys.Count(); j++) + if(guys.spr(j)->getUID() == UID) + { + set_register(sarg1, 10000); + return; + } + + set_register(sarg1, 0); +} + +void do_isvalidlwpn() +{ + long WID = get_register(sarg1); + + for(int j = 0; j < Lwpns.Count(); j++) + if(Lwpns.spr(j)->getUID() == WID) + { + set_register(sarg1, 10000); + return; + } + + set_register(sarg1, 0); +} + +void do_isvalidewpn() +{ + long WID = get_register(sarg1); + + for(int j = 0; j < Ewpns.Count(); j++) + if(Ewpns.spr(j)->getUID() == WID) + { + set_register(sarg1, 10000); + return; + } + + set_register(sarg1, 0); +} + +void do_lwpnusesprite(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkWeaponMiscSprite(ID, "lweapon->UseSprite") != SH::_NoError) + return; + + if(LwpnH::loadWeapon(ri->lwpn, "lweapon->UseSprite") == SH::_NoError) + LwpnH::getWeapon()->LOADGFX(ID); +} + +void do_ewpnusesprite(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkWeaponMiscSprite(ID, "eweapon->UseSprite") != SH::_NoError) + return; + + if(EwpnH::loadWeapon(ri->ewpn, "eweapon->UseSprite") == SH::_NoError) + EwpnH::getWeapon()->LOADGFX(ID); +} + +void do_clearsprites(const bool v) +{ + long spritelist = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkBounds(spritelist, 0, 5, "Screen->ClearSprites") != SH::_NoError) + return; + + switch(spritelist) + { + case 0: + guys.clear(); + break; + + case 1: + items.clear(); + break; + + case 2: + Ewpns.clear(); + break; + + case 3: + Lwpns.clear(); + Link.reset_hookshot(); + break; + + case 4: + decorations.clear(); + break; + + case 5: + particles.clear(); + break; + } +} + +void do_loadlweapon(const bool v) +{ + long index = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkLWeaponIndex(index, "Screen->LoadLWeapon") != SH::_NoError) + ri->lwpn = LONG_MAX; + else + { + ri->lwpn = Lwpns.spr(index)->getUID(); + // This is too trivial to log. -L + //Z_eventlog("Script loaded lweapon with UID = %ld\n", ri->lwpn); + } +} + +void do_loadeweapon(const bool v) +{ + long index = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkEWeaponIndex(index, "Screen->LoadEWeapon") != SH::_NoError) + ri->ewpn = LONG_MAX; + else + { + ri->ewpn = Ewpns.spr(index)->getUID(); + //Z_eventlog("Script loaded eweapon with UID = %ld\n", ri->ewpn); + } +} + +void do_loaditem(const bool v) +{ + long index = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkItemIndex(index, "Screen->LoadItem") != SH::_NoError) + ri->itemref = LONG_MAX; + else + { + ri->itemref = items.spr(index)->getUID(); + //Z_eventlog("Script loaded item with UID = %ld\n", ri->itemref); + } +} + +void do_loaditemdata(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + + //I *think* this is the right check ~Joe + if(BC::checkItemID(ID, "Game->LoadItemData") != SH::_NoError) + return; + + ri->idata = ID; + //Z_eventlog("Script loaded itemdata with ID = %ld\n", ri->idata); +} + +void do_loadnpc(const bool v) +{ + long index = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkGuyIndex(index, "Screen->LoadNPC") != SH::_NoError) + ri->guyref = LONG_MAX; + else + { + ri->guyref = guys.spr(index)->getUID(); + //Z_eventlog("Script loaded NPC with UID = %ld\n", ri->guyref); + } +} + +void do_createlweapon(const bool v) +{ + const long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkWeaponID(ID, "Screen->CreateLWeapon") != SH::_NoError) + return; + + addLwpn(0, 0, 0, ID, 0, 0, 0, Link.getUID()); + + if(Lwpns.Count() < 1) + { + ri->lwpn = LONG_MAX; + Z_scripterrlog("Couldn't create lweapon %ld, screen lweapon limit reached\n", ID); + } + else + { + ri->lwpn = Lwpns.spr(Lwpns.Count() - 1)->getUID(); + Z_eventlog("Script created lweapon %ld with UID = %ld\n", ID, ri->lwpn); + } +} + +void do_createeweapon(const bool v) +{ + const long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkWeaponID(ID, "Screen->CreateEWeapon") != SH::_NoError) + return; + + if(ID>wEnemyWeapons || (ID >= wScript1 && ID <= wScript10)) + { + weapon* w=new weapon(fix(0), fix(0), fix(0), ID, 0, 0, 0, -1, -1); + Ewpns.add(w); + } + + if(Ewpns.Count() < 1) + { + ri->ewpn = LONG_MAX; + Z_scripterrlog("Couldn't create eweapon %ld, screen eweapon limit reached\n", ID); + } + else + { + ri->ewpn = Ewpns.spr(Ewpns.Count() - 1)->getUID(); + Z_eventlog("Script created eweapon %ld with UID = %ld\n", ID, ri->ewpn); + } +} + +void do_createitem(const bool v) +{ + const long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkItemID(ID, "Screen->CreateItem") != SH::_NoError) + return; + + additem(0, (get_bit(quest_rules, qr_NOITEMOFFSET) ? 1: 0), ID, ipBIGRANGE); + + if(items.Count() < 1) + { + ri->itemref = LONG_MAX; + Z_scripterrlog("Couldn't create item \"%s\", screen item limit reached\n", item_string[ID]); + } + else + { + ri->itemref = items.spr(items.Count() - 1)->getUID(); + Z_eventlog("Script created item \"%s\" with UID = %ld\n", item_string[ID], ri->itemref); + } +} + +void do_createnpc(const bool v) +{ + const long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkGuyID(ID, "Screen->CreateNPC") != SH::_NoError) + return; + + //If we make a segmented enemy there'll be more than one sprite created + word numcreated = addenemy(0, 0, ID, -10); + + if(numcreated == 0) + { + ri->guyref = LONG_MAX; + Z_scripterrlog("Couldn't create NPC \"%s\", screen NPC limit reached\n", guy_string[ID]); + } + else + { + word index = guys.Count() - numcreated; //Get the main enemy, not a segment + ri->guyref = guys.spr(index)->getUID(); + + for(; indexscript_spawned=true; + + Z_eventlog("Script created NPC \"%s\" with UID = %ld\n", guy_string[ID], ri->guyref); + } +} + +///----------------------------------------------------------------------------------------------------// +//Drawing & Sound + +void do_message(const bool v) +{ + const long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkMessage(ID, "Screen->Message") != SH::_NoError) + return; + + if(ID == 0) + { + messageMgr.clear(true); + blockpath = false; + Link.finishedmsg(); + } + else + messageMgr.showMessage(ID); +} + +INLINE void set_drawing_command_args(const int j, const word numargs) +{ + for(int k = 1; k <= numargs; k++) + script_drawing_commands[j][k] = SH::read_stack(ri->sp + (numargs - k)); +} + +void do_drawing_command(const int script_command) +{ + int j = script_drawing_commands.GetNext(); + + if(j == -1) //out of drawing command space + { + Z_scripterrlog("Max draw primitive limit reached\n"); + return; + } + + script_drawing_commands[j][0] = script_command; + script_drawing_commands[j][18] = zscriptDrawingRenderTarget->GetCurrentRenderTarget(); // no fixed bs. + + switch(script_command) + { + case RECTR: + set_drawing_command_args(j, 12); + break; + + case CIRCLER: + set_drawing_command_args(j, 11); + break; + + case ARCR: + set_drawing_command_args(j, 14); + break; + + case ELLIPSER: + set_drawing_command_args(j, 12); + break; + + case LINER: + set_drawing_command_args(j, 11); + break; + + case PUTPIXELR: + set_drawing_command_args(j, 8); + break; + + case DRAWTILER: + set_drawing_command_args(j, 15); + break; + + case DRAWCOMBOR: + set_drawing_command_args(j, 16); + break; + + case FASTTILER: + set_drawing_command_args(j, 6); + break; + + case FASTCOMBOR: + set_drawing_command_args(j, 6); + break; + + case DRAWCHARR: + set_drawing_command_args(j, 10); + break; + + case DRAWINTR: + set_drawing_command_args(j, 11); + break; + + case SPLINER: + set_drawing_command_args(j, 11); + break; + + case QUADR: + set_drawing_command_args(j, 15); + break; + + case TRIANGLER: + set_drawing_command_args(j, 13); + break; + + case BITMAPR: + set_drawing_command_args(j, 12); + break; + + case DRAWLAYERR: + set_drawing_command_args(j, 8); + break; + + case DRAWSCREENR: + set_drawing_command_args(j, 6); + break; + + case QUAD3DR: + { + std::vector *v = script_drawing_commands.GetVector(); + v->resize(26, 0); + + long* pos = &v->at(0); + long* uv = &v->at(12); + long* col = &v->at(20); + long* size = &v->at(24); + + set_drawing_command_args(j, 8); + ArrayH::getValues(script_drawing_commands[j][2] / 10000, pos, 12); + ArrayH::getValues(script_drawing_commands[j][3] / 10000, uv, 8); + ArrayH::getValues(script_drawing_commands[j][4] / 10000, col, 4); + ArrayH::getValues(script_drawing_commands[j][5] / 10000, size, 2); + + script_drawing_commands[j].SetVector(v); + } + break; + + case TRIANGLE3DR: + { + std::vector *v = script_drawing_commands.GetVector(); + v->resize(20, 0); + + long* pos = &v->at(0); + long* uv = &v->at(9); + long* col = &v->at(15); + long* size = &v->at(18); + + set_drawing_command_args(j, 8); + ArrayH::getValues(script_drawing_commands[j][2] / 10000, pos, 8); + ArrayH::getValues(script_drawing_commands[j][3] / 10000, uv, 6); + ArrayH::getValues(script_drawing_commands[j][4] / 10000, col, 3); + ArrayH::getValues(script_drawing_commands[j][5] / 10000, size, 2); + + script_drawing_commands[j].SetVector(v); + } + break; + + case DRAWSTRINGR: + { + set_drawing_command_args(j, 9); + // Unused + //const int index = script_drawing_commands[j][19] = j; + + string *str = script_drawing_commands.GetString(); + ArrayH::getString(script_drawing_commands[j][8] / 10000, *str); + script_drawing_commands[j].SetString(str); + } + break; + } +} + +void do_set_rendertarget(bool) +{ + int target = int(SH::read_stack(ri->sp) / 10000); + zscriptDrawingRenderTarget->SetCurrentRenderTarget(target); +} + +void do_sfx(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkSFXID(ID, "Game->PlaySound") != SH::_NoError) + return; + + sfxMgr.playSFX(ID); +} + +void do_midi(bool v) +{ + long MIDI = SH::get_arg(sarg1, v) / 10000; + + if(MIDI == 0) + music_stop(); + else + jukebox(MIDI + (ZC_MIDI_COUNT - 1)); +} + +void do_enh_music(bool v) +{ + long arrayptr = SH::get_arg(sarg1, v) / 10000; + long track = (SH::get_arg(sarg2, v) / 10000)-1; + + if(arrayptr == 0) + music_stop(); + else // Pointer to a string.. + { + string filename_str; + char filename_char[256]; + bool ret; + ArrayH::getString(arrayptr, filename_str, 256); + strncpy(filename_char, filename_str.c_str(), 255); + filename_char[255]='\0'; + ret=try_zcmusic(filename_char, track, -1000); + set_register(sarg2, ret ? 10000 : 0); + } +} + +void do_get_enh_music_filename(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + long arrayptr = get_register(sarg2) / 10000; + + if(BC::checkDMapID(ID, "Game->GetDMapMusicFilename") != SH::_NoError) + return; + + if(ArrayH::setArray(arrayptr, string(DMaps[ID].tmusic)) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetDMapMusicFilename' not large enough\n"); +} + +void do_get_enh_music_track(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkDMapID(ID, "Game->GetDMapMusicTrack") != SH::_NoError) + return; + + set_register(sarg1, (DMaps[ID].tmusictrack+1)*10000); +} + +void do_set_dmap_enh_music(const bool v) +{ + long ID = SH::read_stack(ri->sp + 2) / 10000; + long arrayptr = SH::read_stack(ri->sp + 1) / 10000; + long track = (SH::read_stack(ri->sp + 0) / 10000)-1; + string filename_str; + + if(BC::checkDMapID(ID, "Game->SetDMapEnhancedMusic") != SH::_NoError) + return; + + + ArrayH::getString(arrayptr, filename_str, 56); + strncpy(DMaps[ID].tmusic, filename_str.c_str(), 55); + DMaps[ID].tmusic[55]='\0'; + DMaps[ID].tmusictrack=track; +} + +///----------------------------------------------------------------------------------------------------// +//Tracing + +void do_trace(bool v) +{ + long temp = SH::get_arg(sarg1, v); + + char tmp[100]; + sprintf(tmp, (temp < 0 ? "%06ld" : "%05ld"), temp); + string s2(tmp); + s2 = s2.substr(0, s2.size() - 4) + "." + s2.substr(s2.size() - 4, 4); + al_trace("%s\n", s2.c_str()); + + if(zconsole) + printf("%s\n", s2.c_str()); +} + +void do_tracebool(const bool v) +{ + long temp = SH::get_arg(sarg1, v); + + al_trace("%s\n", temp ? "true": "false"); + + if(zconsole) + printf("%s\n", temp ? "true": "false"); +} + +void do_tracestring() +{ + long arrayptr = get_register(sarg1) / 10000; + string str; + ArrayH::getString(arrayptr, str, 512); + al_trace("%s", str.c_str()); + + if(zconsole) + printf("%s", str.c_str()); +} + +void do_tracenl() +{ + al_trace("\n"); + + if(zconsole) + printf("\n"); +} + +void do_cleartrace() +{ + zc_trace_clear(); +} + +string inttobase(word base, long x, word mindigits) +{ + static const char coeff[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + string s2; + word digits = zc_max(mindigits - 1, word(floor(log(double(x)) / log(double(base))))); + + for(int i = digits; i >= 0; i--) + { + s2 += coeff[word(floor(x / pow(double(base), i))) % base]; + } + + return s2; +} + +void do_tracetobase() +{ + long x = SH::read_stack(ri->sp + 2) / 10000; + unsigned long base = vbound(SH::read_stack(ri->sp + 1) / 10000, 2, 36); + unsigned long mindigits = zc_max(1, SH::read_stack(ri->sp) / 10000); + + string s2 = x < 0 ? "-": ""; + + switch(base) + { + case 8: + s2 += '0'; + break; + + case 16: + s2 += "0x"; + break; + } + + s2 += inttobase(base, int(fabs(double(x))), mindigits); + + switch(base) + { + case 8: + case 10: + case 16: + break; + + case 2: + s2 += 'b'; + break; + + default: + std::stringstream ss; + ss << " (Base " << base << ')'; + s2 += ss.str(); + break; + } + + al_trace("%s\n", s2.c_str()); + + if(zconsole) + printf("%s\n", s2.c_str()); +} + +///----------------------------------------------------------------------------------------------------// +//Array & string related + +void do_arraysize() +{ + long arrayptr = get_register(sarg1) / 10000; + set_register(sarg1, ArrayH::getSize(arrayptr) * 10000); +} + +void do_getsavename() +{ + long arrayptr = get_register(sarg1) / 10000; + + if(ArrayH::setArray(arrayptr, string(game->get_name())) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetSaveName' not large enough\n"); +} + +void do_setsavename() +{ + long arrayptr = get_register(sarg1) / 10000; + + string str; + ArrayH::getString(arrayptr, str); + byte j; + + for(j = 0; str[j] != '\0'; j++) + { + if(j >= 8) + { + Z_scripterrlog("String supplied to 'Game->GetSaveName' too large\n"); + break; + } + + game->get_name()[j] = str[j]; + } + + game->get_name()[j] = '\0'; +} + +void do_getmessage(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + long arrayptr = get_register(sarg2) / 10000; + + if(BC::checkMessage(ID, "Game->GetMessage") != SH::_NoError) + return; + + if(ArrayH::setArray(arrayptr, string(MsgStrings[ID].s)) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetMessage' not large enough\n"); +} + +void do_getdmapname(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + long arrayptr = get_register(sarg2) / 10000; + + if(BC::checkDMapID(ID, "Game->GetDMapName") != SH::_NoError) + return; + + if(ArrayH::setArray(arrayptr, string(DMaps[ID].name)) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetDMapName' not large enough\n"); +} + +void do_getdmaptitle(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + long arrayptr = get_register(sarg2) / 10000; + + if(BC::checkDMapID(ID, "Game->GetDMapTitle") != SH::_NoError) + return; + + if(ArrayH::setArray(arrayptr, string(DMaps[ID].title)) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetDMapTitle' not large enough\n"); +} + +void do_getdmapintro(const bool v) +{ + long ID = SH::get_arg(sarg1, v) / 10000; + long arrayptr = get_register(sarg2) / 10000; + + if(BC::checkDMapID(ID, "Game->GetDMapIntro") != SH::_NoError) + return; + + if(ArrayH::setArray(arrayptr, string(DMaps[ID].intro)) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'Game->GetDMapIntro' not large enough\n"); +} + +void do_getitemname() +{ + long arrayptr = get_register(sarg1) / 10000; + + if(ArrayH::setArray(arrayptr, item_string[ri->idata]) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'itemdata->GetName' not large enough\n"); +} + +void do_getnpcname() +{ + long arrayptr = get_register(sarg1) / 10000; + + if(GuyH::loadNPC(ri->guyref, "npc->GetName") != SH::_NoError) + return; + + word ID = (GuyH::getNPC()->id & 0xFFF); + + if(ArrayH::setArray(arrayptr, guy_string[ID]) == SH::_Overflow) + Z_scripterrlog("Array supplied to 'npc->GetName' not large enough\n"); +} + +void do_getffcscript() +{ + long arrayptr = get_register(sarg1) / 10000; + string name; + int num=-1; + ArrayH::getString(arrayptr, name, 256); // What's the limit on name length? + + for(int i=0; i<512; i++) + { + if(strcmp(name.c_str(), ffcmap[i].second.c_str())==0) + { + num=i+1; + break; + } + } + + set_register(sarg1, num * 10000); +} + +///----------------------------------------------------------------------------------------------------// +//Tile Manipulation + +void do_copytile(const bool v, const bool v2) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + long tile2 = SH::get_arg(sarg2, v2) / 10000; + + copy_tile(newtilebuf, tile, tile2, false); +} + +void do_swaptile(const bool v, const bool v2) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + long tile2 = SH::get_arg(sarg2, v2) / 10000; + + copy_tile(newtilebuf, tile, tile2, true); +} + +void do_overlaytile(const bool v, const bool v2) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + long tile2 = SH::get_arg(sarg2, v2) / 10000; + + if(BC::checkTile(tile, "OverlayTile") != SH::_NoError || + BC::checkTile(tile2, "OverlayTile") != SH::_NoError) + return; + + //Could add an arg for the CSet or something instead of just passing 0, currently only 8-bit is supported + overlay_tile(newtilebuf, tile, tile2, 0, false); +} + +void do_fliprotatetile(const bool v, const bool v2) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + long tile2 = SH::get_arg(sarg2, v2) / 10000; + + if(BC::checkTile(tile, "FlipRotateTile") != SH::_NoError || + BC::checkTile(tile2, "FlipRotateTile") != SH::_NoError) + return; + + //fliprotatetile +} + +void do_settilepixel(const bool v) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkTile(tile, "SetTilePixel") != SH::_NoError) + return; + + //settilepixel +} + +void do_gettilepixel(const bool v) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkTile(tile, "GetTilePixel") != SH::_NoError) + return; + + //gettilepixel +} + +void do_shifttile(const bool v, const bool v2) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + long tile2 = SH::get_arg(sarg2, v2) / 10000; + + if(BC::checkTile(tile, "ShiftTile") != SH::_NoError || + BC::checkTile(tile2, "ShiftTile") != SH::_NoError) + return; + + //shifttile +} + +void do_cleartile(const bool v) +{ + long tile = SH::get_arg(sarg1, v) / 10000; + + if(BC::checkTile(tile, "ClearTile") != SH::_NoError) + return; + + reset_tile(newtilebuf, tile, newtilebuf[tile].format); +} + +void do_combotile(const bool v) +{ + long combo = SH::get_arg(sarg2, v) / 10000; + + if(BC::checkCombo(combo, "Game->ComboTile") != SH::_NoError) + return; + + set_register(sarg1, combobuf[combo].tile * 10000); +} + + +///----------------------------------------------------------------------------------------------------// +// Run the script // +///----------------------------------------------------------------------------------------------------// + +INLINE void check_quit() +{ + if(key[KEY_F4] && (key[KEY_ALT] || key[KEY_ALTGR])) + { + quit_game(); + exit(101); + } +} + +// Let's do this +int run_script(const byte type, const word script, const byte i) +{ + curScriptType=type; + curScriptNum=script; + +#ifdef _SCRIPT_COUNTER + dword script_timer[NUMCOMMANDS]; + dword script_execount[NUMCOMMANDS]; + + for(int j = 0; j < NUMCOMMANDS; j++) + { + script_timer[j]=0; + script_execount[j]=0; + } + + dword start_time, end_time; + + script_counter = 0; +#endif + + switch(type) + { + case SCRIPT_FFC: + { + ri = &(tmpscr->ffcs[i].scriptData); + + curscript = ffscripts[script]; + stack = &(ffc_stack[i]); + + if(!tmpscr->ffcs[i].initialized) + { + memcpy(ri->d, tmpscr->ffcs[i].initd, 8 * sizeof(long)); + memcpy(ri->a, tmpscr->ffcs[i].inita, 2 * sizeof(long)); + } + + ri->ffcref = i; //'this' pointer + } + break; + + case SCRIPT_ITEM: + { + ri = &itemScriptData; + ri->Clear(); //Only runs for one frame so we just zero it out + + curscript = itemscripts[script]; + stack = &item_stack; + memset(stack, 0, 256 * sizeof(long)); //zero here too + + memcpy(ri->d, itemsbuf[i].initiald, 8 * sizeof(long)); + memcpy(ri->a, itemsbuf[i].initiala, 2 * sizeof(long)); + + ri->idata = i; //'this' pointer + + } + break; + + case SCRIPT_GLOBAL: + { + ri = &globalScriptData; + + curscript = globalscripts[script]; + stack = &global_stack; + } + break; + + default: + al_trace("No other scripts are currently supported\n"); + return 1; + break; + } + + dword pc = ri->pc; //this is (marginally) quicker than dereferencing ri each time + word scommand = curscript[pc].command; + sarg1 = curscript[pc].arg1; + sarg2 = curscript[pc].arg2; + + +#ifdef _FFDISSASSEMBLY + + if(scommand != 0xFFFF) + { +#ifdef _FFONESCRIPTDISSASSEMBLY + zc_trace_clear(); +#endif + + switch(type) + { + case SCRIPT_FFC: + al_trace("\nStart of FFC script %i processing on FFC %i:\n", script, i); + break; + + case SCRIPT_ITEM: + al_trace("\nStart of item script %i processing:\n", script); + break; + + case SCRIPT_GLOBAL: + al_trace("\nStart of global script %I processing:\n", script); + break; + } + } + +#endif + + bool increment = true; + + while(scommand != 0xFFFF && scommand != WAITFRAME && scommand != WAITDRAW) + { + check_quit(); + +#ifdef _FFDEBUG +#ifdef _FFDISSASSEMBLY + ffdebug::print_dissassembly(scommand); +#endif +#ifdef _SCRIPT_COUNTER + start_time = script_counter; +#endif +#endif + + switch(scommand) + { + case QUIT: + scommand = 0xFFFF; + break; + + case GOTO: + pc = sarg1; + increment = false; + break; + + case GOTOR: + { + pc = (get_register(sarg1) / 10000) - 1; + increment = false; + } + break; + + case GOTOTRUE: + if(ri->scriptflag & TRUEFLAG) + { + pc = sarg1; + increment = false; + } + + break; + + case GOTOFALSE: + if(!(ri->scriptflag & TRUEFLAG)) + { + pc = sarg1; + increment = false; + } + + break; + + case GOTOMORE: + if(ri->scriptflag & MOREFLAG) + { + pc = sarg1; + increment = false; + } + + break; + + case GOTOLESS: + if(!(ri->scriptflag & MOREFLAG) || (!get_bit(quest_rules,qr_GOTOLESSNOTEQUAL) && (ri->scriptflag & TRUEFLAG))) + { + pc = sarg1; + increment = false; + } + + break; + + case LOOP: + { + if(get_register(sarg2) > 0) + { + pc = sarg1; + increment = false; + } + else + { + set_register(sarg1, sarg1 - 1); + } + } + break; + + case SETTRUE: + set_register(sarg1, (ri->scriptflag & TRUEFLAG) ? 1 : 0); + break; + + case SETFALSE: + set_register(sarg1, (ri->scriptflag & TRUEFLAG) ? 0 : 1); + break; + + case SETMORE: + set_register(sarg1, (ri->scriptflag & MOREFLAG) ? 1 : 0); + break; + + case SETLESS: + set_register(sarg1, (!(ri->scriptflag & MOREFLAG) + || (ri->scriptflag & TRUEFLAG)) ? 1 : 0); + break; + + case NOT: + do_not(false); + break; + + case COMPAREV: + do_comp(true); + break; + + case COMPARER: + do_comp(false); + break; + + case SETV: + do_set(true, type==SCRIPT_FFC ? i : -1); + break; + + case SETR: + do_set(false, type==SCRIPT_FFC ? i : -1); + break; + + case PUSHR: + do_push(false); + break; + + case PUSHV: + do_push(true); + break; + + case POP: + do_pop(); + break; + + case LOADI: + do_loadi(); + break; + + case STOREI: + do_storei(); + break; + + case LOAD1: + do_loada(0); + break; + + case LOAD2: + do_loada(1); + break; + + case SETA1: + do_seta(0); + break; + + case SETA2: + do_seta(1); + break; + + case ALLOCATEGMEMR: + if(type == SCRIPT_GLOBAL) do_allocatemem(false, false, type==SCRIPT_FFC?i:255); + + break; + + case ALLOCATEGMEMV: + if(type == SCRIPT_GLOBAL) do_allocatemem(true, false, type==SCRIPT_FFC?i:255); + + break; + + case ALLOCATEMEMR: + do_allocatemem(false, true, type==SCRIPT_FFC?i:255); + break; + + case ALLOCATEMEMV: + do_allocatemem(true, true, type==SCRIPT_FFC?i:255); + break; + + case DEALLOCATEMEMR: + do_deallocatemem(); + break; + + case ARRAYSIZE: + do_arraysize(); + break; + + case GETFFCSCRIPT: + do_getffcscript(); + break; + + + case ADDV: + do_add(true); + break; + + case ADDR: + do_add(false); + break; + + case SUBV: + do_sub(true); + break; + + case SUBR: + do_sub(false); + break; + + case MULTV: + do_mult(true); + break; + + case MULTR: + do_mult(false); + break; + + case DIVV: + do_div(true); + break; + + case DIVR: + do_div(false); + break; + + case MODV: + do_mod(true); + break; + + case MODR: + do_mod(false); + break; + + case SINV: + do_trig(true, 0); + break; + + case SINR: + do_trig(false, 0); + break; + + case COSV: + do_trig(true, 1); + break; + + case COSR: + do_trig(false, 1); + break; + + case TANV: + do_trig(true, 2); + break; + + case TANR: + do_trig(false, 2); + break; + + case ARCSINR: + do_asin(false); + break; + + case ARCCOSR: + do_acos(false); + break; + + case ARCTANR: + do_arctan(); + break; + + case ABSR: + do_abs(false); + break; + + case MINR: + do_min(false); + break; + + case MINV: + do_min(true); + break; + + case MAXR: + do_max(false); + break; + + case MAXV: + do_max(true); + break; + + case RNDR: + do_rnd(false); + break; + + case RNDV: + do_rnd(true); + break; + + case FACTORIAL: + do_factorial(false); + break; + + case SQROOTV: + do_sqroot(true); + break; + + case SQROOTR: + do_sqroot(false); + break; + + case POWERR: + do_power(false); + break; + + case POWERV: + do_power(true); + break; + + case IPOWERR: + do_ipower(false); + break; + + case IPOWERV: + do_ipower(true); + break; + + case LOG10: + do_log10(false); + break; + + case LOGE: + do_naturallog(false); + break; + + case ANDR: + do_and(false); + break; + + case ANDV: + do_and(true); + break; + + case ORR: + do_or(false); + break; + + case ORV: + do_or(true); + break; + + case XORR: + do_xor(false); + break; + + case XORV: + do_xor(true); + break; + + case NANDR: + do_nand(false); + break; + + case NANDV: + do_nand(true); + break; + + case NORR: + do_nor(false); + break; + + case NORV: + do_nor(true); + break; + + case XNORR: + do_xnor(false); + break; + + case XNORV: + do_xnor(true); + break; + + case BITNOT: + do_bitwisenot(false); + break; + + case LSHIFTR: + do_lshift(false); + break; + + case LSHIFTV: + do_lshift(true); + break; + + case RSHIFTR: + do_rshift(false); + break; + + case RSHIFTV: + do_rshift(true); + break; + + case TRACER: + do_trace(false); + break; + + case TRACEV: + do_trace(true); + break; + + case TRACE2R: + do_tracebool(false); + break; + + case TRACE2V: + do_tracebool(true); + break; + + case TRACE3: + do_tracenl(); + break; + + case TRACE4: + do_cleartrace(); + break; + + case TRACE5: + do_tracetobase(); + break; + + case TRACE6: + do_tracestring(); + break; + + case WARP: + do_warp(true, false); + break; + + case WARPR: + do_warp(false, false); + break; + + case PITWARP: + do_warp(true, true); + break; + + case PITWARPR: + do_warp(false, true); + break; + + case BREAKSHIELD: + do_breakshield(); + break; + + case SELECTAWPNV: + do_selectweapon(true, true); + break; + + case SELECTAWPNR: + do_selectweapon(false, true); + break; + + case SELECTBWPNV: + do_selectweapon(true, false); + break; + + case SELECTBWPNR: + do_selectweapon(false, false); + break; + + case PLAYSOUNDR: + do_sfx(false); + break; + + case PLAYSOUNDV: + do_sfx(true); + break; + + case PLAYMIDIR: + do_midi(false); + break; + + case PLAYMIDIV: + do_midi(true); + break; + + case PLAYENHMUSIC: + do_enh_music(false); + break; + + case GETMUSICFILE: + do_get_enh_music_filename(false); + break; + + case GETMUSICTRACK: + do_get_enh_music_track(false); + break; + + case SETDMAPENHMUSIC: + do_set_dmap_enh_music(false); + break; + + case MSGSTRR: + do_message(false); + break; + + case MSGSTRV: + do_message(true); + break; + + case ITEMNAME: + do_getitemname(); + break; + + case NPCNAME: + do_getnpcname(); + break; + + case GETSAVENAME: + do_getsavename(); + break; + + case SETSAVENAME: + do_setsavename(); + break; + + case GETMESSAGE: + do_getmessage(false); + break; + + case GETDMAPNAME: + do_getdmapname(false); + break; + + case GETDMAPTITLE: + do_getdmaptitle(false); + break; + + case GETDMAPINTRO: + do_getdmapintro(false); + break; + + case LOADLWEAPONR: + do_loadlweapon(false); + break; + + case LOADLWEAPONV: + do_loadlweapon(true); + break; + + case LOADEWEAPONR: + do_loadeweapon(false); + break; + + case LOADEWEAPONV: + do_loadeweapon(true); + break; + + case LOADITEMR: + do_loaditem(false); + break; + + case LOADITEMV: + do_loaditem(true); + break; + + case LOADITEMDATAR: + do_loaditemdata(false); + break; + + case LOADITEMDATAV: + do_loaditemdata(true); + break; + + case LOADNPCR: + do_loadnpc(false); + break; + + case LOADNPCV: + do_loadnpc(true); + break; + + case CREATELWEAPONR: + do_createlweapon(false); + break; + + case CREATELWEAPONV: + do_createlweapon(true); + break; + + case CREATEEWEAPONR: + do_createeweapon(false); + break; + + case CREATEEWEAPONV: + do_createeweapon(true); + break; + + case CREATEITEMR: + do_createitem(false); + break; + + case CREATEITEMV: + do_createitem(true); + break; + + case CREATENPCR: + do_createnpc(false); + break; + + case CREATENPCV: + do_createnpc(true); + break; + + case ISVALIDITEM: + do_isvaliditem(); + break; + + case ISVALIDNPC: + do_isvalidnpc(); + break; + + case ISVALIDLWPN: + do_isvalidlwpn(); + break; + + case ISVALIDEWPN: + do_isvalidewpn(); + break; + + case LWPNUSESPRITER: + do_lwpnusesprite(false); + break; + + case LWPNUSESPRITEV: + do_lwpnusesprite(true); + break; + + case EWPNUSESPRITER: + do_ewpnusesprite(false); + break; + + case EWPNUSESPRITEV: + do_ewpnusesprite(true); + break; + + case CLEARSPRITESR: + do_clearsprites(false); + break; + + case CLEARSPRITESV: + do_clearsprites(true); + break; + + case ISSOLID: + do_issolid(); + break; + + case SETSIDEWARP: + do_setsidewarp(); + break; + + case SETTILEWARP: + do_settilewarp(); + break; + + case GETSIDEWARPDMAP: + do_getsidewarpdmap(false); + break; + + case GETSIDEWARPSCR: + do_getsidewarpscr(false); + break; + + case GETSIDEWARPTYPE: + do_getsidewarptype(false); + break; + + case GETTILEWARPDMAP: + do_gettilewarpdmap(false); + break; + + case GETTILEWARPSCR: + do_gettilewarpscr(false); + break; + + case GETTILEWARPTYPE: + do_gettilewarptype(false); + break; + + case LAYERSCREEN: + do_layerscreen(); + break; + + case LAYERMAP: + do_layermap(); + break; + + case SECRETS: + do_triggersecrets(); + break; + + case GETSCREENFLAGS: + do_getscreenflags(); + break; + + case GETSCREENEFLAGS: + do_getscreeneflags(); + break; + + case COMBOTILE: + do_combotile(false); + break; + + case RECTR: + case CIRCLER: + case ARCR: + case ELLIPSER: + case LINER: + case PUTPIXELR: + case DRAWTILER: + case DRAWCOMBOR: + case DRAWCHARR: + case DRAWINTR: + case QUADR: + case TRIANGLER: + case QUAD3DR: + case TRIANGLE3DR: + case FASTTILER: + case FASTCOMBOR: + case DRAWSTRINGR: + case SPLINER: + case BITMAPR: + case DRAWLAYERR: + case DRAWSCREENR: + do_drawing_command(scommand); + break; + + case COPYTILEVV: + do_copytile(true, true); + break; + + case COPYTILEVR: + do_copytile(true, false); + break; + + case COPYTILERV: + do_copytile(false, true); + break; + + case COPYTILERR: + do_copytile(false, false); + break; + + case SWAPTILEVV: + do_swaptile(true, true); + break; + + case SWAPTILEVR: + do_swaptile(true, false); + break; + + case SWAPTILERV: + do_swaptile(false, true); + break; + + case SWAPTILERR: + do_swaptile(false, false); + break; + + case CLEARTILEV: + do_cleartile(true); + break; + + case CLEARTILER: + do_cleartile(false); + break; + + case OVERLAYTILEVV: + do_overlaytile(true, true); + break; + + case OVERLAYTILEVR: + do_overlaytile(true, false); + break; + + case OVERLAYTILERV: + do_overlaytile(false, true); + break; + + case OVERLAYTILERR: + do_overlaytile(false, false); + break; + + case FLIPROTTILEVV: + do_fliprotatetile(true, true); + break; + + case FLIPROTTILEVR: + do_fliprotatetile(true, false); + break; + + case FLIPROTTILERV: + do_fliprotatetile(false, true); + break; + + case FLIPROTTILERR: + do_fliprotatetile(false, false); + break; + + case GETTILEPIXELV: + do_gettilepixel(true); + break; + + case GETTILEPIXELR: + do_gettilepixel(false); + break; + + case SETTILEPIXELV: + do_settilepixel(true); + break; + + case SETTILEPIXELR: + do_settilepixel(false); + break; + + case SHIFTTILEVV: + do_shifttile(true, true); + break; + + case SHIFTTILEVR: + do_shifttile(true, false); + break; + + case SHIFTTILERV: + do_shifttile(false, true); + break; + + case SHIFTTILERR: + do_shifttile(false, false); + break; + + case SETRENDERTARGET: + do_set_rendertarget(true); + break; + + case GAMEEND: + Quit = qQUIT; + skipcont = 1; + scommand = 0xFFFF; + break; + + case SAVE: + if(scriptCanSave) + { + save_game(false); + scriptCanSave=false; + } + break; + + case SAVESCREEN: + do_showsavescreen(); + break; + + case SAVEQUITSCREEN: + save_game(false, 1); + break; + + //Not Implemented + case ELLIPSE2: + case FLOODFILL: + break; + + case SETCOLORB: + case SETDEPTHB: + case GETCOLORB: + case GETDEPTHB: + break; + + case ENQUEUER: + do_enqueue(false); + break; + + case ENQUEUEV: + do_enqueue(true); + break; + + case DEQUEUE: + do_dequeue(false); + break; + + default: + Z_scripterrlog("Invalid ZASM command %ld reached\n", scommand); + break; + } + +#ifdef _SCRIPT_COUNTER + end_time = script_counter; + script_timer[*command] += end_time - start_time; + ++script_execount[*command]; +#endif + + if(increment) pc++; + else increment = true; + + if(scommand != 0xFFFF) + { + scommand = curscript[pc].command; + sarg1 = curscript[pc].arg1; + sarg2 = curscript[pc].arg2; + } + } + + if(!scriptCanSave) + scriptCanSave=true; + + if(scommand == WAITDRAW) + { + switch(type) + { + case SCRIPT_GLOBAL: + global_wait = true; + break; + + default: + Z_scripterrlog("Waitdraw can only be used in the active global script\n"); + break; + } + } + + if(scommand == 0xFFFF) //Quit/command list end reached/bad command + { + switch(type) + { + case SCRIPT_FFC: + tmpscr->ffcs[i].script = 0; + break; + + case SCRIPT_GLOBAL: + g_doscript = 0; + break; + + case SCRIPT_ITEM: + break; //item scripts aren't gonna go again anyway + } + } + else + pc++; + + ri->pc = pc; //Put it back where we got it from + +#ifdef _SCRIPT_COUNTER + + for(int j = 0; j < NUMCOMMANDS; j++) + { + if(script_execount[j] != 0) + al_trace("Command %s took %ld ticks in all to complete in %ld executions.\n", + command_list[j].name, script_timer[j], script_execount[j]); + } + + remove_int(update_script_counter); +#endif + + return 0; +} + +int ffscript_engine(const bool preload) +{ + for(byte i = 0; i < MAXFFCS; i++) + { + if(tmpscr->ffcs[i].script == 0) + continue; + + if(preload && !(tmpscr->ffcs[i].flags&ffPRELOAD)) + continue; + + if((tmpscr->ffcs[i].flags&ffIGNOREHOLDUP)==0 && Link.isHoldingItem()) + continue; + + ZScriptVersion::RunScript(SCRIPT_FFC, tmpscr->ffcs[i].script, i); + tmpscr->ffcs[i].initialized = true; + } + + return 0; +} + + +///---------------------------------------------------------------------------------------------------- diff --git a/src/ffscript.h b/src/ffscript.h new file mode 100644 index 0000000000..48b822c648 --- /dev/null +++ b/src/ffscript.h @@ -0,0 +1,802 @@ +#ifndef _FFSCRIPT_H_ +#define _FFSCRIPT_H_ +#include "zdefs.h" +#include +#include +#include + +long get_register(const long arg); +int run_script(const byte type, const word script, const byte i = -1); //Global scripts don't need 'i' +int ffscript_engine(const bool preload); + +void clear_ffc_stack(const byte i); +void clear_global_stack(); +void deallocateArray(const long ptrval); +void clearScriptHelperData(); + +struct script_command +{ + char name[16]; + byte args; + byte arg1_type; //0=reg, 1=val; + byte arg2_type; //0=reg, 1=val; + bool more_stuff; +}; + +struct script_variable +{ + char name[16]; + long id; + word maxcount; + byte multiple; +}; + +// Defines for script flags +#define TRUEFLAG 0x0001 +#define MOREFLAG 0x0002 +#define TRIGGERED 0x0004 + +//What are these for exactly? +//#define fflong(x,y,z) (((x[(y)][(z)])<<24)+((x[(y)][(z)+1])<<16)+((x[(y)][(z)+2])<<8)+(x[(y)][(z)+3])) +//#define ffword(x,y,z) (((x[(y)][(z)])<<8)+(x[(y)][(z)+1])) + +// Defines for the ASM operations +enum ASM_DEFINE +{ + SETV, //0x0000 + SETR, //0x0001 + ADDR, //0x0002 + ADDV, //0x0003 + SUBR, //0x0004 + SUBV, //0x0005 + MULTR, //0x0006 + MULTV, //0x0007 + DIVR, //0x0008 + DIVV, //0x0009 + WAITFRAME, //0x000A + GOTO, //0x000B + CHECKTRIG, //0x000C //NOT IMPLEMENTED + WARP, //0x000D + COMPARER, //0x000E + COMPAREV, //0x000F + GOTOTRUE, //0x0010 + GOTOFALSE, //0x0011 + GOTOLESS, //0x0012 + GOTOMORE, //0x0013 + LOAD1, //0x0014 + LOAD2, //0x0015 + SETA1, //0x0016 + SETA2, //0x0017 + QUIT, //0x0018 + SINR, //0x0019 + SINV, //0x001A + COSR, //0x001B + COSV, //0x001C + TANR, //0x001D + TANV, //0x001E + MODR, //0x001F + MODV, //0x0020 + ABSR, //0x0021 + MINR, //0x0022 + MINV, //0x0023 + MAXR, //0x0024 + MAXV, //0x0025 + RNDR, //0x0026 + RNDV, //0x0027 + FACTORIAL, //0x0028 + POWERR, //0x0029 + POWERV, //0x002A + IPOWERR, //0x002B + IPOWERV, //0x002C + ANDR, //0x002D + ANDV, //0x002E + ORR, //0x002F + ORV, //0x0030 + XORR, //0x0031 + XORV, //0x0032 + NANDR, //0x0033 + NANDV, //0x0034 + NORR, //0x0035 + NORV, //0x0036 + XNORR, //0x0037 + XNORV, //0x0038 + NOT, //0x0039 + LSHIFTR, //0x003A + LSHIFTV, //0x003B + RSHIFTR, //0x003C + RSHIFTV, //0x003D + TRACER, //0x003E + TRACEV, //0x003F + TRACE3, //0x0040 + LOOP, //0x0041 + PUSHR, //0x0042 + PUSHV, //0x0043 + POP, //0x0044 + ENQUEUER, //0x0045 //NOT IMPLEMENTED + ENQUEUEV, //0x0046 //NOT IMPLEMENTED + DEQUEUE, //0x0047 //NOT IMPLEMENTED + PLAYSOUNDR, //0x0048 + PLAYSOUNDV, //0x0049 + LOADLWEAPONR, //0x004A + LOADLWEAPONV, //0x004B + LOADITEMR, //0x004C + LOADITEMV, //0x004D + LOADNPCR, //0x004E + LOADNPCV, //0x004F + CREATELWEAPONR, //0x0050 + CREATELWEAPONV, //0x0051 + CREATEITEMR, //0x0052 + CREATEITEMV, //0x0053 + CREATENPCR, //0x0054 + CREATENPCV, //0x0055 + LOADI, //0x0056 + STOREI, //0x0057 + GOTOR, //0x0058 + SQROOTV, //0x0059 + SQROOTR, //0x005A + CREATEEWEAPONR, //0x005B + CREATEEWEAPONV, //0x005C + PITWARP, //0x005D + WARPR, //0x005E + PITWARPR, //0x005F + CLEARSPRITESR, //0x0060 + CLEARSPRITESV, //0x0061 + RECTR, //0x0062 + CIRCLER, //0x0063 + ARCR, //0x0064 + ELLIPSER, //0x0065 + LINER, //0x0066 + PUTPIXELR, //0x0067 + DRAWTILER, //0x0068 + DRAWCOMBOR, //0x0069 + ELLIPSE2, //0x006A + SPLINER, //0x006B + FLOODFILL, //0x006C + COMPOUNDR, //0x006D + COMPOUNDV, //0x006E + MSGSTRR, //0x006F + MSGSTRV, //0x0070 + ISVALIDITEM, //0x0071 + ISVALIDNPC, //0x0072 + PLAYMIDIR, //0x0073 + PLAYMIDIV, //0x0074 + COPYTILEVV, //0x0075 + COPYTILEVR, //0x0076 + COPYTILERV, //0x0077 + COPYTILERR, //0x0078 + SWAPTILEVV, //0x0079 + SWAPTILEVR, //0x007A + SWAPTILERV, //0x007B + SWAPTILERR, //0x007C + CLEARTILEV, //0x007D + CLEARTILER, //0x007E + OVERLAYTILEVV, //0x007F + OVERLAYTILEVR, //0x0080 + OVERLAYTILERV, //0x0081 + OVERLAYTILERR, //0x0082 + FLIPROTTILEVV, //0x0083 + FLIPROTTILEVR, //0x0084 + FLIPROTTILERV, //0x0085 + FLIPROTTILERR, //0x0086 + GETTILEPIXELV, //0x0087 + GETTILEPIXELR, //0x0088 + SETTILEPIXELV, //0x0089 + SETTILEPIXELR, //0x008A + SHIFTTILEVV, //0x008B + SHIFTTILEVR, //0x008C + SHIFTTILERV, //0x008D + SHIFTTILERR, //0x008E + ISVALIDLWPN, //0x008F + ISVALIDEWPN, //0x0090 + LOADEWEAPONR, //0x0091 + LOADEWEAPONV, //0x0092 + ALLOCATEMEMR, //0x0093 + ALLOCATEMEMV, //0x0094 + ALLOCATEGMEMV, //0x0095 + DEALLOCATEMEMR, //0x0096 + DEALLOCATEMEMV, //0x0097 //Pointless, can't deallocate a value + WAITDRAW, //0x0098 + ARCTANR, //0x0099 + LWPNUSESPRITER, //0x09A + LWPNUSESPRITEV, //0x09B + EWPNUSESPRITER, //0x09C + EWPNUSESPRITEV, //0x09D + LOADITEMDATAR, //0x09E + LOADITEMDATAV, //0x09F + BITNOT, //0x00A0 + LOG10, //0x00A1 + LOGE, //0x00A2 + ISSOLID, //0x00A3 + LAYERSCREEN, //0x00A4 + LAYERMAP, //0x00A5 + TRACE2R, //0x00A6 + TRACE2V, //0x00A7 + TRACE4, //0x00A8 + TRACE5, //0x00A9 + SECRETS, //0x00AA + DRAWCHARR, //0x00AB + GETSCREENFLAGS, //0x00AC + QUADR, //0X00AD + TRIANGLER, //0X00AE + ARCSINR, //0x00AF + ARCSINV, //0x00B0 + ARCCOSR, //0x00B1 + ARCCOSV, //0x00B2 + GAMEEND, //0x00B3 + DRAWINTR, //0x00B4 + SETTRUE, //0x00B5 + SETFALSE, //0x00B6 + SETMORE, //0x00B7 + SETLESS, //0x00B8 + FASTTILER, //0x00B9 + FASTCOMBOR, //0x00BA + DRAWSTRINGR, //0x00BB + SETSIDEWARP, //0x00BC + SAVE, //0x00BD + TRACE6, //0x00BE + WHATNO0x00BF, //PTROFF,//0x00BF + QUAD3DR, //0x00C0 + TRIANGLE3DR, //0x00C1 + SETCOLORB, //0x00C2 for 2.6 + SETDEPTHB, //0x00C3 ' + GETCOLORB, //0x00C4 ' + GETDEPTHB, //0x00C5 ' + COMBOTILE, //0x00C6 + SETTILEWARP, //0x00C7 + GETSCREENEFLAGS, //0x00C8 + GETSAVENAME, //0x00C9 + ARRAYSIZE, //0x00CA + ITEMNAME, //0x00CB + SETSAVENAME, //0x00CC + NPCNAME, //0x00CD + GETMESSAGE, //0x00CE + GETDMAPNAME, //0x00CF + GETDMAPTITLE, //0x00D0 + GETDMAPINTRO, //0x00D1 + ALLOCATEGMEMR, //0x00D2 + BITMAPR, //0x00D3 + SETRENDERTARGET, //0x00D4 + PLAYENHMUSIC, //0x00D5 + GETMUSICFILE, //0x00D6 + GETMUSICTRACK, //0x00D7 + SETDMAPENHMUSIC, //0x00D8 + DRAWLAYERR, //0x00D9 + DRAWSCREENR, //0x00DA + BREAKSHIELD, //0x00DB + SAVESCREEN, //0x00DC + SAVEQUITSCREEN, //0x00DD + SELECTAWPNR, //0x00DE + SELECTAWPNV, //0x00DF + SELECTBWPNR, //0x00E0 + SELECTBWPNV, //0x00E1 + GETSIDEWARPDMAP, //0x00E2 + GETSIDEWARPSCR, //0x00E3 + GETSIDEWARPTYPE, //0x00E4 + GETTILEWARPDMAP, //0x00E5 + GETTILEWARPSCR, //0x00E6 + GETTILEWARPTYPE, //0x00E7 + GETFFCSCRIPT, //0x00E8 + /* ..sorry, forgot about these ...for now. -Gleeok + CALCSPLINE, //0x00 + COLLISIONRECT, ? //0x00 + COLLISIONBOX, ? //0x00 + SETBITMAPBUFFER, + GETBITMAPBUFFER, + CLEARBITMAPBUFFER, + RENDERBITMAPBUFFER, + */ + NUMCOMMANDS //0x00E9 +}; + +//ZASM registers +//When adding indexed variables the index will be loaded into ri.d[0], don't add a register for each one! +#define REG_D(n) ((0x0000)+(n)) //8 +#define REG_A(n) ((0x0008)+(n)) //2 +#define DATA 0x000A +#define FCSET 0x000B +#define DELAY 0x000C +#define FX 0x000D +#define FY 0x000E +#define XD 0x000F +#define YD 0x0010 +#define XD2 0x0011 +#define YD2 0x0012 +#define FLAG 0x0013 +#define WIDTH 0x0014 +#define HEIGHT 0x0015 +#define LINK 0x0016 +//#define COMBOD(n) ((0x0017)+((n)*3)) ~loads spare here... +//#define COMBOC(n) ((0x0018)+((n)*3)) +//#define COMBOF(n) ((0x0019)+((n)*3)) + +//n=0-175, so if n=175, then ((0x0019)+((n)*3))=0x00226 +#define INPUTSTART 0x0227 +#define INPUTUP 0x0228 +#define INPUTDOWN 0x0229 +#define INPUTLEFT 0x022A +#define INPUTRIGHT 0x022B +#define INPUTA 0x022C +#define INPUTB 0x022D +#define INPUTL 0x022E +#define INPUTR 0x022F + +#define LINKX 0x0230 +#define LINKY 0x0231 +#define LINKDIR 0x0232 +#define LINKHP 0x0233 +#define LINKMP 0x0234 +#define LINKMAXHP 0x0235 +#define LINKMAXMP 0x0236 +#define LINKACTION 0x0237 +#define LINKITEMD 0x0238 +#define LINKZ 0x0239 +#define LINKJUMP 0x023A +#define LINKSWORDJINX 0x023B +#define LINKITEMJINX 0x023C +#define LINKDRUNK 0x023D +#define LINKHELD 0x023E +#define INPUTMAP 0x023F +#define LINKEQUIP 0x0240 +#define LINKINVIS 0x0241 +#define LINKINVINC 0x0242 +#define LINKLADDERX 0x0243 +#define LINKLADDERY 0x0244 +#define LINKHITDIR 0x0245 +#define LINKTILE 0x0246 +#define LINKFLIP 0x0247 +#define INPUTPRESSMAP 0x0248 +//0x0249-0x0258 are reserved for future Link variables +#define UNUSED25 0x0249 +#define UNUSED26 0x024A +#define UNUSED27 0x024B +#define UNUSED28 0x024C +#define UNUSED29 0x024D +#define UNUSED30 0x024E +#define UNUSED31 0x024F +#define UNUSED32 0x0250 +#define UNUSED33 0x0251 +#define UNUSED34 0x0252 +#define UNUSED35 0x0253 +#define UNUSED36 0x0254 +#define UNUSED37 0x0255 +#define UNUSED38 0x0256 +#define UNUSED39 0x0257 +#define UNUSED40 0x0258 + +#define LWPNX 0x0259 +#define LWPNY 0x025A +#define LWPNDIR 0x025B +#define LWPNSTEP 0x025C +#define LWPNANGULAR 0x025D +#define LWPNANGLE 0x025E +#define LWPNDRAWTYPE 0x025F +#define LWPNPOWER 0x0260 +#define LWPNDEAD 0x0261 +#define LWPNID 0x0262 +#define LWPNTILE 0x0263 +#define LWPNCSET 0x0264 +#define LWPNFLASHCSET 0x0265 +#define LWPNFRAMES 0x0266 +#define LWPNFRAME 0x0267 +#define LWPNASPEED 0x0268 +#define LWPNFLASH 0x0269 +#define LWPNFLIP 0x026A +#define LWPNCOUNT 0x026B +#define LWPNEXTEND 0x026C +#define LWPNOTILE 0x026D +#define LWPNOCSET 0x026E +#define LWPNZ 0x026F +#define LWPNJUMP 0x0270 +#define LWPNCOLLDET 0x0271 +// 0x0272- 0x028B are reserved for future weapon variables +#define UNUSED47 0x0272 +#define UNUSED48 0x0273 +#define UNUSED49 0x0274 +#define UNUSED50 0x0275 +#define UNUSED51 0x0276 +#define UNUSED52 0x0277 +#define UNUSED53 0x0278 +#define UNUSED54 0x0279 +#define UNUSED55 0x027A +#define UNUSED56 0x027B +#define UNUSED57 0x027C +#define UNUSED58 0x027D +#define UNUSED59 0x027E +#define UNUSED60 0x027F +#define UNUSED61 0x0280 +#define UNUSED62 0x0281 +#define UNUSED63 0x0282 +#define UNUSED64 0x0283 +#define UNUSED65 0x0284 +#define UNUSED66 0x0285 +#define UNUSED67 0x0286 +#define UNUSED68 0x0287 +#define UNUSED69 0x0288 +#define UNUSED70 0x0289 +#define UNUSED71 0x028A +#define UNUSED72 0x028B + +#define ITEMX 0x028C +#define ITEMY 0x028D +#define ITEMDRAWTYPE 0x028E +#define ITEMID 0x028F +#define ITEMTILE 0x0290 +#define ITEMCSET 0x0291 +#define ITEMFLASHCSET 0x0292 +#define ITEMFRAMES 0x0293 +#define ITEMFRAME 0x0294 +#define ITEMASPEED 0x0295 +#define ITEMDELAY 0x0296 +#define ITEMFLASH 0x0297 +#define ITEMFLIP 0x0298 +#define ITEMCOUNT 0x0299 +#define IDATAFAMILY 0x029A +#define IDATALEVEL 0x029B +#define IDATAKEEP 0x029C +#define IDATAAMOUNT 0x029D +#define IDATASETMAX 0x029E +#define IDATAMAX 0x029F +#define IDATACOUNTER 0x02A0 +#define ITEMEXTEND 0x02A1 +#define ITEMZ 0x02A2 +#define ITEMJUMP 0x02A3 +#define ITEMOTILE 0x02A4 +#define IDATAUSESOUND 0x02A5 +#define IDATAPOWER 0x02A6 + +//0x02A7-0x02B9 are reserved for future item variables +#define UNUSED86 0x02A7 +#define UNUSED87 0x02A8 +#define UNUSED88 0x02A9 +#define UNUSED89 0x02AA +#define UNUSED90 0x02AB +#define UNUSED91 0x02AC +#define UNUSED92 0x02AD +#define UNUSED93 0x02AE +#define UNUSED94 0x02AF +#define UNUSED95 0x02B0 +#define UNUSED96 0x02B1 +#define UNUSED97 0x02B2 +#define UNUSED98 0x02B3 +#define UNUSED99 0x02B4 +#define UNUSED100 0x02B5 +#define UNUSED101 0x02B6 +#define UNUSED102 0x02B7 +#define UNUSED103 0x02B8 +#define UNUSED104 0x02B9 + +#define NPCX 0x02BA +#define NPCY 0x02BB +#define NPCDIR 0x02BC +#define NPCRATE 0x02BD +#define NPCFRAMERATE 0x02BE +#define NPCHALTRATE 0x02BF +#define NPCDRAWTYPE 0x02C0 +#define NPCHP 0x02C1 +#define NPCID 0x02C2 +#define NPCDP 0x02C3 +#define NPCWDP 0x02C4 +#define NPCOTILE 0x02C5 +#define NPCENEMY 0x02C6 +#define NPCWEAPON 0x02C7 +#define NPCITEMSET 0x02C8 +#define NPCCSET 0x02C9 +#define NPCBOSSPAL 0x02CA +#define NPCBGSFX 0x02CB +#define NPCCOUNT 0x02CC +#define NPCEXTEND 0x02CD +#define NPCZ 0x02CE +#define NPCJUMP 0x02CF +#define NPCSTEP 0x02D0 +#define NPCTILE 0x02D1 +#define NPCHOMING 0x02D2 +#define NPCDD 0x02D3 +//#define NPCD(n) ((0x101D)+(n)) //10 spare +#define NPCTYPE 0x02DE +#define NPCMFLAGS 0x02DF +#define NPCCOLLDET 0x02E0 +#define NPCSTUN 0x02E1 +#define NPCHUNGER 0x02E2 +//0x02E3-0x02EB are reserved for future NPC variables +#define UNUSED126 0x02E2 +#define UNUSED127 0x02E3 +#define UNUSED128 0x02E4 +#define UNUSED129 0x02E5 +#define UNUSED130 0x02E6 +#define UNUSED131 0x02E7 +#define UNUSED132 0x02E8 +#define UNUSED133 0x02E9 +#define UNUSED134 0x02EA +#define UNUSED135 0x02EB +//I'm stealing this one for the stack pointer -DD +#define SP 0x02EC + +//#define SD(n) ((0x02ED)+(n)) //Spare 8 +#define GD(n) ((0x02F5)+(n)) //256 + +// Defines for accessing gamedata +//#define GAMECOUNTER(n) ((0x03F5)+((n)*3)) //All of these spare +//#define GAMEMCOUNTER(n) ((0x03F6)+((n)*3)) +//#define GAMEDCOUNTER(n) ((0x03F7)+((n)*3)) +//#define GAMEGENERIC(n) ((0x0455)+(n)) +//#define GAMEITEMS(n) ((0x0555)+(n)) +//#define GAMELITEMS(n) ((0x0655)+(n)) +//#define GAMELKEYS(n) ((0x0755)+(n)) +#define GAMEDEATHS 0x0855 +#define GAMECHEAT 0x0856 +#define GAMETIME 0x0857 +#define GAMEHASPLAYED 0x0858 +#define GAMETIMEVALID 0x0859 +#define GAMEGUYCOUNTD 0x085A +#define GAMEGUYCOUNT 0x085B +#define GAMECONTSCR 0x085C +#define GAMECONTDMAP 0x085D +#define GAMECOUNTERD 0x085E +#define GAMEMCOUNTERD 0x085F +#define GAMEDCOUNTERD 0x0860 +#define GAMEGENERICD 0x0861 +#define GAMEITEMSD 0x0862 +#define GAMELITEMSD 0x0863 +#define GAMELKEYSD 0x0864 +#define ROOMTYPE 0x0865 +#define ROOMDATA 0x0866 +//#define SCREENSTATE(n) ((0x0867)+(n)) //spare 30 +#define SCREENSTATED 0x0885 + +#define CURSCR 0x0886 +#define CURMAP 0x0887 +#define CURDMAP 0x0888 +#define COMBODD 0x0889 +#define COMBOCD 0x088A +#define COMBOFD 0x088B +#define COMBOTD 0x088C +#define COMBOID 0x088D + +//Defines for all the extra crap that's been added since +#define REFITEMCLASS 0x088E +#define REFITEM 0x088F +#define REFFFC 0x0890 +#define REFLWPN 0x0891 +#define REFNPC 0x0892 +#define REFLWPNCLASS 0x0893 +#define REFNPCCLASS 0x0894 +//#define REFSUBSCREEN 0x0895 //Not implemented +#define REFEWPN 0x0896 +#define REFEWPNCLASS 0x0897 + +#define EWPNX 0x0898 +#define EWPNY 0x0899 +#define EWPNDIR 0x089A +#define EWPNSTEP 0x089B +#define EWPNANGULAR 0x089C +#define EWPNANGLE 0x089D +#define EWPNDRAWTYPE 0x089E +#define EWPNPOWER 0x089F +#define EWPNDEAD 0x08A0 +#define EWPNID 0x08A1 +#define EWPNTILE 0x08A2 +#define EWPNCSET 0x08A3 +#define EWPNFLASHCSET 0x08A4 +#define EWPNFRAMES 0x08A5 +#define EWPNFRAME 0x08A6 +#define EWPNASPEED 0x08A7 +#define EWPNFLASH 0x08A8 +#define EWPNFLIP 0x08A9 +#define EWPNCOUNT 0x08AA +#define EWPNEXTEND 0x08AB +#define EWPNOTILE 0x08AC +#define EWPNOCSET 0x08AD +#define EWPNZ 0x08AE +#define EWPNJUMP 0x08AF + +//#define SCRDOOR(n) ((0x08B0)+(n)) //spare one +#define SCRDOORD 0x08B4 + +#define CURDSCR 0x08B5 +//#define GETSTART 0x08B6 //? + +#define COMBOSD 0x08B7 +#define SCREENSTATEDD 0x08B8 +#define SDD 0x08B9 +#define SDDD 0x08BA +#define GDD 0x08BB + +#define FFFLAGSD 0x08BC +#define FFCWIDTH 0x08BD +#define FFCHEIGHT 0x08BE +#define FFTWIDTH 0x08BF +#define FFTHEIGHT 0x08C0 +#define FFLINK 0x08C1 + +//#define GS(n) ((0x08C2)+(n)) //this never did anything anyway + +#define WAVY 0x09C2 +#define QUAKE 0x09C3 +#define INPUTMOUSEX 0x09C4 +#define INPUTMOUSEY 0x09C5 +#define INPUTMOUSEZ 0x09C6 +#define INPUTMOUSEB 0x09C7 + +#define COMBODDM 0x09C8 +#define COMBOCDM 0x09C9 +#define COMBOFDM 0x09CA +#define COMBOTDM 0x09CB +#define COMBOIDM 0x09CC +#define COMBOSDM 0x09CD + +#define SCRIPTRAM 0x09CE +#define GLOBALRAM 0x09CF +#define SCRIPTRAMD 0x09D0 +#define GLOBALRAMD 0x09D1 +//#define SAVERAM 0x09D2 //Spare one here + +#define LWPNHXOFS 0x09D3 +#define LWPNHYOFS 0x09D4 +#define LWPNXOFS 0x09D5 +#define LWPNYOFS 0x09D6 +#define LWPNZOFS 0x09D7 +#define LWPNHXSZ 0x09D8 +#define LWPNHYSZ 0x09D9 +#define LWPNHZSZ 0x09DA + +#define EWPNHXOFS 0x09DB +#define EWPNHYOFS 0x09DC +#define EWPNXOFS 0x09DD +#define EWPNYOFS 0x09DE +#define EWPNZOFS 0x09DF +#define EWPNHXSZ 0x09E0 +#define EWPNHYSZ 0x09E1 +#define EWPNHZSZ 0x09E2 + +#define NPCHXOFS 0x09E3 +#define NPCHYOFS 0x09E4 +#define NPCXOFS 0x09E5 +#define NPCYOFS 0x09E6 +#define NPCZOFS 0x09E7 +#define NPCHXSZ 0x09E8 +#define NPCHYSZ 0x09E9 +#define NPCHZSZ 0x09EA + +#define ITEMHXOFS 0x09EB +#define ITEMHYOFS 0x09EC +#define ITEMXOFS 0x09ED +#define ITEMYOFS 0x09EE +#define ITEMZOFS 0x09EF +#define ITEMHXSZ 0x09F0 +#define ITEMHYSZ 0x09F1 +#define ITEMHZSZ 0x09F2 + +#define LWPNTXSZ 0x09F3 +#define LWPNTYSZ 0x09F4 + +#define EWPNTXSZ 0x09F5 +#define EWPNTYSZ 0x09F6 + +#define NPCTXSZ 0x09F7 +#define NPCTYSZ 0x09F8 + +#define ITEMTXSZ 0x09F9 +#define ITEMTYSZ 0x09FA + +#define LINKHXOFS 0x09FB +#define LINKHYOFS 0x09FC +#define LINKXOFS 0x09FD +#define LINKYOFS 0x09FE +#define LINKZOFS 0x09FF +#define LINKHXSZ 0x1000 +#define LINKHYSZ 0x1001 +#define LINKHZSZ 0x1002 +#define LINKTXSZ 0x1003 +#define LINKTYSZ 0x1004 + +#define LWPNBEHIND 0x1005 +#define EWPNBEHIND 0x1006 + +#define SDDDD 0x1007 +#define CURLEVEL 0x1008 +#define ITEMPICKUP 0x1009 +#define LIT 0x100A +#define INPUTEX1 0x100B +#define INPUTEX2 0x100C +#define INPUTEX3 0x100D +#define INPUTEX4 0x100E +#define INPUTPRESSSTART 0x100F +#define INPUTPRESSUP 0x1010 +#define INPUTPRESSDOWN 0x1011 +#define INPUTPRESSLEFT 0x1012 +#define INPUTPRESSRIGHT 0x1013 +#define INPUTPRESSA 0x1014 +#define INPUTPRESSB 0x1015 +#define INPUTPRESSL 0x1016 +#define INPUTPRESSR 0x1017 +#define INPUTPRESSEX1 0x1018 +#define INPUTPRESSEX2 0x1019 +#define INPUTPRESSEX3 0x101A +#define INPUTPRESSEX4 0x101B + +#define LWPNMISCD 0x101C +//#define LWPNMISC(n) ((0x101D)+(n)) //16 spare +#define EWPNMISCD 0x102D +//#define EWPNMISC(n) ((0x102E)+(n)) //16 spare +#define NPCMISCD 0x103E +//#define NPCMISC(n) ((0x103F)+(n)) //16 spare +#define ITEMMISCD 0x104F +//#define ITEMMISC(n) ((0x1050)+(n)) //16 spare +#define FFMISCD 0x1060 +//#define FFMISC(n) ((0x1061)+(n)) //16 spare + +#define GETMIDI 0x1071 + +#define INPUTAXISUP 0x1072 +#define INPUTAXISDOWN 0x1073 +#define INPUTAXISLEFT 0x1074 +#define INPUTAXISRIGHT 0x1075 +#define INPUTPRESSAXISUP 0x1076 +#define INPUTPRESSAXISDOWN 0x1077 +#define INPUTPRESSAXISLEFT 0x1078 +#define INPUTPRESSAXISRIGHT 0x1079 + +#define FFSCRIPT 0x107A +#define SCREENFLAGSD 0x107B +//#define SCREENFLAGS(n) ((0x107C)+(n)) //10 spare here +#define SCREENEFLAGSD 0x1086 +//#define SCREENEFLAGS(n) ((0x1087)+(n)) //3 spare here +#define FFINITDD 0x108B +//#define FFINITD(n) ((0x108C)+(n)) //8 spare +#define LINKMISCD 0x1094 +//#define LINKMISC(n) ((0x1095)+(n)) //16 spare +#define DMAPFLAGSD 0x10A5 +#define EWPNCOLLDET 0x10A6 + +#define NPCDEFENSED 0x10A7 +#define DMAPLEVELD 0x10A8 +#define DMAPCOMPASSD 0x10A9 +#define DMAPCONTINUED 0x10AA +#define DMAPMIDID 0x10AB +#define IDATAINITDD 0x10AC //8 + +#define GAMESTANDALONE 0x10AD + +#define GAMEENTRSCR 0x10AE +#define GAMEENTRDMAP 0x10AF + +#define GAMECLICKFREEZE 0x10B0 + +#define PUSHBLOCKX 0x10B1 +#define PUSHBLOCKY 0x10B2 +#define PUSHBLOCKCOMBO 0x10B3 +#define PUSHBLOCKCSET 0x10B4 +#define UNDERCOMBO 0x10B5 +#define UNDERCSET 0x10B6 +#define DMAPOFFSET 0x10B7 +#define DMAPMAP 0x10B8 + +#define NUMVARIABLES 0x10B9 + +// Script types + +#define SCRIPT_GLOBAL 0 +#define SCRIPT_FFC 1 +#define SCRIPT_SCREEN 2 +#define SCRIPT_LINK 3 +#define SCRIPT_ITEM 4 +#define SCRIPT_LWPN 5 +#define SCRIPT_NPC 6 +#define SCRIPT_SUBSCREEN 7 +#define SCRIPT_EWPN 8 + +struct quad3Dstruct +{ + int index; + float pos[12], uv[8]; + int size[2], color[4]; +}; + +struct triangle3Dstruct +{ + int index; + float pos[9], uv[6]; + int size[2], color[3]; +}; + +#endif diff --git a/src/font.cpp b/src/font.cpp new file mode 100644 index 0000000000..3083ad5ffa --- /dev/null +++ b/src/font.cpp @@ -0,0 +1,187 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Grabber plugin for managing font objects. + * + * By Shawn Hargreaves. + * + * GRX font file reader by Mark Wodrich. + * + * See readme.txt for copyright information. + */ +#ifndef __FONT_C__ +#define __FONT_C__ + +#include +#include + +#include "zc_alleg.h" +#include +#include +#include "font.h" + +extern FONT* create_font(); + +typedef unsigned char byte; //0-255 ( 8 bits) +typedef unsigned short word; //0-65535 (16 bits) +typedef unsigned long dword; //0-4294967295 (32 bits) + +extern byte *tilebuf; + +// in tiles.cc +byte unpackbuf[256]; + +void unpack_tile(int tile) +{ + byte *si = tilebuf+((tile+1)<<7); + int di; + + for(di=254; di>=0; di-=2) + { + --si; + unpackbuf[di] = (*si) & 15; + unpackbuf[di+1] = (*si) >> 4; + } +} + +static int convert_8x8_tiles_to_mono_font(FONT_GLYPH** gl, int start, int num) +{ + int w = 8, h = 8, i; + + for(i = 0; i < 32; i++) + { + int sx = ((w + 7) / 8), j; + gl[i] = _al_malloc(sizeof(FONT_GLYPH) + sx * h); + gl[i]->w = w; + gl[i]->h = h; + + for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; + } + + for(i = 32; i < num+32; i++) + { + int tile=(((i-32)/16)*20)+((i-32)%16); + + int sx = ((w + 7) / 8), j, k; + + unpack_tile(start+tile); + gl[i] = _al_malloc(sizeof(FONT_GLYPH) + sx * h); + gl[i]->w = w; + gl[i]->h = h; + + for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; + + for(j = 0; j < h; j++) + { + for(k = 0; k < w; k++) + { + if(unpackbuf[j*16+k]) + { + gl[i]->dat[(j * sx) + (k / 8)] |= 0x80 >> (k & 7); + } + } + } + } + + return 0; +} + +static int convert_16x16_tiles_to_mono_font(FONT_GLYPH** gl, int start, int num) +{ + int w = 8, h = 8, i; + + for(i = 0; i < 32; i++) + { + int sx = ((w + 7) / 8), j; + gl[i] = _al_malloc(sizeof(FONT_GLYPH) + sx * h); + gl[i]->w = w; + gl[i]->h = h; + + for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; + } + + for(i = 32; i < num+32; i++) + { + int tile=(((i-32)/16)*20)+((i-32)%16); + + int sx = ((w + 7) / 8), j, k; + + unpack_tile(start+tile); + gl[i] = _al_malloc(sizeof(FONT_GLYPH) + sx * h); + gl[i]->w = w; + gl[i]->h = h; + + for(j = 0; j < sx * h; j++) gl[i]->dat[j] = 0; + + for(j = 0; j < h; j++) + { + for(k = 0; k < w; k++) + { + if(unpackbuf[j*16+k]) + { + gl[i]->dat[(j * sx) + (k / 8)] |= 0x80 >> (k & 7); + } + } + } + } + + return 0; +} + +/* import routine for the Allegro .pcx font format */ +FONT* create_font() +{ + FONT *f; + FONT_MONO_DATA* mf = _al_malloc(sizeof(FONT_MONO_DATA)); + + f = _al_malloc(sizeof(FONT)); + + mf->glyphs = _al_malloc(sizeof(FONT_GLYPH*) * (192)); + + if(convert_8x8_tiles_to_mono_font(mf->glyphs, 10920, 192)) + { + free(mf->glyphs); + free(mf); + free(f); + f = 0; + } + else + { + f->data = mf; + f->vtable = font_vtable_mono; + f->height = mf->glyphs[0]->h; + mf->begin = 0; + mf->end = 192; + mf->next = 0; + } + + //delete this. only added to keep compiler from whining + if(convert_16x16_tiles_to_mono_font(mf->glyphs, 10920, 192)) + { + free(mf->glyphs); + free(mf); + free(f); + f = 0; + } + else + { + f->data = mf; + f->vtable = font_vtable_mono; + f->height = mf->glyphs[0]->h; + mf->begin = 0; + mf->end = 192; + mf->next = 0; + } + + return f; + +} +#endif //__FONT_C__ + diff --git a/src/font.h b/src/font.h new file mode 100644 index 0000000000..1ecb69d660 --- /dev/null +++ b/src/font.h @@ -0,0 +1,32 @@ +/* ______ ___ ___ + * /\ _ \ /\_ \ /\_ \ + * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ + * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ + * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ + * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ + * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ + * /\____/ + * \_/__/ + * + * Grabber plugin for managing font objects. + * + * By Shawn Hargreaves. + * + * GRX font file reader by Mark Wodrich. + * + * See readme.txt for copyright information. + */ +#ifndef __FONT_H__ +#define __FONT_H__ +#ifdef __cplusplus +extern "C" +{ +#endif + +//extern FONT *zfont; +extern FONT *create_font(); +#ifdef __cplusplus +} +#endif +#endif //__FONT_H__ + diff --git a/src/fontClass.cpp b/src/fontClass.cpp new file mode 100644 index 0000000000..85b3b6b311 --- /dev/null +++ b/src/fontClass.cpp @@ -0,0 +1,101 @@ +#include "fontClass.h" +#include "zelda.h" + +Font Font::getByID(int id) +{ + switch(id) + { + case font_z3font: + return Font(z3font); + + case font_z3smallfont: + return Font(z3smallfont); + + case font_deffont: + return Font(deffont); + + case font_lfont: + return Font(lfont); + + case font_lfont_l: + return Font(lfont_l); + + case font_pfont: + return Font(pfont); + + case font_mfont: + return Font(mfont); + + case font_ztfont: + return Font(ztfont); + + case font_sfont: + return Font(sfont); + + case font_sfont2: + return Font(sfont2); + + case font_spfont: + return Font(spfont); + + case font_ssfont1: + return Font(ssfont1); + + case font_ssfont2: + return Font(ssfont2); + + case font_ssfont3: + return Font(ssfont3); + + case font_ssfont4: + return Font(ssfont4); + + case font_gblafont: + return Font(gblafont); + + case font_goronfont: + return Font(goronfont); + + case font_zoranfont: + return Font(zoranfont); + + case font_hylian1font: + return Font(hylian1font); + + case font_hylian2font: + return Font(hylian2font); + + case font_hylian3font: + return Font(hylian3font); + + case font_hylian4font: + return Font(hylian4font); + + case font_gboraclefont: + return Font(gboraclefont); + + case font_gboraclepfont: + return Font(gboraclepfont); + + case font_dsphantomfont: + return Font(dsphantomfont); + + case font_dsphantompfont: + return Font(dsphantompfont); + + case font_zfont: + default: + return Font(zfont); + } +} + +Font::Font(): + allegroFont(zfont) +{ +} + + +Font::Font(FONT* f): + allegroFont(f) +{ +} diff --git a/src/fontClass.h b/src/fontClass.h new file mode 100644 index 0000000000..222315d6de --- /dev/null +++ b/src/fontClass.h @@ -0,0 +1,35 @@ +#ifndef _ZC_FONTCLASS_H_ +#define _ZC_FONTCLASS_H_ + +#include + +#include + +class Font +{ +public: + static Font getByID(int id); + + Font(); + Font(FONT* f); + + inline const FONT* get() const + { + return allegroFont; + } + + inline int getWidth(char c) const + { + return allegroFont->vtable->char_length(allegroFont, c); + } + + inline int getHeight() const + { + return text_height(allegroFont); + } + +private: + const FONT* allegroFont; +}; + +#endif diff --git a/src/fontsdat.h b/src/fontsdat.h new file mode 100644 index 0000000000..0758d418b2 --- /dev/null +++ b/src/fontsdat.h @@ -0,0 +1,37 @@ +/* Allegro datafile object indexes, produced by grabber v4.2.0, MSVC.s */ +/* Datafile: c:\zc\fonts.dat */ +/* Date: Sun Jun 21 22:16:34 2009 */ +/* Do not hand edit! */ + +#define _SIGNATURE 0 /* DATA */ +#define FONT_12x8 1 /* FONT */ +#define FONT_6x4 2 /* FONT */ +#define FONT_6x6 3 /* FONT */ +#define FONT_6xPROP 4 /* FONT */ +#define FONT_8xPROP_THIN 5 /* FONT */ +#define FONT_DS_PHANTOM 6 /* FONT */ +#define FONT_DS_PHANTOM_P 7 /* FONT */ +#define FONT_GB_LA 8 /* FONT */ +#define FONT_GB_ORACLE 9 /* FONT */ +#define FONT_GB_ORACLE_P 10 /* FONT */ +#define FONT_GORON 11 /* FONT */ +#define FONT_GUI_MONO 12 /* FONT */ +#define FONT_GUI_PROP 13 /* FONT */ +#define FONT_HYLIAN1 14 /* FONT */ +#define FONT_HYLIAN2 15 /* FONT */ +#define FONT_HYLIAN3 16 /* FONT */ +#define FONT_HYLIAN4 17 /* FONT */ +#define FONT_LARGEFIXED 18 /* FONT */ +#define FONT_LARGEPROP 19 /* FONT */ +#define FONT_LARGEPROP_L 20 /* FONT */ +#define FONT_MATRIX 21 /* FONT */ +#define FONT_NES 22 /* FONT */ +#define FONT_SUBSCREEN1 23 /* FONT */ +#define FONT_SUBSCREEN2 24 /* FONT */ +#define FONT_SUBSCREEN3 25 /* FONT */ +#define FONT_SUBSCREEN4 26 /* FONT */ +#define FONT_Z3 27 /* FONT */ +#define FONT_Z3SMALL 28 /* FONT */ +#define FONT_ZORAN 29 /* FONT */ +#define FONT_ZTIME 30 /* FONT */ + diff --git a/src/gamedata.cpp b/src/gamedata.cpp new file mode 100644 index 0000000000..34c839700b --- /dev/null +++ b/src/gamedata.cpp @@ -0,0 +1,808 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zelda.cc +// +// Main code for Zelda Classic. Originally written in +// SPHINX C--, now rewritten in DJGPP with Allegro. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include +#include "zc_alleg.h" +#include "zc_sys.h" +#include "zdefs.h" +#include "zelda.h" +#include "items.h" +#include "pal.h" + +extern int dlevel; +extern void flushItemCache(); +extern zinitdata zinit; +extern void Z_eventlog(char *format,...); +extern void ringcolor(bool forceDefault); + +// Debug variables: these log certain operations on gamedata when active. +// Should help me debug those item bugs. + +// #define DEBUG_GD_ITEMS +// #define DEBUG_GD_COUNTERS +//#define DEBUG_GD_HCP + +void gamedata::Clear() +{ + isclearing=true; + std::fill(_name, _name+9, 0); + _quest=0; + _deaths=0; + _cheat=0; + std::fill(item, item+MAXITEMS, false); + std::fill(items_off, items_off+MAXITEMS, 0); + std::fill(_maxcounter, _maxcounter+32, 0); + std::fill(_counter, _counter+32, 0); + std::fill(_dcounter, _dcounter+32, 0); + std::fill(version, version+9, 0); + std::fill(title, title+65, 0); + _hasplayed=false; + _time=0; + _timevalid=false; + std::fill(lvlitems, lvlitems+MAXLEVELS, 0); + std::fill(lvlkeys, lvlkeys+MAXLEVELS, 0); + _continue_scrn=0; + _continue_dmap=0; + std::fill(_generic, _generic+256, 0); + std::fill(visited, visited+MAXDMAPS, 0); + std::fill(bmaps, bmaps+MAXDMAPS*64, 0); + std::fill(maps, maps+MAXMAPS2*MAPSCRSNORMAL, 0); + std::fill(guys, guys+MAXMAPS2*MAPSCRSNORMAL, 0); + std::fill(qstpath, qstpath+2048, 0); + std::fill(icon, icon+128, 0); + std::fill(pal, pal+48, 0); + + for(int i=0; i=32) // Sanity check + return 0; + + return _counter[c]; +} + +void gamedata::set_counter(word change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + al_trace("Changing counter %i from %i to %i\n", c, _counter[c], change); +#endif + + if(c>=32) // Sanity check + return; + + if(game!=NULL) + { + int ringID=current_item_id(itype_ring, true); + _counter[c]=zc_max(change, 0); + + // ringcolor is very slow, so make sure the ring has actually changed + if(ringID!=current_item_id(itype_ring, true)) + ringcolor(false); + } + else + _counter[c]=zc_max(change, 0); + + return; +} + +void gamedata::change_counter(short change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + al_trace("Changing counter %i from %i by %i\n", c, _counter[c], change); +#endif + + if(c>=32) // Sanity check + return; + + if(game!=NULL) + { + int ringID=current_item_id(itype_ring, true); + _counter[c]=vbound(_counter[c]+change, 0, _maxcounter[c]); + + if(ringID!=current_item_id(itype_ring, true)) + ringcolor(false); + } + else + _counter[c]=vbound(_counter[c]+change, 0, _maxcounter[c]); + + return; +} + +word gamedata::get_maxcounter(byte c) +{ + if(c>=32) // Sanity check + return 0; + + return _maxcounter[c]; +} + +void gamedata::set_maxcounter(word change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + + if(c==0) al_trace("Changing max counter %i from %i to %i\n", c, _maxcounter[c], change); + +#endif + + if(c==2) + { + set_maxbombs(change); + return; + } + + if(c>=32) // Sanity check + return; + + _maxcounter[c]=change; + return; +} + +void gamedata::change_maxcounter(short change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + al_trace("Changing max counter %i from %i by +%i\n", c, _maxcounter[c], change); +#endif + + if(c==2) + { + change_maxbombs(change); + return; + } + + if(c>=32) // Sanity check + return; + + _maxcounter[c]=zc_max(0, _maxcounter[c]+change); + return; +} + +short gamedata::get_dcounter(byte c) +{ + if(c>=32) // Sanity check + return 0; + + return _dcounter[c]; +} + +void gamedata::set_dcounter(short change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + + if(c==0) + al_trace("Changing D counter %i from %i to %i\n", c, _dcounter[c], change); + +#endif + + if(c>=32) // Sanity check + return; + + if(game!=NULL) + { + int ringID=current_item_id(itype_ring, true); + _dcounter[c]=change; + + if(ringID!=current_item_id(itype_ring, true)) + ringcolor(false); + } + else + _dcounter[c]=change; + + return; +} + +void gamedata::change_dcounter(short change, byte c) +{ +#ifdef DEBUG_GD_COUNTERS + + if(c==0) al_trace("Changing D counter %i from %i by %i\n", c, _dcounter[c], change); + +#endif + + if(c>=32) // Sanity check + return; + + if(game!=NULL) + { + int ringID=current_item_id(itype_ring, true); + _dcounter[c]+=change; + + if(ringID!=current_item_id(itype_ring, true)) + ringcolor(false); + } + else + _dcounter[c]+=change; + + return; +} + +short gamedata::get_generic(byte c) +{ + return _generic[c]; +} + +void gamedata::set_generic(byte change, byte c) +{ + _generic[c]=change; + return; +} + +void gamedata::change_generic(short change, byte c) +{ + _generic[c]+=change; + return; +} + +word gamedata::get_life() +{ + return get_counter(0); +} +void gamedata::set_life(word l) +{ + if(l <= 0) l = 0; + + set_counter(l, 0); + return; +} +void gamedata::change_life(short l) +{ + change_counter(l, 0); + + if(_dcounter[0] <= 0) _dcounter[0] = 0; + + return; +} + +word gamedata::get_maxlife() +{ + return get_maxcounter(0); +} +void gamedata::set_maxlife(word m) +{ + set_maxcounter(m, 0); + return; +} +void gamedata::change_maxlife(short m) +{ + change_maxcounter(m, 0); + return; +} + +short gamedata::get_drupy() +{ + return get_dcounter(1); +} +void gamedata::set_drupy(short d) +{ + set_dcounter(d, 1); + return; +} +void gamedata::change_drupy(short d) +{ + change_dcounter(d, 1); + return; +} + +word gamedata::get_rupies() +{ + return get_counter(1); +} +word gamedata::get_spendable_rupies() +{ + if(get_bit(quest_rules, qr_SHOPCHEAT) || get_dcounter(1)>=0) + return get_counter(1); + else + return get_counter(1)+get_dcounter(1); +} +void gamedata::set_rupies(word r) +{ + set_counter(r, 1); + return; +} +void gamedata::change_rupies(short r) +{ + change_counter(r, 1); + return; +} + +word gamedata::get_maxarrows() +{ + return get_maxcounter(3); +} +void gamedata::set_maxarrows(word a) +{ + set_maxcounter(a, 3); +} +void gamedata::change_maxarrows(short a) +{ + change_maxcounter(a, 3); + return; +} + +word gamedata::get_arrows() +{ + return get_counter(3); +} +void gamedata::set_arrows(word a) +{ + set_counter(a, 3); +} +void gamedata::change_arrows(short a) +{ + change_counter(a, 3); + return; +} + +word gamedata::get_deaths() +{ + return _deaths; +} +void gamedata::set_deaths(word d) +{ + _deaths=d; + return; +} +void gamedata::change_deaths(short d) +{ + _deaths+=d; + return; +} + +word gamedata::get_keys() +{ + return get_counter(5); +} +void gamedata::set_keys(word k) +{ + set_counter(k, 5); + return; +} +void gamedata::change_keys(short k) +{ + change_counter(k, 5); + return; +} + +word gamedata::get_bombs() +{ + return get_counter(2); +} +void gamedata::set_bombs(word k) +{ + set_counter(k, 2); + return; +} +void gamedata::change_bombs(short k) +{ + change_counter(k, 2); + return; +} + +word gamedata::get_maxbombs() +{ + return get_maxcounter(2); +} +void gamedata::set_maxbombs(word b, bool setSuperBombs) +{ + _maxcounter[2]=b; + int div = zinit.bomb_ratio; + + if(div != 0 && setSuperBombs) + set_maxcounter(b/div,6); + + return; +} +void gamedata::change_maxbombs(short b) +{ + _maxcounter[2]+=b; + int div = zinit.bomb_ratio; + + if(div != 0) + change_maxcounter(b/div,6); + + return; +} + +word gamedata::get_sbombs() +{ + return get_counter(6); +} +void gamedata::set_sbombs(word k) +{ + set_counter(k, 6); + return; +} +void gamedata::change_sbombs(short k) +{ + change_counter(k, 6); + return; +} + +word gamedata::get_wlevel() +{ + return get_generic(3); +} +void gamedata::set_wlevel(word l) +{ + set_generic(l, 3); + return; +} +void gamedata::change_wlevel(short l) +{ + change_generic(l, 3); + return; +} + +byte gamedata::get_cheat() +{ + return _cheat; +} +void gamedata::set_cheat(byte c) +{ + _cheat=c; + return; +} +void gamedata::change_cheat(short c) +{ + _cheat+=c; + return; +} + +byte gamedata::get_hasplayed() +{ + return _hasplayed; +} +void gamedata::set_hasplayed(byte p) +{ + _hasplayed=p; + return; +} +void gamedata::change_hasplayed(short p) +{ + _hasplayed+=p; + return; +} + +dword gamedata::get_time() +{ + return _time; +} +void gamedata::set_time(dword t) +{ + _time=t; + return; +} +void gamedata::change_time(long long t) +{ + _time+=t; + return; +} + +byte gamedata::get_timevalid() +{ + return _timevalid; +} +void gamedata::set_timevalid(byte t) +{ + _timevalid=t; + return; +} +void gamedata::change_timevalid(short t) +{ + _timevalid+=t; + return; +} + +byte gamedata::get_HCpieces() +{ + return get_generic(0); +} +void gamedata::set_HCpieces(byte p) +{ +#ifdef DEBUG_GD_HCP + al_trace("Setting HCP to %i\n",p); +#endif + + set_generic(p, 0); + return; +} +void gamedata::change_HCpieces(short p) +{ +#ifdef DEBUG_GD_HCP + al_trace("Changing HCP by %d to %d\n",p, get_generic(0)); +#endif + change_generic(p, 0); + return; +} + +byte gamedata::get_continue_scrn() +{ + return _continue_scrn; +} +void gamedata::set_continue_scrn(byte s) +{ + if(!isclearing && _continue_scrn != s) Z_eventlog("Continue screen set to %x\n", s); + + _continue_scrn=s; + return; +} +void gamedata::change_continue_scrn(short s) +{ + if(!isclearing && s!=0) Z_eventlog("Continue screen set to %x\n", _continue_scrn+s); + + _continue_scrn+=s; + return; +} + +word gamedata::get_continue_dmap() +{ + return _continue_dmap; +} +void gamedata::set_continue_dmap(word d) +{ + if(!isclearing && _continue_dmap!=d) Z_eventlog("Continue DMap set to %d\n", d); + + _continue_dmap=d; + return; +} +void gamedata::change_continue_dmap(short d) +{ + if(!isclearing && d!=0) Z_eventlog("Continue DMap set to %d\n", _continue_dmap+d); + + _continue_dmap+=d; + return; +} + + +word gamedata::get_maxmagic() +{ + return get_maxcounter(4); +} +void gamedata::set_maxmagic(word m) +{ + set_maxcounter(m, 4); + return; +} +void gamedata::change_maxmagic(short m) +{ + change_maxcounter(m, 4); + return; +} + +word gamedata::get_magic() +{ + return get_counter(4); +} +void gamedata::set_magic(word m) +{ + set_counter(m, 4); + return; +} +void gamedata::change_magic(short m) +{ + change_counter(m, 4); + return; +} + +short gamedata::get_dmagic() +{ + return get_dcounter(4); +} +void gamedata::set_dmagic(short d) +{ + set_dcounter(d, 4); + return; +} +void gamedata::change_dmagic(short d) +{ + change_dcounter(d, 4); + return; +} + +byte gamedata::get_magicdrainrate() +{ + return get_generic(1); +} +void gamedata::set_magicdrainrate(byte r) +{ + set_generic(r, 1); + return; +} +void gamedata::change_magicdrainrate(short r) +{ + change_generic((char)r, 1); + return; +} + +byte gamedata::get_canslash() +{ + return get_generic(2); +} +void gamedata::set_canslash(byte s) +{ + set_generic(s, 2); + return; +} +void gamedata::change_canslash(short s) +{ + change_generic(s, 2); + return; +} + +byte gamedata::get_lkeys() +{ + return lvlkeys[dlevel]; +} + +/*bool gamedata::get_item(int id) +{ +return item[id]; +}*/ + +byte gamedata::get_hcp_per_hc() +{ + return get_generic(4); +} + +void gamedata::set_hcp_per_hc(byte val) +{ + set_generic(val, 4); +} + +byte gamedata::get_cont_hearts() +{ + return get_generic(5); +} + +void gamedata::set_cont_hearts(byte val) +{ + set_generic(val, 5); +} + +bool gamedata::get_cont_percent() +{ + return get_generic(6) != 0; +} + +void gamedata::set_cont_percent(bool ispercent) +{ + set_generic(ispercent ? 1 : 0, 6); +} +void gamedata::set_item(int id, bool value) +{ + set_item_no_flush(id, value); + flushItemCache(); +} + +void gamedata::set_item_no_flush(int id, bool value) +{ + if(!isclearing && !(value == item[id])) + Z_eventlog("%sed item %i: %s\n", value ? "Gain" : "Remov", id, item_string[id]); + + item[id]=value; +} + +/*** end of gamedata.cpp ***/ + diff --git a/src/gamedata.h b/src/gamedata.h new file mode 100644 index 0000000000..734e9bd7d0 --- /dev/null +++ b/src/gamedata.h @@ -0,0 +1,20 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zelda.h +// +// Definitions, function prototypes, etc. for zelda.cc +// +//-------------------------------------------------------- + +#include "zdefs.h" + +#ifndef _GAMEDATA_H_ +#define _GAMEDATA_H_ + + + +#endif +/*** end of gamedata.h ***/ + diff --git a/src/gfxpal.h b/src/gfxpal.h new file mode 100644 index 0000000000..70be6d62ce --- /dev/null +++ b/src/gfxpal.h @@ -0,0 +1,142 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// gfxpal.cc +// +// Array of colors. +// +//-------------------------------------------------------- + +byte gfx_pal[128*3] = +{ + 63, 0, 1, // 0 + 63, 0, 3, // 2 + 63, 0, 7, // 4 + 63, 0,11, // 6 + 63, 0,15, // 8 + 63, 0,19, // 10 + 63, 0,23, // 12 + 63, 0,27, // 14 + 63, 0,31, // 16 + 63, 0,35, // 18 + 63, 0,39, // 20 + 63, 0,43, // 22 + 63, 0,47, // 24 + 63, 0,51, // 26 + 63, 0,56, // 28 + 63, 0,60, // 30 + 62, 0,63, // 32 + 60, 0,63, // 33 + 58, 0,63, // 34 + 56, 0,63, // 35 + 53, 0,63, // 36 + 51, 0,63, // 37 + 49, 0,63, // 38 + 47, 0,63, // 39 + 45, 0,63, // 40 + 43, 0,63, // 41 + 41, 0,63, // 42 + 39, 0,63, // 43 + 37, 0,63, // 44 + 35, 0,63, // 45 + 33, 0,63, // 46 + 31, 0,63, // 47 + 27, 0,63, // 49 + 23, 0,63, // 51 + 19, 0,63, // 53 + 15, 0,63, // 55 + 11, 0,63, // 57 + 7, 0,63, // 59 + 0, 0,63, // 63 + 0, 9,63, // 67 + 0,12,63, // 68 + 0,17,63, // 70 + 0,20,63, // 71 + 0,22,63, // 72 + 0,25,63, // 73 + 0,27,63, // 74 + 0,30,63, // 75 + 0,33,63, // 76 + 0,35,63, // 77 + 0,38,63, // 78 + 0,40,63, // 79 + 0,43,63, // 80 + 0,46,63, // 81 + 0,48,63, // 82 + 0,51,63, // 83 + 0,53,63, // 84 + 0,56,63, // 85 + 0,59,63, // 86 + 0,61,63, // 87 + 0,63,61, // 88 + 0,63,59, // 89 + 0,63,56, // 90 + 0,63,53, // 91 + 0,63,51, // 92 + 0,63,48, // 93 + 0,63,46, // 94 + 0,63,43, // 95 + 0,63,40, // 96 + 0,63,35, // 98 + 0,63,30, //100 + 0,63,25, //102 + 0,63,20, //104 + 0,63,14, //106 + 0,63, 9, //108 + 0,63, 0, //112 + 5,63, 0, //116 + 12,63, 0, //120 + 15,63, 0, //122 + 18,63, 0, //124 + 21,63, 0, //126 + 25,63, 0, //128 + 28,63, 0, //130 + 31,63, 0, //132 + 34,63, 0, //134 + 38,63, 0, //136 + 41,63, 0, //138 + 44,63, 0, //140 + 47,63, 0, //142 + 50,63, 0, //144 + 52,63, 0, //145 + 54,63, 0, //146 + 55,63, 0, //147 + 57,63, 0, //148 + 59,63, 0, //149 + 60,63, 0, //150 + 62,63, 0, //151 + 63,62, 0, //152 + 63,60, 0, //153 + 63,59, 0, //154 + 63,57, 0, //155 + 63,55, 0, //156 + 63,54, 0, //157 + 63,52, 0, //158 + 63,50, 0, //159 + 63,49, 0, //160 + 63,47, 0, //161 + 63,46, 0, //162 + 63,44, 0, //163 + 63,42, 0, //164 + 63,41, 0, //165 + 63,39, 0, //166 + 63,38, 0, //167 + 63,36, 0, //168 + 63,34, 0, //169 + 63,33, 0, //170 + 63,31, 0, //171 + 63,29, 0, //172 + 63,28, 0, //173 + 63,26, 0, //174 + 63,25, 0, //175 + 63,23, 0, //176 + 63,20, 0, //178 + 63,16, 0, //180 + 63,13, 0, //182 + 63,10, 0, //184 + 63, 7, 0, //186 + 63, 3, 0, //188 + 63, 0, 0 //191 +}; + diff --git a/src/gui.cpp b/src/gui.cpp new file mode 100644 index 0000000000..05d6493942 --- /dev/null +++ b/src/gui.cpp @@ -0,0 +1,266 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// gui.c +// +// System functions, input handlers, GUI stuff, etc. +// for Zelda Classic. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include +#include +#include +#include +//#include +#include +#include "zc_alleg.h" + +#ifdef ALLEGRO_DOS +#include +#endif + +#include "zdefs.h" +#include "zelda.h" +#include "zquest.h" +#include "tiles.h" +#include "colors.h" +#include "pal.h" +#include "zsys.h" +#include "qst.h" +#include "zc_sys.h" +#include "debug.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "gui.h" +#include "mem_debug.h" + +/****************************/ +/********** GUI ***********/ +/****************************/ + + +// make it global so the joystick button routine can set joy_on=TRUE +DIALOG_PLAYER *player = NULL; + +int zc_do_dialog(DIALOG *d, int f) +{ + int ret=do_zqdialog(d,f); + position_mouse_z(0); + return ret; +} + +int zc_popup_dialog(DIALOG *d, int f) +{ + int ret=popup_zqdialog(d,f); + position_mouse_z(0); + return ret; +} + +int do_dialog_through_bitmap(BITMAP *buffer, DIALOG *dialog, int focus_obj) +{ + BITMAP* orig_screen = screen; + screen = buffer; + + int ret=do_dialog(dialog, focus_obj); + + screen = orig_screen; + blit(buffer, screen, 0, 0, 0, 0, screen->w, screen->h); + position_mouse_z(0); + + return ret; +} + +int zc_popup_dialog_dbuf(DIALOG *dialog, int focus_obj) +{ + BITMAP* buffer = create_bitmap_ex(get_color_depth(),SCREEN_H,SCREEN_W); + blit(screen, buffer, 0, 0, 0, 0, SCREEN_W, SCREEN_H); + + gui_set_screen(buffer); + int ret=popup_dialog(dialog, focus_obj); + gui_set_screen(NULL); + + blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); + position_mouse_z(0); + return ret; +} + +int PopUp_dialog(DIALOG *d,int f) +{ + // uses the bitmap that's already allocated + go(); + player = init_dialog(d,f); + + while(update_dialog(player)) + { + /* do nothing */ + } + + int ret = shutdown_dialog(player); + comeback(); + position_mouse_z(0); + return ret; +} + +int popup_dialog_through_bitmap(BITMAP *buffer, DIALOG *dialog, int focus_obj) +{ + //these are here to bypass compiler warnings about unused arguments + buffer=buffer; + + BITMAP *bmp; + int ret; + + bmp = create_bitmap_ex(bitmap_color_depth(screen),dialog->w+1, dialog->h+1); + + if(bmp) + { + scare_mouse(); + blit(screen, bmp, dialog->x, dialog->y, 0, 0, dialog->w+1, dialog->h+1); + unscare_mouse(); + } + else + *allegro_errno = ENOMEM; + + ret = do_zqdialog(dialog, focus_obj); + + if(bmp) + { + scare_mouse(); + blit(bmp, screen, 0, 0, dialog->x, dialog->y, dialog->w+1, dialog->h+1); + unscare_mouse(); + destroy_bitmap(bmp); + } + + position_mouse_z(0); + + return ret; +} + +int PopUp_dialog_through_bitmap(BITMAP *buffer,DIALOG *d,int f) +{ + // uses the bitmap that's already allocated + go(); + player = init_dialog(d,f); + + while(update_dialog_through_bitmap(buffer,player)) + { + /* do nothing */ + } + + int ret = shutdown_dialog(player); + comeback(); + position_mouse_z(0); + return ret; +} + +int update_dialog_through_bitmap(BITMAP* buffer, DIALOG_PLAYER *the_player) +{ + BITMAP* orig_screen = screen; + int result; + screen = buffer; + result = update_dialog(the_player); + screen = orig_screen; + blit(buffer, screen, 0, 0, 0, 0, screen->w, screen->h); + position_mouse_z(0); + return result; +} + +extern int zqwin_scale; + +int do_zqdialog(DIALOG *dialog, int focus_obj) +{ + BITMAP *mouse_screen = _mouse_screen; + BITMAP *gui_bmp = screen; + int screen_count = _gfx_mode_set_count; + DIALOG_PLAYER *player2; + ASSERT(dialog); + + if(!is_same_bitmap(_mouse_screen, gui_bmp) && !(gfx_capabilities&GFX_HW_CURSOR)) + { + show_mouse(gui_bmp); + } + + player2 = init_dialog(dialog, focus_obj); + + while(update_dialog(player2)) + { + /* If a menu is active, we yield here, since the dialog + * engine is shut down so no user code can be running. + */ + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + + //if (active_menu_player2) + //rest(1); + } + + if(_gfx_mode_set_count == screen_count && !(gfx_capabilities&GFX_HW_CURSOR)) + { + show_mouse(mouse_screen); + } + + return shutdown_dialog(player2); +} + + + +/* popup_dialog: + * Like do_dialog(), but it stores the data on the screen before drawing + * the dialog and restores it when the dialog is closed. The screen area + * to be stored is calculated from the dimensions of the first object in + * the dialog, so all the other objects should lie within this one. + */ +int popup_zqdialog(DIALOG *dialog, int focus_obj) +{ + BITMAP *bmp; + BITMAP *gui_bmp; + int ret; + ASSERT(dialog); + + // I know we're in editor mode here, but shouldn't this be cached somehow? + bmp = create_bitmap_ex(8, dialog->w, dialog->h); + gui_bmp = screen; + + if(bmp) + { + scare_mouse_area(dialog->x, dialog->y, dialog->w, dialog->h); + blit(gui_bmp, bmp, dialog->x, dialog->y, 0, 0, dialog->w, dialog->h); + unscare_mouse(); + } + else + { + *allegro_errno = ENOMEM; + } + + ret = do_zqdialog(dialog, focus_obj); + + if(bmp) + { + scare_mouse_area(dialog->x, dialog->y, dialog->w, dialog->h); + blit(bmp, gui_bmp, 0, 0, dialog->x, dialog->y, dialog->w, dialog->h); + unscare_mouse(); + destroy_bitmap(bmp); + } + + return ret; +} + +/*** end of gui.cpp ***/ + diff --git a/src/gui.h b/src/gui.h new file mode 100644 index 0000000000..4b2d74d545 --- /dev/null +++ b/src/gui.h @@ -0,0 +1,30 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zc_sys.h +// +// System functions, input handlers, GUI stuff, etc. +// for Zelda Classic. +// +//-------------------------------------------------------- + +#ifndef _GUI_H_ +#define _GUI_H_ + +#include "zdefs.h" + +extern DIALOG_PLAYER *player; + +int zc_do_dialog(DIALOG *d, int f); +int zc_popup_dialog(DIALOG *d, int f); +int PopUp_dialog(DIALOG *d,int f); +int update_dialog_through_bitmap(BITMAP* buffer, DIALOG_PLAYER *player); +int do_dialog_through_bitmap(BITMAP *buffer, DIALOG *dialog, int focus_obj); +int popup_dialog_through_bitmap(BITMAP *buffer,DIALOG *d,int f); +int zc_popup_dialog_dbuf(DIALOG* , int); +int PopUp_dialog_through_bitmap(BITMAP *buffer,DIALOG *d,int f); +//int popup_zqdialog(DIALOG *dialog, int focus_obj); +//int do_zqdialog(DIALOG *dialog, int focus_obj); +#endif // _GUI_H_ + diff --git a/src/gui/alert.cpp b/src/gui/alert.cpp new file mode 100644 index 0000000000..a461d63cff --- /dev/null +++ b/src/gui/alert.cpp @@ -0,0 +1,94 @@ +#include "alert.h" +#include "factory.h" +#include + +using std::string; + +namespace GUI +{ + +Alert::Alert(const string& t, const string& x, const string& b): + numButtons(1), + defaultValue(1), + returnValue(1), + title(t), + text(x), + btn1(b) +{ + fixText(); +} + +Alert::Alert(const string& t, const string& x, const string& b1, + const string& b2, int def): + numButtons(2), + defaultValue(def), + returnValue(def), + title(t), + text(x), + btn1(b1), + btn2(b2) +{ + fixText(); +} + +Alert::Alert(const string& t, const string& x, const string& b1, + const string& b2, const string& b3, int def): + numButtons(3), + defaultValue(def), + returnValue(def), + title(t), + text(x), + btn1(b1), + btn2(b2), + btn3(b3) +{ + fixText(); +} + +int Alert::getResult() const +{ + return returnValue; +} + +void Alert::fixText() +{ + size_t space=0; + while(true) + { + space=text.find(' ', space+50); + if(space==string::npos) + return; + text.replace(space, 1, "\n"); + } +} + +#define SETVAL(v) boost::bind(&Alert::setValue, this, v) + +Widget* Alert::createDialog(const GUI::WidgetFactory& f) +{ + GUI::SerialContainer* btns; + + GUI::Window* win=f.window(title, + f.column(GUI::Contents( + f.text(text), + btns=f.buttonRow(GUI::Contents( + f.button(btn1, SETVAL(1))) + ) + )) + ); + + if(numButtons>1) + btns->add(f.button(btn2, SETVAL(2))); + if(numButtons==3) + btns->add(f.button(btn3, SETVAL(3))); + + return win; +} + +void Alert::setValue(int val) +{ + returnValue=val; + shutDown(); +} + +} diff --git a/src/gui/alert.h b/src/gui/alert.h new file mode 100644 index 0000000000..cd5a98b354 --- /dev/null +++ b/src/gui/alert.h @@ -0,0 +1,40 @@ +#ifndef _ZC_GUI_ALERT_H_ +#define _ZC_GUI_ALERT_H_ + +#include "dialog.h" +#include + +namespace GUI +{ + +class Alert: public Dialog +{ +public: + Alert(const std::string& title, const std::string& text, + const std::string& btn); + Alert(const std::string& title, const std::string& text, + const std::string& btn1, const std::string& btn2, int def); + Alert(const std::string& title, const std::string& text, + const std::string& btn1, const std::string& btn2, const std::string& btn3, + int def); + int getResult() const; + +private: + const int numButtons, defaultValue; + int returnValue; + std::string title, text, btn1, btn2, btn3; + + Widget* createDialog(const GUI::WidgetFactory& f); + + /// Sets the return value and closes the alert. + void setValue(int val); + + /// Splits the text into reasonably-sized lines. + void fixText(); +}; + +} + +#endif + + diff --git a/src/gui/allegro/bitmap.cpp b/src/gui/allegro/bitmap.cpp new file mode 100644 index 0000000000..d3c563f24e --- /dev/null +++ b/src/gui/allegro/bitmap.cpp @@ -0,0 +1,87 @@ +#include "bitmap.h" +#include "common.h" +#include "renderer.h" +#include "../mouse.h" +#include + +namespace GUI +{ + +int AllegroBitmapWidget::proc(int msg, DIALOG* d, int c) +{ + AllegroBitmapWidget* bmp=static_cast(d->dp); + + switch(msg) + { + case MSG_START: + bmp->underMouse=dialogUnderMouse(d); + bmp->lastMouseX=gui_mouse_x(); + bmp->lastMouseY=gui_mouse_y(); + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_GOTMOUSE: + bmp->underMouse=true; + break; + + case MSG_LOSTMOUSE: + bmp->underMouse=true; + break; + + case MSG_LPRESS: + case MSG_LRELEASE: + case MSG_RPRESS: + case MSG_RRELEASE: + case MSG_WHEEL: + case MSG_IDLE: // There's no mouse motion event... + if(bmp->handlingMouseInput) + bmp->onMouseInput(msg, c); + break; + } + + return D_O_K; +} + +AllegroBitmapWidget::AllegroBitmapWidget(BitmapBackend* be): + backend(be), + handlingMouseInput(false), + underMouse(false), + lastMouseX(gui_mouse_x()), + lastMouseY(gui_mouse_y()) +{ + backend->setWidget(this); + backend->initialize(); +} + +void AllegroBitmapWidget::getPreferredSize(int& prefWidth, int& prefHeight) +{ + backend->getSize(prefWidth, prefHeight); +} + +int AllegroBitmapWidget::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void AllegroBitmapWidget::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + backend->redraw(); + renderer.blitBitmap(backend->getBitmap(), 0, 0); +} + +void AllegroBitmapWidget::onMouseInput(int msg, int c) +{ + if(msg==MSG_IDLE && lastMouseX==gui_mouse_x() && lastMouseY==gui_mouse_y()) + return; + + MouseInput mi; + translateMouseInput(msg, c, x, y, backend->getScale(), mi); + backend->onMouseInput(mi); + lastMouseX=gui_mouse_x(); + lastMouseY=gui_mouse_y(); +} + +} diff --git a/src/gui/allegro/bitmap.h b/src/gui/allegro/bitmap.h new file mode 100644 index 0000000000..d9cff795d8 --- /dev/null +++ b/src/gui/allegro/bitmap.h @@ -0,0 +1,32 @@ +#ifndef _ZC_GUI_ALLEGRO_BITMAP_H_ +#define _ZC_GUI_ALLEGRO_BITMAP_H_ + +#include "../bitmap.h" +#include "standardWidget.h" + +namespace GUI +{ + +class AllegroBitmapWidget: public BitmapWidget, public StandardAllegroWidget +{ +public: + AllegroBitmapWidget(BitmapBackend* backend); + void getPreferredSize(int& prefWidth, int& prefHeight); + int realize(DIALOG dlgArray[], int index); + void draw(AllegroGUIRenderer& renderer) const; + inline void setHandleMouseInput(bool h) { handlingMouseInput=h; } + + static int proc(int msg, DIALOG* d, int c); + +private: + scoped_ptr backend; + bool handlingMouseInput; + bool underMouse; + int lastMouseX, lastMouseY; + + void onMouseInput(int msg, int c); +}; + +} + +#endif diff --git a/src/gui/allegro/button.cpp b/src/gui/allegro/button.cpp new file mode 100644 index 0000000000..ce9cbb9cac --- /dev/null +++ b/src/gui/allegro/button.cpp @@ -0,0 +1,130 @@ +#include "button.h" +#include "common.h" +#include "renderer.h" +#include + +namespace GUI +{ + +int AllegroButton::proc(int msg, DIALOG* d, int c) +{ + AllegroButton* btn=static_cast(d->dp); + + switch(msg) + { + case MSG_START: + btn->underMouse=dialogUnderMouse(d); + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_GOTMOUSE: + btn->onMouseEnter(); + break; + + case MSG_LOSTMOUSE: + btn->onMouseExit(); + break; + + case MSG_LPRESS: + btn->onMouseDown(); + break; + + case MSG_LRELEASE: + btn->onMouseUp(); + break; + + case MSG_KEY: + btn->onClick(); + break; + + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + } + + return D_O_K; +} + +AllegroButton::AllegroButton(AllegroWidget* i, boost::function f): + image(i), + onClick(f), + underMouse(false), + clicked(false) +{ +} + +void AllegroButton::onMouseEnter() +{ + underMouse=true; + //if(clicked) + //image->move(0, 2); +} + +void AllegroButton::onMouseExit() +{ + underMouse=false; + //if(clicked) + //image->move(0, -2); +} + +void AllegroButton::onMouseDown() +{ + clicked=true; + //image->move(0, 2); +} + +void AllegroButton::onMouseUp() +{ + clicked=false; + if(underMouse) + { + //if(clicked) + //image->move(0, 2); + onClick(); + } +} + +void AllegroButton::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + const GUIColor& fg=underMouse ? pal.buttonTextHL : pal.buttonText; + const GUIColor& bg=underMouse ? pal.buttonHL : pal.button; + int offset=(underMouse && clicked) ? 2 : 0; + + renderer.fillRoundedRect(0, offset, width, height, 8, bg); + renderer.drawRoundedRect(0, offset, width, height, 8, pal.outline); + if((dialog->flags&D_GOTFOCUS)!=0) + renderer.drawRoundedRect(4, 4+offset, width-8, height-8, 5, pal.buttonHL); + + image->draw(renderer); +} + +void AllegroButton::getPreferredSize(int& prefWidth, int& prefHeight) +{ + prefWidth=90; + prefHeight=50; +} + +void AllegroButton::setSizeAndPos(int newX, int newY, + int newWidth, int newHeight) +{ + adjustSizeAndPos(newX, newWidth, 80); + adjustSizeAndPos(newY, newHeight, 30); + image->setSizeAndPos(newX+5, newY+5, newWidth-10, newHeight-10); + StandardAllegroWidget::setSizeAndPos(newX, newY, newWidth, newHeight); +} + +int AllegroButton::getDataSize() const +{ + return image->getDataSize()+1; +} + +int AllegroButton::realize(DIALOG dlgArray[], int index) +{ + realizeAs(dlgArray, index, 0); //getKey(text)); + return 1+image->realize(dlgArray, index+1); +} + +} diff --git a/src/gui/allegro/button.h b/src/gui/allegro/button.h new file mode 100644 index 0000000000..d7f01e401a --- /dev/null +++ b/src/gui/allegro/button.h @@ -0,0 +1,42 @@ +#ifndef _ZC_GUI_ALLEGRO_BUTTON_H_ +#define _ZC_GUI_ALLEGRO_BUTTON_H_ + +#include "../button.h" +#include "standardWidget.h" +#include +#include + +struct FONT; + +namespace GUI +{ + +class AllegroButton: public Button, public StandardAllegroWidget +{ +public: + AllegroButton(AllegroWidget* image, boost::function onClick); + + // Inherited + void draw(AllegroGUIRenderer& renderer) const; + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroWidget* image; + boost::function onClick; + bool underMouse, clicked; + + void onMouseEnter(); + void onMouseExit(); + void onMouseDown(); + void onMouseUp(); +}; + +} + +#endif + diff --git a/src/gui/allegro/checkbox.cpp b/src/gui/allegro/checkbox.cpp new file mode 100644 index 0000000000..995ca2ce1b --- /dev/null +++ b/src/gui/allegro/checkbox.cpp @@ -0,0 +1,87 @@ +#include "checkbox.h" +#include "common.h" +#include "renderer.h" +#include + +extern FONT* zfont; + +namespace GUI +{ + +int AllegroCheckbox::proc(int msg, DIALOG* d, int c) +{ + AllegroCheckbox* cb=static_cast(d->dp); + + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_LPRESS: + case MSG_KEY: + cb->toggle(); + break; + + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + } + + return D_O_K; +} + +AllegroCheckbox::AllegroCheckbox(const std::string& t, FONT* f): + StandardAllegroWidget(), + text(t), + font(f), + checked(false) +{ +} + +void AllegroCheckbox::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + if((dialog->flags&D_GOTFOCUS)!=0) + renderer.drawRoundedRect(0, 0, width, height, 7, pal.buttonHL); + + renderer.fillRoundedRect(2, 2, 14, 14, 3, pal.editBG); + renderer.drawRoundedRect(2, 2, 14, 14, 3, pal.outline); + renderer.drawText(text, 20, (18-text_height(font))/2, font, pal.winBodyText); + + if(checked) + { + // This sucks + static const char check[2]={ (char)129, 0 }; + renderer.drawText(check, 5, 6, zfont, pal.winBodyText); + } +} + +void AllegroCheckbox::getPreferredSize(int& prefWidth, int& prefHeight) +{ + FONT* tempFont=::font; + ::font=font; + prefWidth=22+gui_strlen(text.c_str()); + ::font=tempFont; + prefHeight=18; +} + +void AllegroCheckbox::setSizeAndPos(int newX, int newY, + int newWidth, int newHeight) +{ + adjustSizeAndPos(newY, newHeight, 18); + StandardAllegroWidget::setSizeAndPos(newX, newY, newWidth, newHeight); +} + +void AllegroCheckbox::toggle() +{ + checked=!checked; + if(onValueChanged) + onValueChanged(checked); +} + +int AllegroCheckbox::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index, getKey(text)); +} + +} diff --git a/src/gui/allegro/checkbox.h b/src/gui/allegro/checkbox.h new file mode 100644 index 0000000000..218187e926 --- /dev/null +++ b/src/gui/allegro/checkbox.h @@ -0,0 +1,43 @@ +#ifndef _ZC_GUI_ALLEGRO_CHECKBOX_H_ +#define _ZC_GUI_ALLEGRO_CHECKBOX_H_ + +#include "../checkbox.h" +#include "standardWidget.h" +#include +#include + +struct FONT; + +namespace GUI +{ + +class AllegroCheckbox: public Checkbox, public StandardAllegroWidget +{ +public: + AllegroCheckbox(const std::string& text, FONT* font); + + // Inherited + inline bool getValue() const { return checked; } + inline void setValue(bool newValue) { checked=newValue; } + inline void setCallback(boost::function func) { onValueChanged=func; } + void draw(AllegroGUIRenderer& renderer) const; + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + int realize(DIALOG dlgArray[], int index); + + static int proc(int msg, DIALOG* d, int c); + +private: + std::string text; + FONT* font; + bool checked; + boost::function onValueChanged; + + /// Toggles the checkbox's state. + void toggle(); +}; + +} + +#endif + diff --git a/src/gui/allegro/column.cpp b/src/gui/allegro/column.cpp new file mode 100644 index 0000000000..38507e222e --- /dev/null +++ b/src/gui/allegro/column.cpp @@ -0,0 +1,104 @@ +#include "column.h" +#include + +namespace GUI +{ + +AllegroColumn::AllegroColumn(): + targetHeight(0), + numExpanders(0), + padding(0) +{ +} + +void AllegroColumn::add(Widget* w) +{ + AllegroSerialContainer::add(w); + //if(dynamic_cast(w)->heightIsFlexible()) + //numExpanders++; +} + +void AllegroColumn::getPreferredSize(int& prefWidth, int& prefHeight) +{ + //prefWidth=getGreatestContentWidth(); + //prefHeight=getTotalContentHeight(); + + prefWidth=0; + prefHeight=0; + numExpanders=0; + padding=0; + bool lastHadPadding=false; + + for(int i=0; igetPreferredSize(tempW, tempH); + prefHeight+=tempH; + + if(false) //c->wantsPadding()) + { + if(lastHadPadding) + prefHeight+=16; + else + prefHeight+=32; + tempW+=32; + lastHadPadding=true; + } + else + lastHadPadding=false; + + if(tempW>prefWidth) + prefWidth=tempW; + + if(c->heightIsFlexible()) + numExpanders++; + } + + // If everything wants padding, don't add too much + if(padding==contents.size()) + padding--; + + prefHeight+=padding; + targetHeight=prefHeight; +} + +void AllegroColumn::setSizeAndPos(int newX, int newY, int newW, int newH) +{ + bool lastHadPadding=false; + + // Divide extra space evenly among expanding widgets + int extraSpace=(newH-targetHeight)/((numExpanders>0) ? numExpanders : contents.size()); + + for(int i=0; igetPreferredSize(dummy, compH); + if(numExpanders==0 || c->heightIsFlexible()) + compH+=extraSpace; + + if(false) //c->wantsPadding()) + { + if(lastHadPadding) + { + c->setSizeAndPos(newX, newY, newW, compH); + newY+=compH+16; + } + else + { + c->setSizeAndPos(newX, newY+16, newW, compH); + newY+=compH+32; + } + lastHadPadding=true; + } + else + { + c->setSizeAndPos(newX, newY, newW, compH); + newY+=compH; + lastHadPadding=false; + } + } +} + +} diff --git a/src/gui/allegro/column.h b/src/gui/allegro/column.h new file mode 100644 index 0000000000..ce3dee1a1b --- /dev/null +++ b/src/gui/allegro/column.h @@ -0,0 +1,29 @@ +#ifndef _ZC_GUI_ALLEGRO_COLUMN_H_ +#define _ZC_GUI_ALLEGRO_COLUMN_H_ + +#include "serialContainer.h" +#include + +namespace GUI +{ + +class AllegroColumn: public AllegroSerialContainer +{ +public: + AllegroColumn(); + + // Inherited + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newW, int newH); + void add(Widget* w); + + bool heightIsFlexible() const { return numExpanders>0; } + +private: + int targetHeight, numExpanders, padding; +}; + +} + +#endif + diff --git a/src/gui/allegro/comboBox.cpp b/src/gui/allegro/comboBox.cpp new file mode 100644 index 0000000000..d34924b7f7 --- /dev/null +++ b/src/gui/allegro/comboBox.cpp @@ -0,0 +1,128 @@ +#include "comboBox.h" +#include "common.h" +#include "controller.h" +#include "factory.h" +#include "list.h" +#include "renderer.h" +#include "text.h" +#include +#include + +namespace GUI +{ + +int AllegroComboBox::proc(int msg, DIALOG* d, int c) +{ + AllegroComboBox* cb=static_cast(d->dp); + + switch(msg) + { + case MSG_LPRESS: + cb->onClick(); + break; + } + + return D_O_K; +} + +AllegroComboBox::AllegroComboBox(const ListData* ld, const AllegroWidgetFactory& awf): + list(static_cast(awf.list(ld))), + text(static_cast(awf.text(""))), + data(ld), + selected(-1) +{ + list->setOnValueChanged(boost::bind(&AllegroComboBox::selectionChanged, this, _1)); +} + +AllegroComboBox::~AllegroComboBox() +{ + delete list; // This will also delete the ListData + delete text; +} + +void AllegroComboBox::onClick() +{ + while(gui_mouse_b()) + // Don't open the list immediately or it might get clicked + rest(1); + controller->beginSubDialog(list); +} + +void AllegroComboBox::selectionChanged(int newSel) +{ + selected=newSel; + while(gui_mouse_b()) + // Don't let whatever was behind the list get clicked + rest(1); + controller->closeSubDialog(); + text->setText(data->get(newSel)); + if(onValueChanged) + onValueChanged(newSel); +} + +void AllegroComboBox::getPreferredSize(int& prefWidth, int& prefHeight) +{ + // Ask the list so it can do whatever calculation it wants... + list->getPreferredSize(prefWidth, prefHeight); + + // And ignore the result, because it's a drop-down list + text->getPreferredSize(prefWidth, prefHeight); + if(prefWidth>116) + prefWidth=120; + else + prefWidth+=4; + prefHeight+=4; +} + +int AllegroComboBox::getDataSize() const +{ + // Don't include the list; it runs as a sub-dialog + return text->getDataSize()+1; +} + +int AllegroComboBox::realize(DIALOG dlgArray[], int index) +{ + // Same here + int used=realizeAs(dlgArray, index); + used+=text->realize(dlgArray, index+used); + return used; +} + +void AllegroComboBox::setController(AllegroDialogController* c) +{ + StandardAllegroWidget::setController(c); + text->setController(c); + list->setController(c); +} + +void AllegroComboBox::setSizeAndPos(int x, int y, int width, int height) +{ + int dummyW=width, dummyH=height; + text->getPreferredSize(dummyW, dummyH); + adjustSizeAndPos(y, height, dummyH+4); + StandardAllegroWidget::setSizeAndPos(x, y, width, height); + text->setSizeAndPos(x+2, y+2, width-4, height-4); + list->setSizeAndPos(x, y+height, width, 80); +} + +void AllegroComboBox::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.fillRect(0, 0, width, height, pal.editBG); + renderer.drawRect(0, 0, width, height, pal.winBodyText); + renderer.fillTriangle(width-14, 4, width-2, 4, width-8, height-4, pal.editText); + renderer.pushClipRect(2, 2, width-16, height-4); + text->draw(renderer); + renderer.popClipRect(); +} + +void AllegroComboBox::setSelected(int num) +{ + selected=num; + text->setText(data->get(num)); +} + +} + + + diff --git a/src/gui/allegro/comboBox.h b/src/gui/allegro/comboBox.h new file mode 100644 index 0000000000..69b6ea55fe --- /dev/null +++ b/src/gui/allegro/comboBox.h @@ -0,0 +1,44 @@ +#ifndef _ZC_GUI_ALLEGRO_COMBOBOX_H_ +#define _ZC_GUI_ALLEGRO_COMBOBOX_H_ + +#include "../list.h" +#include "standardWidget.h" + +namespace GUI +{ + +class AllegroList; +class AllegroText; +class AllegroWidgetFactory; + +class AllegroComboBox: public List, public StandardAllegroWidget +{ +public: + AllegroComboBox(const ListData* ld, const AllegroWidgetFactory& awf); + ~AllegroComboBox(); + void getPreferredSize(int& prefWidth, int& prefHeight); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void setController(AllegroDialogController* c); + void setSizeAndPos(int x, int y, int width, int height); + void draw(AllegroGUIRenderer& renderer) const; + + void setSelected(int num); + inline int getSelected() const { return selected; } + inline void setOnValueChanged(const boost::function& f) { onValueChanged=f; } + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroList* list; + AllegroText* text; + const ListData* data; + int selected; + boost::function onValueChanged; + + void onClick(); + void selectionChanged(int newSel); +}; + +} + +#endif diff --git a/src/gui/allegro/common.cpp b/src/gui/allegro/common.cpp new file mode 100644 index 0000000000..89e164d1b4 --- /dev/null +++ b/src/gui/allegro/common.cpp @@ -0,0 +1,117 @@ +#include "common.h" +#include "scrollbar.h" +#include "../mouse.h" +#include "../../zsys.h" + +namespace GUI +{ + +GUIColor GUIColor::adjust(int ar, int ag, int ab) const +{ + GUIColor gc; + gc.red=vbound(red+ar, 0, 255); + gc.green=vbound(green+ag, 0, 255); + gc.blue=vbound(blue+ab, 0, 255); + return gc; +} + +GUIColor GUIColor::adjust(float ar, float ag, float ab) const +{ + GUIColor gc; + gc.red=vbound(static_cast(ar*red), 0, 255); + gc.green=vbound(static_cast(ag*green), 0, 255); + gc.blue=vbound(static_cast(ab*blue), 0, 255); + return gc; +} + +GUIPalette pal= +{ + { 0, 16, 32 }, // outline + + { 0, 64, 128 }, // winBorder + { 255, 255, 255 }, // winTitleText + { 224, 224, 224 }, // winBody + { 0, 0, 0}, // winBodyText + + { 255, 255, 255 }, // editBG + { 0, 0, 0 }, // editText + { 0, 64, 128 }, // editHL + { 64, 64, 64 }, // editInactiveHL + { 255, 255, 255 }, // editTextHL + + { 0, 64, 128 }, // button + { 128, 192, 255 }, // buttonHL + { 255, 255, 255 }, // buttonText + { 255, 255, 255 }, // buttonTextHL + + { 128, 192, 255 }, // scrollbarFill + { 0, 64, 128 } // scrollbarSlider +}; + +// Allegro doesn't offer an easy way for two DIALOGs in the same place +// both to handle only a subset of mouse input... +void forwardMouseWheel(DIALOG* d, int c) +{ + for(DIALOG* d2=d; d2->proc; d2++) + { + if((d2->flags&D_WANTWHEEL)!=0 && dialogUnderMouse(d2)) + { + object_message(d2, MSG_WHEEL, c); + break; + } + } +} + +void translateMouseInput(int msg, int c, int bmpX, int bmpY, int scale, + MouseInput& out) +{ + switch(msg) + { + case MSG_IDLE: + out.type=mouse_MOTION; + break; + + case MSG_LPRESS: + out.type=mouse_LEFTBUTTONDOWN; + break; + + case MSG_LRELEASE: + out.type=mouse_LEFTBUTTONUP; + break; + + case MSG_RPRESS: + out.type=mouse_RIGHTBUTTONDOWN; + break; + + case MSG_RRELEASE: + out.type=mouse_RIGHTBUTTONUP; + break; + + case MSG_WHEEL: + if(c<0) + out.type=mouse_WHEELUP; + else + out.type=mouse_WHEELDOWN; + break; + + default: + return; + } + + out.x=(gui_mouse_x()-bmpX)/scale; + out.y=(gui_mouse_y()-bmpY)/scale; + out.shiftPressed=key[KEY_LSHIFT] || key[KEY_RSHIFT]; + out.ctrlPressed=key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]; + out.altPressed=key[KEY_ALT]||key[KEY_ALTGR]; +} + +int dummyProc(int msg, DIALOG* d, int c) +{ + // TODO: Does this need to refuse mouse input? Won't it block + // the scroll wheel otherwise? + if(msg==MSG_WHEEL) + forwardMouseWheel(d, c); + return D_O_K; +} + +} diff --git a/src/gui/allegro/common.h b/src/gui/allegro/common.h new file mode 100644 index 0000000000..b2c5bf00d1 --- /dev/null +++ b/src/gui/allegro/common.h @@ -0,0 +1,91 @@ +#ifndef _ZC_GUI_ALLEGRO_COMMON_H_ +#define _ZC_GUI_ALLEGRO_COMMON_H_ + +#include +#include +#include + +struct MouseInput; + +extern BITMAP* hw_screen; +extern volatile int myvsync; +extern int zqwin_scale; +extern int scheme[jcMAX]; + +int gui_textout_ln(BITMAP *bmp, unsigned char *s, int x, int y, int color, int bg, int pos); +bool is_zquest(); + +namespace GUI +{ + +struct GUIColor +{ + int red, green, blue; + inline operator int() const { return makecol(red, green, blue); } + GUIColor adjust(int ar, int ag, int ab) const; + GUIColor adjust(float ar, float ag, float ab) const; +}; + +struct GUIPalette +{ + GUIColor outline; + + GUIColor winBorder; + GUIColor winTitleText; + GUIColor winBody; + GUIColor winBodyText; + + GUIColor editBG; + GUIColor editText; + GUIColor editHL; + GUIColor editInactiveHL; + GUIColor editTextHL; + + GUIColor button; + GUIColor buttonHL; + GUIColor buttonText; + GUIColor buttonTextHL; + + GUIColor scrollbarFill; + GUIColor scrollbarSlider; +}; + +extern GUIPalette pal; + +#define MSG_SCROLL MSG_USER +#define D_WANTWHEEL D_USER + +// Is this useful? Not sure. +inline bool dialogUnderMouse(DIALOG* d) +{ + return mouse_in_rect(d->x, d->y, d->w, d->h); +} + +// Things that have maximum sizes call this from setSizeAndPos() +// to adjust inputs. +inline void adjustSizeAndPos(int& pos, int& size, int maxSize) +{ + pos+=(size-maxSize)/2; + size=maxSize; +} + +/// Forwards MSG_WHEEL to DIALOGs that handle it. +void forwardMouseWheel(DIALOG* d, int c); + +/// Translates Allegro dialog messages into MouseInput. +void translateMouseInput(int msg, int c, int bmpX, int bmpY, int scale, + MouseInput& out); + +/// Dialog proc that does nothing. +int dummyProc(int msg, DIALOG* d, int c); + +/// Finds the character preceded by '&' in a string. +inline char getKey(const std::string& text) +{ + int amp=text.find('&'); + return (amp>=0) ? text[amp+1] : '\0'; +} + +} + +#endif diff --git a/src/gui/allegro/controller.cpp b/src/gui/allegro/controller.cpp new file mode 100644 index 0000000000..60289948b6 --- /dev/null +++ b/src/gui/allegro/controller.cpp @@ -0,0 +1,194 @@ +#include "controller.h" +#include "widget.h" +#include +#include + +extern BITMAP *hw_screen; // Because ZQuest replaces screen... + +namespace GUI +{ + +AllegroDialogController::AllegroDialogController(): + root(0), + subRoot(0), + allegDlg(0), + subAllegDlg(0), + player(0), + subPlayer(0), + open(false) +{ + savedBG.bmp=0; + savedBG.x=0; + savedBG.y=0; +} + +AllegroDialogController::~AllegroDialogController() +{ + if(open) + { + if(subPlayer) + { + shutdown_dialog(subPlayer); + delete[] subAllegDlg; + } + + shutdown_dialog(player); + delete[] allegDlg; + } + + if(savedBG.bmp) + destroy_bitmap(savedBG.bmp); + + delete root; +} + +void AllegroDialogController::setDialogRoot(Widget* r) +{ + root=dynamic_cast(r); + root->setController(this); +} + +void AllegroDialogController::initialize() +{ + int dialogSize=root->getDataSize()+1; // Last one is the terminator + allegDlg=new DIALOG[dialogSize]; + std::memset(allegDlg, 0, dialogSize*sizeof(DIALOG)); + + int x, y, w, h; + root->getPreferredSize(w, h); + x=(SCREEN_W-w)/2; + y=(SCREEN_H-h)/2; + root->setSizeAndPos(x, y, w, h); + root->realize(allegDlg, 0); + + savedBG.bmp=create_bitmap_ex(8, w, h); + savedBG.x=x; + savedBG.y=y; + blit(screen, savedBG.bmp, x, y, 0, 0, w, h); + + player=init_dialog(allegDlg, -1); + open=true; + updating=false; +} + +void AllegroDialogController::update() +{ + if(open) + { + updating=true; + bool ret; + if(subPlayer) + ret=update_dialog(subPlayer); + else + ret=update_dialog(player); + + // Undo any clipping before drawing or quitting + screen->ct=0; + screen->cb=screen->h-1; + screen->cl=0; + screen->cr=screen->w-1; + + if(ret) + { + if(subPlayer && !subRoot) // Sub-dialog was closed + closeSubDialog(true); + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + rest(1); // This should probably be moved... + } + else + { + // User pressed escape + if(subPlayer) + closeSubDialog(true); + else + open=false; + } + + if(open) + { + if(subRoot) + subRoot->draw(renderer); + else + root->draw(renderer); + } + else + { + // Escape was pressed or the dialog was closed mid-update + deleteDialogData(); + restoreBG(); + } + + updating=false; + } +} + +void AllegroDialogController::shutDown() +{ + if(open) + { + open=false; + + // If updating is true, the dialog was shut down by a dialog element. + // Deleting everything in the middle of an update would be a bad idea. + if(!updating) + { + deleteDialogData(); + restoreBG(); + } + } + + position_mouse_z(0); +} + +void AllegroDialogController::deleteDialogData() +{ + if(subPlayer) + { + shutdown_dialog(subPlayer); + subPlayer=0; + delete[] subAllegDlg; + } + + shutdown_dialog(player); + player=0; + delete[] allegDlg; + allegDlg=0; + open=false; +} + +void AllegroDialogController::restoreBG() +{ + blit(savedBG.bmp, screen, 0, 0, savedBG.x, savedBG.y, savedBG.bmp->w, savedBG.bmp->h); + destroy_bitmap(savedBG.bmp); + savedBG.bmp=0; +} + +void AllegroDialogController::beginSubDialog(AllegroWidget* r) +{ + subRoot=r; + subRoot->setController(this); // Shouldn't be necessary... + + int size=subRoot->getDataSize()+1; + subAllegDlg=new DIALOG[size]; // Still needs one more to catch clicks outside the dialog + std::memset(subAllegDlg, 0, size*sizeof(DIALOG)); + subRoot->realize(subAllegDlg, 0); + subPlayer=init_dialog(subAllegDlg, -1); +} + +void AllegroDialogController::closeSubDialog(bool safe) +{ + if(subRoot) + subRoot->unrealize(); + subRoot=0; + + if(updating && !safe) + // Still in mid-update; don't shut down yet + return; + + shutdown_dialog(subPlayer); + subPlayer=0; + delete[] subAllegDlg; + subAllegDlg=0; +} + +} diff --git a/src/gui/allegro/controller.h b/src/gui/allegro/controller.h new file mode 100644 index 0000000000..6f3888ba2f --- /dev/null +++ b/src/gui/allegro/controller.h @@ -0,0 +1,55 @@ +#ifndef _ZC_GUI_ALLEGRO_CONTROLLER_H_ +#define _ZC_GUI_ALLEGRO_CONTROLLER_H_ + +#include "../controller.h" +#include "renderer.h" +struct BITMAP; +struct DIALOG; +struct DIALOG_PLAYER; + +namespace GUI +{ + +class AllegroWidget; + +class AllegroDialogController: public DialogController +{ +public: + AllegroDialogController(); + ~AllegroDialogController(); + + void setDialogRoot(Widget* root); + void initialize(); + void update(); + void shutDown(); + inline bool isOpen() { return open; } + + /// Runs a widget as the root of a new dialog over the current one. + void beginSubDialog(AllegroWidget* root); + void closeSubDialog(bool safe=false); + +private: + struct BackupBitmap + { + BITMAP* bmp; + int x, y; + }; + + AllegroWidget* root; + AllegroWidget* subRoot; + DIALOG* allegDlg; + DIALOG* subAllegDlg; + DIALOG_PLAYER* player; + DIALOG_PLAYER* subPlayer; + bool open; + bool updating; + BackupBitmap savedBG; + AllegroGUIRenderer renderer; + + void deleteDialogData(); + void restoreBG(); +}; + +} + +#endif diff --git a/src/gui/allegro/dummy.cpp b/src/gui/allegro/dummy.cpp new file mode 100644 index 0000000000..3259e6f4c2 --- /dev/null +++ b/src/gui/allegro/dummy.cpp @@ -0,0 +1,39 @@ +#include "dummy.h" +#include "common.h" +#include "renderer.h" + +extern FONT* lfont; + +namespace GUI +{ + +int DummyAllegroWidget::proc(int msg, DIALOG* d, int c) +{ + return dummyProc(msg, d, c); +} + +DummyAllegroWidget::DummyAllegroWidget(int w, int h): + width(w), + height(h) +{ +} + +void DummyAllegroWidget::getPreferredSize(int& prefWidth, int& prefHeight) +{ + prefWidth=width; + prefHeight=height; +} + +int DummyAllegroWidget::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void DummyAllegroWidget::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.drawRect(0, 0, width, height, pal.winBorder); + renderer.drawText("Dummy", 3, 3, lfont, pal.winBodyText); +} + +} diff --git a/src/gui/allegro/dummy.h b/src/gui/allegro/dummy.h new file mode 100644 index 0000000000..55ce942e94 --- /dev/null +++ b/src/gui/allegro/dummy.h @@ -0,0 +1,43 @@ +#ifndef _ZC_GUI_ALLEGRO_DUMMY_H_ +#define _ZC_GUI_ALLEGRO_DUMMY_H_ + +#include "standardWidget.h" +#include "../spinner.h" +#include "../textBox.h" + +// A placeholder for any widgets that aren't implemented yet (and possibly won't be) + +namespace GUI +{ + +class DummyAllegroWidget: public StandardAllegroWidget, + public Spinner, + public TextBox +{ +public: + DummyAllegroWidget(int w, int h); + + void getPreferredSize(int& prefWidth, int& prefHeight); + int realize(DIALOG dlgArray[], int index); + void draw(AllegroGUIRenderer& renderer) const; + + static int proc(int msg, DIALOG* d, int c); + + // Spinner + void setValue(int val) {} + int getValue() const { return 0; } + void setOnValueChanged(boost::function func) {} + + // TextBox + void setText(const std::string& text) {} + std::string getText() const { return ""; } + +private: + int width, height; +}; + +} + +#endif + + diff --git a/src/gui/allegro/editableText.cpp b/src/gui/allegro/editableText.cpp new file mode 100644 index 0000000000..9c3a876409 --- /dev/null +++ b/src/gui/allegro/editableText.cpp @@ -0,0 +1,59 @@ +#include "editableText.h" +#include "common.h" +#include "renderer.h" +#include +#include + +using std::max; +using std::min; + +namespace GUI +{ + +EditableText::EditableText(FONT* f): + font(f), + height(text_height(f)) +{ +} + +void EditableText::deleteText(int start, int end) +{ + start=max(start, 0); + end=min(end, (int)text.length()); + text.erase(start, end-start); +} + +void EditableText::putChar(int character, int pos) +{ + if((character<32) || (character>255)) + return; + + text.insert(pos, 1, character); +} + +void EditableText::draw(AllegroGUIRenderer& renderer, int x, int y, int width, + int cursorPos, int highlightPos, bool active) const +{ + renderer.setOrigin(x, y); + + renderer.drawText(text, 1, 0, font, pal.editText); + + if(active) + { + int cursorX=text_length(font, text.substr(0, cursorPos).c_str()); + renderer.drawLine(cursorX, 1, cursorX, height-1, pal.editText); + } + + if(highlightPos!=cursorPos) + { + int start=min(cursorPos, highlightPos); + int end=max(cursorPos, highlightPos); + int hlStartX=text_length(font, text.substr(0, start).c_str()); + int hlEndX=text_length(font, text.substr(0, end).c_str()); + const GUIColor& bg=active ? pal.editHL : pal.editInactiveHL; + renderer.fillRect(hlStartX, 0, hlEndX-hlStartX, height-1, bg); + renderer.drawText(text.substr(start, end-start), hlStartX+1, 0, font, pal.editTextHL); + } +} + +} // Namespace diff --git a/src/gui/allegro/editableText.h b/src/gui/allegro/editableText.h new file mode 100644 index 0000000000..c3612ea56b --- /dev/null +++ b/src/gui/allegro/editableText.h @@ -0,0 +1,36 @@ +#ifndef _ZC_GUI_ALLEGRO__EDITABLETEXT_H_ +#define _ZC_GUI_ALLEGRO__EDITABLETEXT_H_ + +#include +struct BITMAP; +struct FONT; + +namespace GUI +{ + +class AllegroGUIRenderer; + +/** Editable text for use in text editing widgets */ +// The implementation could be more efficient. +// std::string isn't made for this sort of thing. +class EditableText +{ +public: + EditableText(FONT* font); + void putChar(int character, int pos); + inline void setText(const std::string& newText) { text.assign(newText); } + void draw(AllegroGUIRenderer& renderer, int x, int y, int width, int cursorPos, int highlightPos, bool active) const; + void deleteText(int start, int end); + inline size_t length() const { return text.length(); } + inline std::string getText() const { return text; } + inline int getHeight() const { return height; } + +private: + std::string text; + FONT* font; + const int height; +}; + +} + +#endif diff --git a/src/gui/allegro/factory.cpp b/src/gui/allegro/factory.cpp new file mode 100644 index 0000000000..a886791a79 --- /dev/null +++ b/src/gui/allegro/factory.cpp @@ -0,0 +1,141 @@ +#include "factory.h" +#include "bitmap.h" +#include "button.h" +#include "checkbox.h" +#include "column.h" +#include "comboBox.h" +#include "common.h" +#include "controller.h" +#include "frame.h" +#include "list.h" +#include "row.h" +#include "tabPanel.h" +#include "text.h" +#include "textField.h" +#include "window.h" +#include + +#include "dummy.h" + +extern FONT* lfont; +extern FONT* lfont_l; +extern FONT* dsphantompfont; + +namespace GUI +{ + +DialogController* AllegroWidgetFactory::controller() const +{ + return new AllegroDialogController(); +} + +BitmapWidget* AllegroWidgetFactory::bitmap(BitmapBackend* backend, int scale) const +{ + backend->setRenderer(new GUIBitmapRenderer(scale)); + return new AllegroBitmapWidget(backend); +} + +Window* AllegroWidgetFactory::window(const std::string& title, + Widget* contents) const +{ + return new AllegroWindow(title, lfont, + dynamic_cast(contents)); +} + +Button* AllegroWidgetFactory::button(const std::string& text, + boost::function onClick) const +{ + AllegroText* allText=new AllegroText(text, lfont, pal.buttonText); + allText->setCentered(true); + return new AllegroButton(allText, onClick); +} + +Checkbox* AllegroWidgetFactory::checkbox(const std::string& text) const +{ + return new AllegroCheckbox(text, lfont_l); +} + +List* AllegroWidgetFactory::comboBox(const ListData* data) const +{ + return new AllegroComboBox(data, *this); +} + +List* AllegroWidgetFactory::list(const ListData* data) const +{ + return new AllegroList(data, *this); +} + +Spinner* AllegroWidgetFactory::spinner(int minVal, int maxVal) const +{ + return new DummyAllegroWidget(64, 16); +} + +Text* AllegroWidgetFactory::text(const std::string& text) const +{ + return new AllegroText(text, lfont_l, pal.winBodyText); +} + +TextBox* AllegroWidgetFactory::textBox() const +{ + return new DummyAllegroWidget(256, 128); +} + +TextField* AllegroWidgetFactory::textField(int maxLength) const +{ + return new AllegroTextField(maxLength); +} + +// Containers + +Widget* AllegroWidgetFactory::frame(const std::string& label, Widget* content) const +{ + AllegroText* text=new AllegroText(label, lfont_l, pal.winBodyText); + return new AllegroFrame(text, dynamic_cast(content)); +} + +SerialContainer* AllegroWidgetFactory::column(const Contents& contents) const +{ + AllegroColumn* col=new AllegroColumn(); + for(int i=0; iadd(contents[i]); + return col; +} + +SerialContainer* AllegroWidgetFactory::spacedColumn(const Contents& contents) const +{ + AllegroColumn* col=new AllegroColumn(); + for(int i=0; iadd(contents[i]); + return col; +} + +SerialContainer* AllegroWidgetFactory::row(const Contents& contents) const +{ + AllegroRow* row=new AllegroRow(); + for(int i=0; iadd(contents[i]); + return row; +} + +SerialContainer* AllegroWidgetFactory::spacedRow(const Contents& contents) const +{ + AllegroRow* row=new AllegroRow(); + for(int i=0; iadd(contents[i]); + return row; +} + +SerialContainer* AllegroWidgetFactory::buttonRow(const Contents& contents) const +{ + AllegroRow* row=new AllegroRow(); + for(int i=0; iadd(contents[i]); + return row; +} + +TabPanel* AllegroWidgetFactory::tabPanel() const +{ + return new AllegroTabPanel(); +} + +} diff --git a/src/gui/allegro/factory.h b/src/gui/allegro/factory.h new file mode 100644 index 0000000000..a7dcf44e31 --- /dev/null +++ b/src/gui/allegro/factory.h @@ -0,0 +1,42 @@ +#ifndef _ZC_GUI_ALLEGRO_FACTORY_H_ +#define _ZC_GUI_ALLEGRO_FACTORY_H_ + +#include "../factory.h" + +namespace GUI +{ + +class AllegroWidgetFactory: public WidgetFactory +{ +public: + DialogController* controller() const; + + // Regular widgets + BitmapWidget* bitmap(BitmapBackend* backend, int scale) const; + Button* button(const std::string& text, boost::function onClick) const; + Checkbox* checkbox(const std::string& text) const; + List* comboBox(const ListData* data) const; + List* list(const ListData* data) const; + Spinner* spinner(int minVal, int maxVal) const; + Text* text(const std::string& text) const; + TextBox* textBox() const; + TextField* textField(int maxLength) const; + + // Toplevels + Window* window(const std::string& title, Widget* contents) const; + + // Containers + Widget* frame(const std::string& label, Widget* content) const; + SerialContainer* column(const Contents& contents=Contents()) const; + SerialContainer* spacedColumn(const Contents& contents=Contents()) const; + SerialContainer* row(const Contents& contents=Contents()) const; + SerialContainer* spacedRow(const Contents& contents=Contents()) const; + SerialContainer* buttonRow(const Contents& contents=Contents()) const; + TabPanel* tabPanel() const; +}; + +} + +#endif + + diff --git a/src/gui/allegro/frame.cpp b/src/gui/allegro/frame.cpp new file mode 100644 index 0000000000..2ac4feab8e --- /dev/null +++ b/src/gui/allegro/frame.cpp @@ -0,0 +1,78 @@ +#include "frame.h" +#include "common.h" +#include "renderer.h" +#include "text.h" + +namespace GUI +{ + +int AllegroFrame::proc(int msg, DIALOG* d, int c) +{ + return dummyProc(msg, d, c); +} + +AllegroFrame::AllegroFrame(AllegroText* l, AllegroWidget* c): + label(l), + contents(c) +{ +} + +AllegroFrame::~AllegroFrame() +{ + delete contents; + delete label; +} + +void AllegroFrame::getPreferredSize(int& prefWidth, int& prefHeight) +{ + contents->getPreferredSize(prefWidth, prefHeight); + prefWidth+=16; + prefHeight+=16; +} + +void AllegroFrame::setSizeAndPos(int x, int y, int width, int height) +{ + StandardAllegroWidget::setSizeAndPos(x, y, width, height); + label->setSizeAndPos(x+8, y, width, height); + contents->setSizeAndPos(x+8, y+8, width-16, height-16); +} + +int AllegroFrame::getDataSize() const +{ + return contents->getDataSize()+label->getDataSize()+1; +} + +int AllegroFrame::realize(DIALOG dlgArray[], int index) +{ + int used=realizeAs(dlgArray, index); + used+=label->realize(dlgArray, index+used); + used+=contents->realize(dlgArray, index+used); + return used; +} + +void AllegroFrame::setController(AllegroDialogController* c) +{ + StandardAllegroWidget::setController(c); + label->setController(c); + contents->setController(c); +} + +bool AllegroFrame::widthIsFlexible() const +{ + return contents->widthIsFlexible(); +} + +bool AllegroFrame::heightIsFlexible() const +{ + return contents->heightIsFlexible(); +} + +void AllegroFrame::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.drawRect(2, 2, width-4, height-4, pal.winBorder); + label->draw(renderer); + contents->draw(renderer); +} + +} diff --git a/src/gui/allegro/frame.h b/src/gui/allegro/frame.h new file mode 100644 index 0000000000..f740fbbac0 --- /dev/null +++ b/src/gui/allegro/frame.h @@ -0,0 +1,35 @@ +#ifndef _ZC_GUI_ALLEGRO_FRAME_H_ +#define _ZC_GUI_ALLEGRO_FRAME_H_ + +#include "standardWidget.h" + +namespace GUI +{ + +class AllegroText; + +class AllegroFrame: public StandardAllegroWidget +{ +public: + AllegroFrame(AllegroText* label, AllegroWidget* contents); + ~AllegroFrame(); + + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int x, int y, int width, int height); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void setController(AllegroDialogController* controller); + bool widthIsFlexible() const; + bool heightIsFlexible() const; + void draw(AllegroGUIRenderer& renderer) const; + + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroText* label; + AllegroWidget* contents; +}; + +} + +#endif diff --git a/src/gui/allegro/list.cpp b/src/gui/allegro/list.cpp new file mode 100644 index 0000000000..c9a866a4ec --- /dev/null +++ b/src/gui/allegro/list.cpp @@ -0,0 +1,87 @@ +#include "list.h" +#include "column.h" +#include "common.h" +#include "factory.h" +#include "renderer.h" +#include "text.h" + +namespace GUI +{ + +AllegroList::AllegroList(const ListData* ld, const AllegroWidgetFactory& awf): + data(ld), + AllegroScrollingPane(dynamic_cast(awf.column())), + widgetFactory(awf), + selected(-1) +{ + int size=ld->size(); + for(int i=0; i(widgetFactory.text(ld->get(i))); + text->setList(this); + text->setListNum(i); + // Ambiguous base class... + static_cast(content)->add( + static_cast(text)); + } + + if(size>0) + setSelected(0); +} + +AllegroList::~AllegroList() +{ + delete data; +} + +void AllegroList::setSelected(int num) +{ + if(selected==num) + return; + + AllegroColumn* col=static_cast(content); + AllegroText* text; + + if(selected>=0) + { + text=static_cast(col->getWidget(selected)); + text->setSelected(false); + } + + selected=num; + text=static_cast(col->getWidget(num)); + text->setSelected(true); +} + +void AllegroList::changeSelection(int num) +{ + setSelected(num); + if(onSelectionChanged) + onSelectionChanged(num); +} + +void AllegroList::doubleClick(int num) +{ + // The selection should already be set from the first click + if(onDoubleClick) + onDoubleClick(num); +} + +void AllegroList::getPreferredSize(int& prefWidth, int& prefHeight) +{ + AllegroScrollingPane::getPreferredSize(prefWidth, prefHeight); + prefHeight=120; + if(prefWidth>400) + prefWidth=400; +} + +void AllegroList::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.fillRect(0, 0, width-7, height, pal.editBG); + renderer.drawRect(0, 0, width-7, height, pal.winBodyText); + AllegroScrollingPane::draw(renderer); +} + +} diff --git a/src/gui/allegro/list.h b/src/gui/allegro/list.h new file mode 100644 index 0000000000..a0d024a2a5 --- /dev/null +++ b/src/gui/allegro/list.h @@ -0,0 +1,39 @@ +#ifndef _ZC_GUI_ALLEGRO_LIST_H_ +#define _ZC_GUI_ALLEGRO_LIST_H_ + +#include "../list.h" +#include "scrollingPane.h" + +namespace GUI +{ + +class AllegroWidgetFactory; + +class AllegroList: public List, public AllegroScrollingPane +{ +public: + AllegroList(const ListData* ld, const AllegroWidgetFactory& awf); + ~AllegroList(); + void getPreferredSize(int& prefWidth, int& prefHeight); + void draw(AllegroGUIRenderer& renderer) const; + + inline void setOnValueChanged(const boost::function& f) { onSelectionChanged=f; } + inline void setOnDoubleClick(const boost::function& f) { onDoubleClick=f; } + void setSelected(int num); + inline int getSelected() const { return selected; } + + // Called when list items are clicked + void changeSelection(int num); + void doubleClick(int num); + +private: + const ListData* data; + const AllegroWidgetFactory& widgetFactory; + int selected; + boost::function onSelectionChanged; + boost::function onDoubleClick; +}; + +} + +#endif diff --git a/src/gui/allegro/manager.h b/src/gui/allegro/manager.h new file mode 100644 index 0000000000..07ec5d7d5e --- /dev/null +++ b/src/gui/allegro/manager.h @@ -0,0 +1,20 @@ +#ifndef _ZC_GUI_ALLEGRO_MANAGER_H_ +#define _ZC_GUI_ALLEGRO_MANAGER_H_ + +#include "../manager.h" +#include "factory.h" + +namespace GUI +{ + +class AllegroGUIManager: public GUIManager +{ +private: + AllegroWidgetFactory factory; + + inline const WidgetFactory& getFactory() const { return factory; } +}; + +} + +#endif diff --git a/src/gui/allegro/renderer.cpp b/src/gui/allegro/renderer.cpp new file mode 100644 index 0000000000..aa5299ba69 --- /dev/null +++ b/src/gui/allegro/renderer.cpp @@ -0,0 +1,228 @@ +#include "renderer.h" +#include "common.h" +#include +#include + +using std::min; +using std::max; + +extern BITMAP* hw_screen; + +namespace GUI +{ + +AllegroGUIRenderer::AllegroGUIRenderer(): + target(screen), + originX(0), + originY(0) +{ +} + +AllegroGUIRenderer::~AllegroGUIRenderer() +{ +} + +void AllegroGUIRenderer::pushClipRect(int x, int y, int w, int h) +{ + adjustPoint(x, y); + ClipRect newCR; + + if(clipRectStack.empty()) + { + newCR.x1=x; + newCR.y1=y; + newCR.x2=x+w-1; + newCR.y2=y+h-1; + } + else + { + ClipRect& current=clipRectStack.top(); + newCR.x1=max(x, current.x1); + newCR.y1=max(y, current.y1); + newCR.x2=min(x+w-1, current.x2); + newCR.y2=min(y+h-1, current.y2); + } + + set_clip_rect(target, newCR.x1, newCR.y1, newCR.x2, newCR.y2); + clipRectStack.push(newCR); +} + +void AllegroGUIRenderer::popClipRect() +{ + clipRectStack.pop(); + if(clipRectStack.empty()) + set_clip_rect(target, 0, 0, target->w-1, target->h-1); + else + { + ClipRect& top=clipRectStack.top(); + set_clip_rect(target, top.x1, top.y1, top.x2, top.y2); + } +} + +void AllegroGUIRenderer::drawLine(int x1, int y1, int x2, int y2, const GUIColor& color) +{ + adjustPoint(x1, y1); + adjustPoint(x2, y2); + line(target, x1, y1, x2, y2, color); +} + +void AllegroGUIRenderer::drawText(const std::string& text, int x, int y, + FONT* font, const GUIColor& color, textAlignment alignment) +{ + adjustPoint(x, y); + FONT* tempFont=::font; + ::font=font; + gui_textout_ex(target, text.c_str(), x, y, color, -1, alignment==ta_center); + ::font=tempFont; +} + +void AllegroGUIRenderer::drawRect(int x, int y, int width, int height, const GUIColor& color) +{ + adjustPoint(x, y); + rect(target, x, y, x+width-1, y+height-1, color); +} + +void AllegroGUIRenderer::fillRect(int x, int y, int width, int height, const GUIColor& color) +{ + adjustPoint(x, y); + rectfill(target, x, y, x+width-1, y+height-1, color); +} + +void AllegroGUIRenderer::fillCircle(int x, int y, int radius, const GUIColor& color) +{ + adjustPoint(x, y); + circlefill(target, x, y, radius, color); +} + +void AllegroGUIRenderer::drawRoundedRect(int x, int y, int width, int height, + int radius, const GUIColor& color) +{ + adjustPoint(x, y); + arc(target, x+radius, y+radius, itofix(64), itofix(128), radius, color); + arc(target, x+width-radius-1, y+radius, itofix(0), itofix(64), radius, color); + arc(target, x+radius, y+height-radius-1, itofix(128), itofix(192), radius, color); + arc(target, x+width-radius-1, y+height-radius-1, itofix(192), itofix(256), radius, color); + hline(target, x+radius, y, x+width-radius, color); + hline(target, x+radius, y+height-1, x+width-radius-1, color); + vline(target, x, y+radius, y+height-radius-1, color); + vline(target, x+width-1, y+radius, y+height-radius-1, color); +} + +void AllegroGUIRenderer::fillRoundedRect(int x, int y, int width, int height, + int radius, const GUIColor& color) +{ + adjustPoint(x, y); + circlefill(target, x+radius, y+radius, radius, color); + circlefill(target, x+width-radius-1, y+radius, radius, color); + circlefill(target, x+radius, y+height-radius-1, radius, color); + circlefill(target, x+width-radius-1, y+height-radius-1, radius, color); + rectfill(target, x, y+radius, x+radius, y+height-radius-1, color); + rectfill(target, x+width-radius, y+radius, x+width-1, y+height-radius-1, color); + rectfill(target, x+radius, y, x+width-radius-1, y+height-1, color); +} + +void AllegroGUIRenderer::drawPartialRoundedRect(int x, int y, int width, + int height, int radius, partialRoundedRect part, const GUIColor& color) +{ + adjustPoint(x, y); + switch(part) + { + case prr_top: + arc(target, x+radius, y+radius, itofix(64), itofix(128), radius, color); + arc(target, x+width-radius-1, y+radius, itofix(0), itofix(64), radius, color); + hline(target, x+radius, y, x+width-radius, color); + vline(target, x, y+radius, y+height-1, color); + vline(target, x+width-1, y+radius, y+height-1, color); + break; + + case prr_bottom: + arc(target, x+radius, y+height-radius-1, itofix(128), itofix(192), radius, color); + arc(target, x+width-radius-1, y+height-radius-1, itofix(192), itofix(256), radius, color); + hline(target, x+radius, y+height-1, x+width-radius-1, color); + vline(target, x, y, y+height-radius-1, color); + vline(target, x+width-1, y, y+height-radius-1, color); + break; + + case prr_topRight: + break; + + case prr_bottomRight: + break; + } +} + +void AllegroGUIRenderer::fillPartialRoundedRect(int x, int y, int width, + int height, int radius,partialRoundedRect part, const GUIColor& color) +{ + adjustPoint(x, y); + switch(part) + { + case prr_top: + circlefill(target, x+radius, y+radius, radius, color); + circlefill(target, x+width-radius-1, y+radius, radius, color); + rectfill(target, x, y+radius, x+width-1, y+height-1, color); + rectfill(target, x+radius, y, x+width-radius-1, y+radius-1, color); + break; + case prr_bottom: + circlefill(target, x+radius, y+height-radius-1, radius, color); + circlefill(target, x+width-radius-1, y+height-radius-1, radius, color); + rectfill(target, x, y, x+width-1, y+height-radius-1, color); + rectfill(target, x+radius, y+height-radius, x+width-radius-1, y+height-1, color); + break; + + case prr_topRight: + break; + + case prr_bottomRight: + break; + } +} + +void AllegroGUIRenderer::fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const GUIColor& color) +{ + adjustPoint(x1, y1); + adjustPoint(x2, y2); + adjustPoint(x3, y3); + triangle(target, x1, y1, x2, y2, x3, y3, color); +} + +void AllegroGUIRenderer::drawFrame(int x1, int y1, int width, int height, const GUIColor& color, frameType type, int depth) +{ + adjustPoint(x1, y1); + int x2=x1+width-1; + int y2=y1+height-1; + int lightColor=makecol(color.red*1.2, color.green*1.2, color.blue*1.2); + int darkColor=makecol(color.red*0.8, color.green*0.8, color.blue*0.8); + + int topLeft, bottomRight; + if(type==ft_convex) + { + topLeft=lightColor; + bottomRight=darkColor; + } + else + { + topLeft=darkColor; + bottomRight=lightColor; + } + + for(int i=0; iw, bmp->h); +} + +} diff --git a/src/gui/allegro/renderer.h b/src/gui/allegro/renderer.h new file mode 100644 index 0000000000..3eb62e60ac --- /dev/null +++ b/src/gui/allegro/renderer.h @@ -0,0 +1,56 @@ +#ifndef _ZC_GUI_ALLEGRO_RENDERER_H_ +#define _ZC_GUI_ALLEGRO_RENDERER_H_ + +#include +#include +struct BITMAP; +struct FONT; + +namespace GUI +{ + +struct GUIColor; + +class AllegroGUIRenderer +{ +public: + enum textAlignment { ta_left, ta_center }; + enum frameType { ft_convex, ft_concave }; + enum partialRoundedRect { prr_top, prr_bottom, prr_topRight, prr_bottomRight }; + + AllegroGUIRenderer(); + ~AllegroGUIRenderer(); + void pushClipRect(int x, int y, int width, int height); + void popClipRect(); + + void drawLine(int x1, int y1, int x2, int y2, const GUIColor& color); + void drawText(const std::string& text, int x, int y, FONT* font, + const GUIColor& color, textAlignment alignment=ta_left); + void drawRect(int x, int y, int width, int height, const GUIColor& color); + void fillRect(int x, int y, int width, int height, const GUIColor& color); + void fillCircle(int x, int y, int radius, const GUIColor& color); + void drawRoundedRect(int x, int y, int width, int height, int radius, const GUIColor& color); + void fillRoundedRect(int x, int y, int width, int height, int radius, const GUIColor& color); + void drawPartialRoundedRect(int x, int y, int width, int height, int radius, + partialRoundedRect part, const GUIColor& color); + void fillPartialRoundedRect(int x, int y, int width, int height, int radius, + partialRoundedRect part, const GUIColor& color); + void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, const GUIColor& color); + void drawFrame(int x, int y, int width, int height, const GUIColor& color, frameType type, int depth); + void blitBitmap(BITMAP* bmp, int x, int y); + + inline void setOrigin(int x, int y) { originX=x; originY=y; } + +private: + struct ClipRect { int x1, y1, x2, y2; }; + + BITMAP* target; + int originX, originY; + std::stack clipRectStack; + + inline void adjustPoint(int& x, int& y) const { x+=originX; y+=originY; } +}; + +} + +#endif diff --git a/src/gui/allegro/row.cpp b/src/gui/allegro/row.cpp new file mode 100644 index 0000000000..962020efbd --- /dev/null +++ b/src/gui/allegro/row.cpp @@ -0,0 +1,104 @@ +#include "row.h" +#include + +namespace GUI +{ + +AllegroRow::AllegroRow(): + targetWidth(0), + numExpanders(0), + padding(0) +{ +} + +void AllegroRow::add(Widget* w) +{ + AllegroSerialContainer::add(w); + //if(dynamic_cast(w)->heightIsFlexible()) + //numExpanders++; +} + +void AllegroRow::getPreferredSize(int& prefWidth, int& prefHeight) +{ + //prefWidth=getTotalContentWidth(); + //prefHeight=getGreatestContentHeight(); + + prefWidth=0; + prefHeight=0; + numExpanders=0; + padding=0; + bool lastHadPadding=false; + + for(int i=0; igetPreferredSize(tempW, tempH); + prefWidth+=tempW; + + if(false) //c->wantsPadding()) + { + if(lastHadPadding) + prefWidth+=16; + else + prefWidth+=32; + tempH+=32; + lastHadPadding=true; + } + else + lastHadPadding=false; + + if(tempH>prefHeight) + prefHeight=tempH; + + if(c->widthIsFlexible()) + numExpanders++; + } + + // If everything wants padding, don't add too much + if(padding==contents.size()) + padding--; + + prefWidth+=padding; + targetWidth=prefWidth; +} + +void AllegroRow::setSizeAndPos(int newX, int newY, int newW, int newH) +{ + bool lastHadPadding=false; + + // Divide extra space evenly among expanding widgets, if there are any + int extraSpace=(newW-targetWidth)/((numExpanders>0) ? numExpanders : contents.size()); + + for(int i=0; igetPreferredSize(compW, dummy); + if(numExpanders==0 || c->widthIsFlexible()) + compW+=extraSpace; + + if(false) //c->wantsPadding()) + { + if(lastHadPadding) + { + c->setSizeAndPos(newX, newY, compW, newH); + newX+=compW+16; + } + else + { + c->setSizeAndPos(newX+16, newY, compW, newH); + newX+=compW+32; + } + lastHadPadding=true; + } + else + { + c->setSizeAndPos(newX, newY, compW, newH); + newX+=compW; + lastHadPadding=false; + } + } +} + +} diff --git a/src/gui/allegro/row.h b/src/gui/allegro/row.h new file mode 100644 index 0000000000..ccf6f4e87c --- /dev/null +++ b/src/gui/allegro/row.h @@ -0,0 +1,29 @@ +#ifndef _ZC_GUI_ALLEGRO_ROW_H_ +#define _ZC_GUI_ALLEGRO_ROW_H_ + +#include "serialContainer.h" +#include + +namespace GUI +{ + +class AllegroRow: public AllegroSerialContainer +{ +public: + AllegroRow(); + + // Inherited + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newW, int newH); + void add(Widget* w); + + bool widthIsFlexible() const { return numExpanders>0; } + +private: + //std::vector contents; + int targetWidth, numExpanders, padding; +}; + +} + +#endif diff --git a/src/gui/allegro/scrollbar.cpp b/src/gui/allegro/scrollbar.cpp new file mode 100644 index 0000000000..b2ea5bef69 --- /dev/null +++ b/src/gui/allegro/scrollbar.cpp @@ -0,0 +1,124 @@ +#include "scrollbar.h" +#include "common.h" +#include "renderer.h" +#include "scrollingPane.h" +#include + +namespace GUI +{ + +int AllegroScrollbar::proc(int msg, DIALOG* d, int c) +{ + switch(msg) + { + case MSG_IDLE: + if(d->d1!=0) + { + d->d1=0; + } + break; + case MSG_LPRESS: + static_cast(d->dp)->onClick(gui_mouse_x(), gui_mouse_y()); + d->d1=1; + break; + + case MSG_WHEEL: + forwardMouseWheel(d, c); + } + return D_O_K; +} + +AllegroScrollbar::AllegroScrollbar(AllegroScrollingPane& o, int btn): + owner(o), + buttonStep(btn), + sliderPos(0), + sliderSize(0), + contentSize(0), + viewportSize(0) +{ +} + +void AllegroScrollbar::updateSize(int cSize, int vpSize) +{ + contentSize=cSize; + viewportSize=vpSize; + recalculateSliderSize(); +} + +void AllegroScrollbar::updatePos(int scrollPos) +{ + const int maxOffset=height-30-sliderSize; + if(maxOffset<=0) + { + sliderPos=15; + return; + } + float relPos=static_cast(scrollPos)/(contentSize-viewportSize); + sliderPos=15+relPos*maxOffset; +} + +void AllegroScrollbar::draw(GUI::AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + + // Slider background + renderer.fillRect(0, 15, width, height-30, pal.scrollbarFill); + renderer.drawRect(0, 15, width, height-30, pal.outline); + + // Slider + renderer.fillRoundedRect(0, sliderPos, width, sliderSize, 3, pal.scrollbarSlider); + renderer.drawRoundedRect(0, sliderPos, width, sliderSize, 3, pal.outline); + + // Top button + renderer.fillPartialRoundedRect(0, 0, width, 15, 7, AllegroGUIRenderer::prr_top, pal.button); + renderer.drawPartialRoundedRect(0, 0, width, 15, 7, AllegroGUIRenderer::prr_top, pal.outline); + renderer.fillTriangle(4, 9, 7, 6, 10, 9, pal.buttonText); + + // Bottom button + renderer.fillPartialRoundedRect(0, height-15, width, 15, 7, AllegroGUIRenderer::prr_bottom, pal.button); + renderer.drawPartialRoundedRect(0, height-15, width, 15, 7, AllegroGUIRenderer::prr_bottom, pal.outline); + renderer.fillTriangle(4, height-10, 7, height-7, 10, height-10, pal.buttonText); +} + +void AllegroScrollbar::getPreferredSize(int& prefWidth, int& prefHeight) +{ + // I don't think this will ever be called, but whatever. + prefWidth=15; + prefHeight=100; +} + +void AllegroScrollbar::setSizeAndPos(int newX, int newY, int newW, int newH) +{ + StandardAllegroWidget::setSizeAndPos(newX, newY, newW, newH); + recalculateSliderSize(); +} + +void AllegroScrollbar::recalculateSliderSize() +{ + if(viewportSize>=contentSize) + return; + + float portion=static_cast(viewportSize)/contentSize; + sliderSize=portion*(height-30); + if(sliderSize<15) + sliderSize=15; +} + +int AllegroScrollbar::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void AllegroScrollbar::onClick(int mouseX, int mouseY) +{ + if(mouseY=y+height-15) + owner.scroll(buttonStep); + else if(mouseY=y+sliderPos+sliderSize) + owner.scroll(viewportSize-buttonStep); +} + +} diff --git a/src/gui/allegro/scrollbar.h b/src/gui/allegro/scrollbar.h new file mode 100644 index 0000000000..53cb955254 --- /dev/null +++ b/src/gui/allegro/scrollbar.h @@ -0,0 +1,37 @@ +#ifndef _ZC_GUI_ALLEGRO_SCROLLBAR_H_ +#define _ZC_GUI_ALLEGRO_SCROLLBAR_H_ + +#include "standardWidget.h" + +namespace GUI +{ + +class AllegroScrollingPane; + +class AllegroScrollbar: public StandardAllegroWidget +{ +public: + AllegroScrollbar(AllegroScrollingPane& owner, int buttonStep); + //void setSizes + + void draw(GUI::AllegroGUIRenderer& renderer) const; + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int x, int y, int width, int height); + void updateSize(int contentSize, int viewportSize); + void updatePos(int scrollPos); + int realize(DIALOG dlgArray[], int index); + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroScrollingPane& owner; + int buttonStep; + int sliderPos, sliderSize; + int contentSize, viewportSize; + + void recalculateSliderSize(); + void onClick(int mouseX, int mouseY); +}; + +} + +#endif diff --git a/src/gui/allegro/scrollingPane.cpp b/src/gui/allegro/scrollingPane.cpp new file mode 100644 index 0000000000..0f24de69e5 --- /dev/null +++ b/src/gui/allegro/scrollingPane.cpp @@ -0,0 +1,136 @@ +#include "scrollingPane.h" +#include "common.h" +#include "renderer.h" + +namespace GUI +{ + +int AllegroScrollingPane::proc(int msg, DIALOG* d, int c) +{ + switch(msg) + { + // We have to tell Allegro the pane doesn't want mouse input; + // otherwise, it'll be the only thing that gets it. Other dialog + // procs call forwardMouseWheel(). + case MSG_WANTMOUSE: + return D_DONTWANTMOUSE; + + case MSG_WHEEL: + static_cast(d->dp)->scroll(c*-10); + break; + } + + return D_O_K; +} + +AllegroScrollingPane::AllegroScrollingPane(AllegroWidget* c): + content(c), + verticalSB(*this, 10), + contentWidth(0), + contentHeight(0), + scrollPos(0) +{ +} + +AllegroScrollingPane::~AllegroScrollingPane() +{ + delete content; +} + +void AllegroScrollingPane::scroll(int amt) +{ + const int maxScroll=contentHeight-viewportHeight; + if(maxScroll<=0) + return; + + if(scrollPos+amt<0) + amt=-scrollPos; + else if(scrollPos+amt>maxScroll) + amt=maxScroll-scrollPos; + + if(amt==0) + return; + scrollPos+=amt; + content->onScrollV(-amt, y, y+viewportHeight-1); + verticalSB.updatePos(scrollPos); +} + +void AllegroScrollingPane::setSizeAndPos(int x, int y, int w, int h) +{ + content->setSizeAndPos(x, y, contentWidth, contentHeight); + StandardAllegroWidget::setSizeAndPos(x, y, w, h); + viewportHeight=h; + if(contentHeight>h) + { + viewportWidth=w-15; + verticalSB.setActive(true); + } + else + { + viewportWidth=w; + verticalSB.setActive(false); + } + + verticalSB.setSizeAndPos(x+w-15, y, 15, h); + verticalSB.updateSize(contentHeight, viewportHeight); + scrollPos=0; + verticalSB.updatePos(0); +} + +int AllegroScrollingPane::getDataSize() const +{ + return content->getDataSize()+verticalSB.getDataSize()+1; +} + +int AllegroScrollingPane::realize(DIALOG dlgArray[], int index) +{ + // forwardMouseWheel() needs the pane's DIALOG to be placed after + // those of its contents. + int used=content->realize(dlgArray, index); + used+=verticalSB.realize(dlgArray, index+used); + used+=realizeAs(dlgArray, index+used); + dialog->flags|=D_WANTWHEEL; + return used; +} + +void AllegroScrollingPane::unrealize() +{ + StandardAllegroWidget::unrealize(); + verticalSB.unrealize(); + content->unrealize(); +} + +void AllegroScrollingPane::setController(AllegroDialogController* c) +{ + StandardAllegroWidget::setController(c); + if(content) + content->setController(c); +} + +void AllegroScrollingPane::getPreferredSize(int& prefWidth, int& prefHeight) +{ + content->getPreferredSize(prefWidth, prefHeight); + contentWidth=prefWidth; + contentHeight=prefHeight; + + // Not gonna bother asking the scrollbars. +} + +void AllegroScrollingPane::draw(GUI::AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.pushClipRect(0, 0, viewportWidth, viewportHeight); + content->draw(renderer); + renderer.popClipRect(); + if(contentHeight>viewportHeight) + verticalSB.draw(renderer); +} + +void AllegroScrollingPane::setActive(bool val) +{ + StandardAllegroWidget::setActive(val); + content->setActive(val); + verticalSB.setActive(val); +} + +} diff --git a/src/gui/allegro/scrollingPane.h b/src/gui/allegro/scrollingPane.h new file mode 100644 index 0000000000..e8caa44961 --- /dev/null +++ b/src/gui/allegro/scrollingPane.h @@ -0,0 +1,43 @@ +#ifndef _ZC_GUI_ALLEGRO_SCROLLINGPANE_H_ +#define _ZC_GUI_ALLEGRO_SCROLLINGPANE_H_ + +#include "standardWidget.h" +#include "scrollbar.h" + +namespace GUI +{ + +class AllegroScrollingPane: public StandardAllegroWidget +{ +public: + AllegroScrollingPane(AllegroWidget* content); + ~AllegroScrollingPane(); + void scroll(int amt); + void setSizeAndPos(int x, int y, int width, int height); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void unrealize(); + void setController(AllegroDialogController* c); + void getPreferredSize(int& prefWidth, int& prefHeight); + void setActive(bool val); + + void draw(AllegroGUIRenderer& renderer) const; + + int getContentWidth() { return contentWidth; } + int getContentHeight() { return contentHeight; } + + static int proc(int msg, DIALOG* d, int c); + +protected: + AllegroWidget* content; + +private: + AllegroScrollbar verticalSB; + int viewportWidth, viewportHeight; + int contentWidth, contentHeight; + int scrollPos; +}; + +} + +#endif diff --git a/src/gui/allegro/serialContainer.cpp b/src/gui/allegro/serialContainer.cpp new file mode 100644 index 0000000000..2a5ef6f8d8 --- /dev/null +++ b/src/gui/allegro/serialContainer.cpp @@ -0,0 +1,112 @@ +#include "serialContainer.h" + +namespace GUI +{ + +AllegroSerialContainer::~AllegroSerialContainer() +{ + for(int i=0; i(w); + contents.push_back(aw); + int ww, wh; + aw->getPreferredSize(ww, wh); + contentSizes.push_back(std::make_pair(ww, wh)); +} + +int AllegroSerialContainer::getDataSize() const +{ + int total=0; + for(int i=0; igetDataSize(); + return total; +} + +int AllegroSerialContainer::realize(DIALOG dlgArray[], int index) +{ + int added=0; + for(int i=0; irealize(dlgArray, index+added); + return added; +} + +void AllegroSerialContainer::unrealize() +{ + for(int i=0; iunrealize(); +} + +void AllegroSerialContainer::setController(AllegroDialogController* controller) +{ + for(int i=0; isetController(controller); +} + +void AllegroSerialContainer::setActive(bool val) +{ + for(int i=0; isetActive(val); +} + +void AllegroSerialContainer::draw(AllegroGUIRenderer& renderer) const +{ + for(int i=0; idraw(renderer); +} + +void AllegroSerialContainer::onScrollH(int amount, int left, int right) +{ + for(int i=0; ionScrollH(amount, left, right); +} + +void AllegroSerialContainer::onScrollV(int amount, int top, int bottom) +{ + for(int i=0; ionScrollV(amount, top, bottom); +} + +int AllegroSerialContainer::getGreatestContentWidth() const +{ + int ret=0; + for(int i=0; iret) + ret=contentSizes[i].first; + } + return ret; +} + +int AllegroSerialContainer::getGreatestContentHeight() const +{ + int ret=0; + for(int i=0; iret) + ret=contentSizes[i].second; + } + return ret; +} + +int AllegroSerialContainer::getTotalContentWidth() const +{ + int ret=0; + for(int i=0; i +#include + +namespace GUI +{ + +class AllegroSerialContainer: public SerialContainer, public AllegroWidget +{ +public: + virtual ~AllegroSerialContainer(); + + void add(Widget* w); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void draw(AllegroGUIRenderer& renderer) const; + void onScrollH(int amount, int left, int right); + void onScrollV(int amount, int top, int bottom); + void unrealize(); + void setController(AllegroDialogController* controller); + void setActive(bool val); + inline AllegroWidget* getWidget(int index) { return contents[index]; } + +protected: + std::vector contents; + std::vector > contentSizes; + + int getGreatestContentWidth() const; + int getGreatestContentHeight() const; + int getTotalContentWidth() const; + int getTotalContentHeight() const; +}; + +} + +#endif diff --git a/src/gui/allegro/standardWidget.cpp b/src/gui/allegro/standardWidget.cpp new file mode 100644 index 0000000000..35bb749e22 --- /dev/null +++ b/src/gui/allegro/standardWidget.cpp @@ -0,0 +1,115 @@ +#include "standardWidget.h" +#include "common.h" +#include +#include +#include + +#ifndef zc_max +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) +#endif + +namespace GUI +{ + +StandardAllegroWidget::StandardAllegroWidget(): + dialog(0), + controller(0), + x(0), + y(0), + width(0), + height(0), + hidden(false) +{ +} + +void StandardAllegroWidget::setSizeAndPos(int newX, int newY, + int newWidth, int newHeight) +{ + x=newX; + y=newY; + width=newWidth; + height=newHeight; + + if(dialog) + { + dialog->x=newX; + dialog->y=newY; + dialog->w=newWidth; + dialog->h=newHeight; + } +} + +int StandardAllegroWidget::realizeCommon(DIALOG dlgArray[], int index, + dialogProc proc, int key) +{ + dialog=&dlgArray[index]; + dialog->proc=proc; + dialog->x=x; + dialog->y=y; + dialog->w=width; + dialog->h=height; + dialog->key=key; + if(hidden) + dialog->flags|=D_HIDDEN; + + return 1; +} + +void StandardAllegroWidget::onScrollH(int amount, int left, int right) +{ + x+=amount; + if(dialog) + { + dialog->x=zc_max(x, left); + if(dialog->x+widthw=width; + else + dialog->w=right-dialog->x; // may be negative; that's okay + } +} + +void StandardAllegroWidget::onScrollV(int amount, int top, int bottom) +{ + y+=amount; + if(dialog) + { + dialog->y=zc_max(y, top); + if(dialog->y+heighth=height; + else + dialog->h=bottom-dialog->y; + } +} + +void StandardAllegroWidget::unrealize() +{ + if(dialog) + { + std::memset(dialog, 0, sizeof(DIALOG)); + dialog->proc=dummyProc; + dialog=0; + } +} + +void StandardAllegroWidget::setActive(bool val) +{ + hidden=!val; + if(dialog) + { + if(val) + dialog->flags&=~D_HIDDEN; + else + dialog->flags|=D_HIDDEN; + } + // else what? +} + +bool StandardAllegroWidget::isActive() +{ + if(!dialog) + return false; + return (dialog->flags&D_HIDDEN)==0; +} + +} // Namespace diff --git a/src/gui/allegro/standardWidget.h b/src/gui/allegro/standardWidget.h new file mode 100644 index 0000000000..068f6a87ad --- /dev/null +++ b/src/gui/allegro/standardWidget.h @@ -0,0 +1,54 @@ +#ifndef _ZC_GUI_ALLEGRO_STANDARDWIDGET_H_ +#define _ZC_GUI_ALLEGRO_STANDARDWIDGET_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +/// Base class for most widgets. +/** This class provides a straightforward implementation of most AllegroWidget + * functions. Its realizeAs() function stores a pointer to this in DIALOG->dp. + */ +class StandardAllegroWidget: public AllegroWidget +{ +public: + typedef int(*dialogProc)(int, DIALOG*, int); + + StandardAllegroWidget(); + virtual ~StandardAllegroWidget() {} + + // Inherited + virtual void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + virtual inline int getDataSize() const { return 1; } + inline void setController(AllegroDialogController* c) { controller=c; } + virtual void unrealize(); + virtual void setActive(bool val); + virtual bool isActive(); + + void onScrollH(int amount, int left, int right); + void onScrollV(int amount, int top, int bottom); + +protected: + DIALOG* dialog; + AllegroDialogController* controller; + int x, y; + int width, height; + + template + inline int realizeAs(DIALOG dlgArray[], int index, int key=0) + { + realizeCommon(dlgArray, index, T::proc, key); + dialog->dp=static_cast(this); + return 1; + } + +private: + bool hidden; + int realizeCommon(DIALOG dlgArray[], int index, dialogProc proc, int key); +}; + +} + +#endif diff --git a/src/gui/allegro/tab.cpp b/src/gui/allegro/tab.cpp new file mode 100644 index 0000000000..2e74cf0817 --- /dev/null +++ b/src/gui/allegro/tab.cpp @@ -0,0 +1,103 @@ +#include "tab.h" +#include "common.h" +#include "renderer.h" +#include "tabBar.h" +#include + +namespace GUI +{ + +int AllegroTab::proc(int msg, DIALOG* d, int c) +{ + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_LPRESS: + static_cast(d->dp)->onClick(); + break; + + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + + case MSG_CHAR: + switch(c>>8) + { + case KEY_LEFT: + if(static_cast(d->dp)->owner->switchTab(-1)) + return D_USED_CHAR; + break; + case KEY_RIGHT: + if(static_cast(d->dp)->owner->switchTab(1)) + return D_USED_CHAR; + break; + } + break; + } + + return D_O_K; +} + +AllegroTab::AllegroTab(AllegroTabBar* o, int i, const std::string& t, FONT* f): + owner(o), + id(i), + text(t), + font(f), + selected(false) +{ +} + +void AllegroTab::onClick() +{ + if(selected) + return; + owner->onTabClicked(id); +} + +int AllegroTab::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void AllegroTab::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + int offset=selected ? 0 : 3; + renderer.drawPartialRoundedRect(0, offset, width, height-offset, 3, AllegroGUIRenderer::prr_top, pal.outline); + renderer.drawText(text, 5, 3+offset, font, pal.winBodyText); + if(selected) + // Cover up the corresponding part of the frame below + renderer.drawLine(1, height-1, width-1, height-1, pal.winBody); + + if((dialog->flags&D_GOTFOCUS)!=0) + renderer.drawRoundedRect(2, 2, width-4, height-4, 2, pal.buttonHL); +} + +void AllegroTab::getPreferredSize(int& prefWidth, int& prefHeight) +{ + prefWidth=text_length(font, text.c_str())+10; + prefHeight=text_height(font)+8; +} + +void AllegroTab::setSelected(bool s) +{ + selected=s; + if(dialog) + { + if(s) + dialog->flags|=D_GOTFOCUS; + else + dialog->flags&=~D_GOTFOCUS; + } +} + +void AllegroTab::setX(int newX) +{ + x=newX; + if(dialog) + dialog->x=newX; +} + +} diff --git a/src/gui/allegro/tab.h b/src/gui/allegro/tab.h new file mode 100644 index 0000000000..c8b949474c --- /dev/null +++ b/src/gui/allegro/tab.h @@ -0,0 +1,35 @@ +#ifndef _ZC_GUI_ALLEGRO_TAB_H_ +#define _ZC_GUI_ALLEGRO_TAB_H_ + +#include "standardWidget.h" +#include + +namespace GUI +{ + +class AllegroTabBar; + +class AllegroTab: public StandardAllegroWidget +{ +public: + AllegroTab(AllegroTabBar* owner, int id, const std::string& text, FONT* font); + int realize(DIALOG dlgArray[], int index); + void draw(AllegroGUIRenderer& renderer) const; + void getPreferredSize(int& prefWidth, int& prefHeight); + void onClick(); + void setSelected(bool s); + void setX(int newX); + + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroTabBar* owner; + int id; + std::string text; + FONT* font; + bool selected; +}; + +} + +#endif diff --git a/src/gui/allegro/tabBar.cpp b/src/gui/allegro/tabBar.cpp new file mode 100644 index 0000000000..ee7d3d1b74 --- /dev/null +++ b/src/gui/allegro/tabBar.cpp @@ -0,0 +1,190 @@ +#include "tabBar.h" +#include "common.h" +#include "renderer.h" +#include "tabPanel.h" + +extern FONT* lfont_l; + +namespace GUI +{ + +int AllegroTabBar::proc(int msg, DIALOG* d, int c) +{ + if(msg==MSG_CLICK) + static_cast(d->dp)->onClick(gui_mouse_x()); + return D_O_K; +} + +AllegroTabBar::AllegroTabBar(AllegroTabPanel& o): + owner(o), + tooBig(false), + firstVisible(0), + lastVisible(0) +{ + tabs.reserve(10); + tabX.reserve(10); + // tabX is always one larger than tabs. + tabX.push_back(0); +} + +void AllegroTabBar::getPreferredSize(int& prefWidth, int& prefHeight) +{ + if(tabs.size()==0) + { + prefWidth=0; + prefHeight=0; + return; + } + + tabs[0].getPreferredSize(prefWidth, prefHeight); // Just to get the height + prefWidth=tabX.back()+32; +} + +void AllegroTabBar::onTabClicked(int tabNum) +{ + tabs[selectedTab].setSelected(false); + selectedTab=tabNum; + tabs[selectedTab].setSelected(true); + owner.activateTab(tabNum); +} + +void AllegroTabBar::addTab(const std::string& text) +{ + tabs.push_back(AllegroTab(this, tabs.size(), text, lfont_l)); + if(tabs.size()==1) + { + selectedTab=0; + tabs[0].setSelected(true); + } + + // Get the size, but subtract 1 from the width because we want them to + // overlap by a pixel. That's to stop their outlines from doubling up. + int tw, th; + tabs[tabs.size()-1].getPreferredSize(tw, th); + tabX.push_back(tabX.back()+tw-1); +} + +void AllegroTabBar::draw(AllegroGUIRenderer& renderer) const +{ + for(int i=firstVisible; i<=lastVisible; i++) + tabs[i].draw(renderer); + + // Draw the tab shift arrows + renderer.setOrigin(x, y); + if(tooBig) + { + if(firstVisible>0) + renderer.fillTriangle(9, 5, 4, 10, 9, 15, pal.winBodyText); + if(lastVisible=newX+newWidth-3) + tabs[i].setActive(false); + else + lastVisible=i; + } + + tooBig=lastVisible!=tabs.size()-1; +} + +int AllegroTabBar::getDataSize() const +{ + int size=0; + for(int i=0; i(dlgArray, index); + for(int i=0; i=0 && newTab<=tabs.size()-1) + { + if(newTablastVisible) + { + lastVisible=newTab; + updateVisibleTabs(false); + } + + onTabClicked(newTab); + return true; + } + else + return false; +} + +void AllegroTabBar::onClick(int mouseX) +{ + if(!tooBig) + return; + if(mouseX0) + { + firstVisible--; + updateVisibleTabs(true); + } + else if(mouseX>=x+visibleTabWidth() && lastVisiblewidth-32) + lastVisible--; + } + else + { + while(visibleTabWidth()>width-32) + firstVisible++; + } + + int tx=x+(firstVisible==0 ? 3 : 16); + for(int i=0; ilastVisible) + tabs[i].setActive(false); + else + { + tabs[i].setActive(true); + tabs[i].setX(tx+tabX[i]-tabX[firstVisible]); + } + } +} + +} diff --git a/src/gui/allegro/tabBar.h b/src/gui/allegro/tabBar.h new file mode 100644 index 0000000000..bd4ddebe7b --- /dev/null +++ b/src/gui/allegro/tabBar.h @@ -0,0 +1,61 @@ +#ifndef _ZC_GUI_ALLEGRO_TABBAR_H_ +#define _ZC_GUI_ALLEGRO_TABBAR_H_ + +#include "standardWidget.h" +#include "tab.h" +#include + +namespace GUI +{ + +class AllegroTabPanel; + +class AllegroTabBar: public StandardAllegroWidget +{ +public: + AllegroTabBar(AllegroTabPanel& owner); + void getPreferredSize(int& prefWidth, int& prefHeight); + void onTabClicked(int tabNum); + void addTab(const std::string& text); + void draw(AllegroGUIRenderer& renderer) const; + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void unrealize(); + bool switchTab(int val); + + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroTabPanel& owner; + std::vector tabs; + std::vector tabX; + int selectedTab; + bool tooBig; + int firstVisible, lastVisible; + + void onClick(int mouseX); + + /** Called after the first or last visible tab is changed to correct + * the other end of the range. + * \param adjustLast If true, firstVisible is correct and lastVisible + * needs updated. If false, it's the other way around. + */ + void updateVisibleTabs(bool adjustLast); + + /// Returns the width of tab i. + inline int tabWidth(int i) const + { + return tabX[i+1]-tabX[i]; + } + + /// Returns the total width of the currently visible tabs. + inline int visibleTabWidth() const + { + return tabX[lastVisible+1]-tabX[firstVisible]; + } +}; + +} + +#endif diff --git a/src/gui/allegro/tabPanel.cpp b/src/gui/allegro/tabPanel.cpp new file mode 100644 index 0000000000..6d374dddb0 --- /dev/null +++ b/src/gui/allegro/tabPanel.cpp @@ -0,0 +1,119 @@ +#include "tabPanel.h" +#include "common.h" +#include "renderer.h" +#include "scrollingPane.h" +#include +#include + +extern FONT* lfont_l; + +namespace GUI +{ + +int AllegroTabPanel::proc(int msg, DIALOG* d, int c) +{ + switch(msg) + { + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + } + + return D_O_K; +} + +AllegroTabPanel::AllegroTabPanel(): + tabBar(*this) +{ +} + +AllegroTabPanel::~AllegroTabPanel() +{ + for(int i=0; i(c); + contents.push_back(new AllegroScrollingPane(alWidget)); + tabBar.addTab(name); + if(contents.size()==1) + activeTab=0; +} + +void AllegroTabPanel::getPreferredSize(int& prefW, int& prefH) +{ + int tbW, tbH; + tabBar.getPreferredSize(tbW, tbH); + prefW=prefH=0; + for(int i=0; igetPreferredSize(tempW, tempH); + if(tempW>prefW) + prefW=tempW; + if(tempH>prefH) + prefH=tempH; + } + prefW+=6; + prefH+=tbH+6; +} + +void AllegroTabPanel::activateTab(int newTab) +{ + contents[activeTab]->setActive(false); + activeTab=newTab; + contents[activeTab]->setActive(true); +} + +void AllegroTabPanel::setController(AllegroDialogController* c) +{ + StandardAllegroWidget::setController(c); +} + +int AllegroTabPanel::getDataSize() const +{ + contentDataSize=0; + for(int i=0; igetDataSize(); + contentDataSize+=tabBar.getDataSize(); + return contentDataSize+1; +} + +int AllegroTabPanel::realize(DIALOG dlgArray[], int index) +{ + int used=realizeAs(dlgArray, index); + + used+=tabBar.realize(dlgArray, index+used); + for(int i=0; irealize(dlgArray, index+used); + if(i!=activeTab) + contents[i]->setActive(false); + } + return used; +} + +void AllegroTabPanel::setSizeAndPos(int newX, int newY, int newW, int newH) +{ + StandardAllegroWidget::setSizeAndPos(newX, newY, newW, newH); + + int tbW, tbH; + tabBar.getPreferredSize(tbW, tbH); + tabBar.setSizeAndPos(x, y, newW, tbH); + for(int i=0; isetSizeAndPos(newX+3, newY+tbH+3, newW-6, newH-tbH-6); +} + +void AllegroTabPanel::draw(AllegroGUIRenderer& renderer) const +{ + int tbW, tbH; + const_cast(&tabBar)->getPreferredSize(tbW, tbH); + renderer.setOrigin(x, y); + renderer.drawRoundedRect(0, tbH-1, width, height-tbH+1, 3, pal.outline); + tabBar.draw(renderer); + contents[activeTab]->draw(renderer); +} + +} diff --git a/src/gui/allegro/tabPanel.h b/src/gui/allegro/tabPanel.h new file mode 100644 index 0000000000..da56684167 --- /dev/null +++ b/src/gui/allegro/tabPanel.h @@ -0,0 +1,47 @@ +#ifndef _ZC_GUI_ALLEGRO_TABPANEL_H_ +#define _ZC_GUI_ALLEGRO_TABPANEL_H_ + +#include "../tabPanel.h" +#include "standardWidget.h" +#include "tabBar.h" +#include + +namespace GUI +{ + +class AllegroScrollingPane; + +class AllegroTabPanel: public TabPanel, public StandardAllegroWidget +{ +public: + AllegroTabPanel(); + ~AllegroTabPanel(); + // Inherited + void addTab(const std::string& name, Widget* contents); + + void getPreferredSize(int& prefWidth, int& prefHeight); + int getDataSize() const; + int realize(DIALOG dlg[], int index); + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + void setController(AllegroDialogController* controller); + void draw(AllegroGUIRenderer& renderer) const; + void activateTab(int newTab); + + bool widthIsFlexible() const { return true; } + bool heightIsFlexible() const { return true; } + + static int proc(int msg, DIALOG* d, int c); + +private: + AllegroTabBar tabBar; + std::vector contents; + int activeTab; + mutable int contentDataSize; + DIALOG* contentDlgStart; +}; + +} + +#endif + + diff --git a/src/gui/allegro/text.cpp b/src/gui/allegro/text.cpp new file mode 100644 index 0000000000..e9b7a2951e --- /dev/null +++ b/src/gui/allegro/text.cpp @@ -0,0 +1,94 @@ +#include "text.h" +#include "common.h" +#include "list.h" +#include "renderer.h" +#include + +namespace GUI +{ + +int AllegroText::proc(int msg, DIALOG* d, int c) +{ + AllegroText* text=static_cast(d->dp); + + switch(msg) + { + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + + case MSG_WANTMOUSE: + if(!text->list) + return D_DONTWANTMOUSE; + break; + + case MSG_CLICK: + if(!text->list) + return D_O_K; + text->list->changeSelection(text->listNum); + break; + + case MSG_DCLICK: + if(!text->list) + return D_O_K; + text->list->doubleClick(text->listNum); + break; + } + + return D_O_K; +} + +AllegroText::AllegroText(const std::string& t, FONT* f, const GUIColor& c): + StandardAllegroWidget(), + text(t), + font(f), + color(c), + centered(false), + list(0), + listNum(0), + selected(false) +{ +} + +void AllegroText::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + GUIColor col=color; + if(selected) + { + col=pal.editTextHL; + renderer.fillRect(0, 0, width, height, pal.editHL); + } + if(centered) + renderer.drawText(text, width/2, 0, font, col, AllegroGUIRenderer::ta_center); + else + renderer.drawText(text, 4, 0, font, col, AllegroGUIRenderer::ta_left); +} + +void AllegroText::getPreferredSize(int& prefWidth, int& prefHeight) +{ + prefWidth=text_length(font, text.c_str())+8; + prefHeight=text_height(font); +} + +void AllegroText::setSizeAndPos(int newX, int newY, + int newWidth, int newHeight) +{ + adjustSizeAndPos(newY, newHeight, text_height(font)); + StandardAllegroWidget::setSizeAndPos(newX, newY, newWidth, newHeight); +} + +int AllegroText::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void AllegroText::setText(const std::string& newText) +{ + // TODO: Handle size change + text=newText; + if(dialog) + object_message(dialog, MSG_DRAW, 0); +} + +} // Namespace diff --git a/src/gui/allegro/text.h b/src/gui/allegro/text.h new file mode 100644 index 0000000000..7d77c9c100 --- /dev/null +++ b/src/gui/allegro/text.h @@ -0,0 +1,50 @@ +#ifndef _ZC_GUI_ALLEGRO_TEXT_H_ +#define _ZC_GUI_ALLEGRO_TEXT_H_ + +#include "../text.h" +#include "standardWidget.h" +#include +#include + +struct FONT; + +namespace GUI +{ + +class AllegroList; +struct GUIColor; + +class AllegroText: public Text, public StandardAllegroWidget +{ +public: + AllegroText(const std::string& text, FONT* font, const GUIColor& color); + + inline void setCentered(bool val) { centered=val; } + + inline void setList(AllegroList* al) { list=al; } + inline void setListNum(int num) { listNum=num; } + inline void setSelected(bool s) { selected=s; } + + // Inherited + void draw(AllegroGUIRenderer& renderer) const; + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + void setText(const std::string& newText); + int realize(DIALOG dlgArray[], int index); + + static int proc(int msg, DIALOG* d, int c); + +private: + std::string text; + FONT* font; + const GUIColor& color; + bool centered; + AllegroList* list; + int listNum; + bool selected; +}; + +} + +#endif + diff --git a/src/gui/allegro/textField.cpp b/src/gui/allegro/textField.cpp new file mode 100644 index 0000000000..04601e8961 --- /dev/null +++ b/src/gui/allegro/textField.cpp @@ -0,0 +1,189 @@ +#include "textField.h" +#include "common.h" +#include "renderer.h" +#include "../../zsys.h" // vbound +#include +#include + +extern FONT* lfont_l; + +using std::max; +using std::min; + +namespace GUI +{ + +int AllegroTextField::proc(int msg, DIALOG *d, int c) +{ + AllegroTextField* tf=static_cast(d->dp); + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_LPRESS: + // TODO + break; + + case MSG_CHAR: + { + if(tf->onKeyPress(c)) + return D_USED_CHAR; + break; + } + + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + } + + return D_O_K; +} + +AllegroTextField::AllegroTextField(int len): + StandardAllegroWidget(), + maxLength(len), + text(lfont_l), + cursorPos(0), + highlightPos(0), + offset(0) +{ +} + +void AllegroTextField::getPreferredSize(int& prefWidth, int& prefHeight) +{ + prefWidth=6*maxLength; + prefHeight=text.getHeight()+12; +} + +void AllegroTextField::setText(const std::string& newText) +{ + // TODO: limit length + if(newText.length()<=maxLength) + text.setText(newText); + else + text.setText(newText.substr(0, maxLength)); + cursorPos=highlightPos=text.length(); +} + +void AllegroTextField::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + renderer.fillRoundedRect(0, 0, width, height, 4, pal.editBG); + renderer.drawRoundedRect(0, 0, width, height, 4, pal.outline); + renderer.pushClipRect(3, 4, width-6, height-6); + text.draw(renderer, x+3+offset, y+4, width-6, cursorPos, highlightPos, (dialog->flags&D_GOTFOCUS)!=0); + renderer.popClipRect(); +} + +bool AllegroTextField::onKeyPress(int kp) +{ + // Check for special keys first + switch(kp>>8) + { + case KEY_LEFT: + moveCursor(cursorPos-1); + break; + + case KEY_RIGHT: + moveCursor(cursorPos+1); + break; + + case KEY_HOME: + moveCursor(0); + break; + + case KEY_END: + moveCursor(text.length()); + break; + + case KEY_DEL: + case KEY_BACKSPACE: + { + if(highlightPos!=cursorPos) + deleteHighlighted(); + else if((kp>>8)==KEY_BACKSPACE) + { + text.deleteText(cursorPos-1, cursorPos); + if(cursorPos>0) + { + cursorPos--; + highlightPos--; + } + } + else + text.deleteText(cursorPos, cursorPos+1); + + break; + } + + case KEY_ENTER: + // TODO + return true; + + case KEY_TAB: + // Ignore + return false; + + default: + // Not one of those; is it a text character? + kp&=0xFF; + if((kp<32) || (kp>255)) + return false; + + if(highlightPos!=cursorPos) + deleteHighlighted(); + if(text.length()width-20) // Too far right + offset=width-cursorX-20; +} + +int AllegroTextField::realize(DIALOG dlgArray[], int index) +{ + return realizeAs(dlgArray, index); +} + +void AllegroTextField::setSizeAndPos(int newX, int newY, + int newWidth, int newHeight) +{ + adjustSizeAndPos(newY, newHeight, text.getHeight()+8); + if(newWidth>6*maxLength) + newWidth=6*maxLength; + StandardAllegroWidget::setSizeAndPos(newX, newY, newWidth, newHeight); +} + +} // Namespace diff --git a/src/gui/allegro/textField.h b/src/gui/allegro/textField.h new file mode 100644 index 0000000000..2a3111345d --- /dev/null +++ b/src/gui/allegro/textField.h @@ -0,0 +1,42 @@ +#ifndef _ZC_GUI_ALLEGRO_TEXTFIELD_H_ +#define _ZC_GUI_ALLEGRO_TEXTFIELD_H_ + +#include "../textField.h" +#include "standardWidget.h" +#include "editableText.h" +#include + +namespace GUI +{ + +class AllegroTextField: public TextField, public StandardAllegroWidget +{ +public: + AllegroTextField(int maxLength); + void setText(const std::string& text); + inline std::string getText() const { return text.getText(); } + void getPreferredSize(int& prefWidth, int& prefHeight); + void setSizeAndPos(int newX, int newY, int newWidth, int newHeight); + void draw(AllegroGUIRenderer& renderer) const; + void putChar(int character, int pos); + + bool fillsWidth() const { return true; } + int realize(DIALOG dlgArray[], int index); + + static int proc(int msg, DIALOG* d, int c); + +private: + int maxLength; + EditableText text; + int cursorPos, highlightPos; + int offset; + + bool onKeyPress(int key); + void moveCursor(int newPos); + void deleteHighlighted(); + void updateOffset(); +}; + +} + +#endif diff --git a/src/gui/allegro/widget.h b/src/gui/allegro/widget.h new file mode 100644 index 0000000000..2d9ac53c53 --- /dev/null +++ b/src/gui/allegro/widget.h @@ -0,0 +1,62 @@ +#ifndef _ZC_GUI_ALLEGRO_WIDGET_H_ +#define _ZC_GUI_ALLEGRO_WIDGET_H_ + +#include "../widget.h" +struct DIALOG; + +namespace GUI +{ + +class AllegroDialogController; +class AllegroGUIRenderer; + +/// Base class for dialog widgets implemented using Allegro DIALOGs. +class AllegroWidget: public Widget +{ + +public: + virtual ~AllegroWidget() {} + + /// Get the dimensions this widget would prefer to use. + /** prefWidth and prefHeight are both input and output. The values + * passed in are the maximum size available. The output values may + * still be higher, however. + */ + virtual void getPreferredSize(int& prefWidth, int& prefHeight) {} + + virtual void onScrollH(int amount, int left, int right) {} + virtual void onScrollV(int amount, int top, int bottom) {} + + /// Sets the size and position of this widget. + /** Containers will arrange their contents accordingly. */ + virtual void setSizeAndPos(int x, int y, int width, int height)=0; + + /// Get the number of DIALOGs this widget uses. + virtual int getDataSize() const { return 1; } + + /// Load DIALOG data into dlgArray[index]. + /** \return The number of DIALOGs used (the same number as getDataSize()). */ + virtual int realize(DIALOG dlgArray[], int index) { return 0; } + + /// Informs the widget that the DIALOG array is no longer valid. + virtual void unrealize() {} + + /// Provides a pointer to the dialog controller. + virtual void setController(AllegroDialogController* controller)=0; + + /// Whether this widget expands and contracts to fill the available width. + virtual bool widthIsFlexible() const { return false; } + + /// Whether this widget expands and contracts to fill the available height. + virtual bool heightIsFlexible() const { return false; } + + virtual void draw(AllegroGUIRenderer& renderer) const=0; + + virtual void setActive(bool val) {} + + virtual bool isActive() { return true; } +}; + +} + +#endif diff --git a/src/gui/allegro/window.cpp b/src/gui/allegro/window.cpp new file mode 100644 index 0000000000..b58775542c --- /dev/null +++ b/src/gui/allegro/window.cpp @@ -0,0 +1,119 @@ +#include "window.h" +#include "common.h" +#include "renderer.h" +#include + +namespace GUI +{ + +int AllegroWindow::proc(int msg, DIALOG* d, int c) +{ + AllegroWindow* window=static_cast(d->dp); + + switch(msg) + { + case MSG_WHEEL: + forwardMouseWheel(d, c); + break; + } + + return D_O_K; +} + +AllegroWindow::AllegroWindow(const std::string& t, FONT* f, + AllegroWidget* c): + StandardAllegroWidget(), + title(t), + titleFont(f), + contents(c) +{ +} + +AllegroWindow::~AllegroWindow() +{ + delete contents; +} + +void AllegroWindow::draw(AllegroGUIRenderer& renderer) const +{ + renderer.setOrigin(x, y); + + // Border, title bar, and outline + renderer.fillRoundedRect(0, 0, width, height, 9, pal.winBorder); + renderer.drawRoundedRect(0, 0, width, height, 9, pal.outline); + renderer.drawText(title, width/2, 4, titleFont, pal.winTitleText, AllegroGUIRenderer::ta_center); + + // Body and outline + renderer.fillPartialRoundedRect(3, 22, width-6, height-25, 7, AllegroGUIRenderer::prr_bottom, pal.winBody); + renderer.drawPartialRoundedRect(3, 22, width-6, height-25, 7, AllegroGUIRenderer::prr_bottom, pal.outline); + renderer.drawLine(3, 21, width-4, 21, pal.outline); + + if(contents) + contents->draw(renderer); +} + +void AllegroWindow::getPreferredSize(int& prefWidth, int& prefHeight) +{ + if(contents) + { + contents->getPreferredSize(prefWidth, prefHeight); + prefWidth+=48; + prefHeight+=34; + } + else + { + prefWidth=48; + prefHeight=34; + } + + // Limit size to 95% of screen height. At the moment, this doesn't cause any problems... + if(prefHeight>0.95f*SCREEN_H) + prefHeight=0.95f*SCREEN_H; +} + +int AllegroWindow::getDataSize() const +{ + if(contents) + return contents->getDataSize()+1; + else + return 1; +} + +int AllegroWindow::realize(DIALOG arr[], int index) +{ + realizeAs(arr, index); + + dlgArray=arr; + int contentSize=0; + if(contents) + contentSize=contents->realize(arr, index+1); + contentStart=index+1; + contentEnd=index+1+contentSize; + + return contentSize+1; +} + +void AllegroWindow::unrealize() +{ + if(onClose()) + onClose(); + StandardAllegroWidget::unrealize(); + if(contents) + contents->unrealize(); +} + +void AllegroWindow::setController(AllegroDialogController* c) +{ + StandardAllegroWidget::setController(c); + if(contents) + contents->setController(c); +} + +void AllegroWindow::setSizeAndPos(int newX, int newY, int newW, int newH) +{ + StandardAllegroWidget::setSizeAndPos(newX, newY, newW, newH); + if(contents) + contents->setSizeAndPos(newX+24, newY+30, newW-48, newH-34); +} + +} // Namespace diff --git a/src/gui/allegro/window.h b/src/gui/allegro/window.h new file mode 100644 index 0000000000..09b9873541 --- /dev/null +++ b/src/gui/allegro/window.h @@ -0,0 +1,44 @@ +#ifndef _ZC_GUI_ALLEGRO_WINDOW_H_ +#define _ZC_GUI_ALLEGRO_WINDOW_H_ + +#include "standardWidget.h" +#include "../window.h" +#include + +struct DIALOG; +struct FONT; + +namespace GUI +{ + +class AllegroWindow: public Window, public StandardAllegroWidget +{ +public: + AllegroWindow(const std::string& title, FONT* titleFont, AllegroWidget* contents); + ~AllegroWindow(); + void getPreferredSize(int& prefWidth, int& prefHeight); + int getDataSize() const; + int realize(DIALOG dlgArray[], int index); + void unrealize(); + void setController(AllegroDialogController* c); + void setSizeAndPos(int newX, int newY, int newW, int newH); + void draw(AllegroGUIRenderer& renderer) const; + void setMenu(Menu* menu) {} + inline void setOnClose(boost::function func) { onClose=func; } + + static int proc(int msg, DIALOG* d, int c); + +private: + std::string title; + FONT* titleFont; + AllegroWidget* contents; + boost::function onClose; + + DIALOG* dlgArray; + int contentStart, contentEnd; +}; + +} + +#endif + diff --git a/src/gui/bitmap.h b/src/gui/bitmap.h new file mode 100644 index 0000000000..c9680ff5bd --- /dev/null +++ b/src/gui/bitmap.h @@ -0,0 +1,78 @@ +#ifndef _ZC_GUI_BITMAP_H_ +#define _ZC_GUI_BITMAP_H_ + +#include "widget.h" +#include "../guiBitmapRenderer.h" +#include "../scoped_ptr.h" +struct BITMAP; +struct MouseInput; + +namespace GUI +{ + +class BitmapWidget: public Widget +{ +public: + virtual ~BitmapWidget() {} + virtual void setHandleMouseInput(bool handle)=0; +}; + +class BitmapBackend +{ +public: + BitmapBackend(): widget(0) {} + virtual ~BitmapBackend() {} + + /// Initializes the renderer and tells the widget what input to forward. + virtual void initialize()=0; // const? + + /// Redraws the bitmap. Called 60 times per second. + virtual void redraw()=0; // const? + + /// Called on mouse input if enabled. + virtual void onMouseInput(const MouseInput& mouse) {} + + /// Returns the current scaling factor. Needed to adjust mouse input. + // This might return a float or double at some point. + inline int getScale() const + { + return renderer->getScale(); + } + + /// Returns an Allegro BITMAP. + inline BITMAP* getBitmap() + { + return renderer->getBitmap(); + } + + /// Returns pixel data that can be used to construct a GdkPixbuf. + inline void* getData() + { + return renderer->getData(); + } + + /// Gets the size of the bitmap in pixels. + inline void getSize(int& width, int& height) const + { + renderer->getActualSize(width, height); + } + + inline void setWidget(BitmapWidget* w) + { + widget=w; + } + + inline void setRenderer(GUIBitmapRenderer* r) + { + renderer.reset(r); + } + +protected: + BitmapWidget* widget; + scoped_ptr renderer; +}; + +} + +#endif + diff --git a/src/gui/button.h b/src/gui/button.h new file mode 100644 index 0000000000..0f0b124e8d --- /dev/null +++ b/src/gui/button.h @@ -0,0 +1,19 @@ +#ifndef _ZC_GUI_BUTTON_H_ +#define _ZC_GUI_BUTTON_H_ + +#include "widget.h" + +namespace GUI +{ + +/// Base class for buttons. +class Button: public Widget +{ +public: + virtual ~Button() {} +}; + +} + +#endif + diff --git a/src/gui/checkbox.h b/src/gui/checkbox.h new file mode 100644 index 0000000000..4549522e97 --- /dev/null +++ b/src/gui/checkbox.h @@ -0,0 +1,28 @@ +#ifndef _ZC_GUI_CHECKBOX_H_ +#define _ZC_GUI_CHECKBOX_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +/// Base class for checkboxes. +class Checkbox: public Widget +{ +public: + virtual ~Checkbox() {} + + /// Get the current state of the checkbox. + virtual bool getValue() const=0; + + /// Check or uncheck the checkbox. + virtual void setValue(bool newValue)=0; + + /// Set a function to be called when the box is checked or unchecked. + virtual void setCallback(boost::function func)=0; +}; + +} + +#endif diff --git a/src/gui/contents.cpp b/src/gui/contents.cpp new file mode 100644 index 0000000000..a5a14175c1 --- /dev/null +++ b/src/gui/contents.cpp @@ -0,0 +1,76 @@ +#include "contents.h" + +namespace GUI +{ + +Contents::Contents(): + numWidgets(0) +{ +} + +Contents::Contents(Widget* w1): + numWidgets(1) +{ + widgets[0]=w1; +} + +Contents::Contents(Widget* w1, Widget* w2): + numWidgets(2) +{ + widgets[0]=w1; + widgets[1]=w2; +} + +Contents::Contents(Widget* w1, Widget* w2, Widget* w3): + numWidgets(3) +{ + widgets[0]=w1; + widgets[1]=w2; + widgets[2]=w3; +} + +Contents::Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4): + numWidgets(4) +{ + widgets[0]=w1; + widgets[1]=w2; + widgets[2]=w3; + widgets[3]=w4; +} + +Contents::Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5): + numWidgets(5) +{ + widgets[0]=w1; + widgets[1]=w2; + widgets[2]=w3; + widgets[3]=w4; + widgets[4]=w5; +} + +Contents::Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5, + Widget* w6): + numWidgets(6) +{ + widgets[0]=w1; + widgets[1]=w2; + widgets[2]=w3; + widgets[3]=w4; + widgets[4]=w5; + widgets[5]=w6; +} + +Contents::Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5, + Widget* w6, Widget* w7): + numWidgets(6) +{ + widgets[0]=w1; + widgets[1]=w2; + widgets[2]=w3; + widgets[3]=w4; + widgets[4]=w5; + widgets[5]=w6; + widgets[6]=w7; +} + +} diff --git a/src/gui/contents.h b/src/gui/contents.h new file mode 100644 index 0000000000..d9a7aebc97 --- /dev/null +++ b/src/gui/contents.h @@ -0,0 +1,39 @@ +#ifndef _ZC_GUI_CONTENTS_H_ +#define _ZC_GUI_CONTENTS_H_ + +#include // for size_t + +// A class to be used in creating containers. Variadic functions are a pain +// to use correctly, and variadic templates and initializer_lists aren't +// available. This is an easy and not-too-ugly alternative. + +namespace GUI +{ + +class Widget; + +class Contents +{ +public: + Contents(); + Contents(Widget* w1); + Contents(Widget* w1, Widget* w2); + Contents(Widget* w1, Widget* w2, Widget* w3); + Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4); + Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5); + Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5, + Widget* w6); + Contents(Widget* w1, Widget* w2, Widget* w3, Widget* w4, Widget* w5, + Widget* w6, Widget* w7); + + inline Widget* operator [](int index) const { return widgets[index]; } + inline size_t size() const { return numWidgets; } + +private: + const int numWidgets; + GUI::Widget* widgets[7]; +}; + +} + +#endif diff --git a/src/gui/controller.cpp b/src/gui/controller.cpp new file mode 100644 index 0000000000..0cc581a6be --- /dev/null +++ b/src/gui/controller.cpp @@ -0,0 +1,12 @@ +#include "controller.h" +#include "dialog.h" + +namespace GUI +{ + +bool DialogController::onKeyPressed(const KeyInput& key) +{ + return owner->onKeyPressed(key); +} + +} diff --git a/src/gui/controller.h b/src/gui/controller.h new file mode 100644 index 0000000000..a2fc7fa559 --- /dev/null +++ b/src/gui/controller.h @@ -0,0 +1,31 @@ +#ifndef _ZC_GUI_CONTROLLER_H_ +#define _ZC_GUI_CONTROLLER_H_ + +struct KeyInput; + +namespace GUI +{ + +class Dialog; +class Widget; + +class DialogController +{ +public: + virtual ~DialogController() {} + virtual void setDialogRoot(Widget* root)=0; + virtual void initialize()=0; + virtual void update()=0; + virtual void shutDown()=0; + virtual bool isOpen()=0; + + inline void setOwner(Dialog* d) { owner=d; } + bool onKeyPressed(const KeyInput& key); + +private: + Dialog* owner; +}; + +} + +#endif diff --git a/src/gui/dialog.cpp b/src/gui/dialog.cpp new file mode 100644 index 0000000000..89adffbba0 --- /dev/null +++ b/src/gui/dialog.cpp @@ -0,0 +1,27 @@ +#include "dialog.h" +#include "factory.h" +#include "key.h" + +namespace GUI +{ + +void Dialog::initialize(const WidgetFactory& f) +{ + controller.reset(f.controller()); + controller->setOwner(this); + controller->setDialogRoot(createDialog(f)); + controller->initialize(); +} + +bool Dialog::onKeyPressed(const KeyInput& key) +{ + if(key.key==key_ESCAPE) + { + shutDown(); + return true; + } + + return false; +} + +} diff --git a/src/gui/dialog.h b/src/gui/dialog.h new file mode 100644 index 0000000000..6574fb5a44 --- /dev/null +++ b/src/gui/dialog.h @@ -0,0 +1,33 @@ +#ifndef _ZC_GUI_DIALOG_H_ +#define _ZC_GUI_DIALOG_H_ + +#include "controller.h" +#include "../scoped_ptr.h" +struct KeyInput; + +namespace GUI +{ + +class Widget; +class WidgetFactory; + +/// Base type for dialogs to be displayed by GUIManager::showDialog(). +class Dialog +{ +public: + virtual ~Dialog() {} + void initialize(const WidgetFactory& f); + inline void update() { controller->update(); } + inline bool isOpen() const { return controller->isOpen(); } + inline void shutDown() { controller->shutDown(); } + virtual bool onKeyPressed(const KeyInput& key); + +private: + scoped_ptr controller; + + virtual Widget* createDialog(const WidgetFactory& f)=0; +}; + +} + +#endif diff --git a/src/gui/factory.h b/src/gui/factory.h new file mode 100644 index 0000000000..c6b5e93e71 --- /dev/null +++ b/src/gui/factory.h @@ -0,0 +1,61 @@ +#ifndef _ZC_GUI_FACTORY_H_ +#define _ZC_GUI_FACTORY_H_ + +#include "bitmap.h" +#include "button.h" +#include "checkbox.h" +#include "controller.h" +#include "contents.h" +#include "list.h" +#include "menu.h" +#include "menuItem.h" +#include "serialContainer.h" +#include "spinner.h" +#include "tabPanel.h" +#include "text.h" +#include "textBox.h" +#include "textField.h" +#include "widget.h" +#include "window.h" +#include +#include + +namespace GUI +{ + +class WidgetFactory +{ +public: + virtual ~WidgetFactory() {} + + virtual DialogController* controller() const=0; + + // Regular widgets + virtual BitmapWidget* bitmap(BitmapBackend* backend, int scale=2) const=0; + virtual Button* button(const std::string& text, boost::function onClick) const=0; + virtual Checkbox* checkbox(const std::string& text) const=0; + virtual List* comboBox(const ListData* data) const=0; + virtual List* list(const ListData* data) const=0; + virtual Spinner* spinner(int minVal, int maxVal) const=0; + virtual Text* text(const std::string& text) const=0; + virtual TextBox* textBox() const=0; + virtual TextField* textField(int maxLength) const=0; + + // Toplevels + virtual Window* window(const std::string& title, Widget* contents) const=0; + + // Containers + virtual Widget* frame(const std::string& label, Widget* content) const=0; + virtual SerialContainer* column(const Contents& contents=Contents()) const=0; + virtual SerialContainer* spacedColumn(const Contents& contents=Contents()) const=0; + virtual SerialContainer* row(const Contents& contents=Contents()) const=0; + virtual SerialContainer* spacedRow(const Contents& contents=Contents()) const=0; + virtual SerialContainer* buttonRow(const Contents& contents=Contents()) const=0; + virtual TabPanel* tabPanel() const=0; +}; + +} + +#endif + + diff --git a/src/gui/gtk/bitmap.cpp b/src/gui/gtk/bitmap.cpp new file mode 100644 index 0000000000..01eab8b64c --- /dev/null +++ b/src/gui/gtk/bitmap.cpp @@ -0,0 +1,167 @@ +#include "bitmap.h" +#include "util.h" +#include + +namespace GUI +{ + +gboolean ZCGtkBitmap::redraw(GtkWidget* widget, cairo_t* cr, ZCGtkBitmap* bmp) +{ + bmp->backend->redraw(); + GtkStyleContext* ctx=gtk_widget_get_style_context(widget); + gtk_render_icon(ctx, cr, bmp->pixbuf, 0, 0); + return TRUE; +} + +gboolean ZCGtkBitmap::mouseInput(GtkWidget*, GdkEvent* event, BitmapBackend* bb) +{ + // The return value shouldn't make any difference; the bitmap will be + // the only thing under the mouse that might be interested in it. + MouseInput mi; + if(translateMouseEvent(event, bb->getScale(), mi)) + { + bb->onMouseInput(mi); + return TRUE; + } + return FALSE; +} + +gboolean ZCGtkBitmap::makeDirty(gpointer data) +{ + RedrawData* rd=static_cast(data); + if(rd->valid) + { + gtk_widget_queue_draw(rd->image); + return TRUE; + } + else + { + delete rd; + return FALSE; + } +} + +ZCGtkBitmap::ZCGtkBitmap(BitmapBackend* be): + backend(be), + pixbuf(0), + image(0), + events(0), + frame(0), + handleMouseInput(false), + mousePressedHandler(0), + mouseReleasedHandler(0), + mouseMotionHandler(0), + redrawData(0), + redrawEventID(0) +{ + backend->setWidget(this); + backend->initialize(); + + int width, height; + guchar* data=static_cast(backend->getData()); + backend->getSize(width, height); + + pixbuf=gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, FALSE, 8, + width, height, width*3, 0, 0); + image=gtk_image_new_from_pixbuf(pixbuf); + g_signal_connect(image, "destroy", G_CALLBACK(gtk_widget_destroyed), &image); + + redrawData=new RedrawData(image); + g_signal_connect(image, "draw", G_CALLBACK(redraw), this); + // Redraw every 17 ms. Not exactly 60 FPS, but it should do. + redrawEventID=g_timeout_add(17, makeDirty, redrawData); + + events=gtk_event_box_new(); + gtk_widget_add_events(events, + GDK_POINTER_MOTION_MASK|GDK_SCROLL_MASK| + GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + g_signal_connect(events, "destroy", G_CALLBACK(gtk_widget_destroyed), &events); + + frame=gtk_frame_new(0); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); + gtk_widget_set_halign(frame, GTK_ALIGN_START); + gtk_widget_set_valign(frame, GTK_ALIGN_START); + g_signal_connect(frame, "destroy", G_CALLBACK(gtk_widget_destroyed), &frame); + + gtk_container_add(GTK_CONTAINER(events), image); + gtk_container_add(GTK_CONTAINER(frame), events); + + if(handleMouseInput) + { + mousePressedHandler=g_signal_connect(events, + "button-press-event",G_CALLBACK(mouseInput), backend.get()); + mouseReleasedHandler=g_signal_connect(events, + "button-release-event", G_CALLBACK(mouseInput), backend.get()); + mouseMotionHandler=g_signal_connect(events, + "motion-notify-event", G_CALLBACK(mouseInput), backend.get()); + mouseWheelHandler=g_signal_connect(events, + "scroll-event", G_CALLBACK(mouseInput), backend.get()); + } +} + +ZCGtkBitmap::~ZCGtkBitmap() +{ + // This should probably be handled when the image is destroyed, + // but I had serious problems getting that to work. + // I don't think locking is needed here, but I'm not certain. + if(redrawEventID>0) + { + if(events) + g_source_remove(redrawEventID); + redrawEventID=0; + } + if(redrawData) + redrawData->valid=false; +} + +void ZCGtkBitmap::setHandleMouseInput(bool handle) +{ + handleMouseInput=handle; + + if(events) + { + // Does setting this repeatedly cause problems? + // Will that ever happen, anyway? + if(handle) + { + mousePressedHandler=g_signal_connect(events, + "button-press-event",G_CALLBACK(mouseInput), backend.get()); + mouseReleasedHandler=g_signal_connect(events, + "button-release-event", G_CALLBACK(mouseInput), backend.get()); + mouseMotionHandler=g_signal_connect(events, + "motion-notify-event", G_CALLBACK(mouseInput), backend.get()); + mouseWheelHandler=g_signal_connect(events, + "scroll-event", G_CALLBACK(mouseInput), backend.get()); + } + else + { + if(mousePressedHandler!=0) + { + g_signal_handler_disconnect(events, mousePressedHandler); + mousePressedHandler=0; + } + if(mouseReleasedHandler!=0) + { + g_signal_handler_disconnect(events, mouseReleasedHandler); + mouseReleasedHandler=0; + } + if(mouseMotionHandler!=0) + { + g_signal_handler_disconnect(events, mouseMotionHandler); + mouseMotionHandler=0; + } + if(mouseWheelHandler!=0) + { + g_signal_handler_disconnect(events, mouseWheelHandler); + mouseWheelHandler=0; + } + } + } +} + +GtkWidget* ZCGtkBitmap::get() +{ + return frame; +} + +} diff --git a/src/gui/gtk/bitmap.h b/src/gui/gtk/bitmap.h new file mode 100644 index 0000000000..2f252f1ef8 --- /dev/null +++ b/src/gui/gtk/bitmap.h @@ -0,0 +1,45 @@ +#ifndef _ZC_GUI_GTK_BITMAP_H_ +#define _ZC_GUI_GTK_BITMAP_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkBitmap: public BitmapWidget, public ZCGtkWidget +{ +public: + ZCGtkBitmap(BitmapBackend* backend); + ~ZCGtkBitmap(); + void setHandleMouseInput(bool handle); + GtkWidget* get(); + +private: + struct RedrawData + { + RedrawData(GtkWidget* w): valid(true), image(w) {} + bool valid; + GtkWidget* image; + }; + + GdkPixbuf* pixbuf; + GtkWidget* image; + GtkWidget* events; + GtkWidget* frame; + scoped_ptr backend; + bool handleMouseInput; + gulong mousePressedHandler, mouseReleasedHandler, mouseMotionHandler, + mouseWheelHandler; + RedrawData* redrawData; + guint redrawEventID; + + static gboolean redraw(GtkWidget* widget, cairo_t* cr, ZCGtkBitmap* bmp); + static gboolean makeDirty(gpointer data); + static gboolean mouseInput(GtkWidget* widget, GdkEvent* event, BitmapBackend* bb); +}; + +} + +#endif diff --git a/src/gui/gtk/button.cpp b/src/gui/gtk/button.cpp new file mode 100644 index 0000000000..2aec5bc057 --- /dev/null +++ b/src/gui/gtk/button.cpp @@ -0,0 +1,28 @@ +#include "button.h" +#include "util.h" + +namespace GUI +{ + +void ZCGtkButton::onClick(GtkButton*, ZCGtkButton* btn) +{ + btn->onClickFunc(); +} + +ZCGtkButton::ZCGtkButton(const std::string& text, boost::function c): + onClickFunc(c) +{ + std::string mod=convertMnemonic(text); + button=gtk_button_new_with_mnemonic(mod.c_str()); + gtk_widget_set_halign(button, GTK_ALIGN_CENTER); + gtk_widget_set_valign(button, GTK_ALIGN_START); + g_signal_connect(button, "destroy", G_CALLBACK(gtk_widget_destroyed), &button); + g_signal_connect(button, "clicked", G_CALLBACK(onClick), this); +} + +GtkWidget* ZCGtkButton::get() +{ + return button; +} + +} diff --git a/src/gui/gtk/button.h b/src/gui/gtk/button.h new file mode 100644 index 0000000000..6166067b9e --- /dev/null +++ b/src/gui/gtk/button.h @@ -0,0 +1,27 @@ +#ifndef _ZC_GUI_GTK_BUTTON_H_ +#define _ZC_GUI_GTK_BUTTON_H_ + +#include +#include "widget.h" +#include +#include + +namespace GUI +{ + +class ZCGtkButton: public Button, public ZCGtkWidget +{ +public: + ZCGtkButton(const std::string& text, boost::function onClick); + GtkWidget* get(); + +private: + GtkWidget* button; + boost::function onClickFunc; + + static void onClick(GtkButton*, ZCGtkButton* btn); +}; + +} + +#endif diff --git a/src/gui/gtk/buttonRow.cpp b/src/gui/gtk/buttonRow.cpp new file mode 100644 index 0000000000..a64c70693b --- /dev/null +++ b/src/gui/gtk/buttonRow.cpp @@ -0,0 +1,46 @@ +#include "buttonRow.h" +#include "util.h" + +namespace GUI +{ + +ZCGtkButtonRow::ZCGtkButtonRow(): + box(0) +{ + box=gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); + gtk_button_box_set_layout(GTK_BUTTON_BOX(box), GTK_BUTTONBOX_CENTER); + gtk_box_set_spacing(GTK_BOX(box), 20); + g_signal_connect(box, "destroy", G_CALLBACK(gtk_widget_destroyed), &box); +} + +ZCGtkButtonRow::~ZCGtkButtonRow() +{ + for(int i=0; i(w); + buttons.push_back(btn); + gtk_container_add(GTK_CONTAINER(box), btn->get()); +} + +void ZCGtkButtonRow::setController(ZCGtkController* c) +{ + ZCGtkWidget::setController(c); + for(int i=0; isetController(c); +} + +bool ZCGtkButtonRow::fillsWidth() const +{ + return true; +} + +GtkWidget* ZCGtkButtonRow::get() +{ + return box; +} + +} diff --git a/src/gui/gtk/buttonRow.h b/src/gui/gtk/buttonRow.h new file mode 100644 index 0000000000..0d26128101 --- /dev/null +++ b/src/gui/gtk/buttonRow.h @@ -0,0 +1,28 @@ +#ifndef _ZC_GUI_GTK_BUTTONROW_H_ +#define _ZC_GUI_GTK_BUTTONROW_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkButtonRow: public SerialContainer, public ZCGtkWidget +{ +public: + ZCGtkButtonRow(); + ~ZCGtkButtonRow(); + void add(Widget* newWidget); + void setController(ZCGtkController* c); + bool fillsWidth() const; + GtkWidget* get(); + +private: + GtkWidget* box; + std::vector buttons; +}; + +} + +#endif diff --git a/src/gui/gtk/checkbox.cpp b/src/gui/gtk/checkbox.cpp new file mode 100644 index 0000000000..522b1b8b83 --- /dev/null +++ b/src/gui/gtk/checkbox.cpp @@ -0,0 +1,43 @@ +#include "checkbox.h" +#include "util.h" + +namespace GUI +{ + +void ZCGtkCheckbox::onToggle(GtkToggleButton* gtb, ZCGtkCheckbox* cb) +{ + if(cb->onToggleFunc) + cb->onToggleFunc(gtk_toggle_button_get_active(gtb)); +} + +ZCGtkCheckbox::ZCGtkCheckbox(const std::string& text) +{ + std::string mod=convertMnemonic(text); + checkbox=gtk_check_button_new_with_mnemonic(mod.c_str()); + g_signal_connect(checkbox, "destroy", G_CALLBACK(gtk_widget_destroyed), &checkbox); + g_signal_connect(checkbox, "toggled", G_CALLBACK (onToggle), this); +} + +bool ZCGtkCheckbox::getValue() const +{ + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox)); +} + +void ZCGtkCheckbox::setValue(bool newValue) +{ + gtk_toggle_button_set_active( + GTK_TOGGLE_BUTTON(checkbox), + newValue ? TRUE : FALSE); +} + +void ZCGtkCheckbox::setCallback(boost::function func) +{ + onToggleFunc=func; +} + +GtkWidget* ZCGtkCheckbox::get() +{ + return checkbox; +} + +} diff --git a/src/gui/gtk/checkbox.h b/src/gui/gtk/checkbox.h new file mode 100644 index 0000000000..43e0497054 --- /dev/null +++ b/src/gui/gtk/checkbox.h @@ -0,0 +1,29 @@ +#ifndef _ZC_GUI_GTK_CHECKBOX_H_ +#define _ZC_GUI_GTK_CHECKBOX_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkCheckbox: public Checkbox, public ZCGtkWidget +{ +public: + ZCGtkCheckbox(const std::string& text); + bool getValue() const; + void setValue(bool newValue); + void setCallback(boost::function func); + GtkWidget* get(); + +private: + GtkWidget* checkbox; + boost::function onToggleFunc; + + static void onToggle(GtkToggleButton*, ZCGtkCheckbox* cb); +}; + +} + +#endif diff --git a/src/gui/gtk/controller.cpp b/src/gui/gtk/controller.cpp new file mode 100644 index 0000000000..0b722f6d7b --- /dev/null +++ b/src/gui/gtk/controller.cpp @@ -0,0 +1,51 @@ +#include "controller.h" +#include "../widget.h" +#include + +namespace GUI +{ + +/* +~ZCGtkDialogController() +{ + // shut down if running, maybe? +} +*/ + +void ZCGtkController::setDialogRoot(Widget* r) +{ + ZCGtkWidget* w=dynamic_cast(r); + root.reset(w); + w->setController(this); +} + +void ZCGtkController::initialize() +{ + gtk_widget_show_all(root->get()); + gtk_main(); +} + +void ZCGtkController::update() +{ + // Nothing to do here? +} + +void ZCGtkController::shutDown() +{ + // This might have been called by the window, so it may have closed already + GtkWidget* w=root->get(); + if(w) + gtk_widget_destroy(w); + root.reset(); + + // Does this need to be conditional? + gtk_main_quit(); +} + +bool ZCGtkController::isOpen() +{ + // Pretty sure this will never be called while a dialog is actually open... + return false; +} + +} diff --git a/src/gui/gtk/controller.h b/src/gui/gtk/controller.h new file mode 100644 index 0000000000..7e7cc2787b --- /dev/null +++ b/src/gui/gtk/controller.h @@ -0,0 +1,26 @@ +#ifndef _ZC_GUI_GTK_CONTROLLER_H_ +#define _ZC_GUI_GTK_CONTROLLER_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkController: public DialogController +{ +public: + void setDialogRoot(Widget* root); + void initialize(); + void update(); + void shutDown(); + bool isOpen(); + +private: + scoped_ptr root; +}; + +} + +#endif diff --git a/src/gui/gtk/factory.cpp b/src/gui/gtk/factory.cpp new file mode 100644 index 0000000000..68971b8849 --- /dev/null +++ b/src/gui/gtk/factory.cpp @@ -0,0 +1,118 @@ +#include "factory.h" + +#include "bitmap.h" +#include "button.h" +#include "buttonRow.h" +#include "checkbox.h" +#include "controller.h" +#include "frame.h" +#include "serialContainer.h" +#include "spinner.h" +#include "tabPanel.h" +#include "text.h" +#include "textBox.h" +#include "textField.h" +#include "window.h" +#include +#include + +namespace GUI +{ + +DialogController* GtkWidgetFactory::controller() const +{ + return new ZCGtkController(); +} + +BitmapWidget* GtkWidgetFactory::bitmap(BitmapBackend* backend, int scale) const +{ + backend->setRenderer(new GUIBitmapRenderer(scale)); + return new ZCGtkBitmap(backend); +} + +Button* GtkWidgetFactory::button(const std::string& text, boost::function onClick) const +{ + return new ZCGtkButton(text, onClick); +} + +Checkbox* GtkWidgetFactory::checkbox(const std::string& text) const +{ + return new ZCGtkCheckbox(text); +} + +Spinner* GtkWidgetFactory::spinner(int minVal, int maxVal) const +{ + return new ZCGtkSpinner(minVal, maxVal); +} + +Text* GtkWidgetFactory::text(const std::string& text) const +{ + return new ZCGtkText(text); +} + +TextBox* GtkWidgetFactory::textBox() const +{ + return new ZCGtkTextBox(); +} + +TextField* GtkWidgetFactory::textField(int maxLength) const +{ + return new ZCGtkTextField(maxLength); +} + +Window* GtkWidgetFactory::window(const std::string& title, Widget* content) const +{ + return new ZCGtkWindow(title, dynamic_cast(content)); +} + +Widget* GtkWidgetFactory::frame(const std::string& label, Widget* content) const +{ + return new ZCGtkFrame(label, dynamic_cast(content)); +} + +SerialContainer* GtkWidgetFactory::column(const Contents& contents) const +{ + ZCGtkSerialContainer* col=new ZCGtkSerialContainer(true, false); + for(int i=0; iadd(contents[i]); + return col; +} + +SerialContainer* GtkWidgetFactory::spacedColumn(const Contents& contents) const +{ + ZCGtkSerialContainer* col=new ZCGtkSerialContainer(true, true); + for(int i=0; iadd(contents[i]); + return col; +} + +SerialContainer* GtkWidgetFactory::row(const Contents& contents) const +{ + ZCGtkSerialContainer* row=new ZCGtkSerialContainer(false, false); + for(int i=0; iadd(contents[i]); + return row; +} + +SerialContainer* GtkWidgetFactory::spacedRow(const Contents& contents) const +{ + ZCGtkSerialContainer* row=new ZCGtkSerialContainer(false, true); + for(int i=0; iadd(contents[i]); + return row; +} + +SerialContainer* GtkWidgetFactory::buttonRow(const Contents& contents) const +{ + ZCGtkButtonRow* row=new ZCGtkButtonRow(); + for(int i=0; iadd(contents[i]); + return row; +} + +TabPanel* GtkWidgetFactory::tabPanel() const +{ + return new ZCGtkTabPanel(); +} + +} diff --git a/src/gui/gtk/factory.h b/src/gui/gtk/factory.h new file mode 100644 index 0000000000..9ef5065e80 --- /dev/null +++ b/src/gui/gtk/factory.h @@ -0,0 +1,42 @@ +#ifndef _ZC_GUI_GTK_FACTORY_H_ +#define _ZC_GUI_GTK_FACTORY_H_ + +#include + +namespace GUI +{ + +class GtkWidgetFactory: public WidgetFactory +{ +public: + + DialogController* controller() const; + + // Regular widgets + BitmapWidget* bitmap(BitmapBackend* backend, int scale) const; + Button* button(const std::string& text, boost::function onClick) const; + Checkbox* checkbox(const std::string& text) const; + List* comboBox(const ListData* data) const { return 0; } + List* list(const ListData* data) const { return 0; } + Spinner* spinner(int minVal, int maxVal) const; + Text* text(const std::string& text) const; + TextBox* textBox() const; + TextField* textField(int maxLength) const; + + // Toplevels + Window* window(const std::string& title, Widget* content) const; + + // Containers + Widget* frame(const std::string& label, Widget* content) const; + SerialContainer* column(const Contents& contents) const; + SerialContainer* spacedColumn(const Contents& contents) const; + SerialContainer* row(const Contents& contents) const; + SerialContainer* spacedRow(const Contents& contents) const; + SerialContainer* buttonRow(const Contents& contents) const; + TabPanel* tabPanel() const; +}; + +}; + +#endif + diff --git a/src/gui/gtk/frame.cpp b/src/gui/gtk/frame.cpp new file mode 100644 index 0000000000..ca336568ec --- /dev/null +++ b/src/gui/gtk/frame.cpp @@ -0,0 +1,22 @@ +#include "frame.h" +#include "util.h" + +namespace GUI +{ + +ZCGtkFrame::ZCGtkFrame(const std::string& label, ZCGtkWidget* content) +{ + if(label!="") + frame=gtk_frame_new(label.c_str()); + else + frame=gtk_frame_new(0); + g_signal_connect(frame, "destroy", G_CALLBACK(gtk_widget_destroyed), &frame); + gtk_container_add(GTK_CONTAINER(frame), content->get()); +} + +GtkWidget* ZCGtkFrame::get() +{ + return frame; +} + +} diff --git a/src/gui/gtk/frame.h b/src/gui/gtk/frame.h new file mode 100644 index 0000000000..68d438f8c6 --- /dev/null +++ b/src/gui/gtk/frame.h @@ -0,0 +1,23 @@ +#ifndef _ZC_GUI_GTK_FRAME_H_ +#define _ZC_GUI_GTK_FRAME_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkFrame: public Widget, public ZCGtkWidget +{ +public: + ZCGtkFrame(const std::string& label, ZCGtkWidget* content); + GtkWidget* get(); + +private: + GtkWidget* frame; +}; + +} + +#endif diff --git a/src/gui/gtk/manager.cpp b/src/gui/gtk/manager.cpp new file mode 100644 index 0000000000..12ad4b8128 --- /dev/null +++ b/src/gui/gtk/manager.cpp @@ -0,0 +1,12 @@ +#include "manager.h" +#include + +namespace GUI +{ + +GtkGUIManager::GtkGUIManager() +{ + gtk_init(0, 0); +} + +} diff --git a/src/gui/gtk/manager.h b/src/gui/gtk/manager.h new file mode 100644 index 0000000000..e4c4728e87 --- /dev/null +++ b/src/gui/gtk/manager.h @@ -0,0 +1,23 @@ +#ifndef _ZC_GUI_GTK_MANAGER_H_ +#define _ZC_GUI_GTK_MANAGER_H_ + +#include +#include "factory.h" + +namespace GUI +{ + +class GtkGUIManager: public GUIManager +{ +public: + GtkGUIManager(); + +private: + GtkWidgetFactory factory; + + inline const WidgetFactory& getFactory() const { return factory; } +}; + +}; + +#endif diff --git a/src/gui/gtk/serialContainer.cpp b/src/gui/gtk/serialContainer.cpp new file mode 100644 index 0000000000..ed7e9b6f1a --- /dev/null +++ b/src/gui/gtk/serialContainer.cpp @@ -0,0 +1,87 @@ +#include "serialContainer.h" +#include "util.h" + +namespace GUI +{ + +namespace +{ + +// Used to fix space allocation when an expanding widget is added to a container +// that previously contained only fixed-size widgets. +void repackChildren(GtkWidget* child, gpointer box) +{ + gtk_box_set_child_packing(GTK_BOX(box), child, FALSE, FALSE, 0, GTK_PACK_START); +} + +} + +ZCGtkSerialContainer::ZCGtkSerialContainer(bool v, bool es): + vertical(v), + evenlySpaced(es), + hasExpanders(false) +{ + box=gtk_box_new(v ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL, 5); + g_signal_connect(box, "destroy", G_CALLBACK(gtk_widget_destroyed), &box); + gtk_box_set_homogeneous(GTK_BOX(box), es); +} + +ZCGtkSerialContainer::~ZCGtkSerialContainer() +{ + for(int i=0; i(newWidget); + contents.push_back(w); + + gboolean isExpander=vertical ? w->fillsHeight() : w->fillsWidth(); + GtkWidget* child=w->get(); + + // If any widgets in the container expand to fill available space, + // all extra space should be allocated to those widgets. Otherwise, + // extra space should be distributed evenly if this is an evenly- + // spaced container and unused otherwise. + + if(evenlySpaced) + gtk_box_pack_start(GTK_BOX(box), child, TRUE, isExpander, 0); + else if(hasExpanders) + gtk_box_pack_start(GTK_BOX(box), child, isExpander, isExpander, 0); + else + { + if(isExpander) + { + hasExpanders=true; + gtk_container_foreach(GTK_CONTAINER(box), repackChildren, box); + gtk_box_pack_start(GTK_BOX(box), child, TRUE, TRUE, 0); + } + else + gtk_box_pack_start(GTK_BOX(box), child, FALSE, FALSE, 0); + } +} + +void ZCGtkSerialContainer::setController(ZCGtkController* c) +{ + ZCGtkWidget::setController(c); + for(int i=0; isetController(c); +} + +bool ZCGtkSerialContainer::fillsWidth() const +{ + return true; +} + +bool ZCGtkSerialContainer::fillsHeight() const +{ + return true; +} + +GtkWidget* ZCGtkSerialContainer::get() +{ + return box; +} + +} diff --git a/src/gui/gtk/serialContainer.h b/src/gui/gtk/serialContainer.h new file mode 100644 index 0000000000..29ea2f6e91 --- /dev/null +++ b/src/gui/gtk/serialContainer.h @@ -0,0 +1,31 @@ +#ifndef _ZC_GUI_GTK_SERIALCONTAINER_H_ +#define _ZC_GUI_GTK_SERIALCONTAINER_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkSerialContainer: public SerialContainer, public ZCGtkWidget +{ +public: + ZCGtkSerialContainer(bool vertical, bool evenlySpaced); + ~ZCGtkSerialContainer(); + void add(Widget* newWidget); + void setController(ZCGtkController* c); + bool fillsWidth() const; + bool fillsHeight() const; + GtkWidget* get(); + +private: + GtkWidget* box; + const bool vertical, evenlySpaced; + bool hasExpanders; + std::vector contents; +}; + +} + +#endif diff --git a/src/gui/gtk/spinner.cpp b/src/gui/gtk/spinner.cpp new file mode 100644 index 0000000000..a68cb28a14 --- /dev/null +++ b/src/gui/gtk/spinner.cpp @@ -0,0 +1,44 @@ +#include "spinner.h" + +namespace GUI +{ + +void ZCGtkSpinner::valueChanged(GtkSpinButton* widget, ZCGtkSpinner* spinner) +{ + if(spinner->onValueChanged) + spinner->onValueChanged(gtk_spin_button_get_value_as_int(widget)); +} + +ZCGtkSpinner::ZCGtkSpinner(int minVal, int maxVal): + spinner(0), + signalHandlerID(0) +{ + spinner=gtk_spin_button_new_with_range(minVal, maxVal, 1); + signalHandlerID=g_signal_connect(spinner, "value-changed", G_CALLBACK(valueChanged), this); + g_signal_connect(spinner, "destroy", G_CALLBACK(gtk_widget_destroyed), &spinner); +} + +void ZCGtkSpinner::setValue(int val) +{ + if(signalHandlerID>0) + g_signal_handler_disconnect(spinner, signalHandlerID); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner), val); + signalHandlerID=g_signal_connect(spinner, "value-changed", G_CALLBACK(valueChanged), this); +} + +int ZCGtkSpinner::getValue() const +{ + return gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinner)); +} + +void ZCGtkSpinner::setOnValueChanged(boost::function func) +{ + onValueChanged=func; +} + +GtkWidget* ZCGtkSpinner::get() +{ + return spinner; +} + +} diff --git a/src/gui/gtk/spinner.h b/src/gui/gtk/spinner.h new file mode 100644 index 0000000000..91bd8f8d94 --- /dev/null +++ b/src/gui/gtk/spinner.h @@ -0,0 +1,31 @@ +#ifndef _ZC_GUI_GTK_SPINNER_H_ +#define _ZC_GUI_GTK_SPINNER_H_ + +#include +#include "widget.h" + +namespace GUI +{ + +class ZCGtkSpinner: public Spinner, public ZCGtkWidget +{ +public: + ZCGtkSpinner(int minVal, int maxVal); + void setValue(int val); + int getValue() const; + void setOnValueChanged(boost::function func); + GtkWidget* get(); + +private: + GtkWidget* spinner; + boost::function onValueChanged; + gulong signalHandlerID; + + static void valueChanged(GtkSpinButton* widget, ZCGtkSpinner* spinner); +}; + +} + + +#endif + diff --git a/src/gui/gtk/tabPanel.cpp b/src/gui/gtk/tabPanel.cpp new file mode 100644 index 0000000000..1a85c76bbb --- /dev/null +++ b/src/gui/gtk/tabPanel.cpp @@ -0,0 +1,48 @@ +#include "tabPanel.h" +#include "util.h" + +namespace GUI +{ + +ZCGtkTabPanel::ZCGtkTabPanel() +{ + tabPanel=gtk_notebook_new(); + g_signal_connect(tabPanel, "destroy", G_CALLBACK(gtk_widget_destroyed), &tabPanel); +} + +ZCGtkTabPanel::~ZCGtkTabPanel() +{ + for(int i=0; i(w); + contents.push_back(zw); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollPane), zw->get()); + gtk_notebook_append_page(GTK_NOTEBOOK(tabPanel), scrollPane, label); +} + +void ZCGtkTabPanel::setController(ZCGtkController* c) +{ + ZCGtkWidget::setController(c); + for(int i=0; isetController(c); +} + +GtkWidget* ZCGtkTabPanel::get() +{ + return tabPanel; +} + +} diff --git a/src/gui/gtk/tabPanel.h b/src/gui/gtk/tabPanel.h new file mode 100644 index 0000000000..99bb529d17 --- /dev/null +++ b/src/gui/gtk/tabPanel.h @@ -0,0 +1,27 @@ +#ifndef _ZC_GUI_GTK_TABPANEL_H_ +#define _ZC_GUI_GTK_TABPANEL_H_ + +#include +#include "widget.h" +#include + +namespace GUI +{ + +class ZCGtkTabPanel: public TabPanel, public ZCGtkWidget +{ +public: + ZCGtkTabPanel(); + ~ZCGtkTabPanel(); + void addTab(const std::string& name, Widget* contents); + void setController(ZCGtkController* c); + GtkWidget* get(); + +private: + GtkWidget* tabPanel; + std::vector contents; +}; + +} + +#endif diff --git a/src/gui/gtk/text.cpp b/src/gui/gtk/text.cpp new file mode 100644 index 0000000000..9034f17483 --- /dev/null +++ b/src/gui/gtk/text.cpp @@ -0,0 +1,25 @@ +#include "text.h" +#include "util.h" + +namespace GUI +{ + +ZCGtkText::ZCGtkText(const std::string& t) +{ + text=gtk_label_new(t.c_str()); + gtk_label_set_max_width_chars(GTK_LABEL(text), 50); // Maybe? We'll see how it goes. + gtk_label_set_line_wrap(GTK_LABEL(text), TRUE); + g_signal_connect(text, "destroy", G_CALLBACK(gtk_widget_destroyed), &text); +} + +void ZCGtkText::setText(const std::string& newText) +{ + gtk_label_set_text(GTK_LABEL(text), newText.c_str()); +} + +GtkWidget* ZCGtkText::get() +{ + return text; +} + +} diff --git a/src/gui/gtk/text.h b/src/gui/gtk/text.h new file mode 100644 index 0000000000..31538c8053 --- /dev/null +++ b/src/gui/gtk/text.h @@ -0,0 +1,23 @@ +#ifndef _ZC_GUI_GTK_TEXT_H_ +#define _ZC_GUI_GTK_TEXT_H_ + +#include +#include "widget.h" + +namespace GUI +{ + +class ZCGtkText: public Text, public ZCGtkWidget +{ +public: + ZCGtkText(const std::string& text); + void setText(const std::string& newText); + GtkWidget* get(); + +private: + GtkWidget *text; +}; + +} + +#endif diff --git a/src/gui/gtk/textBox.cpp b/src/gui/gtk/textBox.cpp new file mode 100644 index 0000000000..c23a4ca26f --- /dev/null +++ b/src/gui/gtk/textBox.cpp @@ -0,0 +1,50 @@ +#include "textBox.h" +#include +namespace GUI +{ + +ZCGtkTextBox::ZCGtkTextBox(float width, float height): + textBox(0), + scrollPane(0) +{ + textBox=gtk_text_view_new(); + g_signal_connect(textBox, "destroy", G_CALLBACK(gtk_widget_destroyed), &textBox); + + scrollPane=gtk_scrolled_window_new( + gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(textBox)), // Unnecessary? + gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(textBox))); + gtk_widget_set_size_request(scrollPane, 800, 600); + g_signal_connect(scrollPane, "destroy", G_CALLBACK(gtk_widget_destroyed), &scrollPane); + gtk_container_add(GTK_CONTAINER(scrollPane), textBox); +} + +void ZCGtkTextBox::setText(const std::string& text) +{ + GtkTextBuffer* buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textBox)); + gtk_text_buffer_set_text(buffer, text.c_str(), -1); +} + +std::string ZCGtkTextBox::getText() const +{ + GtkTextBuffer* buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(textBox)); + GtkTextIter start, end; + gtk_text_buffer_get_bounds(buffer, &start, &end); + return gtk_text_buffer_get_text(buffer, &start, &end, TRUE); +} + +bool ZCGtkTextBox::fillsWidth() const +{ + return true; +} + +bool ZCGtkTextBox::fillsHeight() const +{ + return true; +} + +GtkWidget* ZCGtkTextBox::get() +{ + return scrollPane; +} + +} diff --git a/src/gui/gtk/textBox.h b/src/gui/gtk/textBox.h new file mode 100644 index 0000000000..abfef6a882 --- /dev/null +++ b/src/gui/gtk/textBox.h @@ -0,0 +1,27 @@ +#ifndef _ZC_GUI_GTK_TEXTBOX_H_ +#define _ZC_GUI_GTK_TEXTBOX_H_ + +#include +#include "widget.h" + +namespace GUI +{ + +class ZCGtkTextBox: public TextBox, public ZCGtkWidget +{ +public: + ZCGtkTextBox(float width=1.0f, float height=1.0f); // TODO + void setText(const std::string& text); + std::string getText() const; + bool fillsWidth() const; + bool fillsHeight() const; + GtkWidget* get(); + +private: + GtkWidget* textBox; + GtkWidget* scrollPane; +}; + +} + +#endif diff --git a/src/gui/gtk/textField.cpp b/src/gui/gtk/textField.cpp new file mode 100644 index 0000000000..d85a310a24 --- /dev/null +++ b/src/gui/gtk/textField.cpp @@ -0,0 +1,37 @@ +#include "textField.h" +#include "util.h" + +namespace GUI +{ + +ZCGtkTextField::ZCGtkTextField(int maxLength) +{ + textField=gtk_entry_new(); + gtk_entry_set_max_length(GTK_ENTRY(textField), maxLength); + + // TODO: Do something better with the size + gtk_widget_set_size_request(textField, 256, -1); + g_signal_connect(textField, "destroy", G_CALLBACK(gtk_widget_destroyed), &textField); +} + +void ZCGtkTextField::setText(const std::string& text) +{ + gtk_entry_set_text(GTK_ENTRY(textField), text.c_str()); +} + +std::string ZCGtkTextField::getText() const +{ + return gtk_entry_get_text(GTK_ENTRY(textField)); +} + +bool ZCGtkTextField::fillsWidth() const +{ + return true; +} + +GtkWidget* ZCGtkTextField::get() +{ + return textField; +} + +} diff --git a/src/gui/gtk/textField.h b/src/gui/gtk/textField.h new file mode 100644 index 0000000000..b120704a8e --- /dev/null +++ b/src/gui/gtk/textField.h @@ -0,0 +1,27 @@ +#ifndef _ZC_GUI_GTK_TEXTFIELD_H_ +#define _ZC_GUI_GTK_TEXTFIELD_H_ + +#include +#include "widget.h" + +namespace GUI +{ + +class ZCGtkTextField: public TextField, public ZCGtkWidget +{ +public: + ZCGtkTextField(int maxLength); + void setText(const std::string& text); + std::string getText() const; + bool fillsWidth() const; + GtkWidget* get(); + +private: + GtkWidget* textField; + +}; + +} + + +#endif diff --git a/src/gui/gtk/util.cpp b/src/gui/gtk/util.cpp new file mode 100644 index 0000000000..d5b160706d --- /dev/null +++ b/src/gui/gtk/util.cpp @@ -0,0 +1,170 @@ +#include "util.h" +#include "../key.h" +#include "../mouse.h" + +namespace +{ + +struct KeyMapEntry +{ + int gtk; + zcKey zc; +}; + +const KeyMapEntry keyMap[]={ + { GDK_KEY_Escape, key_ESCAPE }, + { GDK_KEY_Return, key_ENTER }, + { GDK_KEY_space, key_SPACE }, + { GDK_KEY_plus, key_PLUS }, + { GDK_KEY_equal, key_PLUS }, + { GDK_KEY_KP_Add, key_PLUS }, + { GDK_KEY_minus, key_MINUS }, + { GDK_KEY_underscore, key_MINUS }, + { GDK_KEY_KP_Subtract, key_MINUS }, + { GDK_KEY_Up, key_UP }, + { GDK_KEY_Down, key_DOWN }, + { GDK_KEY_Left, key_LEFT }, + { GDK_KEY_Right, key_RIGHT }, + { GDK_KEY_Page_Up, key_PAGEUP }, + { GDK_KEY_Page_Down, key_PAGEDOWN }, + { GDK_KEY_Home, key_HOME }, + { GDK_KEY_End, key_END }, + { GDK_KEY_A, key_A }, { GDK_KEY_a, key_A }, + { GDK_KEY_B, key_B }, { GDK_KEY_b, key_B }, + { GDK_KEY_C, key_C }, { GDK_KEY_c, key_C }, + { GDK_KEY_D, key_D }, { GDK_KEY_d, key_D }, + { GDK_KEY_E, key_E }, { GDK_KEY_e, key_E }, + { GDK_KEY_F, key_F }, { GDK_KEY_f, key_F }, + { GDK_KEY_G, key_G }, { GDK_KEY_g, key_G }, + { GDK_KEY_H, key_H }, { GDK_KEY_h, key_H }, + { GDK_KEY_I, key_I }, { GDK_KEY_i, key_I }, + { GDK_KEY_J, key_J }, { GDK_KEY_j, key_J }, + { GDK_KEY_K, key_K }, { GDK_KEY_k, key_K }, + { GDK_KEY_L, key_L }, { GDK_KEY_l, key_L }, + { GDK_KEY_M, key_M }, { GDK_KEY_m, key_M }, + { GDK_KEY_N, key_N }, { GDK_KEY_n, key_N }, + { GDK_KEY_O, key_O }, { GDK_KEY_o, key_O }, + { GDK_KEY_P, key_P }, { GDK_KEY_p, key_P }, + { GDK_KEY_Q, key_Q }, { GDK_KEY_q, key_Q }, + { GDK_KEY_R, key_R }, { GDK_KEY_r, key_R }, + { GDK_KEY_S, key_S }, { GDK_KEY_s, key_S }, + { GDK_KEY_T, key_T }, { GDK_KEY_t, key_T }, + { GDK_KEY_U, key_U }, { GDK_KEY_u, key_U }, + { GDK_KEY_V, key_V }, { GDK_KEY_v, key_V }, + { GDK_KEY_W, key_W }, { GDK_KEY_w, key_W }, + { GDK_KEY_X, key_X }, { GDK_KEY_x, key_X }, + { GDK_KEY_Y, key_Y }, { GDK_KEY_y, key_Y }, + { GDK_KEY_Z, key_Z }, { GDK_KEY_z, key_Z }, + { GDK_KEY_1, key_1 }, + { GDK_KEY_2, key_2 }, + { GDK_KEY_3, key_3 }, + { GDK_KEY_4, key_4 }, + { GDK_KEY_5, key_5 }, + { GDK_KEY_6, key_6 }, + { GDK_KEY_7, key_7 }, + { GDK_KEY_8, key_8 }, + { GDK_KEY_9, key_9 }, + { GDK_KEY_0, key_0 }, + { GDK_KEY_F1, key_F1 }, + { GDK_KEY_F2, key_F2 }, + { GDK_KEY_F3, key_F3 }, + { GDK_KEY_F4, key_F4 }, + { GDK_KEY_F5, key_F5 }, + { GDK_KEY_F6, key_F6 }, + { GDK_KEY_F7, key_F7 }, + { GDK_KEY_F8, key_F8 }, + { GDK_KEY_F9, key_F9 }, + { GDK_KEY_F10, key_F10 }, + { GDK_KEY_F11, key_F11 }, + { GDK_KEY_F12, key_F12 }, + { 0, key_ESCAPE } +}; + +} + +bool translateKeyEvent(GdkEvent* event, KeyInput& out) +{ + bool found=false; + int i=0; + for(; keyMap[i].gtk!=0; i++) + { + if(keyMap[i].gtk==event->key.keyval) + { + found=true; + break; + } + } + + if(!found) + return false; + + out.key=keyMap[i].zc; + out.shiftPressed=(event->key.state&GDK_SHIFT_MASK)!=0; + out.ctrlPressed=(event->key.state&GDK_CONTROL_MASK)!=0; + out.altPressed=(event->key.state&GDK_META_MASK)!=0; + return true; +} + +bool translateMouseEvent(GdkEvent* event, int scale, MouseInput& out) +{ + switch(event->type) + { + case GDK_MOTION_NOTIFY: + out.type=mouse_MOTION; + break; + + case GDK_BUTTON_PRESS: + if(event->button.button==1) + out.type=mouse_LEFTBUTTONDOWN; + else if(event->button.button==3) + out.type=mouse_RIGHTBUTTONDOWN; + else + return false; + break; + + case GDK_BUTTON_RELEASE: + if(event->button.button==1) + out.type=mouse_LEFTBUTTONUP; + else if(event->button.button==3) + out.type=mouse_RIGHTBUTTONUP; + else + return false; + break; + + case GDK_2BUTTON_PRESS: + if(event->button.button==1) + out.type=mouse_DOUBLECLICK; + else + return false; + break; + + case GDK_SCROLL: + if(event->scroll.direction==GDK_SCROLL_UP) + out.type=mouse_WHEELUP; + else if(event->scroll.direction==GDK_SCROLL_DOWN) + out.type=mouse_WHEELDOWN; + // There's also a delta_y field - does that need to be considered? + break; + + default: + return false; + } + + // The relevant data for all three event types are in the same place + out.x=event->button.x/scale; + out.y=event->button.y/scale; + out.shiftPressed=(event->button.state&GDK_SHIFT_MASK)!=0; + out.ctrlPressed=(event->button.state&GDK_CONTROL_MASK)!=0; + out.altPressed=(event->button.state&GDK_META_MASK)!=0; + return true; +} + +std::string convertMnemonic(const std::string& str) +{ + size_t pos=str.find('&'); + if(pos==std::string::npos) + return str; + std::string mod=str; + mod.replace(pos, 1, "_"); + return mod; +} diff --git a/src/gui/gtk/util.h b/src/gui/gtk/util.h new file mode 100644 index 0000000000..45efb9cc9a --- /dev/null +++ b/src/gui/gtk/util.h @@ -0,0 +1,13 @@ +#ifndef _ZC_GUI_GTK_UTIL_H_ +#define _ZC_GUI_GTK_UTIL_H_ + +#include +#include +struct KeyInput; +struct MouseInput; + +bool translateKeyEvent(GdkEvent* event, KeyInput& out); +bool translateMouseEvent(GdkEvent* event, int scale, MouseInput& out); +std::string convertMnemonic(const std::string& str); + +#endif diff --git a/src/gui/gtk/widget.cpp b/src/gui/gtk/widget.cpp new file mode 100644 index 0000000000..653464e55f --- /dev/null +++ b/src/gui/gtk/widget.cpp @@ -0,0 +1,25 @@ +#include "widget.h" + +namespace GUI +{ + +ZCGtkWidget::ZCGtkWidget(): + controller(0) +{ +} + +ZCGtkWidget::~ZCGtkWidget() +{ +} + +bool ZCGtkWidget::fillsWidth() const +{ + return false; +} + +bool ZCGtkWidget::fillsHeight() const +{ + return false; +} + +} diff --git a/src/gui/gtk/widget.h b/src/gui/gtk/widget.h new file mode 100644 index 0000000000..84011347eb --- /dev/null +++ b/src/gui/gtk/widget.h @@ -0,0 +1,31 @@ +#ifndef _ZC_GUI_GTK_WIDGET_H_ +#define _ZC_GUI_GTK_WIDGET_H_ + +#include + +namespace GUI +{ + +class ZCGtkController; + +// Named to distinguish it from GtkWidget +class ZCGtkWidget +{ +public: + ZCGtkWidget(); + virtual ~ZCGtkWidget(); + virtual inline void setController(ZCGtkController* c) { controller=c; } + inline ZCGtkController* getController() { return controller; } + virtual GtkWidget* get()=0; + + virtual bool fillsWidth() const; + virtual bool fillsHeight() const; + +private: + ZCGtkController* controller; +}; + +} + +#endif + diff --git a/src/gui/gtk/window.cpp b/src/gui/gtk/window.cpp new file mode 100644 index 0000000000..6acee15a7b --- /dev/null +++ b/src/gui/gtk/window.cpp @@ -0,0 +1,70 @@ +#include "window.h" +#include "controller.h" +#include "util.h" +#include + +namespace GUI +{ + +void ZCGtkWindow::windowClosed(GtkWidget*, ZCGtkWindow* window) +{ + // Currently, a window is always a top-level widget, + // and it's the only thing that can be. + window->window=0; + window->getController()->shutDown(); +} + +gboolean ZCGtkWindow::keyPressed(GtkWidget*, GdkEvent* event, ZCGtkWindow* window) +{ + KeyInput keys; + if(translateKeyEvent(event, keys)) + return window->getController()->onKeyPressed(keys); + else + return FALSE; +} + +gboolean ZCGtkWindow::deleteEvent(GtkWidget*, GdkEvent*, ZCGtkWindow* window) +{ + if(!window->onCloseFunc) + return FALSE; + if(window->onCloseFunc()) + return FALSE; + return TRUE; +} + +ZCGtkWindow::ZCGtkWindow(const std::string& title, ZCGtkWidget* c): + window(0), + contents(c) +{ + window=gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window), title.c_str()); + gtk_window_set_type_hint (GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); + g_signal_connect(window, "delete-event", G_CALLBACK(deleteEvent), this); + g_signal_connect(window, "key-press-event", G_CALLBACK(keyPressed), this); + g_signal_connect(window, "destroy", G_CALLBACK(windowClosed), this); + + gtk_container_set_border_width(GTK_CONTAINER(window), 15); + gtk_container_add(GTK_CONTAINER(window), c->get()); +} + +ZCGtkWindow::~ZCGtkWindow() +{ +} + +void ZCGtkWindow::setOnClose(boost::function func) +{ + onCloseFunc=func; +} + +void ZCGtkWindow::setController(ZCGtkController* c) +{ + ZCGtkWidget::setController(c); + contents->setController(c); +} + +GtkWidget* ZCGtkWindow::get() +{ + return window; +} + +} diff --git a/src/gui/gtk/window.h b/src/gui/gtk/window.h new file mode 100644 index 0000000000..d77859f599 --- /dev/null +++ b/src/gui/gtk/window.h @@ -0,0 +1,36 @@ +#ifndef _ZC_GUI_GTK_WINDOW_H_ +#define _ZC_GUI_GTK_WINDOW_H_ + +#include +#include "widget.h" +#include +#include +#include + +namespace GUI +{ + +class ZCGtkWindow: public Window, public ZCGtkWidget +{ +public: + ZCGtkWindow(const std::string& title, ZCGtkWidget* contents); + ~ZCGtkWindow(); + void setMenu(Menu* menu) {} // TODO... + void setOnClose(boost::function func); + void setController(ZCGtkController* c); + GtkWidget* get(); + +private: + GtkWidget* window; + GtkAccelGroup* accelerators; + scoped_ptr contents; + boost::function onCloseFunc; + + static void windowClosed(GtkWidget*, ZCGtkWindow* window); + static gboolean keyPressed(GtkWidget*, GdkEvent* event, ZCGtkWindow* window); + static gboolean deleteEvent(GtkWidget*, GdkEvent*, ZCGtkWindow* window); +}; + +} + +#endif diff --git a/src/gui/key.h b/src/gui/key.h new file mode 100644 index 0000000000..3efca3e776 --- /dev/null +++ b/src/gui/key.h @@ -0,0 +1,35 @@ +#ifndef _ZC_GUI_KEY_H_ +#define _ZC_GUI_KEY_H_ + +// Keyboard inputs. We'll likely want to replace this at some point, +// but it works for now. + +enum zcKey +{ + key_ESCAPE, key_ENTER, key_SPACE, + key_PLUS, key_MINUS, + key_UP, key_DOWN, key_LEFT, key_RIGHT, + key_PAGEUP, key_PAGEDOWN, key_HOME, key_END, + key_A, key_B, key_C, key_D, + key_E, key_F, key_G, key_H, + key_I, key_J, key_K, key_L, + key_M, key_N, key_O, key_P, + key_Q, key_R, key_S, key_T, + key_U, key_V, key_W, key_X, + key_Y, key_Z, key_1, key_2, + key_3, key_4, key_5, key_6, + key_7, key_8, key_9, key_0, + key_F1, key_F2, key_F3, key_F4, + key_F5, key_F6, key_F7, key_F8, + key_F9, key_F10, key_F11, key_F12 +}; + +struct KeyInput +{ + zcKey key; + bool shiftPressed; + bool ctrlPressed; + bool altPressed; +}; + +#endif diff --git a/src/gui/list.h b/src/gui/list.h new file mode 100644 index 0000000000..67a55ab6f8 --- /dev/null +++ b/src/gui/list.h @@ -0,0 +1,46 @@ +#ifndef _ZC_GUI_LIST_H_ +#define _ZC_GUI_LIST_H_ + +#include "widget.h" +#include +#include + +namespace GUI +{ + +class List: public Widget +{ +public: + /// Set a function to be called when a different item is selected. + virtual void setOnValueChanged(const boost::function& func)=0; + + /// Set a function to be called when an item is double-clicked. + // Doesn't make sense for combo boxes; maybe those should + // use a different interface. + virtual void setOnDoubleClick(const boost::function& func) {} + + /// Set the selected item. + virtual void setSelected(int index)=0; + + /// Get the current selection. + virtual int getSelected() const=0; +}; + +class ListData +{ +public: + ListData(const boost::function& strF, + const boost::function& sizeF): strFunc(strF), sizeFunc(sizeF) {} + inline std::string get(int index) const { return strFunc(index); } + inline int size() const { return sizeFunc(); } + +private: + boost::function strFunc; + boost::function sizeFunc; +}; + +} + +#endif + + diff --git a/src/gui/manager.cpp b/src/gui/manager.cpp new file mode 100644 index 0000000000..f920da0afa --- /dev/null +++ b/src/gui/manager.cpp @@ -0,0 +1,39 @@ +#include "manager.h" +#include "alert.h" +#include "dialog.h" + +using std::string; + +namespace GUI +{ + +void GUIManager::showDialog(Dialog& d) +{ + d.initialize(getFactory()); + while(d.isOpen()) + d.update(); +} + +void GUIManager::alert(const string& title, const string& text) +{ + Alert a(title, text, "O&K"); + showDialog(a); +} + +int GUIManager::alert(const string& title, const string& text, const string& button1, + const string& button2, int defaultValue) +{ + Alert a(title, text, button1, button2, defaultValue); + showDialog(a); + return a.getResult(); +} + +int GUIManager::alert(const string& title, const string& text, const string& button1, + const string& button2, const string& button3, int defaultValue) +{ + Alert a(title, text, button1, button2, button3, defaultValue); + showDialog(a); + return a.getResult(); +} + +} diff --git a/src/gui/manager.h b/src/gui/manager.h new file mode 100644 index 0000000000..d2b4e4d448 --- /dev/null +++ b/src/gui/manager.h @@ -0,0 +1,37 @@ +#ifndef _ZC_GUI_MANAGER_H_ +#define _ZC_GUI_MANAGER_H_ + +#include + +namespace GUI +{ + +class Dialog; +class WidgetFactory; + +class GUIManager +{ +public: + virtual ~GUIManager() {} + void showDialog(Dialog& d); // const? There may be a dialog stack at some point + + // Should alerts be const? Not sure how they'll work, exactly. + + // Has only an "OK" button and no return value + void alert(const std::string& title, const std::string& text); + + // Has two buttons, returns 1 or 2 + int alert(const std::string& title, const std::string& text, const std::string& button1, + const std::string& button2, int defaultValue); + + // Has three buttons, returns 1, 2, or 3 + int alert(const std::string& title, const std::string& text, const std::string& button1, + const std::string& button2, const std::string& button3, int defaultValue); + +private: + virtual const WidgetFactory& getFactory() const=0; +}; + +} + +#endif diff --git a/src/gui/menu.h b/src/gui/menu.h new file mode 100644 index 0000000000..8709b8accb --- /dev/null +++ b/src/gui/menu.h @@ -0,0 +1,17 @@ +#ifndef _ZC_GUI_MENU_H_ +#define _ZC_GUI_MENU_H_ + +#include "widget.h" + +namespace GUI +{ + +class Menu: public Widget +{ +public: + virtual ~Menu() {} +}; + +} + +#endif diff --git a/src/gui/menuItem.h b/src/gui/menuItem.h new file mode 100644 index 0000000000..a779faa37a --- /dev/null +++ b/src/gui/menuItem.h @@ -0,0 +1,18 @@ +#ifndef _ZC_GUI_MENUITEM_H_ +#define _ZC_GUI_MENUITEM_H_ + +#include "widget.h" + +namespace GUI +{ + +class MenuItem: public Widget +{ +public: + virtual ~MenuItem() {} +}; + +} + +#endif + diff --git a/src/gui/mouse.h b/src/gui/mouse.h new file mode 100644 index 0000000000..d3790a8970 --- /dev/null +++ b/src/gui/mouse.h @@ -0,0 +1,21 @@ +#ifndef _ZC_GUI_MOUSE_H_ +#define _ZC_GUI_MOUSE_H_ + +enum mouseInputType +{ + mouse_LEFTBUTTONDOWN, mouse_LEFTBUTTONUP, + mouse_RIGHTBUTTONDOWN, mouse_RIGHTBUTTONUP, + mouse_WHEELUP, mouse_WHEELDOWN, + mouse_DOUBLECLICK, mouse_MOTION +}; + +struct MouseInput +{ + mouseInputType type; + int x, y; + bool shiftPressed; + bool ctrlPressed; + bool altPressed; +}; + +#endif diff --git a/src/gui/serialContainer.h b/src/gui/serialContainer.h new file mode 100644 index 0000000000..32f30a7010 --- /dev/null +++ b/src/gui/serialContainer.h @@ -0,0 +1,19 @@ +#ifndef _GUI_SERIALCONTAINER_H_ +#define _GUI_SERIALCONTAINER_H_ + +#include "widget.h" + +namespace GUI +{ + +/// Base class for rows and columns. +class SerialContainer: public Widget +{ +public: + /// Add a new widget at the end of the container. + virtual void add(Widget* comp)=0; +}; + +} + +#endif diff --git a/src/gui/spinner.h b/src/gui/spinner.h new file mode 100644 index 0000000000..8fd1cca09f --- /dev/null +++ b/src/gui/spinner.h @@ -0,0 +1,30 @@ +#ifndef _ZC_GUI_SPINNER_H_ +#define _ZC_GUI_SPINNER_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +class Spinner: public Widget +{ +public: + virtual ~Spinner() {} + + /// Set the spinner's current value. + /** If a function is set, it will not be called. */ + virtual void setValue(int val)=0; + + /// Get the spinner's current value. + virtual int getValue() const=0; + + /// Set a function to call when the spinner's value changes. + /** The new value will be the argument to the function. */ + virtual void setOnValueChanged(boost::function func)=0; +}; + +} + +#endif + diff --git a/src/gui/tabPanel.h b/src/gui/tabPanel.h new file mode 100644 index 0000000000..009b83430f --- /dev/null +++ b/src/gui/tabPanel.h @@ -0,0 +1,22 @@ +#ifndef _ZC_GUI_TABPANEL_H_ +#define _ZC_GUI_TABPANEL_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +/// Base class for tab panels. +class TabPanel: public Widget +{ +public: + virtual ~TabPanel() {} + + /// Add a new tab with the given name and contents. + virtual void addTab(const std::string& name, Widget* contents)=0; +}; + +} + +#endif diff --git a/src/gui/text.h b/src/gui/text.h new file mode 100644 index 0000000000..4d250e6ffe --- /dev/null +++ b/src/gui/text.h @@ -0,0 +1,22 @@ +#ifndef _ZC_GUI_TEXT_H_ +#define _ZC_GUI_TEXT_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +/// Base class for text. +class Text: public Widget +{ +public: + virtual ~Text() {} + + /// Set the text to be displayed. + virtual void setText(const std::string& newText)=0; +}; + +} + +#endif diff --git a/src/gui/textBox.h b/src/gui/textBox.h new file mode 100644 index 0000000000..d40f00f338 --- /dev/null +++ b/src/gui/textBox.h @@ -0,0 +1,20 @@ +#ifndef _ZC_GUI_TEXTBOX_H_ +#define _ZC_GUI_TEXTBOX_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +class TextBox: public Widget +{ +public: + virtual ~TextBox() {} + virtual void setText(const std::string& text)=0; + virtual std::string getText() const=0; +}; + +} + +#endif diff --git a/src/gui/textField.h b/src/gui/textField.h new file mode 100644 index 0000000000..8cfa4a0652 --- /dev/null +++ b/src/gui/textField.h @@ -0,0 +1,25 @@ +#ifndef _ZC_GUI_TEXTFIELD_H_ +#define _ZC_GUI_TEXTFIELD_H_ + +#include "widget.h" +#include + +namespace GUI +{ + +/// Base class for text fields. +class TextField: public Widget +{ +public: + virtual ~TextField() {} + + /// Set the text field's current text. + virtual void setText(const std::string& text)=0; + + /// Get the text field's current text. + virtual std::string getText() const=0; +}; + +} + +#endif diff --git a/src/gui/widget.h b/src/gui/widget.h new file mode 100644 index 0000000000..6ba03be4c0 --- /dev/null +++ b/src/gui/widget.h @@ -0,0 +1,26 @@ +#ifndef _ZC_GUI_WIDGET_H_ +#define _ZC_GUI_WIDGET_H_ + +namespace GUI +{ + +/// Base class for all GUI widgets. +class Widget +{ +public: + Widget(): userID(0) {} + virtual ~Widget() {} + + /// Set an ID number to identify this widget later. + inline void setUserID(int id) { userID=id; } + + /// Get the previously set ID number. + inline int getUserID() const { return userID; } + +private: + int userID; +}; + +} + +#endif diff --git a/src/gui/window.h b/src/gui/window.h new file mode 100644 index 0000000000..f26eb3585e --- /dev/null +++ b/src/gui/window.h @@ -0,0 +1,32 @@ +#ifndef _ZC_GUI_WINDOW_H_ +#define _ZC_GUI_WINDOW_H_ + +#include "widget.h" +#include +#include + +namespace GUI +{ + +class Menu; + +/// Base class for windows. +class Window: public Widget +{ +public: + virtual ~Window() {} + + /// Add a menu bar to the window. + virtual void setMenu(Menu* menu)=0; + + /// Set a function to be called when the window's close button is clicked. + /** If the function return false, the window will not close. + */ + virtual void setOnClose(boost::function func)=0; +}; + +} + +#endif + + diff --git a/src/guiBitmapRenderer.cpp b/src/guiBitmapRenderer.cpp new file mode 100644 index 0000000000..2c021c7304 --- /dev/null +++ b/src/guiBitmapRenderer.cpp @@ -0,0 +1,98 @@ +#include "guiBitmapRenderer.h" +#include "tiles.h" +#include + +extern bool blank_tile_table[65520]; + +static int convertColor(int color) +{ + RGB rgb; + get_color(color, &rgb); + return makecol_depth( + 24, + (rgb.r<<2)|(rgb.r>>4), + (rgb.g<<2)|(rgb.g>>4), + (rgb.b<<2)|(rgb.b>>4)); +} + +GUIBitmapRenderer::GUIBitmapRenderer(int s): + scale(s), + bmp(0) +{ +} + +GUIBitmapRenderer::~GUIBitmapRenderer() +{ + destroy_bitmap(bmp); +} + +void GUIBitmapRenderer::initialize(int width, int height) +{ + bmp=create_bitmap_ex(24, width*scale, height*scale); + clear_bitmap(bmp); +} + +void* GUIBitmapRenderer::getData() +{ + return *bmp->line; +} + +void GUIBitmapRenderer::getActualSize(int& width, int& height) const +{ + width=bmp->w; + height=bmp->h; +} + +void GUIBitmapRenderer::clear() +{ + clear_bitmap(bmp); +} + +void GUIBitmapRenderer::drawRect(int x, int y, int width, int height, int color) +{ + rect(bmp, x*scale, y*scale, (x+width)*scale-1, (y+height)*scale-1, convertColor(color)); +} + +void GUIBitmapRenderer::fillRect(int x, int y, int width, int height, int color) +{ + rectfill(bmp, x*scale, y*scale, (x+width)*scale-1, (y+height)*scale-1, convertColor(color)); +} + +void GUIBitmapRenderer::drawLine(int x1, int y1, int x2, int y2, int color) +{ + line(bmp, x1*scale, y1*scale, x2*scale, y2*scale, convertColor(color)); +} + +void GUIBitmapRenderer::putTile(int tile, int cset, Orientation orientation, + int x, int y) +{ + if(!blank_tile_table[tile]) + { + // This can be redone later... + static BITMAP* tempBMP1=0; + static BITMAP* tempBMP2=0; + if(!tempBMP1) + { + tempBMP1=create_bitmap_ex(8, 16, 16); + tempBMP2=create_bitmap_ex(24, 16, 16); + } + + puttile16(tempBMP1, tile, 0, 0, cset, orientation); + blit(tempBMP1, tempBMP2, 0, 0, 0, 0, 16, 16); + stretch_blit(tempBMP2, bmp, 0, 0, 16, 16, x*scale, y*scale, 16*scale, 16*scale); + } + else // Blank + { + int top=(y+2)*scale; + int bottom=(y+13)*scale-1; + int left=(x+2)*scale; + int right=(x+13)*scale-1; + int black=makecol_depth(24, 0, 0, 0); + int white=makecol_depth(24, 255, 255, 255); + + rectfill(bmp, x*scale, y*scale, (x+16)*scale-1, (y+16)*scale-1, black); + rect(bmp, left, top, right, bottom, white); + line(bmp, left, top, right, bottom, white); + line(bmp, left, bottom, right, top, white); + } +} diff --git a/src/guiBitmapRenderer.h b/src/guiBitmapRenderer.h new file mode 100644 index 0000000000..630534a074 --- /dev/null +++ b/src/guiBitmapRenderer.h @@ -0,0 +1,29 @@ +#ifndef _ZC_GUIBITMAPRENDERER_H_ +#define _ZC_GUIBITMAPRENDERER_H_ + +#include +struct BITMAP; + +class GUIBitmapRenderer +{ +public: + GUIBitmapRenderer(int scale); + ~GUIBitmapRenderer(); + void initialize(int width, int height); + inline BITMAP* getBitmap() { return bmp; } + void* getData(); + void getActualSize(int& width, int& height) const; + inline int getScale() const { return scale; } + + void clear(); + void drawRect(int x, int y, int width, int height, int color); + void fillRect(int x, int y, int width, int height, int color); + void drawLine(int x1, int y1, int x2, int y2, int color); + void putTile(int tile, int cset, Orientation orientation, int x, int y); + +private: + const int scale; + BITMAP* bmp; +}; + +#endif diff --git a/src/guys.cpp b/src/guys.cpp new file mode 100644 index 0000000000..666433bf8b --- /dev/null +++ b/src/guys.cpp @@ -0,0 +1,3527 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// guys.cc +// +// "Guys" code (and other related stuff) for zelda.cc +// +//-------------------------------------------------------- + +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +#include "precompiled.h" //always first + +#include +#include +#include "zc_alleg.h" +#include "guys.h" +#include "zelda.h" +#include "zc_sys.h" +#include "zsys.h" +#include "maps.h" +#include "link.h" +#include "subscr.h" +#include "ffscript.h" +#include "gamedata.h" +#include "defdata.h" +#include "mem_debug.h" +#include "zscriptversion.h" +#include "messageManager.h" +#include "room.h" +#include "sound.h" + +#include "sfxManager.h" +#include "angelscript/aszc.h" +#include "angelscript/scriptData.h" + +extern LinkClass Link; +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations; +extern zinitdata zinit; +extern MessageManager messageMgr; +extern SFXManager sfxMgr; + +int wallm_load_clk=0; +int sle_x,sle_y,sle_cnt,sle_clk; +int vhead=0; +int guycarryingitem=0; + +char *guy_string[eMAXGUYS]; + +BITMAP* scriptDrawingTarget; +static bool scriptShadowTrans; + +void never_return(int index); +void playLevelMusic(); + +// If an enemy is this far out of the playing field, just remove it. +#define OUTOFBOUNDS ((int)y>((tmpscr->flags7&fSIDEVIEW && canfall(id))?192:352) || y<-176 || x<-256 || x > 512) + +namespace +{ + int trapConstantHorizontalID; + int trapConstantVerticalID; + int trapLOSHorizontalID; + int trapLOSVerticalID; + int trapLOS4WayID; + + int cornerTrapID; + int centerTrapID; + + int rockID; + int zoraID; + int statueID; +} + +void identifyCFEnemies() +{ + trapConstantHorizontalID=-1; + trapConstantVerticalID=-1; + trapLOSHorizontalID=-1; + trapLOSVerticalID=-1; + trapLOS4WayID=-1; + cornerTrapID=-1; + centerTrapID=-1; + rockID=-1; + zoraID=-1; + statueID=-1; + + for(int i=0; iflags7&fSIDEVIEW) && (iswater(MAPCOMBO(dx,dy)))); +} + +// Returns true iff enemy is floating and blocked by a combo type or flag. +bool flyerblocked(int dx, int dy, int special) +{ + return ((special==spw_floater)&& + ((COMBOTYPE(dx,dy)==cNOFLYZONE)|| + (combo_class_buf[COMBOTYPE(dx,dy)].block_enemies&4)|| + (MAPFLAG(dx,dy)==mfNOENEMY)|| + (MAPCOMBOFLAG(dx,dy)==mfNOENEMY))); +} + +bool m_walkflag(int dx,int dy,int special, int x, int y) +{ + int yg = (special==spw_floater)?8:0; + int nb = get_bit(quest_rules, qr_NOBORDER) ? 16 : 0; + + if(dx<16-nb || dy=240+nb || dy>=160+nb) + return true; + + if(isdungeon() || special==spw_wizzrobe) + { + if((x>=32 && dy<32-yg) || (y>-1000 && y<=144 && dy>=144)) + return true; + + if((x>=32 && dx<32) || (x>-1000 && x<224 && dx>=224)) + if(special!=spw_door) // walk in door way + return true; + } + + switch(special) + { + case spw_clipbottomright: + if(dy>=128 || dx>=208) return true; + + case spw_clipright: + break; //if(x>=208) return true; break; + + case spw_wizzrobe: + case spw_floater: + return false; + } + + dx&=(special==spw_halfstep)?(~7):(~15); + dy&=(special==spw_halfstep || tmpscr->flags7&fSIDEVIEW)?(~7):(~15); + + if(special==spw_water) + return (water_walkflag(dx,dy+8,1) || water_walkflag(dx+8,dy+8,1)); + + return _walkflag(dx,dy+8,1) || _walkflag(dx+8,dy+8,1) || + groundblocked(dx,dy+8) || groundblocked(dx+8,dy+8); +} + + +/**********************************/ +/******* Enemy Base Class *******/ +/**********************************/ + +/* ROM data flags + + */ + +enemy::enemy(fix X,fix Y,int Id,int Clk): + sprite() +{ + d = guysbuf + (Id & 0xFFF); + + bgSFX=sfxMgr.getSFX(d->bgsfx); + hitSFX=sfxMgr.getSFX(d->hitsfx); + deathSFX=sfxMgr.getSFX(d->deadsfx); + + x=X; + y=Y; + id=Id; + clk=Clk; + floor_y=y; + ceiling=false; + fading = misc = clk2 = stunclk = hclk = sclk = superman = 0; + grumble = 0; + yofs = playing_field_offset - ((tmpscr->flags7&fSIDEVIEW) ? 0 : 2); + did_armos=true; + script_spawned=false; + + hp = d->hp; +// cs = d->cset; +//d variables + + flags=d->flags; + flags2=d->flags2; + s_tile=d->s_tile; //secondary (additional) tile(s) + family=d->family; + dcset=d->cset; + cs=dcset; + anim=get_bit(quest_rules,qr_NEWENEMYTILES)?d->e_anim:d->anim; + dp=d->dp; + wdp=d->wdp; + wpn=d->weapon; + + rate=d->rate; + hrate=d->hrate; + dstep=d->step; + homing=d->homing; + dmisc1=d->misc1; + dmisc2=d->misc2; + dmisc3=d->misc3; + dmisc4=d->misc4; + dmisc5=d->misc5; + dmisc6=d->misc6; + dmisc7=d->misc7; + dmisc8=d->misc8; + dmisc9=d->misc9; + dmisc10=d->misc10; + dmisc11=d->misc11; + dmisc12=d->misc12; + dmisc13=d->misc13; + dmisc14=d->misc14; + dmisc15=d->misc15; + + for(int i=0; idefense[i]; + + bgsfx=d->bgsfx; + bosspal=d->bosspal; + + if(bosspal>-1) + { + loadpalset(csBOSS,pSprite(bosspal)); + } + + bgSFX.startLooping(); + + if(get_bit(quest_rules,qr_NEWENEMYTILES)) + { + o_tile=d->e_tile; + frate = d->e_frate; + } + else + { + o_tile=d->tile; + frate = d->frate; + } + + tile=0; + + // If they forgot the invisibility flag, here's another failsafe: + if(o_tile==0 && family!=eeSPINTILE) + flags |= guy_invisible; + +// step = d->step/100.0; + // To preserve the odd step values for Keese & Gleeok heads. -L + if(dstep==62.0) dstep+=fix(0.5); + else if(dstep==89) dstep-=fix(1)/fix(9); + + step = dstep/100.0; + + + item_set = d->item_set; + grumble = d->grumble; + + if(frate == 0) + frate = 256; + + leader = itemguy = dying = scored = false; + canfreeze = count_enemy = true; + mainguy = !(flags & guy_doesntcount); + dir = rand()&3; + + if((wpn==ewBomb || wpn==ewSBomb) && family!=eeOTHER && family!=eeFIRE && (family!=eeWALK || dmisc2 != e2tBOMBCHU)) + wpn = 0; + + dummy_int1=0; +} + +enemy::~enemy() {} + +// Will this only be used by scripts? +void enemy::setBGSFX(SFX newBG) +{ + bgSFX=newBG; + bgSFX.startLooping(); +} + +void enemy::setAttack(EnemyAttack* att) +{ + attack.reset(att); + att->setOwner(this); +} + +void enemy::leave_item() +{ + int drop_item = select_dropitem(item_set, x, y); + + if(drop_item!=-1&&((itemsbuf[drop_item].family!=itype_fairy)||!m_walkflag(x,y,0))) + { + if(extend >= 3) items.add(new item(x+(txsz-1)*8,y+(tysz-1)*8,(fix)0,drop_item,ipBIGRANGE+ipTIMER,0)); + else items.add(new item(x,y,(fix)0,drop_item,ipBIGRANGE+ipTIMER,0)); + } +} + +// auomatically kill off enemy (for rooms with ringleaders) +void enemy::kickbucket() +{ + if(!superman) + hp=-1000; // don't call death_sfx() +} + +// Hit the shield(s)? +// Apparently, this function is only used for hookshots... +bool enemy::hitshield(int wpnx, int wpny, int xdir) +{ + if(!(family==eeWALK || family==eeFIRE || family==eeOTHER)) + return false; + + bool ret = false; + + // TODO: There must be some bitwise operations that can simplify this... + if(wpny > y) ret = ((flags&inv_front && xdir==down) || (flags&inv_back && xdir==up) || (flags&inv_left && xdir==left) || (flags&inv_right && xdir==right)); + else if(wpny < y) ret = ((flags&inv_front && xdir==up) || (flags&inv_back && xdir==down) || (flags&inv_left && xdir==right) || (flags&inv_right && xdir==left)); + + if(wpnx < x) ret = ret || ((flags&inv_front && xdir==left) || (flags&inv_back && xdir==right) || (flags&inv_left && xdir==up) || (flags&inv_right && xdir==down)); + else if(wpnx > x) ret = ret || ((flags&inv_front && xdir==right) || (flags&inv_back && xdir==left) || (flags&inv_left && xdir==down) || (flags&inv_right && xdir==up)); + + return ret; +} + +// Check defenses without actually acting on them. +bool enemy::candamage(int power, int edef) +{ + switch(defense[edef]) + { + case edSTUNORCHINK: + case edSTUNORIGNORE: + case edSTUNONLY: + case edCHINK: + case edIGNORE: + return false; + + case edIGNOREL1: + case edCHINKL1: + return power >= 1*DAMAGE_MULTIPLIER; + + case edCHINKL2: + return power >= 2*DAMAGE_MULTIPLIER; + + case edCHINKL4: + return power >= 4*DAMAGE_MULTIPLIER; + + case edCHINKL6: + return power >= 6*DAMAGE_MULTIPLIER; + + case edCHINKL8: + return power >= 8*DAMAGE_MULTIPLIER; + } + + return true; +} + +// Do we do damage? +// 0: takehit returns 0 +// 1: takehit returns 1 +// -1: do damage +int enemy::defend(int wpnId, int *power, int edef) +{ + if(shieldCanBlock) + { + switch(defense[edef]) + { + case edIGNORE: + return 0; + case edIGNOREL1: + case edSTUNORIGNORE: + if(*power <= 0) + return 0; + } + + sfx(WAV_CHINK,pan(int(x))); + return 1; + } + + switch(defense[edef]) + { + case edSTUNORCHINK: + if(*power <= 0) + { + sfx(WAV_CHINK,pan(int(x))); + return 1; + } + + case edSTUNORIGNORE: + if(*power <= 0) + return 0; + + case edSTUNONLY: + if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wHookshot || wpnId==wSword) && stunclk>=159) + return 1; + + stunclk=160; + sfx(WAV_EHIT,pan(int(x))); + return 1; + + case edCHINKL1: + if(*power >= 1*DAMAGE_MULTIPLIER) break; + + case edCHINKL2: + if(*power >= 2*DAMAGE_MULTIPLIER) break; + + case edCHINKL4: + if(*power >= 4*DAMAGE_MULTIPLIER) break; + + case edCHINKL6: + if(*power >= 6*DAMAGE_MULTIPLIER) break; + + case edCHINKL8: + if(*power >= 8*DAMAGE_MULTIPLIER) break; + + case edCHINK: + sfx(WAV_CHINK,pan(int(x))); + return 1; + + case edIGNOREL1: + if(*power > 0) break; + + case edIGNORE: + return 0; + + case ed1HKO: + *power = hp; + return -2; + + case edQUARTDAMAGE: + *power = zc_max(1,*power/2); + + //fallthrough + case edHALFDAMAGE: + *power = zc_max(1,*power/2); + break; + } + + return -1; +} + +// Defend against a particular item class. +int enemy::defenditemclass(int wpnId, int *power) +{ + int def=-1; + + switch(wpnId) + { + // These first 2 are only used by Gohma... enemy::takehit() has complicated stun-calculation code for these. + case wBrang: + def = defend(wpnId, power, edefBRANG); + break; + + case wHookshot: + def = defend(wpnId, power, edefHOOKSHOT); + break; + + // Anyway... + case wBomb: + def = defend(wpnId, power, edefBOMB); + break; + + case wSBomb: + def = defend(wpnId, power, edefSBOMB); + break; + + case wArrow: + def = defend(wpnId, power, edefARROW); + break; + + case wFire: + def = defend(wpnId, power, edefFIRE); + break; + + case wWand: + def = defend(wpnId, power, edefWAND); + break; + + case wMagic: + def = defend(wpnId, power, edefMAGIC); + break; + + case wHammer: + def = defend(wpnId, power, edefHAMMER); + break; + + case wSword: + def = defend(wpnId, power, edefSWORD); + break; + + case wBeam: + def = defend(wpnId, power, edefBEAM); + break; + + case wRefBeam: + def = defend(wpnId, power, edefREFBEAM); + break; + + case wRefMagic: + def = defend(wpnId, power, edefREFMAGIC); + break; + + case wRefFireball: + def = defend(wpnId, power, edefREFBALL); + break; + + case wRefRock: + def = defend(wpnId, power, edefREFROCK); + break; + + case wStomp: + def = defend(wpnId, power, edefSTOMP); + break; + + case wCByrna: + def = defend(wpnId, power, edefBYRNA); + break; + + default: + if(wpnId>=wScript1 && wpnId<=wScript10) + { + def = defend(wpnId, power, edefSCRIPT); + } + + break; + } + + return def; +} + +// take damage or ignore it +// -1: damage (if any) dealt +// 1: blocked +// 0: weapon passes through unhindered +int enemy::takehit(weapon *w) +{ + int wpnId = w->id; + int power = w->power; + int wpnx = w->x; + int wpny = w->y; + int enemyHitWeapon = w->parentitem; + int wpnDir; + + // If it's a boomerang that just bounced, use the opposite direction; + // otherwise, it might bypass a shield. This probably won't handle + // every case correctly, but it's better than having shields simply + // not work against boomerangs. + if(w->id==wBrang && w->misc==1 && w->clk2>=256 && w->clk2<264) + wpnDir = oppositeDir[w->dir]; + else + wpnDir = w->dir; + + if(dying || clk<0 || hclk>0 || superman) + { + return 0; + } + + int ret = -1; + + // This obscure quest rule... + if(get_bit(quest_rules,qr_BOMBDARKNUTFIX) && (wpnId==wBomb || wpnId==wSBomb)) + { + double ddir=atan2(double(wpny-y),double(x-wpnx)); + wpnDir=rand()&3; + + if((ddir<=(((-1)*PI)/4))&&(ddir>(((-3)*PI)/4))) + { + wpnDir=down; + } + else if((ddir<=(((1)*PI)/4))&&(ddir>(((-1)*PI)/4))) + { + wpnDir=right; + } + else if((ddir<=(((3)*PI)/4))&&(ddir>(((1)*PI)/4))) + { + wpnDir=up; + } + else + { + wpnDir=left; + } + } + + int xdir = dir; + shieldCanBlock=false; + + //if (family==eeFLOAT && flags&(inv_front|inv_back_inv_left|inv_right)) xdir=down; + if((wpnId==wHookshot && hitshield(wpnx, wpny, xdir)) + || ((flags&inv_front && wpnDir==(xdir^down)) || (flags&inv_back && wpnDir==(xdir^up)) || (flags&inv_left && wpnDir==(xdir^left)) || (flags&inv_right && wpnDir==(xdir^right))) + ) + // The hammer should already be dealt with by subclasses (Walker etc.) + { + switch(wpnId) + { + // Weapons which shields protect against + case wSword: + case wWand: + Link.onMeleeWeaponHit(); + + //fallthrough + case wHookshot: + case wHSHandle: + case wBrang: + shieldCanBlock=true; + break; + + case wBeam: + case wRefBeam: + case wRefRock: + case wRefFireball: + case wMagic: + if(wpnId>wEnemyWeapons) + return 0; + + //fallthrough + default: + shieldCanBlock=true; + break; + + // Bombs + case wSBomb: + case wBomb: + goto hitclock; + + // Weapons which ignore shields + case wWhistle: + case wHammer: + break; + + // Weapons which shouldn't be removed by shields + case wLitBomb: + case wLitSBomb: + case wWind: + case wPhantom: + case wSSparkle: + case wBait: + return 0; + + case wFire: + ; + } + } + + switch(wpnId) + { + case wWhistle: + return 0; + + case wPhantom: + return 0; + + case wLitBomb: + case wLitSBomb: + case wBait: + case wWind: + case wSSparkle: + return 0; + + case wFSparkle: + + // Only take sparkle damage if the sparkle's parent item is not + // defended against. + if(enemyHitWeapon > -1) + { + int p = 0; + int f = itemsbuf[enemyHitWeapon].family; + + switch(f) + { + case itype_arrow: + if(!candamage(p, edefARROW)) return 0; + + break; + + case itype_cbyrna: + if(!candamage(p, edefBYRNA)) return 0; + + break; + + case itype_brang: + if(!candamage(p, edefBRANG)) return 0; + + break; + + default: + return 0; + } + } + + wpnId = wSword; + power = DAMAGE_MULTIPLIER>>1; + goto fsparkle; + break; + + case wBrang: + { + int def = defend(wpnId, &power, edefBRANG); + + if(def >= 0) return def; + + // Not hurt by 0-damage weapons + if(!(flags & guy_bhit)) + { + stunclk=160; + + if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang)) + { + hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_brang))*DAMAGE_MULTIPLIER; + goto hitclock; + } + + break; + } + + if(!power) + hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_brang))*DAMAGE_MULTIPLIER; + else + hp-=power; + + goto hitclock; + } + + case wHookshot: + { + int def = defend(wpnId, &power, edefHOOKSHOT); + + if(def >= 0) return def; + + if(!(flags & guy_bhit)) + { + stunclk=160; + + if(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot)) + { + hp -= (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot))*DAMAGE_MULTIPLIER; + goto hitclock; + } + + break; + } + + if(!power) hp-=(enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].fam_type : current_item(itype_hookshot))*DAMAGE_MULTIPLIER; + else + hp-=power; + + goto hitclock; + } + break; + + case wHSHandle: + { + if(itemsbuf[enemyHitWeapon>-1 ? enemyHitWeapon : current_item_id(itype_hookshot)].flags & ITEM_FLAG1) + return 0; + + bool ignorehookshot = ((defense[edefHOOKSHOT] == edIGNORE) || ((defense[edefHOOKSHOT] == edIGNOREL1 || defense[edefHOOKSHOT] == edSTUNORIGNORE) + && (enemyHitWeapon>-1 ? itemsbuf[enemyHitWeapon].power : current_item_power(itype_hookshot)) <= 0)); + + // Peahats, Darknuts, Aquamentuses, Pols Voices, Wizzrobes, Manhandlas + if(!(family==eePEAHAT || family==eeAQUA || family==eeMANHAN || (family==eeWIZZ && !ignorehookshot) + || (family==eeWALK && dmisc9==e9tPOLSVOICE) || (family==eeWALK && flags&(inv_back|inv_front|inv_left|inv_right)))) + return 0; + + power = DAMAGE_MULTIPLIER; + //fallthrough + } + +fsparkle: + + default: + // Work out the defenses! + { + int def = defenditemclass(wpnId, &power); + + if(def >= 0) + return def; + else if(def == -2) + { + ret = 0; + } + } + + if(!power) + { + if(flags & guy_bhit) + hp-=1; + else + { + // Don't make a long chain of 'stun' hits + if((wpnId==wFire || wpnId==wBomb || wpnId==wSBomb || wpnId==wSword) && stunclk>0) + return 1; + + stunclk=160; + break; + } + } + else hp-=power; + +hitclock: + hclk=33; + + // Use w->dir instead of wpnDir to make sure boomerangs don't push enemies the wrong way + if((dir&2)==(w->dir&2)) + { + sclk=(w->dir<<8)+16; + } + } + + if(((wpnId==wBrang) || (get_bit(quest_rules,qr_NOFLASHDEATH))) && hp<=0) + { + fading=fade_blue_poof; + } + + sfx(WAV_EHIT, pan(int(x))); + + hitSFX.play(x); + + if(family==eeGUY) + sfx(WAV_EDEAD, pan(int(x))); + + // Penetrating weapons + if((wpnId==wArrow || wpnId==wBeam) && !cannotpenetrate()) + { + int item=enemyHitWeapon; + + if(wpnId==wArrow) + { + if(item<0) + item=current_item_id(itype_arrow); + + if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG1)) + return 0; + } + + else + { + if(item<0) + item=current_item_id(itype_sword); + + if(item>=0 && (itemsbuf[item].flags&ITEM_FLAG3)) + return 0; + } + } + + return ret; +} + +bool enemy::dont_draw() +{ + if(fading==fade_invisible || (((flags2&guy_blinking)||(fading==fade_flicker)) && (clk&1))) + return true; + + if(flags&guy_invisible) + return true; + + if(flags&lens_only && !lensclk) + return true; + + return false; +} + +// base drawing function to be used by all derived classes instead of +// sprite::draw() +void enemy::draw(BITMAP *dest) +{ + if(dont_draw()) + return; + + int cshold=cs; + + if(dying) + { + if(clk2>=19) + { + if(!(clk2&2)) + sprite::draw(dest); + + return; + } + + flip = 0; + tile = wpnsbuf[iwDeath].tile; + + if(BSZ) + tile += zc_min((15-clk2)/3,4); + else if(clk2>6 && clk2<=12) + ++tile; + + /* trying to get more death frames here + if(wpnsbuf[wid].frames) + { + if(++clk2 >= wpnsbuf[wid].speed) + { + clk2 = 0; + if(++aframe >= wpnsbuf[wid].frames) + aframe = 0; + } + tile = wpnsbuf[wid].tile + aframe; + } + */ + + if(BSZ || fading==fade_blue_poof) + cs = wpnsbuf[iwDeath].csets&15; + else + cs = (((clk2+5)>>1)&3)+6; + } + else if(hclk>0) + { + if(family==eeGANON) + cs=(((hclk-1)>>1)&3)+6; + else if(hclk<33 && !get_bit(quest_rules,qr_ENEMIESFLICKER)) + cs=(((hclk-1)>>1)&3)+6; + } + + if((tmpscr->flags3&fINVISROOM) && + !(current_item(itype_amulet)) && + !(get_bit(quest_rules,qr_LENSSEESENEMIES) && + lensclk) && family!=eeGANON) + { + sprite::drawcloaked(dest); + } + else + { + if(family !=eeGANON && hclk>0 && get_bit(quest_rules,qr_ENEMIESFLICKER)) + { + if((frame&1)==1) + sprite::draw(dest); + } + else + sprite::draw(dest); + } + + cs=cshold; +} + +// similar to the overblock function--can do up to a 32x32 sprite +void enemy::drawblock(BITMAP *dest) +{ + int thold=tile; + int t1=tile; + int t2=tile+20; + int t3=tile+1; + int t4=tile+21; + + if(flip&1) + { + zc_swap(t1,t3); + zc_swap(t2,t4); + } + + if(flip&2) + { + zc_swap(t1,t2); + zc_swap(t3,t4); + } + + tile=t1; + enemy::draw(dest); + tile=t2; + yofs+=16; + enemy::draw(dest); + yofs-=16; + tile=t3; + xofs+=16; + enemy::draw(dest); + tile=t4; + yofs+=16; + enemy::draw(dest); + xofs-=16; + yofs-=16; + + tile=thold; +} + +void enemy::drawshadow(BITMAP *dest, bool translucent) +{ + if(dont_draw() || tmpscr->flags7&fSIDEVIEW) + { + return; + } + + if(dying) + { + return; + } + + if(((tmpscr->flags3&fINVISROOM)&& !(current_item(itype_amulet)))|| + (darkroom)) + { + return; + } + else + { + /* if (canfall(id) && z>0) + shadowtile = wpnsbuf[iwShadow].tile; + sprite::drawshadow(dest,translucent); + if (z==0) + shadowtile = 0;*/ + // a bad idea, as enemies do their own setting of the shadow tile (since some use the + // 2x2 tiles, shadows animate, etc.) -DD + + //this hack is in place as not all enemies that should use the z axis while in the air + //(ie rocks, boulders) actually do. To be removed when the enemy revamp is complete -DD + if(canfall(id) && shadowtile == 0) + shadowtile = wpnsbuf[iwShadow].tile; + + if(z>0 || !canfall(id)) + sprite::drawshadow(dest,translucent); + } +} + +void enemy::masked_draw(BITMAP *dest,int mx,int my,int mw,int mh) +{ + BITMAP *sub=create_sub_bitmap(dest,mx,my,mw,mh); + + if(sub!=NULL) + { + xofs-=mx; + yofs-=my; + enemy::draw(sub); + xofs+=mx; + yofs+=my; + destroy_bitmap(sub); + } + else + enemy::draw(dest); +} + +// override hit detection to check for invicibility, stunned, etc +bool enemy::hit(sprite *s) +{ + if(!(s->scriptcoldet&1)) return false; + + return (dying || hclk>0) ? false : sprite::hit(s); +} + +bool enemy::hit(int tx,int ty,int tz,int txsz2,int tysz2,int tzsz2) +{ + return (dying || hclk>0) ? false : sprite::hit(tx,ty,tz,txsz2,tysz2,tzsz2); +} + +bool enemy::hit(weapon *w) +{ + if(!(w->scriptcoldet&1)) return false; + + return (dying || hclk>0) ? false : sprite::hit(w); +} + +// --==**==-- + +// Movement routines that can be used by derived classes as needed + +// --==**==-- + +bool enemy::cannotpenetrate() +{ + return (family == eeAQUA || family == eeMANHAN || family == eeGHOMA); +} + +// returns true if next step is ok, false if there is something there +bool enemy::canmove(int ndir,fix s,int special,int dx1,int dy1,int dx2,int dy2) +{ + bool ok; + int dx = 0, dy = 0; + int sv = 8; + s += 0.5; // Make the ints round; doesn't seem to cause any problems. + + switch(ndir) + { + case 8: + case up: + if(canfall(id) && tmpscr->flags7&fSIDEVIEW) + return false; + + dy = dy1-s; + special = (special==spw_clipbottomright)?spw_none:special; + ok = !m_walkflag(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special); + break; + + case 12: + case down: + if(canfall(id) && tmpscr->flags7&fSIDEVIEW) + return false; + + dy = dy2+s; + ok = !m_walkflag(x,y+dy,special, x, y) && !flyerblocked(x,y+dy, special); + break; + + case 14: + case left: + dx = dx1-s; + sv = ((tmpscr->flags7&fSIDEVIEW)?7:8); + special = (special==spw_clipbottomright||special==spw_clipright)?spw_none:special; + ok = !m_walkflag(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special); + break; + + case 10: + case right: + dx = dx2+s; + sv = ((tmpscr->flags7&fSIDEVIEW)?7:8); + ok = !m_walkflag(x+dx,y+sv,special, x, y) && !flyerblocked(x+dx,y+8, special); + break; + + case 9: + case r_up: + dx = dx2+s; + dy = dy1-s; + ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) && + !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special); + break; + + case 11: + case r_down: + dx = dx2+s; + dx = dy2+s; + ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) && + !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special); + break; + + case 13: + case l_down: + dx = dx1-s; + dy = dy2+s; + ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) && + !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special); + break; + + case 15: + case l_up: + dx = dx1-s; + dy = dy1-s; + ok = !m_walkflag(x,y+dy,special, x, y) && !m_walkflag(x+dx,y+sv,special, x, y) && + !flyerblocked(x,y+dy, special) && !flyerblocked(x+dx,y+8, special); + break; + + default: + db=99; + return true; + } + + return ok; +} + + +bool enemy::canmove(int ndir,fix s,int special) +{ + return canmove(ndir,s,special,0,-8,15,15); +} + +bool enemy::canmove(int ndir,int special) +{ + bool dodongo_move=true; //yes, it's an ugly hack, but we're going to rewrite everything later anyway - DN + + if(special==spw_clipright&&ndir==right) + { + dodongo_move=canmove(ndir,(fix)1,special,0,-8,31,15); + } + + return canmove(ndir,(fix)1,special,0,-8,15,15)&&dodongo_move; +} + +bool enemy::canmove(int ndir) +{ + return canmove(ndir,(fix)1,spw_none,0,-8,15,15); +} + +int enemy::pos(int newx,int newy) +{ + return (newy<<8)+newx; +} + +int wpnsfx(int wpn) +{ + switch(wpn) + { + case ewFireTrail: + case ewFlame: + case ewFlame2Trail: + case ewFlame2: + return WAV_FIRE; + + case ewWind: + case ewMagic: + return WAV_WAND; + + case ewIce: + return WAV_ZN1ICE; + + case ewRock: + if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1ROCK; + + case ewFireball2: + case ewFireball: + if(get_bit(quest_rules,qr_MORESOUNDS)) return WAV_ZN1FIREBALL; + } + + return -1; +} + +/**********************************************************/ +/********* AngelScript enemy class (temporary) **********/ +/**********************************************************/ + +// scriptFlags +#define asf_ALWAYSDIE 0x0001 // Invincibility doesn't prevent death by ringleader +#define asf_PATRADEFENSE 0x0002 // Center eye is invincible + +ASEnemy::ASEnemy(const char* scriptName, fix x, fix y, int id, int clk): + enemy(x, y, id, clk), + haslink(false), + scriptFlags(0) +{ + assignEnemyScript(this, scriptName); + asUpdate=scriptData->getFunction("bool Update(int)"); + asDraw=scriptData->getFunction("void Draw()"); + asDraw2=scriptData->getFunction("void Draw2()"); + asDrawShadow=scriptData->getFunction("void DrawShadow()"); + asTakeHit=scriptData->getFunction("int takehit(weapon@)"); + asHit=scriptData->getFunction("bool Hit(weapon@)"); + asBreakShield=scriptData->getFunction("void break_shield()"); + asEatLink=scriptData->getFunction("void eatlink()"); +} + +bool ASEnemy::animate(int index) +{ + if(asUpdate) + { + scriptData->runFunction(asUpdate, index); + return scriptData->getLastResult(); + } + + return enemy::animate(index); +} + +void ASEnemy::drawshadow(BITMAP *dest, bool translucent) +{ + if(asDrawShadow) + { + scriptDrawingTarget=dest; + scriptShadowTrans=translucent; + scriptData->runFunction(asDrawShadow); + } + else + enemy::drawshadow(dest, translucent); +} + +void ASEnemy::draw(BITMAP *dest) +{ + if(asDraw) + { + scriptDrawingTarget=dest; + scriptData->runFunction(asDraw); + } + else + enemy::draw(dest); +} + +void ASEnemy::draw2(BITMAP *dest) +{ + if(asDraw2) + { + scriptDrawingTarget=dest; + scriptData->runFunction(asDraw2); + } + else + enemy::draw2(dest); +} + +void ASEnemy::stopBGSFX() +{ + bgSFX.stopLooping(); +} + +void ASEnemy::playDeathSFX() +{ + deathSFX.play(x); +} + +void ASEnemy::playHitSFX(int pan) +{ + hitSFX.play(pan); +} + +bool ASEnemy::hit(weapon *w) +{ + if(asHit) + { + scriptData->runFunction(asHit, w->getScriptObject()); + return scriptData->getLastResult(); + } + else + return enemy::hit(w); +} + +int ASEnemy::takehit(weapon *w) +{ + if(asTakeHit) + { + scriptData->runFunction(asTakeHit, w->getScriptObject()); + return scriptData->getLastResult(); + } + else + return enemy::takehit(w); +} + +int ASEnemy::defend(int wpnId, int *power, int edef) +{ + int ret = enemy::defend(wpnId, power, edef); + if((scriptFlags&asf_PATRADEFENSE)!=0) + return 0; + + return ret; +} + +void ASEnemy::break_shield() +{ + if(asBreakShield) + scriptData->runFunction(asBreakShield); +} + +void ASEnemy::eatlink() +{ + if(asEatLink) + scriptData->runFunction(asEatLink); +} + +void ASEnemy::fireWeapon() +{ + if(attack) + attack->activate(); +} + +bool ASEnemy::isFiring() const +{ + return attack && attack->isActive(); +} + +void ASEnemy::updateFiring() +{ + if(attack && attack->isActive()) + attack->update(); +} + +void ASEnemy::setBreathTimer(int time) +{ + if(attack) + attack->setBreathTimer(time); +} + +void ASEnemy::setAttackOwner(int index) +{ + if(attack) + attack->setOwner((enemy*)guys.spr(index)); +} + +void ASEnemy::activateDeathAttack() +{ + if(deathAttack) + { + deathAttack->activate(); + deathAttack.reset(); + } +} + +void ASEnemy::scriptDraw() +{ + enemy::draw(scriptDrawingTarget); +} + +void ASEnemy::scriptDrawShadow() +{ + enemy::drawshadow(scriptDrawingTarget, scriptShadowTrans); +} + +void ASEnemy::scriptDrawBlock() +{ + drawblock(scriptDrawingTarget); +} + +void ASEnemy::scriptMaskedDraw(int mx, int my, int mw, int mh) +{ + masked_draw(scriptDrawingTarget, mx, my, mw, mh); +} + +void ASEnemy::overTileCloaked16(int tile, int x, int y, int flip) +{ + overtilecloaked16(scriptDrawingTarget, tile, x, y, flip); +} + +void ASEnemy::overTile16(int tile, int x, int y, int cset, int flip) +{ + overtile16(scriptDrawingTarget, tile, x, y, cset, flip); +} + +bool ASEnemy::defaultAnimate(int index) +{ + return enemy::animate(index); +} + +int ASEnemy::defaultTakeHit(weapon* w) +{ + int ret=enemy::takehit(w); + return ret; +} + +void ASEnemy::kickbucket() +{ + if((scriptFlags&asf_ALWAYSDIE) || !superman) + hp=-1000; +} + +// This is really ugly... +int ASEnemy::scriptDefendItemClass(int wpnId, int power) +{ + wpnPower=power; + return defenditemclass(wpnId, &wpnPower); +} + +int ASEnemy::getDefendedItemPower() +{ + return wpnPower; +} + +void ASEnemy::setDeathAttack(EnemyAttack* att) +{ + deathAttack.reset(att); + deathAttack->setOwner(this); +} + +/**********************************/ +/********** Misc Code ***********/ +/**********************************/ + +int hit_enemy(int index, int wpnId,int power,int wpnx,int wpny,int dir, int enemyHitWeapon) +{ + weapon w((fix)wpnx,(fix)wpny,(fix)0,wpnId,0,power,dir,enemyHitWeapon,-1,false); + int ret= ((enemy*)guys.spr(index))->takehit(&w); + return ret; +} + +void enemy_scored(int index) +{ + ((enemy*)guys.spr(index))->scored=true; +} + +void addguy(int x,int y,int id,int clk,bool mainguy) +{ + if(mainguy) // Slightly ugly hack here + id|=0x8000; + ASEnemy* g = new ASEnemy("Guy", (fix)x,(fix)(y+(isdungeon()?1:0)),id,get_bit(quest_rules,qr_NOGUYPOOF)?0:clk); + guys.add(g); +} + +item* additem(int x,int y,int id,int pickup) +{ + item *i = new item(fix(x), fix(y - get_bit(quest_rules, qr_NOITEMOFFSET)), fix(0), id, pickup, 0); + items.add(i); + return i; +} + +item* additem(int x,int y,int id,int pickup,int clk) +{ + item *i = new item((fix)x,(fix)y-(get_bit(quest_rules, qr_NOITEMOFFSET)),(fix)0,id,pickup,clk); + items.add(i); + return i; +} + +void kill_em_all() +{ + for(int i=0; iflags&(1<<3) && !(e->family == eeGHINI && e->dmisc1 == 1)) continue; + + e->kickbucket(); + } +} + +// For Link's hit detection. Don't count them if they are stunned or are guys. +int GuyHit(int tx,int ty,int tz,int txsz,int tysz,int tzsz) +{ + for(int i=0; ihit(tx,ty,tz,txsz,tysz,tzsz)) + { + if(((enemy*)guys.spr(i))->stunclk==0 && (!get_bit(quest_rules, qr_SAFEENEMYFADE) || ((enemy*)guys.spr(i))->fading != fade_flicker) + &&(((enemy*)guys.spr(i))->d->family != eeGUY || ((enemy*)guys.spr(i))->dmisc1)) + { + return i; + } + } + } + + return -1; +} + +// For Link's hit detection. Count them if they are dying. +int GuyHit(int index,int tx,int ty,int tz,int txsz,int tysz,int tzsz) +{ + enemy *e = (enemy*)guys.spr(index); + + if(e->hp > 0) + return -1; + + bool d = e->dying; + int hc = e->hclk; + e->dying = false; + e->hclk = 0; + bool hit = e->hit(tx,ty,tz,txsz,tysz,tzsz); + e->dying = d; + e->hclk = hc; + + return hit ? index : -1; +} + +bool hasMainGuy() +{ + for(int i=0; imainguy) + { + return true; + } + } + + return false; +} + +void EatLink(int index) +{ + ((ASEnemy*)guys.spr(index))->eatlink(); +} + +void GrabLink(int index) +{ + // Move to scripts when possible... + + ASEnemy* wm=(ASEnemy*)guys.spr(index); + wm->haslink=true; + wm->superman=1; +} + +bool CarryLink() +{ + for(int i=0; ifamily==eeWALLM) + { + if(((ASEnemy*)guys.spr(i))->haslink) + { + Link.x=guys.spr(i)->x; + Link.y=guys.spr(i)->y; + return ((ASEnemy*)guys.spr(i))->misc > 0; + } + } + } + + return false; +} + +// Move item with guy +void movefairy(fix &x,fix &y,int misc) +{ + int i = guys.idFirst(eITEMFAIRY+0x1000*misc); + + if(i!=-1) + { + x = guys.spr(i)->x; + y = guys.spr(i)->y; + } +} + +// Move guy with item (used by FFC scripts and hookshot-dragged fairies) +void movefairy2(fix x,fix y,int misc) +{ + int i = guys.idFirst(eITEMFAIRY+0x1000*misc); + + if(i!=-1) + { + guys.spr(i)->x = x; + guys.spr(i)->y = y; + } +} + +void killfairy(int misc) +{ + int i = guys.idFirst(eITEMFAIRY+0x1000*misc); + guys.del(i); +} + +int addenemy(int x,int y,int id,int clk) +{ + return addenemy(x,y,0,id,clk); +} + +static void setStandardAttack(enemy* en, const guydata& data) +{ + fireType ft; + int weapon=data.weapon; + int wType=2; + int power=data.wdp; + int sfx=wpnsfx(data.weapon); + + switch(data.misc1) + { + case e1tFAST: + wType=6; + // Fall through + case e1tNORMAL: + case e1tCONSTANT: // Also e1tHOMINGBRANG + case e1tEACHTILE: + ft=ft_1Shot; + break; + case e1tSLANT: + ft=ft_1ShotSlanted; + break; + case e1t3SHOTSFAST: + wType=6; + // Fall through + case e1t3SHOTS: + ft=ft_3Shots; + break; + case e1t5SHOTS: + ft=ft_5Shots; + break; + case e1t4SHOTS: + ft=ft_4Shots; + wType=0; + break; + case e1t8SHOTS: + ft=ft_8Shots; + wType=0; + break; + case e1tFIREOCTO: + if(data.weapon!=ewFireTrail) + ft=ft_breath; + else + ft=ft_1Shot; + break; + + case e1tSUMMON: + ft=ft_summon; + weapon=data.misc3; + power=zc_max(1, data.misc4); + sfx=get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE; + break; + + case e1tSUMMONLAYER: + ft=ft_summonLayer; + power=zc_max(1, data.misc4); + sfx=get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE; + break; + + default: + return; + } + + EnemyAttack* atk; + atk=new EnemyAttack(weapon, wType, power, ft, sfxMgr.getSFX(sfx)); + en->setAttack(atk); +} + +static void setWalkerDeathAttack(ASEnemy* en, const guydata& data) +{ + fireType ft; + int wType; + + switch(data.misc2) + { + case e2tFIREOCTO: + ft=ft_8Shots; + wType=0; + break; + + case e2tBOMBCHU: + ft=ft_1Shot; + wType=2; + break; + + default: + return; + } + + EnemyAttack* atk; + atk=new EnemyAttack(data.weapon+data.misc3, 0, data.misc4, ft, + sfxMgr.getSFX(data.weapon+data.misc3)); + en->setDeathAttack(atk); +} + +static void setWizzrobeAttack(enemy* en, const guydata& data) +{ + fireType ft; + int weapon; + int power=data.wdp; + int sfx=WAV_FIRE; + + switch(data.misc2) + { + case 0: // Single shot + ft=ft_1Shot; + weapon=data.weapon; + sfx=WAV_WAND; + break; + + case 1: // 8-way + ft=ft_8Shots; + weapon=data.weapon; + break; + + case 2: // Summon misc. 3 + ft=ft_summon; + weapon=data.misc3; + power=3; + break; + + case 3: // Summon from layer + ft=ft_summonLayer; + weapon=-1; + power=3; + sfx=get_bit(quest_rules,qr_MORESOUNDS) ? WAV_ZN1SUMMON : WAV_FIRE; + break; + + default: + return; + } + + if(weapon==0) // wNone==0 + return; + EnemyAttack* atk=new EnemyAttack(weapon, 0, power, ft, + sfxMgr.getSFX(sfx)); + en->setAttack(atk); +} + +static void setAquamentusAttack(enemy* en, const guydata& data) +{ + if(data.weapon==wNone) + return; + EnemyAttack* atk=new EnemyAttack(data.weapon, 2, data.wdp, + ft_aquamentus, sfxMgr.getSFX(wpnsfx(data.weapon))); + en->setAttack(atk); +} + +static void setGohmaAttack(enemy* en, const guydata& data) +{ + if(data.weapon==wNone) + return; + + fireType ft; + int wpnType; + switch(data.misc1) + { + case 0: // Single shot + ft=ft_gohma1Shot; + wpnType=3; + break; + + case 1: // Triple shot + ft=ft_gohma3Shots; + wpnType=3; + break; + + case 2: // Breath + ft=ft_breathAimed; + wpnType=2; + break; + } + + EnemyAttack* atk=new EnemyAttack(data.weapon, wpnType, + data.wdp, ft, sfxMgr.getSFX(wpnsfx(data.weapon))); + if(data.misc1!=2) // Single or triple shot + atk->setYOffset(2); + else // Breath + atk->setBreathTimer(104); + en->setAttack(atk); +} + +static void setSimpleAttack(enemy* en, const guydata& data, int type) +{ + if(data.weapon==wNone) + return; + EnemyAttack* atk=new EnemyAttack(data.weapon, type, data.wdp, + ft_1Shot, sfxMgr.getSFX(wpnsfx(data.weapon))); + en->setAttack(atk); +} + +static void setGleeokBreathAttack(enemy* en, const guydata& data) +{ + if(data.weapon==wNone) + return; + EnemyAttack* atk=new EnemyAttack(data.weapon, 2, data.wdp, + ft_breathAimed, sfxMgr.getSFX(wpnsfx(data.weapon))); + en->setAttack(atk); +} + +// Returns number of enemies/segments created +int addenemy(int x,int y,int z,int id,int clk) +{ + if(id <= 0) return 0; + + int ret = 0; + sprite *e=NULL; + const guydata& data=guysbuf[id&0xFFF]; + + switch(data.family) + { + //Fixme: possible enemy memory leak. (minor) + case eeWALK: + e = new ASEnemy("WalkingEnemy", (fix)x,(fix)y,id,clk); + setStandardAttack((enemy*)e, data); + setWalkerDeathAttack((ASEnemy*)e, data); + break; + + case eeLEV: + e = new ASEnemy("Leever", (fix)x,(fix)y,id,clk); + break; + + case eeTEK: + //e = new eTektite((fix)x,(fix)y,id,clk); + e = new ASEnemy("Tektite", (fix)x,(fix)y,id,clk); + break; + + case eePEAHAT: + //e = new ePeahat((fix)x,(fix)y,id,clk); + e = new ASEnemy("Peahat", (fix)x,(fix)y,id,clk); + break; + + case eeZORA: + e = new ASEnemy("Zora", (fix)x,(fix)y,id,clk); + setSimpleAttack((enemy*)e, data, 2); + break; + + case eeGHINI: + e = new ASEnemy("Ghini", (fix)x,(fix)y,id,clk); + break; + + case eeKEESE: + e = new ASEnemy("Keese", (fix)x,(fix)y,id,clk); + break; + + case eeWIZZ: + e = new ASEnemy("Wizzrobe", (fix)x,(fix)y,id,clk); + setWizzrobeAttack((enemy*)e, data); + break; + + case eePROJECTILE: + e = new ASEnemy("ProjectileShooter", (fix)x,(fix)y,id,clk); + setStandardAttack((enemy*)e, data); + break; + + case eeWALLM: + e = new ASEnemy("WallMaster", (fix)x,(fix)y,id,clk); + break; + + case eeAQUA: + { + e = new ASEnemy("Aquamentus", (fix)x,(fix)y,id,clk); + setAquamentusAttack((enemy*)e, data); + break; + } + + case eeMOLD: + e = new ASEnemy("MoldormController", (fix)x,(fix)y,id,zc_max(1,zc_min(254,data.misc1))); + break; + + case eeMANHAN: + e = new ASEnemy("Manhandla", (fix)x,(fix)y,id,clk); + break; + + case eeGLEEOK: + e = new ASEnemy("Gleeok", (fix)x,(fix)y,id,zc_max(1,zc_min(254,data.misc1))); + setSimpleAttack((enemy*)e, data, 3); + break; + + case eeGHOMA: + e = new ASEnemy("Gohma", (fix)x,(fix)y,id,clk); + setGohmaAttack((enemy*)e, data); + break; + + case eeLANM: + e = new ASEnemy("LanmolaController", (fix)x,(fix)y,id,zc_max(1,zc_min(253,data.misc1))); + break; + + case eeGANON: + e = new ASEnemy("Ganon", (fix)x,(fix)y,id,clk); + setSimpleAttack((enemy*)e, data, 3); + break; + + case eeFAIRY: + e = new ASEnemy("Fairy", (fix)x,(fix)y,id+0x1000*clk,clk); + break; + + case eeFIRE: + e = new ASEnemy("Fire", (fix)x,(fix)y,id,clk); + break; + + case eeOTHER: + e = new ASEnemy("Other", (fix)x,(fix)y,id,clk); + break; + + case eeSPINTILE: + e = new ASEnemy("SpinningTile", (fix)x,(fix)y,id,clk); + break; + + // and these enemies use the misc10/misc2 value + case eeROCK: + e = new ASEnemy("FallingRock", (fix)x,(fix)y,id,0); + break; + + case eeTRAP: + { + switch(data.misc2) + { + case 1: + e = new ASEnemy("TrapConstant", (fix)x,(fix)y,id,clk); + break; + + case 0: + default: + e = new ASEnemy("TrapLOS", (fix)x,(fix)y,id,clk); + break; + } + + break; + } + + case eeDONGO: + e = new ASEnemy("Dodongo", (fix)x,(fix)y,id,clk); + break; + + case eeDIG: + { + switch(data.misc10) + { + case 1: + e = new ASEnemy("DigdoggerKid", (fix)x,(fix)y,id,clk); + break; + + case 0: + default: + e = new ASEnemy("Digdogger", (fix)x,(fix)y,id,clk); + break; + } + + break; + } + + case eePATRA: + { + switch(data.misc10) + { + case 1: + e = new ASEnemy("PatraBS", (fix)x,(fix)y,id,clk); + break; + + case 0: + default: + e = new ASEnemy("Patra", (fix)x,(fix)y,id,clk); + break; + } + // This part's stupid. + if(data.misc5>0) + setSimpleAttack((enemy*)e, data, 3); + break; + } + + case eeGUY: + { + switch(data.misc10) + { + case 1: + e = new ASEnemy("Trigger", (fix)x,(fix)y,id,clk); + break; + + case 0: + default: + e = new ASEnemy("NPC", (fix)x,(fix)y,id,clk); + break; + } + + break; + } + + case eeNONE: + if(data.misc10 ==1) + { + e = new ASEnemy("Trigger", (fix)x,(fix)y,id,clk); + break; + } + + default: + + return 0; + } + + ret++; // Made one enemy. + + if(z && canfall(id)) + { + e->z = (fix)z; + } + + ((enemy*)e)->ceiling = (z && canfall(id)); + + if(!guys.add(e)) + { + return 0; + } + + // add segments of segmented enemies + int c=0; + + switch(data.family) + { + case eeMOLD: + { + byte is=((enemy*)guys.spr(guys.Count()-1))->item_set; + id &= 0xFFF; + + for(int i=0; i0) + ((enemy*)guys.spr(guys.Count()-1))->item_set=is; + + ret++; + } + + break; + } + + case eeLANM: + { + id &= 0xFFF; + int shft = guysbuf[id].misc2; + byte is=((enemy*)guys.spr(guys.Count()-1))->item_set; + + if(!guys.add(new ASEnemy("LanmolaSegment", (fix)x,(fix)y,id+0x1000,0))) + { + al_trace("Lanmola segment 1 could not be created!\n"); + guys.del(guys.Count()-1); + return 0; + } + + ret++; + + for(int i=1; iitem_set=is; + ret++; + } + } + break; + + case eeMANHAN: + id &= 0xFFF; + + for(int i=0; i<((!(data.misc2))?4:8); i++) + { + enemy* en=new ASEnemy("ManhandlaHead", (fix)x,(fix)y,id+0x1000,i); + if(!guys.add(en)) + { + al_trace("Manhandla head %d could not be created!\n",i+1); + + for(int j=0; jfrate=guysbuf[id].misc1; + } + + break; + + case eeGLEEOK: + { + id &= 0xFFF; + + for(int i=0; i=128) ? mBELOW : mITEM; + int onetime = (currscr>=128) ? ipONETIME2 : ipONETIME; + + hasitem=0; + + if(currscr>=128 && DMaps[currdmap].flags&dmfGUYCAVES) + { + if(DMaps[currdmap].flags&dmfCAVES) + { + Guy=tmpscr[1].guy; + } + } + else + { + Guy=tmpscr->guy; + + if(DMaps[currdmap].flags&dmfVIEWMAP) + game->maps[(currmap*MAPSCRSNORMAL)+currscr] |= mVISITED; // mark as visited + } + + // The Guy appears if 'Link is in cave' equals 'Guy is in cave'. + if(Guy && ((currscr>=128) == !!(DMaps[currdmap].flags&dmfGUYCAVES))) + { + if(tmpscr->room==rZELDA) + { + addguy(120,72,Guy,-15,true); + guys.spr(0)->hxofs=1000; + addenemy(128,96,eFIRE,-15); + addenemy(112,96,eFIRE,-15); + addenemy(96,120,eFIRE,-15); + addenemy(144,120,eFIRE,-15); + return; + } + + if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES)) + addfires(); + + if(currscr>=128) + if(getmapflag()) + Guy=0; + + switch(tmpscr->room) + { + case rSP_ITEM: + case rMONEY: + case rGRUMBLE: + case rBOMBS: + case rARROWS: + case rSWINDLE: + case rMUPGRADE: + case rLEARNSLASH: + case rTAKEONE: + case rREPAIR: + case rRP_HC: + if(getmapflag()) + Guy=0; + + break; + + case rTRIFORCE: + { + int tc = TriforceCount(); + + if(get_bit(quest_rules,qr_4TRI)) + { + if((get_bit(quest_rules,qr_3TRI) && tc>=3) || tc>=4) + Guy=0; + } + else + { + if((get_bit(quest_rules,qr_3TRI) && tc>=6) || tc>=8) + Guy=0; + } + } + break; + } + + if(Guy) + { + if(Guy!=gFAIRY || !get_bit(quest_rules,qr_NOFAIRYGUYFIRES)) + blockpath=true; + + if(currscr<128) + sfx(WAV_SCALE); + + addguy(120,64,Guy, (dlevel||BSZ)?-15:startguy[rand()&7], true); + Link.Freeze(); + } + } + else if(Guy==gFAIRY) // The only Guy that somewhat ignores the "Guys In Caves Only" DMap flag + { + sfx(WAV_SCALE); + addguy(120,62,gFAIRY,-14,false); + } + + loaditem(); + + // Collecting a rupee in a '10 Rupees' screen sets the mITEM screen state if + // it doesn't appear in a Cave/Item Cellar, and the mBELOW screen state if it does. + if(tmpscr->room==r10RUPIES && !getmapflag(mf)) + { + //setmapflag(); + for(int i=0; i<10; i++) + additem(ten_rupies_x[i],ten_rupies_y[i],0,ipBIGRANGE+onetime,-14); + } +} + +void loaditem() +{ + byte Item = 0; + + if(currscr<128) + { + Item=tmpscr->item; + + if(!getmapflag(mITEM) && (tmpscr->hasitem != 0)) + { + if(tmpscr->flags&fITEM) + hasitem=1; + else if(tmpscr->enemyflags&efCARRYITEM) + hasitem=4; // Will be set to 2 by roaming_item + else + items.add(new item((fix)tmpscr->itemx, + (tmpscr->flags7&fITEMFALLS && tmpscr->flags7&fSIDEVIEW) ? (fix)-170 : (fix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1), + (tmpscr->flags7&fITEMFALLS && !(tmpscr->flags7&fSIDEVIEW)) ? (fix)170 : (fix)0, + Item,ipONETIME+ipBIGRANGE+((itemsbuf[Item].family==itype_triforcepiece || + (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0),0)); + } + } + else if(!(DMaps[currdmap].flags&dmfCAVES)) + { + if(!getmapflag() && tmpscr[1].room==rSP_ITEM + && (currscr==128 || !get_bit(quest_rules,qr_ITEMSINPASSAGEWAYS))) + { + Item=tmpscr[1].catchall; + + if(Item) + items.add(new item((fix)tmpscr->itemx, + (tmpscr->flags7&fITEMFALLS && tmpscr->flags7&fSIDEVIEW) ? (fix)-170 : (fix)tmpscr->itemy+(get_bit(quest_rules, qr_NOITEMOFFSET)?0:1), + (tmpscr->flags7&fITEMFALLS && !(tmpscr->flags7&fSIDEVIEW)) ? (fix)170 : (fix)0, + Item,ipONETIME2|ipBIGRANGE|ipHOLDUP,0)); + } + } +} + +void never_return(int index) +{ + if(!get_bit(quest_rules,qr_KILLALL)) + goto doit; + + for(int i=0; id->flags)&guy_neverret) && i!=index) + { + goto dontdoit; + } + +doit: + setmapflag(mNEVERRET); +dontdoit: + return; +} + +bool slowguy(int id) +{ + switch(id) + { + case eOCTO1S: + case eOCTO2S: + case eOCTO1F: + case eOCTO2F: + case eLEV1: + case eLEV2: + case eROCK: + case eBOULDER: + return true; + } + + return false; +} + +bool ok2add(int id) +{ + if(getmapflag(mNEVERRET) && (guysbuf[id].flags & guy_neverret)) + return false; + + switch(guysbuf[id].family) + { + // I added a special case for shooters because having traps on the same screen + // was preventing them from spawning due to TMPNORET. This means they will + // never stay dead, though, so it may not be the best solution. - Saf + case eePROJECTILE: + return true; + + case eeGANON: + case eeTRAP: + return false; + + case eeDIG: + { + switch(guysbuf[id].misc10) + { + case 1: + if(!get_bit(quest_rules,qr_NOTMPNORET)) + return !getmapflag(mTMPNORET); + + return true; + + case 0: + default: + return true; + } + } + } + + if(!get_bit(quest_rules,qr_NOTMPNORET)) + return !getmapflag(mTMPNORET); + + return true; +} + +void activate_fireball_statue(int pos) +{ + if(!(tmpscr->enemyflags&efFIREBALLS) || statueID<0) + { + return; + } + + int cx=-1000, cy=-1000; + int x = (pos&15)<<4; + int y = pos&0xF0; + + int ctype = combobuf[MAPCOMBO(x,y)].type; + + if(!isfixedtogrid(statueID)) + { + if(ctype==cL_STATUE) + { + cx=x+4; + cy=y+7; + } + else if(ctype==cR_STATUE) + { + cx=x-8; + cy=y-1; + } + else if(ctype==cC_STATUE) + { + cx=x; + cy=y; + } + } + else if(ctype==cL_STATUE || ctype==cR_STATUE || ctype==cC_STATUE) + { + cx=x; + cy=y; + } + + if(cx!=-1000) // No point creating it if this is false + { + for(int j=0; jx)==cx)&&(int(guys.spr(j)->y)==cy)) + { + if((guys.spr(j)->id&0xFFF) == statueID) // There's already a matching enemy here! + return; // No point deleting it. A script might be toying with it in some way. + else + guys.del(j); + } + } + + addenemy(cx, cy, statueID, !isfixedtogrid(statueID) ? 24 : 0); + } +} + +void activate_fireball_statues() +{ + if(!(tmpscr->enemyflags&efFIREBALLS)) + { + return; + } + + for(int i=0; i<176; i++) + { + activate_fireball_statue(i); + } +} + +void load_default_enemies() +{ + wallm_load_clk=frame-80; + int Id=0; + + if(tmpscr->enemyflags&efZORA) + { + if(zoraID>=0) + addenemy(-16, -16, zoraID, 0); + } + + if(tmpscr->enemyflags&efTRAP4) + { + if(cornerTrapID>=0) + { + addenemy(32, 32, cornerTrapID, -14); + addenemy(208, 32, cornerTrapID, -14); + addenemy(32, 128, cornerTrapID, -14); + addenemy(208, 128, cornerTrapID, -14); + } + } + + for(int y=0; y<176; y+=16) + { + for(int x=0; x<256; x+=16) + { + int ctype = combobuf[MAPCOMBO(x,y)].type; + int cflag = MAPFLAG(x, y); + int cflag2 = MAPCOMBOFLAG(x, y); + + if(ctype==cTRAP_H || cflag==mfTRAP_H || cflag2==mfTRAP_H) + { + if(trapLOSHorizontalID>=0) + addenemy(x, y, trapLOSHorizontalID, -14); + } + else if(ctype==cTRAP_V || cflag==mfTRAP_V || cflag2==mfTRAP_V) + { + if(trapLOSVerticalID>=0) + addenemy(x, y, trapLOSVerticalID, -14); + } + else if(ctype==cTRAP_4 || cflag==mfTRAP_4 || cflag2==mfTRAP_4) + { + if(trapLOS4WayID>=0) + { + if(addenemy(x, y, trapLOS4WayID, -14)) + static_cast(guys.spr(guys.Count()-1))->dummy_int1=2; + } + } + + else if(ctype==cTRAP_LR || cflag==mfTRAP_LR || cflag2==mfTRAP_LR) + { + if(trapConstantHorizontalID>=0) + addenemy(x, y, trapConstantHorizontalID, -14); + } + else if(ctype==cTRAP_UD || cflag==mfTRAP_UD || cflag2==mfTRAP_UD) + { + if(trapConstantVerticalID>=0) + addenemy(x, y, trapConstantVerticalID, -14); + } + + if(ctype==cSPINTILE1) + { + // Awaken spinning tile + awaken_spinning_tile(tmpscr,COMBOPOS(x,y)); + } + } + } + + if(tmpscr->enemyflags&efTRAP2) + { + if(centerTrapID>=-1) + { + if(addenemy(64, 80, centerTrapID, -14)) + static_cast(guys.spr(guys.Count()-1))->dummy_int1=1; + + if(addenemy(176, 80, centerTrapID, -14)) + static_cast(guys.spr(guys.Count()-1))->dummy_int1=1; + } + } + + if(tmpscr->enemyflags&efROCKS) + { + if(rockID>=0) + { + addenemy(rand()&0xF0, 0, rockID, 0); + addenemy(rand()&0xF0, 0, rockID, 0); + addenemy(rand()&0xF0, 0, rockID, 0); + } + } + + activate_fireball_statues(); +} + + +// Everything that must be done before we change a screen's combo to another combo, or a combo's type to another type. +// There's 2 routines because it's unclear if combobuf or tmpscr->data gets modified. -L +void screen_combo_modify_preroutine(mapscr *s, int pos) +{ + delete_fireball_shooter(s, pos); +} + +// Everything that must be done after we change a screen's combo to another combo. -L +void screen_combo_modify_postroutine(mapscr *s, int pos) +{ + activate_fireball_statue(pos); + + if(combobuf[s->data[pos]].type==cSPINTILE1) + { + // Awaken spinning tile + awaken_spinning_tile(s,pos); + } +} + +void awaken_spinning_tile(mapscr *s, int pos) +{ + addenemy((pos&15)<<4,pos&0xF0,(s->cset[pos]<<12)+eSPINTILE1,animated_combo_table[s->data[pos]][1]+zc_max(1,combobuf[s->data[pos]].frames)); +} + + +// It stands for next_side_pos +void nsp(bool random) +// moves sle_x and sle_y to the next position +{ + if(random) + { + if(rand()%2) + { + sle_x = (rand()%2) ? 0 : 240; + sle_y = (rand()%10)*16; + } + else + { + sle_y = (rand()%2) ? 0 : 160; + sle_x = (rand()%15)*16; + } + + return; + } + + if(sle_x==0) + { + if(sle_y<160) + sle_y+=16; + else + sle_x+=16; + } + else if(sle_y==160) + { + if(sle_x<240) + sle_x+=16; + else + sle_y-=16; + } + else if(sle_x==240) + { + if(sle_y>0) + sle_y-=16; + else + sle_x-=16; + } + else if(sle_y==0) + { + if(sle_x>0) + sle_x-=16; + else + sle_y+=16; + } +} + +int next_side_pos(bool random) +// moves sle_x and sle_y to the next available position +// returns the direction the enemy should face +{ + bool blocked; + int c=0; + + do + { + nsp(c>35 ? false : random); + blocked = _walkflag(sle_x,sle_y,2) || _walkflag(sle_x,sle_y+8,2) || + (combo_class_buf[COMBOTYPE(sle_x,sle_y)].block_enemies || + MAPFLAG(sle_x,sle_y) == mfNOENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOENEMY || + MAPFLAG(sle_x,sle_y) == mfNOGROUNDENEMY || MAPCOMBOFLAG(sle_x,sle_y)==mfNOGROUNDENEMY || + iswater(MAPCOMBO(sle_x,sle_y))); + + if(++c>50) + return -1; + } + while(blocked); + + int dir=0; + + if(sle_x==0) dir=right; + + if(sle_y==0) dir=down; + + if(sle_x==240) dir=left; + + if(sle_y==168) dir=up; + + return dir; +} + +bool can_side_load(int id) +{ + switch(guysbuf[id].family) //id&0x0FFF) + { + case eeTEK: + case eeLEV: + case eeAQUA: + case eeDONGO: + case eeMANHAN: + case eeGLEEOK: + case eeDIG: + case eeGHOMA: + case eeLANM: + case eePATRA: + case eeGANON: + case eePROJECTILE: + return false; + break; + } + + return true; +} + + +void side_load_enemies() +{ + if(sle_clk==0) + { + sle_cnt = 0; + int guycnt = 0; + short s = (currmap<<7)+currscr; + bool beenhere=false; + bool reload=true; + + load_default_enemies(); + + for(int i=0; i<6; i++) + if(visited[i]==s) + beenhere=true; + + if(!beenhere) + { + visited[vhead]=s; + vhead = (vhead+1)%6; + } + else if(game->guys[s]==0) + { + sle_cnt=0; + reload=false; + } + + if(reload) + { + sle_cnt = game->guys[s]; + + if(sle_cnt==0) + { + while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0) + ++sle_cnt; + } + } + + if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN)) + { + sle_cnt = 0; + + while(sle_cnt<10 && tmpscr->enemy[sle_cnt]!=0) + ++sle_cnt; + } + + for(int i=0; iguys[s] = guycnt; + } + + if((++sle_clk+8)%24 == 0) + { + int dir = next_side_pos(tmpscr->pattern==pSIDESR); + + if(dir==-1 || tooclose(sle_x,sle_y,32)) + { + return; + } + + int enemy_slot=guys.Count(); + + while(sle_cnt > 0 && !ok2add(tmpscr->enemy[sle_cnt-1])) + sle_cnt--; + + if(sle_cnt > 0) + { + if(addenemy(sle_x,sle_y,tmpscr->enemy[--sle_cnt],0)) + guys.spr(enemy_slot)->dir = dir; + } + } + + if(sle_cnt<=0) + loaded_enemies=true; +} + +bool is_starting_pos(int i, int x, int y, int t) +{ + // No corner enemies + if((x==0 || x==240) && (y==0 || y==160)) + return false; + + // No enemies in dungeon walls + if(isdungeon() && (x<32 || x>=224 || y<32 || y>=144)) + return false; + + // Too close + if(tooclose(x,y,40) && t<11) + return false; + + // Can't fly onto it? + if(isflier(tmpscr->enemy[i])&& + (flyerblocked(x+8,y+8,spw_floater)|| + (_walkflag(x,y+8,2)&&!get_bit(quest_rules,qr_WALLFLIERS)))) + return false; + + // Can't jump onto it? + if(guysbuf[tmpscr->enemy[i]].family==eeTEK && + (COMBOTYPE(x+8,y+8)==cNOJUMPZONE|| + COMBOTYPE(x+8,y+8)==cNOENEMY|| + MAPFLAG(x+8,y+8)==mfNOENEMY|| + MAPCOMBOFLAG(x+8,y+8)==mfNOENEMY)) + return false; + + // Other off-limit combos + if((!isflier(tmpscr->enemy[i])&& guysbuf[tmpscr->enemy[i]].family!=eeTEK && + (_walkflag(x,y+8,2) || groundblocked(x+8,y+8))) && + guysbuf[tmpscr->enemy[i]].family!=eeZORA) + return false; + + // Don't ever generate enemies on these combos! + if(COMBOTYPE(x+8,y+8)==cARMOS||COMBOTYPE(x+8,y+8)==cBSGRAVE) + return false; + + //BS Dodongos need at least 2 spaces. + if((guysbuf[tmpscr->enemy[i]].family==eeDONGO)&&(guysbuf[tmpscr->enemy[i]].misc10==1)) + { + if(((x<16) ||_walkflag(x-16,y+8, 2))&& + ((x>224)||_walkflag(x+16,y+8, 2))&& + ((y<16) ||_walkflag(x, y-8, 2))&& + ((y>144)||_walkflag(x, y+24,2))) + { + return false; + } + } + + return true; +} + +bool is_ceiling_pattern(int i) +{ + return (i==pCEILING || i==pCEILINGR); +} + +int placeenemy(int i) +{ + std::map freeposcache; + int frees = 0; + + for(int y=0; y<176; y+=16) + { + for(int x=0; x<256; x+=16) + { + if(is_starting_pos(i,x,y,0)) + { + freeposcache[frees++] = (y&0xF0)+(x>>4); + } + } + } + + if(frees > 0) + return freeposcache[rand()%frees]; + + return -1; +} + +void loadenemies() +{ + if(loaded_enemies) + return; + + // check if it's the dungeon boss and it has been beaten before + if(tmpscr->enemyflags&efBOSS && game->lvlitems[dlevel]&liBOSS) + { + loaded_enemies = true; + return; + } + + if(tmpscr->pattern==pSIDES || tmpscr->pattern==pSIDESR) + { + side_load_enemies(); + return; + } + + loaded_enemies=true; + + // do enemies that are always loaded + load_default_enemies(); + + // dungeon basements + + static byte dngn_enemy_x[4] = {32,96,144,208}; + + if(currscr>=128) + { + if(DMaps[currdmap].flags&dmfCAVES) return; + + for(int i=0; i<4; i++) + addenemy(dngn_enemy_x[i],96,tmpscr->enemy[i]?tmpscr->enemy[i]:(int)eKEESE1,-14-i); + + return; + } + + // check if it's been long enough to reload all enemies + + int loadcnt = 10; + short s = (currmap<<7)+currscr; + bool beenhere = false; + bool reload = true; + + for(int i=0; i<6; i++) + if(visited[i]==s) + beenhere = true; + + if(!beenhere) + { + visited[vhead]=s; + vhead = (vhead+1)%6; + } + else if(game->guys[s]==0) + { + loadcnt = 0; + reload = false; + } + + if(reload) + { + loadcnt = game->guys[s]; + + if(loadcnt==0) + loadcnt = 10; + } + + if((get_bit(quest_rules,qr_ALWAYSRET)) || (tmpscr->flags3&fENEMIESRETURN)) + loadcnt = 10; + + // load enemies + + //if(true) // enemies appear at random places + //{ + //int set=loadside*9; + int pos=rand()%9; + int clk=-15,x=0,y=0,fastguys=0; + int i=0,guycnt=0; + + for(; ienemy[i]>0; i++) /* i=0 */ + { + bool placed=false; + int t=-1; + + // First: enemy combo flags + for(int sy=0; sy<176; sy+=16) + { + for(int sx=0; sx<256; sx+=16) + { + int cflag = MAPFLAG(sx, sy); + int cflag2 = MAPCOMBOFLAG(sx, sy); + + if(((cflag==mfENEMY0+i)||(cflag2==mfENEMY0+i)) && (!placed)) + { + if(!ok2add(tmpscr->enemy[i])) + ++loadcnt; + else + { + addenemy(sx, + (is_ceiling_pattern(tmpscr->pattern) && tmpscr->flags7&fSIDEVIEW) ? -(150+50*guycnt) : sy, + (is_ceiling_pattern(tmpscr->pattern) && !(tmpscr->flags7&fSIDEVIEW)) ? 150+50*guycnt : 0,tmpscr->enemy[i],-15); + + ++guycnt; + + placed=true; + goto placed_enemy; + } + } + } + } + + // Next: enemy pattern + if((tmpscr->pattern==pRANDOM || tmpscr->pattern==pCEILING) && !(tmpscr->flags7&fSIDEVIEW)) + { + do + { + // NES positions + pos%=9; + x=stx[loadside][pos]; + y=sty[loadside][pos]; + ++pos; + ++t; + } + while((t< 20) && !is_starting_pos(i,x,y,t)); + } + + if(t<0 || t >= 20) // above enemy pattern failed + { + // Final chance: find a random position anywhere onscreen + int randpos = placeenemy(i); + + if(randpos>-1) + { + x=(randpos&15)<<4; + y= randpos&0xF0; + } + else // All opportunities failed - abort + { + --clk; + continue; + } + } + + { + int c=0; + c=clk; + + if(!slowguy(tmpscr->enemy[i])) + ++fastguys; + else if(fastguys>0) + c=-15*(i-fastguys+2); + else + c=-15*(i+1); + + if(BSZ) + { + // Special case for blue leevers + if(guysbuf[tmpscr->enemy[i]].family==eeLEV && guysbuf[tmpscr->enemy[i]].misc1==1) + c=-15*(i+1); + else + c=-15; + } + + if(!ok2add(tmpscr->enemy[i])) + ++loadcnt; + else + { + addenemy(x,(is_ceiling_pattern(tmpscr->pattern) && tmpscr->flags7&fSIDEVIEW) ? -(150+50*guycnt) : y, + (is_ceiling_pattern(tmpscr->pattern) && !(tmpscr->flags7&fSIDEVIEW)) ? 150+50*guycnt : 0,tmpscr->enemy[i],c); + + ++guycnt; + } + + placed=true; + } // if(t < 20) + +placed_enemy: + + // I don't like this, but it seems to work... + static bool foundCarrier; + + if(i==0) + foundCarrier=false; + + if(placed) + { + if(i==0 && tmpscr->enemyflags&efLEADER) + { + int index = guys.idFirst(tmpscr->enemy[i],0xFFF); + + if(index!=-1) + { + ((enemy*)guys.spr(index))->leader = true; + } + } + + if(!foundCarrier && (hasitem)>1) + { + int index = guys.idFirst(tmpscr->enemy[i],0xFFF); + + if(index!=-1 && (((enemy*)guys.spr(index))->flags&guy_doesntcount)==0) + { + ((enemy*)guys.spr(index))->itemguy = true; + foundCarrier=true; + } + } + } + + --clk; + } // for + + game->guys[s] = guycnt; + //} //if(true) +} + +// Setting up special rooms +// Also called when the Letter is used successfully. +void setupscreen() +{ + boughtsomething=false; + setUpRoom(tmpscr[currscr<128?0:1]); +} + +/*** Collision detection & handling ***/ + +void check_collisions() +{ + for(int i=0; iDead()) && w->id!=wSword && w->id!=wHammer && w->id!=wWand) + { + for(int j=0; jhit(w)) + { + int h = e->takehit(w); + + if(h) + { + w->onhit(false); + } + + if(h==2) + { + break; + } + } + + if(w->Dead()) + { + break; + } + } + + if(get_bit(quest_rules,qr_Z3BRANG_HSHOT)) + { + if(w->id == wBrang || w->id==wHookshot) + { + for(int j=0; jhit(w)) + { + bool priced = ((item*)items.spr(j))->PriceIndex >-1; + + if((((item*)items.spr(j))->pickup & ipTIMER && ((item*)items.spr(j))->clk2 >= 32) + || (get_bit(quest_rules,qr_BRANGPICKUP) && !priced && !(((item*)items.spr(j))->pickup & ipDUMMY))) + { + if(w->id == wBrang) + { + w->onhit(false); + } + + if(w->dragging==-1) + { + w->dead=1; + ((item*)items.spr(j))->clk2=256; + w->dragging=j; + } + } + } + } + } + } + else + { + if(w->id == wBrang || w->id == wArrow || w->id==wHookshot) + { + for(int j=0; jhit(w)) + { + bool priced = ((item*)items.spr(j))->PriceIndex >-1; + + if((((item*)items.spr(j))->pickup & ipTIMER && ((item*)items.spr(j))->clk2 >= 32) + || (get_bit(quest_rules,qr_BRANGPICKUP) && !priced)) + { + if(itemsbuf[items.spr(j)->id].collect_script) + { + ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[items.spr(j)->id].collect_script, items.spr(j)->id & 0xFFF); + } + + //getitem(items.spr(j)->id); + //items.del(j); + Link.checkitems(j); + //--j; + } + } + } + } + } + } + } +} + +void dragging_item() +{ + if(get_bit(quest_rules,qr_Z3BRANG_HSHOT)) + { + for(int i=0; iid == wBrang || w->id==wHookshot) + { + if(w->dragging>=0 && w->draggingdragging)->x=w->x; + items.spr(w->dragging)->y=w->y; + + // Drag the Fairy enemy as well as the Fairy item + int id = items.spr(w->dragging)->id; + + if(itemsbuf[id].family ==itype_fairy && itemsbuf[id].misc3) + { + movefairy2(w->x,w->y,items.spr(w->dragging)->misc); + } + } + } + } + } +} + +int more_carried_items() +{ + int hasmorecarries = 0; + + for(int i=0; ipickup & ipENEMY) + { + hasmorecarries++; + } + } + + return hasmorecarries; +} + +// messy code to do the enemy-carrying-the-item thing +void roaming_item() +{ + if(hasitem<2 || !loaded_enemies) + return; + + // All enemies already dead upon entering a room? + if(guys.Count()==0) + { + return; + } + + // Lost track of the carrier? + if(guycarryingitem<0 || guycarryingitem>=guys.Count() || + !((enemy*)guys.spr(guycarryingitem))->itemguy) + { + guycarryingitem=-1; + for(int j=0; jitemguy) + { + guycarryingitem=j; + break; + } + } + } + + if(hasitem&4) + { + guycarryingitem = -1; + + for(int i=0; iitemguy) + { + guycarryingitem = i; + } + } + + if(guycarryingitem == -1) //This happens when "default enemies" such as + { + return; //eSHOOTFBALL are alive but enemies from the list + } //are not. Defer to LinkClass::checkspecial(). + + int Item=tmpscr->item; + + hasitem &= ~4; + + if(!getmapflag(mITEM) && (tmpscr->hasitem != 0)) + { + additem(0,0,Item,ipENEMY+ipONETIME+ipBIGRANGE + + (((tmpscr->flags3&fHOLDITEM) || (itemsbuf[Item].family==itype_triforcepiece)) ? ipHOLDUP : 0) + ); + hasitem |= 2; + } + else + { + return; + } + } + + for(int i=0; ipickup&ipENEMY) + { + if(get_bit(quest_rules,qr_HIDECARRIEDITEMS)) + { + items.spr(i)->x = -128; // Awfully inelegant, innit? + items.spr(i)->y = -128; + } + else if(guycarryingitem>=0 && guycarryingitemx = guys.spr(guycarryingitem)->x; + items.spr(i)->y = guys.spr(guycarryingitem)->y - 2; + } + } + } +} + +const char *old_guy_string[OLDMAXGUYS] = +{ + "(None)","Abei","Ama","Merchant","Moblin","Fire","Fairy","Goriya","Zelda","Abei 2","Empty","","","","","","","","","", + // 020 + "Octorok (L1, Slow)","Octorok (L2, Slow)","Octorok (L1, Fast)","Octorok (L2, Fast)","Tektite (L1)", + // 025 + "Tektite (L2)","Leever (L1)","Leever (L2)","Moblin (L1)","Moblin (L2)", + // 030 + "Lynel (L1)","Lynel (L2)","Peahat (L1)","Zora","Rock", + // 035 + "Ghini (L1, Normal)","Ghini (L1, Phantom)","Armos","Keese (CSet 7)","Keese (CSet 8)", + // 040 + "Keese (CSet 9)","Stalfos (L1)","Gel (L1, Normal)","Zol (L1, Normal)","Rope (L1)", + // 045 + "Goriya (L1)","Goriya (L2)","Trap (4-Way)","Wall Master","Darknut (L1)", + // 050 + "Darknut (L2)","Bubble (Sword, Temporary Disabling)","Vire (Normal)","Like Like","Gibdo", + // 055 + "Pols Voice (Arrow)","Wizzrobe (Teleporting)","Wizzrobe (Floating)","Aquamentus (Facing Left)","Moldorm", + // 060 + "Dodongo","Manhandla (L1)","Gleeok (1 Head)","Gleeok (2 Heads)","Gleeok (3 Heads)", + // 065 + "Gleeok (4 Heads)","Digdogger (1 Kid)","Digdogger (3 Kids)","Digdogger Kid (1)","Digdogger Kid (2)", + // 070 + "Digdogger Kid (3)","Digdogger Kid (4)","Gohma (L1)","Gohma (L2)","Lanmola (L1)", + // 075 + "Lanmola (L2)","Patra (L1, Big Circle)","Patra (L1, Oval)","Ganon","Stalfos (L2)", + // 080 + "Rope (L2)","Bubble (Sword, Permanent Disabling)","Bubble (Sword, Re-enabling)","Shooter (Fireball)","Item Fairy ", + // 085 + "Fire","Octorok (Magic)", "Darknut (Death Knight)", "Gel (L1, Tribble)", "Zol (L1, Tribble)", + // 090 + "Keese (Tribble)", "Vire (Tribble)", "Darknut (Splitting)", "Aquamentus (Facing Right)", "Manhandla (L2)", + // 095 + "Trap (Horizontal, Line of Sight)", "Trap (Vertical, Line of Sight)", "Trap (Horizontal, Constant)", "Trap (Vertical, Constant)", "Wizzrobe (Fire)", + // 100 + "Wizzrobe (Wind)", "Ceiling Master ", "Floor Master ", "Patra (BS Zelda)", "Patra (L2)", + // 105 + "Patra (L3)", "Bat", "Wizzrobe (Bat)", "Wizzrobe (Bat 2) ", "Gleeok (Fire, 1 Head)", + // 110 + "Gleeok (Fire, 2 Heads)", "Gleeok (Fire, 3 Heads)","Gleeok (Fire, 4 Heads)", "Wizzrobe (Mirror)", "Dodongo (BS Zelda)", + // 115 + "Dodongo (Fire) ","Trigger", "Bubble (Item, Temporary Disabling)", "Bubble (Item, Permanent Disabling)", "Bubble (Item, Re-enabling)", + // 120 + "Stalfos (L3)", "Gohma (L3)", "Gohma (L4)", "NPC 1 (Standing) ", "NPC 2 (Standing) ", + // 125 + "NPC 3 (Standing) ", "NPC 4 (Standing) ", "NPC 5 (Standing) ", "NPC 6 (Standing) ", "NPC 1 (Walking) ", + // 130 + "NPC 2 (Walking) ", "NPC 3 (Walking) ", "NPC 4 (Walking) ", "NPC 5 (Walking) ", "NPC 6 (Walking) ", + // 135 + "Boulder", "Goriya (L3)", "Leever (L3)", "Octorok (L3, Slow)", "Octorok (L3, Fast)", + // 140 + "Octorok (L4, Slow)", "Octorok (L4, Fast)", "Trap (8-Way) ", "Trap (Diagonal) ", "Trap (/, Constant) ", + // 145 + "Trap (/, Line of Sight) ", "Trap (\\, Constant) ", "Trap (\\, Line of Sight) ", "Trap (CW, Constant) ", "Trap (CW, Line of Sight) ", + // 150 + "Trap (CCW, Constant) ", "Trap (CCW, Line of Sight) ", "Wizzrobe (Summoner)", "Wizzrobe (Ice) ", "Shooter (Magic)", + // 155 + "Shooter (Rock)", "Shooter (Spear)", "Shooter (Sword)", "Shooter (Fire)", "Shooter (Fire 2)", + // 160 + "Bombchu", "Gel (L2, Normal)", "Zol (L2, Normal)", "Gel (L2, Tribble)", "Zol (L2, Tribble)", + // 165 + "Tektite (L3) ", "Spinning Tile (Combo)", "Spinning Tile (Enemy Sprite)", "Lynel (L3) ", "Peahat (L2) ", + // 170 + "Pols Voice (Magic) ", "Pols Voice (Whistle) ", "Darknut (Mirror) ", "Ghini (L2, Fire) ", "Ghini (L2, Magic) ", + // 175 + "Grappler Bug (HP) ", "Grappler Bug (MP) " +}; + +/*** end of guys.cc ***/ + diff --git a/src/guys.h b/src/guys.h new file mode 100644 index 0000000000..9640c0dc0d --- /dev/null +++ b/src/guys.h @@ -0,0 +1,264 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// guys.cc +// +// "Guys" code (and other related stuff) for zelda.cc +// +// Still has some hardcoded stuff that should be moved +// out into defdata.cc for customizing the enemies. +// +//-------------------------------------------------------- + +//#include "guys.h" +#ifndef _GUYS_H_ +#define _GUYS_H_ +#include +#include "sprite.h" +#include "weapons.h" + +#include "enemyAttack.h" +#include "sfxClass.h" +#include "scoped_ptr.h" + +class item; + +extern int repaircharge; +extern bool adjustmagic; +extern bool learnslash; +extern int itemindex; +extern int wallm_load_clk; +extern int sle_x,sle_y,sle_cnt,sle_clk; +extern int vhead; +extern int guycarryingitem; + +bool tooclose(int x,int y,int d); +bool isflier(int id); +bool never_in_air(int id); +// Returns true iff a combo type or flag precludes enemy movement. +bool groundblocked(int dx, int dy); +// Returns true iff enemy is floating and blocked by a combo type or flag. +bool flyerblocked(int dx, int dy, int special); + +// Start spinning tiles - called by load_default_enemies +void awaken_spinning_tile(mapscr *s, int pos); + +// Used to remove/add fireball shooter enemies +void screen_combo_modify_preroutine(mapscr *s, int pos); +void screen_combo_modify_postroutine(mapscr *s, int pos); + +// Find the IDs of enemies spawned by combos and flags. Called once on loading a quest. +void identifyCFEnemies(); + +// Let's make sure this check is consistent, shall we? +#define ON_SIDEPLATFORM (_walkflag(x+4,y+16,0) || (y>=160 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN))) + +/**********************************/ +/******* Enemy Base Class *******/ +/**********************************/ + +class enemy : public sprite +{ +public: + guydata *d; + // Approximately all of these variables are accessed by either ffscript.cpp or inherited classes + int o_tile, frate, hp, hclk, stunclk, fading, superman; + bool mainguy, did_armos; + byte item_set, grumble; + bool itemguy, count_enemy, dying, ceiling, leader, scored, script_spawned; + fix step, floor_y; + + //d variables + dword flags; + dword flags2; + + short family, dcset, anim; + short dp, wdp, wpn; + + short rate, hrate, homing; + fix dstep; + long dmisc1, dmisc2, dmisc3, dmisc4, dmisc5, dmisc6, dmisc7, dmisc8, dmisc9, dmisc10, dmisc11, dmisc12, dmisc13, dmisc14, dmisc15; + short bgsfx, bosspal; + byte defense[edefLAST]; + + int dummy_int1; + + enemy(fix X,fix Y,int Id,int Clk); // : sprite() + virtual ~enemy(); + + // auomatically kill off enemy (for rooms with ringleaders) + virtual void kickbucket(); + // Take damage or ignore it + virtual int takehit(weapon *w); + // override hit detection to check for invicibility, stunned, etc + virtual bool hit(sprite *s); + virtual bool hit(int tx,int ty,int tz,int txsz,int tysz,int tzsz); + virtual bool hit(weapon *w); + virtual void break_shield() {}; // Overridden by types that can have shields + virtual bool ignore_msg_freeze() + { + return false; + } + +protected: + int clk2,sclk; + word s_tile; //secondary (additional) tile(s) + + //virtual void move(fix s); + void leave_item(); + + // take damage or ignore it + virtual bool hitshield(int wpnx, int wpny, int xdir); + virtual int defend(int wpnId, int *power, int edef); + bool candamage(int power, int edef); + int defenditemclass(int wpnId, int *power); + + bool dont_draw(); + // base drawing function to be used by all derived classes instead of + // sprite::draw() + virtual void draw(BITMAP *dest); + // similar to the overblock function - draws a 32x32 sprite + void drawblock(BITMAP *dest); + virtual void drawshadow(BITMAP *dest, bool translucent); + void masked_draw(BITMAP *dest,int mx,int my,int mw,int mh); + + // --==**==-- + // Movement routines that can be used by derived classes as needed + // --==**==-- + + // returns true if next step is ok, false if there is something there + bool canmove(int ndir,fix s,int special,int dx1,int dy1,int dx2,int dy2); + bool canmove(int ndir,fix s,int special); + bool canmove(int ndir,int special); + bool canmove(int ndir); + // falls through the Z axis; + void falldown(); + int pos(int x,int y); + // Enemies that cannot ever be penetrated by weapons + bool cannotpenetrate(); + +private: + bool shieldCanBlock; + +protected: + SFX bgSFX, hitSFX, deathSFX; + scoped_ptr attack; + +public: + void setBGSFX(SFX newBG); + inline int getDir() const { return dir; } + + void setAttack(EnemyAttack* att); + + friend void registerEnemy(); +}; + +class asIScriptFunction; + +class ASEnemy: public enemy +{ +public: + bool haslink; + + ASEnemy(const char* scriptName, fix x, fix y, int id, int clk); + bool animate(int index); + void draw(BITMAP *dest); + void draw2(BITMAP *dest); + void drawshadow(BITMAP *dest, bool translucent); + bool hit(weapon *w); + int takehit(weapon *w); + int defend(int wpnId, int* power, int edef); + void break_shield(); + void eatlink(); + void setDeathAttack(EnemyAttack* att); + +private: + asIScriptFunction* asUpdate; + asIScriptFunction* asDraw; + asIScriptFunction* asDraw2; + asIScriptFunction* asDrawShadow; + asIScriptFunction* asTakeHit; + asIScriptFunction* asHit; + asIScriptFunction* asBreakShield; + asIScriptFunction* asEatLink; + + int scriptFlags; + int wpnPower; + scoped_ptr deathAttack; + + void fireWeapon(); + bool isFiring() const; + void updateFiring(); + void setBreathTimer(int time); + void setAttackOwner(int index); + void activateDeathAttack(); + void scriptDraw(); + void scriptDrawBlock(); + void scriptDrawShadow(); + void scriptMaskedDraw(int mx, int my, int mw, int mh); + void overTileCloaked16(int tile, int x, int y, int flip); + void overTile16(int tile, int x, int y, int cset, int flip); + void stopBGSFX(); + void playDeathSFX(); + void playHitSFX(int pan); + bool defaultAnimate(int index); + int defaultTakeHit(weapon* w); + void kickbucket(); + int scriptDefendItemClass(int wpnId, int power); + int getDefendedItemPower(); + + friend void registerEnemy(); +}; + +/**********************************/ +/********** Misc Code ***********/ +/**********************************/ +// Used by Link's swords & stomp boots +int hit_enemy(int index,int wpnId,int power,int wpnx,int wpny,int dir, int enemyHitWeapon); +void enemy_scored(int index); +void addguy(int x,int y,int id,int clk,bool mainguy); +item* additem(int x,int y,int id,int pickup); +item* additem(int x,int y,int id,int pickup,int clk); +void kill_em_all(); +// For Link's hit detection. Don't count them if they are stunned or are guys. +int GuyHit(int tx,int ty,int tz,int txsz,int tysz,int tzsz); +// For Link's hit detection. Count them if they are dying. +int GuyHit(int index,int tx,int ty,int tz,int txsz,int tysz,int tzsz); +bool hasMainGuy(); +void EatLink(int index); +void GrabLink(int index); +bool CarryLink(); +void movefairy(fix &x,fix &y,int misc); +void movefairy2(fix x,fix y,int misc); +void killfairy(int misc); +int addenemy(int x,int y,int id,int clk); +int addenemy(int x,int y,int z,int id,int clk); +bool isjumper(int id); +bool canfall(int id); +void addfires(); +void loadguys(); +void loaditem(); +void never_return(int index); +bool hasBoss(); +bool slowguy(int id); +bool ok2add(int id); +void load_default_enemies(); +void nsp(bool random); +int next_side_pos(bool random); +bool can_side_load(int id); +void side_load_enemies(); +void loadenemies(); +void setupscreen(); +int wpnsfx(int wpn); +bool m_walkflag(int dx,int dy,int special, int x=-1000, int y=-1000); + +/*** Collision detection & handling ***/ + +void check_collisions(); +void dragging_item(); +void roaming_item(); +int more_carried_items(); +#endif +/*** end of guys.cc ***/ + diff --git a/src/init.cpp b/src/init.cpp new file mode 100644 index 0000000000..248414d750 --- /dev/null +++ b/src/init.cpp @@ -0,0 +1,2014 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include + +#include + +#include "zc_alleg.h" +#include "jwin.h" +#include "zdefs.h" +#include "zsys.h" +#include "gui.h" +#include "init.h" +#include "zelda.h" +#include "mem_debug.h" +#include "zq_custom.h" + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +#define stringizehelp(L) #L +#define stringize(L) stringizehelp(L) + +#define vc(x) ((x)+224) // offset to 'VGA color' x (row 14) + +//using namespace std; + +extern int jwin_pal[jcMAX]; +extern FONT *sfont2; +extern FONT *lfont; +extern FONT *pfont; +extern dmap *DMaps; +extern itemdata *itemsbuf; +extern byte quest_rules[20]; +extern char *item_string[]; + +void initPopulate(int &i, DIALOG_PROC proc, int x, int y, int w, int h, int fg, int bg, int key, int flags, int d1, int d2, + void *dp, void *dp2 = NULL, void *dp3 = NULL); +void getitem(int id, bool nosound); + +static const int endEquipField = 33; + +void doFamily(int family, zinitdata *data); +int jwin_initlist_proc(int msg,DIALOG *d,int c); + +class Family +{ +public: + Family(int fam, int lvl, int id) : family(fam), level(lvl), itemid(id) {} + int family; + int level; + int itemid; + bool operator<(const Family &other) const + { + return level < other.level; + } +}; + +//extern char *itype_names[itype_last]; + + +extern int d_dummy_proc(int msg,DIALOG *d,int c); +extern int d_dropdmaplist_proc(int msg,DIALOG *d,int c); +extern const char *dmaplist(int index, int *list_size); +extern int onHelp(); +extern int startdmapxy[6]; +extern void onInitOK(); + +std::map listidx2biic; +//sorted by family id +static std::map > families; + +int d_line_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg==MSG_DRAW) + { + int fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + line(screen, d->x, d->y, d->x+d->w, d->y+d->h, palette_color[fg]); + } + + return D_O_K; +} + +static int init_equipment_list[] = +{ + // dialog control number + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, -1 +}; + +static int init_items_list[] = +{ + // dialog control number + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 1692, 1693, 1698, 1699, -1 +}; + +static int init_dmap_items_list[] = +{ + // dialog control number + 137, -1 +}; + +static int init_dmap_items_000s_list[] = +{ + // dialog control number + 138, -1 +}; + +static int init_dmap_items_100s_list[] = +{ + // dialog control number + 139, -1 +}; + +static int init_dmap_items_200s_list[] = +{ + // dialog control number + 140, -1 +}; + +static int init_dmap_items_300s_list[] = +{ + // dialog control number + 1707, -1 +}; + +static int init_dmap_items_400s_list[] = +{ + // dialog control number + 1708, -1 +}; + +static int init_dmap_items_500s_list[] = +{ + // dialog control number + 1709, -1 +}; + +static int init_dmap_items_0_00s_list[] = +{ + // dialog control number + 141, 167, 168, 219, 220, 271, 272, 323, 324, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, -1 +}; + +static int init_dmap_items_0_10s_list[] = +{ + // dialog control number + 142, 169, 170, 221, 222, 273, 274, 325, 326, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, -1 +}; + +static int init_dmap_items_0_20s_list[] = +{ + // dialog control number + 143, 171, 172, 223, 224, 275, 276, 327, 328, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, -1 +}; + +static int init_dmap_items_0_30s_list[] = +{ + // dialog control number + 144, 173, 174, 225, 226, 277, 278, 329, 330, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, -1 +}; + +static int init_dmap_items_0_40s_list[] = +{ + // dialog control number + 145, 175, 176, 227, 228, 279, 280, 331, 332, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, -1 +}; + +static int init_dmap_items_0_50s_list[] = +{ + // dialog control number + 146, 177, 178, 229, 230, 281, 282, 333, 334, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, -1 +}; + +static int init_dmap_items_0_60s_list[] = +{ + // dialog control number + 147, 179, 180, 231, 232, 283, 284, 335, 336, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, -1 +}; + +static int init_dmap_items_0_70s_list[] = +{ + // dialog control number + 148, 181, 182, 233, 234, 285, 286, 337, 338, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, -1 +}; + +static int init_dmap_items_0_80s_list[] = +{ + // dialog control number + 149, 183, 184, 235, 236, 287, 288, 339, 340, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, -1 +}; + +static int init_dmap_items_0_90s_list[] = +{ + // dialog control number + 150, 185, 186, 237, 238, 289, 290, 341, 342, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, -1 +}; + +static int init_dmap_items_1_00s_list[] = +{ + // dialog control number + 151, 187, 188, 239, 240, 291, 292, 343, 344, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, -1 +}; + +static int init_dmap_items_1_10s_list[] = +{ + // dialog control number + 152, 189, 190, 241, 242, 293, 294, 345, 346, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, -1 +}; + +static int init_dmap_items_1_20s_list[] = +{ + // dialog control number + 153, 191, 192, 243, 244, 295, 296, 347, 348, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, -1 +}; + +static int init_dmap_items_1_30s_list[] = +{ + // dialog control number + 154, 193, 194, 245, 246, 297, 298, 349, 350, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, -1 +}; + +static int init_dmap_items_1_40s_list[] = +{ + // dialog control number + 155, 195, 196, 247, 248, 299, 300, 351, 352, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, -1 +}; + +static int init_dmap_items_1_50s_list[] = +{ + // dialog control number + 156, 197, 198, 249, 250, 301, 302, 353, 354, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, -1 +}; + +static int init_dmap_items_1_60s_list[] = +{ + // dialog control number + 157, 199, 200, 251, 252, 303, 304, 355, 356, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, -1 +}; + +static int init_dmap_items_1_70s_list[] = +{ + // dialog control number + 158, 201, 202, 253, 254, 305, 306, 357, 358, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, -1 +}; + +static int init_dmap_items_1_80s_list[] = +{ + // dialog control number + 159, 203, 204, 255, 256, 307, 308, 359, 360, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, -1 +}; + +static int init_dmap_items_1_90s_list[] = +{ + // dialog control number + 160, 205, 206, 257, 258, 309, 310, 361, 362, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, -1 +}; + +static int init_dmap_items_2_00s_list[] = +{ + // dialog control number + 161, 207, 208, 259, 260, 311, 312, 363, 364, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, -1 +}; + +static int init_dmap_items_2_10s_list[] = +{ + // dialog control number + 162, 209, 210, 261, 262, 313, 314, 365, 366, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, -1 +}; + +static int init_dmap_items_2_20s_list[] = +{ + // dialog control number + 163, 211, 212, 263, 264, 315, 316, 367, 368, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, -1 +}; + +static int init_dmap_items_2_30s_list[] = +{ + // dialog control number + 164, 213, 214, 265, 266, 317, 318, 369, 370, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, -1 +}; + +static int init_dmap_items_2_40s_list[] = +{ + // dialog control number + 165, 215, 216, 267, 268, 319, 320, 371, 372, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, -1 +}; + +static int init_dmap_items_2_50s_list[] = +{ + // dialog control number + 166, 217, 218, 269, 270, 321, 322, 373, 374, 625, 626, 627, 628, 629, 630, 881, 882, 883, 884, 885, 886, 1137, 1138, 1139, 1140, 1141, 1142, 1393, 1394, 1395, 1396, 1397, 1398, 1649, 1650, 1651, 1652, 1653, 1654, + 1984, 1985, 1986, 1987, + 2240, 2241, 2242, 2243, + 2496, 2497, 2498, 2499, + 2752, 2753, 2754, 2755, + 3008, 3009, 3010, 3011, -1 +}; + +static int init_dmap_items_2_60s_list[] = +{ + 1750, + 1776, 1777, + 1828, 1829, + 1880, 1881, + 1932, 1933, + 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, + 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, + 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, + 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, + 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, -1 +}; + +static int init_dmap_items_2_70s_list[] = +{ + 1751, + 1778, 1779, + 1830, 1831, + 1882, 1883, + 1934, 1935, + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, + 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, + 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, + 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, -1 +}; + +static int init_dmap_items_2_80s_list[] = +{ + 1752, + 1780, 1781, + 1832, 1833, + 1884, 1885, + 1936, 1937, + 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, + 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, + 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785, + 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, -1 +}; + +static int init_dmap_items_2_90s_list[] = +{ + 1753, + 1782, 1783, + 1834, 1835, + 1886, 1887, + 1938, 1939, + 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, + 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, + 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, + 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, + 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, -1 +}; + +static int init_dmap_items_3_00s_list[] = +{ + 1754, + 1784, 1785, + 1836, 1837, + 1888, 1889, + 1940, 1941, + 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, + 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, + 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, + 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, + 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, -1 +}; + +static int init_dmap_items_3_10s_list[] = +{ + 1755, + 1786, 1787, + 1838, 1839, + 1890, 1891, + 1942, 1943, + 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, + 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, + 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, + 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, + 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, -1 +}; + +static int init_dmap_items_3_20s_list[] = +{ + 1756, + 1788, 1789, + 1840, 1841, + 1892, 1893, + 1944, 1945, + 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, + 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, + 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, + 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, + 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, -1 +}; + +static int init_dmap_items_3_30s_list[] = +{ + 1757, + 1790, 1791, + 1842, 1843, + 1894, 1895, + 1946, 1947, + 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, + 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, + 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, + 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, + 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, -1 +}; + +static int init_dmap_items_3_40s_list[] = +{ + 1758, + 1792, 1793, + 1844, 1845, + 1896, 1897, + 1948, 1949, + 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, + 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, + 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, + 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, + 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, -1 +}; + +static int init_dmap_items_3_50s_list[] = +{ + 1759, + 1794, 1795, + 1846, 1847, + 1898, 1899, + 1950, 1951, + 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, + 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, + 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, + 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, + 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, -1 +}; + +static int init_dmap_items_3_60s_list[] = +{ + 1760, + 1796, 1797, + 1848, 1849, + 1900, 1901, + 1952, 1953, + 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, + 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, + 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, + 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, + 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, -1 +}; + +static int init_dmap_items_3_70s_list[] = +{ + 1761, + 1798, 1799, + 1850, 1851, + 1902, 1903, + 1954, 1955, + 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, + 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, + 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, + 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, + 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, -1 +}; + +static int init_dmap_items_3_80s_list[] = +{ + 1762, + 1800, 1801, + 1852, 1853, + 1904, 1905, + 1956, 1957, + 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, + 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, + 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, + 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, + 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, -1 +}; + +static int init_dmap_items_3_90s_list[] = +{ + 1763, + 1802, 1803, + 1854, 1855, + 1906, 1907, + 1958, 1959, + 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, + 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, + 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, + 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, + 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, -1 +}; + +static int init_dmap_items_4_00s_list[] = +{ + 1764, + 1804, 1805, + 1856, 1857, + 1908, 1909, + 1960, 1961, + 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, + 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, + 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, + 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, + 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, -1 +}; + +static int init_dmap_items_4_10s_list[] = +{ + 1765, + 1806, 1807, + 1858, 1859, + 1910, 1911, + 1962, 1963, + 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, + 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, + 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, + 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, + 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, -1 +}; + +static int init_dmap_items_4_20s_list[] = +{ + 1766, + 1808, 1809, + 1860, 1861, + 1912, 1913, + 1964, 1965, + 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, + 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, + 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, + 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, + 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, -1 +}; + +static int init_dmap_items_4_30s_list[] = +{ + 1767, + 1810, 1811, + 1862, 1863, + 1914, 1915, + 1966, 1967, + 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, + 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2423, + 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, + 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, + 3182, 3183, 3184, 3185, 3186, 3187, 3188, 3189, 3190, 3191, -1 +}; + +static int init_dmap_items_4_40s_list[] = +{ + 1768, + 1812, 1813, + 1864, 1865, + 1916, 1917, + 1968, 1969, + 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, + 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, + 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, + 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, + 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, -1 +}; + +static int init_dmap_items_4_50s_list[] = +{ + 1769, + 1814, 1815, + 1866, 1867, + 1918, 1919, + 1970, 1971, + 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, + 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, + 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, + 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, + 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, -1 +}; + +static int init_dmap_items_4_60s_list[] = +{ + 1770, + 1816, 1817, + 1868, 1869, + 1920, 1921, + 1972, 1973, + 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, + 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, + 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, + 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, + 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, -1 +}; + +static int init_dmap_items_4_70s_list[] = +{ + 1771, + 1818, 1819, + 1870, 1871, + 1922, 1923, + 1974, 1975, + 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, + 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, + 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, + 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, + 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, -1 +}; + +static int init_dmap_items_4_80s_list[] = +{ + 1772, + 1820, 1821, + 1872, 1873, + 1924, 1925, + 1976, 1977, + 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, + 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, + 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, + 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, + 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, -1 +}; + +static int init_dmap_items_4_90s_list[] = +{ + 1773, + 1822, 1823, + 1874, 1875, + 1926, 1927, + 1978, 1979, + 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, + 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, + 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, + 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, + 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, -1 +}; + +static int init_dmap_items_5_00s_list[] = +{ + 1774, + 1824, 1825, + 1876, 1877, + 1928, 1929, + 1980, 1981, + 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, + 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, + 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, + 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, + 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, -1 +}; + +static int init_dmap_items_5_10s_list[] = +{ + 1775, + 1826, 1827, + 1878, 1879, + 1930, 1931, + 1982, 1983, + 2238, 2239, + 2494, 2495, + 2750, 2751, + 3006, 3007, + 3262, 3263, -1 +}; + +static int init_misc_list[] = +{ + // dialog control number + // 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, -1 + 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1694, 1695, 1696, 1697, -1 +}; + +static int init_const_list[] = +{ + 1700, 1701, 1702, 1703, 1704, 1705, 1706, -1 +}; + + +static TABPANEL init_dmap_items_hundreds_tabs[] = +{ + // (text) + { (char *)"000", D_SELECTED, init_dmap_items_000s_list, 0, NULL }, + { (char *)"100", 0, init_dmap_items_100s_list, 0, NULL }, + { (char *)"200", 0, init_dmap_items_200s_list, 0, NULL }, + { (char *)"300", 0, init_dmap_items_300s_list, 0, NULL }, + { (char *)"400", 0, init_dmap_items_400s_list, 0, NULL }, + { (char *)"500", 0, init_dmap_items_500s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + + +static TABPANEL init_dmap_items_000s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_0_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_0_10s_list, 0, NULL }, + { (char *)"20", 0, init_dmap_items_0_20s_list, 0, NULL }, + { (char *)"30", 0, init_dmap_items_0_30s_list, 0, NULL }, + { (char *)"40", 0, init_dmap_items_0_40s_list, 0, NULL }, + { (char *)"50", 0, init_dmap_items_0_50s_list, 0, NULL }, + { (char *)"60", 0, init_dmap_items_0_60s_list, 0, NULL }, + { (char *)"70", 0, init_dmap_items_0_70s_list, 0, NULL }, + { (char *)"80", 0, init_dmap_items_0_80s_list, 0, NULL }, + { (char *)"90", 0, init_dmap_items_0_90s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static TABPANEL init_dmap_items_100s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_1_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_1_10s_list, 0, NULL }, + { (char *)"20", 0, init_dmap_items_1_20s_list, 0, NULL }, + { (char *)"30", 0, init_dmap_items_1_30s_list, 0, NULL }, + { (char *)"40", 0, init_dmap_items_1_40s_list, 0, NULL }, + { (char *)"50", 0, init_dmap_items_1_50s_list, 0, NULL }, + { (char *)"60", 0, init_dmap_items_1_60s_list, 0, NULL }, + { (char *)"70", 0, init_dmap_items_1_70s_list, 0, NULL }, + { (char *)"80", 0, init_dmap_items_1_80s_list, 0, NULL }, + { (char *)"90", 0, init_dmap_items_1_90s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static TABPANEL init_dmap_items_200s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_2_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_2_10s_list, 0, NULL }, + { (char *)"20", 0, init_dmap_items_2_20s_list, 0, NULL }, + { (char *)"30", 0, init_dmap_items_2_30s_list, 0, NULL }, + { (char *)"40", 0, init_dmap_items_2_40s_list, 0, NULL }, + { (char *)"50", 0, init_dmap_items_2_50s_list, 0, NULL }, + { (char *)"60", 0, init_dmap_items_2_60s_list, 0, NULL }, + { (char *)"70", 0, init_dmap_items_2_70s_list, 0, NULL }, + { (char *)"80", 0, init_dmap_items_2_80s_list, 0, NULL }, + { (char *)"90", 0, init_dmap_items_2_90s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static TABPANEL init_dmap_items_300s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_3_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_3_10s_list, 0, NULL }, + { (char *)"20", 0, init_dmap_items_3_20s_list, 0, NULL }, + { (char *)"30", 0, init_dmap_items_3_30s_list, 0, NULL }, + { (char *)"40", 0, init_dmap_items_3_40s_list, 0, NULL }, + { (char *)"50", 0, init_dmap_items_3_50s_list, 0, NULL }, + { (char *)"60", 0, init_dmap_items_3_60s_list, 0, NULL }, + { (char *)"70", 0, init_dmap_items_3_70s_list, 0, NULL }, + { (char *)"80", 0, init_dmap_items_3_80s_list, 0, NULL }, + { (char *)"90", 0, init_dmap_items_3_90s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static TABPANEL init_dmap_items_400s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_4_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_4_10s_list, 0, NULL }, + { (char *)"20", 0, init_dmap_items_4_20s_list, 0, NULL }, + { (char *)"30", 0, init_dmap_items_4_30s_list, 0, NULL }, + { (char *)"40", 0, init_dmap_items_4_40s_list, 0, NULL }, + { (char *)"50", 0, init_dmap_items_4_50s_list, 0, NULL }, + { (char *)"60", 0, init_dmap_items_4_60s_list, 0, NULL }, + { (char *)"70", 0, init_dmap_items_4_70s_list, 0, NULL }, + { (char *)"80", 0, init_dmap_items_4_80s_list, 0, NULL }, + { (char *)"90", 0, init_dmap_items_4_90s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +static TABPANEL init_dmap_items_500s_tabs[] = +{ + // (text) + { (char *)"00", D_SELECTED, init_dmap_items_5_00s_list, 0, NULL }, + { (char *)"10", 0, init_dmap_items_5_10s_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +TABPANEL init_tabs[] = +{ + // (text) + { (char *)"Equipment", D_SELECTED, init_equipment_list, 0, NULL }, + { (char *)"Items", 0, init_items_list, 0, NULL }, + { (char *)"Level Items", 0, init_dmap_items_list, 0, NULL }, + { (char *)"Misc", 0, init_misc_list, 0, NULL }, + { (char *)"Constants", 0, init_const_list, 0, NULL }, + { NULL, 0, 0, 0, NULL } +}; + +//int startdmapxy[6] = {188-68,131-93,188-68,111-93,188-68,120-93}; + +int d_maxbombsedit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_DRAW) + { + scare_mouse(); + int div = atoi((char*)((d+1589)->dp)); + + if(div == 0) + div = 4; + + sprintf((char*)((d+6)->dp), "%d", atoi((char*)(d->dp))/div); + (d+6)->proc(MSG_DRAW,d+6,0); + unscare_mouse(); + } + + return ret; +} + +int d_bombratioedit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_DRAW) + { + int sbombmax = 0; + int div = atoi((char*)(d->dp)); + + if(div == 0) + div = 4; + + if(atoi((char*)(d->dp))) + sbombmax = atoi((char*)((d-1589)->dp))/div; + + scare_mouse(); + sprintf((char*)((d-1583)->dp), "%d", sbombmax); + (d-1583)->proc(MSG_DRAW,d-1583,0); + unscare_mouse(); + } + + return ret; +} + +const char *walkstyles[]= { "2-frame", "3-frame" }; + +char *walkstylelist(int index, int *list_size) +{ + if(index>=0) + { + return (char *)walkstyles[index]; + } + + *list_size=ws_max; + return NULL; +} + + +DIALOG init_dlg[3265]; + + +void initPopulate(int &i, DIALOG_PROC Proc, int X, int Y, int W, int H, int FG, int BG, int Key, int Flags, int D1, int D2, void *DP, void *DP2, void *DP3) +{ + init_dlg[i].proc = Proc; + init_dlg[i].x = X; + init_dlg[i].y = Y; + init_dlg[i].w = W; + init_dlg[i].h = H; + init_dlg[i].fg = FG; + init_dlg[i].bg = BG; + init_dlg[i].key = Key; + init_dlg[i].flags = Flags; + init_dlg[i].d1 = D1; + init_dlg[i].d2 = D2; + init_dlg[i].dp = DP; + init_dlg[i].dp2 = DP2; + init_dlg[i].dp3 = DP3; + ++i; +} + +static ListData dmap_list(dmaplist, &font); + +void PopulateInitDialog() +{ + int i=0; + // 0 + initPopulate(i, jwin_win_proc, 0, 0, 296, 234, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Initialization Data", NULL, NULL); + initPopulate(i, jwin_button_proc, 187, 209, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL); + initPopulate(i, jwin_button_proc, 47, 209, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL); + initPopulate(i, d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL); + initPopulate(i, jwin_tab_proc, 6, 25, 284, 178, vc(14), vc(1), 0, 0, 1, 0, (void *) init_tabs, NULL, (void *)init_dlg); + initPopulate(i, d_dummy_proc, 11, 47, 117, 152, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 130, 47, 154, 152, vc(0), vc(11), 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 57, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "1", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 67, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "2", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 77, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "3", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 87, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "4", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 97, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "5", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 107, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "6", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 117, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "7", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 127, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "8", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 137, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "9", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 147, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "10", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 157, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "11", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 167, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "12", NULL, NULL); + initPopulate(i, jwin_check_proc, 134, 177, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "13", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 57, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "14", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 67, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "15", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 77, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "16", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 87, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "17", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 97, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "18", NULL, NULL); + // 25 + initPopulate(i, jwin_check_proc, 207, 107, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "19", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 117, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "20", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 127, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "21", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 137, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "22", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 147, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "23", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 157, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "24", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 167, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "25", NULL, NULL); + initPopulate(i, jwin_check_proc, 207, 177, 74, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "26", NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 50 + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 100, 50, 86, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 104, 47, 121, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Arrows ", NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 75 + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 100 + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 13, 50, 86, 118, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 17, 47, 113, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Bombs ", NULL, NULL); + initPopulate(i, jwin_frame_proc, 17, 60, 78, 37, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 21, 57, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Normal ", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 36, 67, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 77, 67, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + initPopulate(i, jwin_edit_proc, 25, 77, 21, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, d_maxbombsedit_proc, 66, 77, 21, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 17, 100, 78, 37, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 21, 98, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Super ", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 36, 108, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 77, 108, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + initPopulate(i, jwin_edit_proc, 25, 118, 21, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 66, 118, 21, 16, 0, 0, 0, D_DISABLED, 2, 0, NULL, NULL, NULL); + initPopulate(i, jwin_ctext_proc, 119, 57, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 160, 57, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + initPopulate(i, jwin_edit_proc, 108, 67, 21, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 149, 67, 21, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 187, 50, 86, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 191, 47, 121, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Rupees ", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 206, 57, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 247, 57, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + // 125 + initPopulate(i, jwin_edit_proc, 195, 67, 26, 16, 0, 0, 0, 0, 5, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 236, 67, 26, 16, 0, 0, 0, 0, 5, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 100, 93, 86, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 104, 90, 121, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Keys ", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 119, 100, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 160, 100, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + initPopulate(i, jwin_edit_proc, 108, 110, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 149, 110, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_tab_proc, 12, 47, 272, 150, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_hundreds_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_000s_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_100s_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_200s_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 150 + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 67, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "M", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 196, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "M", NULL, NULL); + } + + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 79, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "C", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 208, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "C", NULL, NULL); + } + + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 92, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "B", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 221, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "B", NULL, NULL); + } + + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 111, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "K", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 240, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "K", NULL, NULL); + } + + // 0-255 level numbers + for(int j=0; j<=255;) + { + for(int x = 39; x<=168 && j<=255; x+=129) + { + for(int y = 103; y<=175 && j<=255; y+=18) + { + char *t = new char[4]; //memory not freed + sprintf(t, "%d", j++); + initPopulate(i, jwin_rtext_proc, x, y, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) t, NULL, NULL); + //delete [] t; + } + } + } + + // Map + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 62, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 62, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // Compass + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 75, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 75, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // Boss Key + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 88, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 88, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // Keys + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_edit_proc, 101, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_edit_proc, 101, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + + initPopulate(i, jwin_text_proc, 12, 51, 128, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Starting DMap: ", NULL, NULL); + initPopulate(i, d_dropdmaplist_proc, 81, 47, 180, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, startdmapxy); + initPopulate(i, jwin_text_proc, 12, 69, 144, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Heart Containers:", NULL, NULL); + initPopulate(i, jwin_text_proc, 12, 87, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Starting HP (hearts):", NULL, NULL); + initPopulate(i, jwin_text_proc, 12, 105, 104, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Continue HP:", NULL, NULL); + initPopulate(i, d_dummy_proc, 12, 123, 48, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 12, 141, 64, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 95, 65, 21, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 112, 83, 21, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 71, 101, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 40, 119, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 50, 137, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 99, 105, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "%", NULL, NULL); + initPopulate(i, jwin_text_proc, 126, 69, 64, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Pieces:", NULL, NULL); + initPopulate(i, jwin_edit_proc, 161, 65, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 197, 69, 64, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Per HC:", NULL, NULL); + initPopulate(i, jwin_edit_proc, 235, 65, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_frame_proc, 148, 88, 122, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + // 1675 + initPopulate(i, jwin_text_proc, 152, 85, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Triforce ", NULL, NULL); + initPopulate(i, jwin_check_proc, 156, 95, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL); + initPopulate(i, jwin_check_proc, 156, 105, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL); + initPopulate(i, jwin_check_proc, 186, 95, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL); + initPopulate(i, jwin_check_proc, 186, 105, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL); + initPopulate(i, jwin_check_proc, 216, 95, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL); + initPopulate(i, jwin_check_proc, 216, 105, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL); + initPopulate(i, jwin_check_proc, 246, 95, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL); + initPopulate(i, jwin_check_proc, 246, 105, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL); + initPopulate(i, jwin_check_proc, 12, 189, 17, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Slash", NULL, NULL); + + initPopulate(i, jwin_frame_proc, 172-24, 122, 98+18, 50, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 176-24, 119, 113, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) " Magic (" stringize(MAGICPERBLOCK) " per block) ", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 191-10, 129, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Start", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 232-10, 129, 73, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Max", NULL, NULL); + initPopulate(i, jwin_edit_proc, 180-10, 139, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 221-10, 139, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 180, 159, 25, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Double", NULL, NULL); + + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 76, 123, 64, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 102, 119, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 96, 141, 64, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 122, 137, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL); + initPopulate(i, jwin_text_proc, 19, 139, 176, 9, vc(15), vc(11), 0, 0, 0, 0, (void *) "Super Bomb Ratio", NULL, NULL); + initPopulate(i, d_bombratioedit_proc, 25, 149, 21, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL); + // 1700 + initPopulate(i, jwin_text_proc, 12, 51, 128, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Gravity:", NULL, NULL); + initPopulate(i, jwin_text_proc, 89, 51, 144, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Terminal Velocity:", NULL, NULL); + initPopulate(i, jwin_text_proc, 12, 72, 104, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Jumping Sprite Layer Threshold:", NULL, NULL); + initPopulate(i, jwin_edit_proc, 52, 47, 32, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 172, 47, 32, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 162, 68, 26, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_300s_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_400s_tabs, NULL, (void *)init_dlg); + initPopulate(i, jwin_tab_proc, 18, 69, 260, 128, vc(14), vc(1), 0, 0, 1, 0, (void *) init_dmap_items_500s_tabs, NULL, (void *)init_dlg); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 1725 + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + // 1750 + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + initPopulate(i, jwin_vline_proc, 147, 91, 40, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); + + // 1776 + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 67, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "M", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 196, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "M", NULL, NULL); + } + + // 1828 + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 79, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "C", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 208, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "C", NULL, NULL); + } + + // 1880 + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 92, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "B", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 221, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "B", NULL, NULL); + } + + // 1932 + for(int j=0; j<26; j++) + { + initPopulate(i, jwin_ctext_proc, 111, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "K", NULL, NULL); + initPopulate(i, jwin_ctext_proc, 240, 91, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "K", NULL, NULL); + } + + // 1984 + // 0-255 level numbers + for(int j=250; j<=511;) + { + for(int x = 39; x<=168 && j<=511; x+=129) + { + for(int y = 103; y<=175 && j<=511; y+=18) + { + if(j>=256) + { + char *t = new char[4]; //memory not freed + sprintf(t, "%d", j++); + initPopulate(i, jwin_rtext_proc, x, y, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) t, NULL, NULL); + //delete [] t; + } + else j++; + } + } + } + + // 2240 + // Map + initPopulate(i, jwin_check_proc, 191, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 62, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 191, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 62, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 62, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // 2496 + // Compass + initPopulate(i, jwin_check_proc, 204, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 75, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 204, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 75, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 75, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // 2752 + // Boss Key + initPopulate(i, jwin_check_proc, 217, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_check_proc, 88, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 139, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 157, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 217, 175, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_check_proc, 88, 103, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + initPopulate(i, jwin_check_proc, 88, 121, 64, 9, vc(0), vc(11), 0, 0, 1, 0, NULL, NULL, NULL); + + // 3008 + // Keys + initPopulate(i, jwin_edit_proc, 230, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + + for(int j=0; j<25; j++) + { + initPopulate(i, jwin_edit_proc, 101, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 135, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 153, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 230, 171, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + } + + initPopulate(i, jwin_edit_proc, 101, 99, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + initPopulate(i, jwin_edit_proc, 101, 117, 29, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL); + + + // 3264 + initPopulate(i, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL); +} + +const char *itype_names[itype_max] = { "Swords", "Boomerangs", "Arrows", "Candles", "Whistles", + "Bait", "Letters", "Potions", "Wands", "Rings", "Wallets", "Amulets", "Shields", "Bows", "Rafts", + "Ladders", "Books", "Magic Keys", "Bracelets", "Flippers", "Boots", "Hookshots", "Lenses", "Hammers", + "Din's Fire", "Farore's Wind", "Nayru's Love", "Bombs", "Super Bombs", "Clocks", "Keys", "Magic Containers", + "Triforce Pieces", "Maps", "Compasses", "Boss Keys", "Quivers", "Level Keys", "Canes of Byrna", "Rupees", "Arrow Ammo", + "Fairies", "Magic", "Hearts", "Heart Containers", "Heart Pieces", "Kill All Enemies", + "Bomb Ammo", "Bomb Bags", "Roc Items", "Hover Boots", "Scroll: Spin Attack", "Scroll: Cross Beams", "Scroll: Quake Hammer", + "Whisp Rings", "Charge Rings", "Scroll: Peril Beam", "Wealth Medals", "Heart Rings", "Magic Rings", "Scroll: Hurricane Spin", "Scroll: Super Quake", + "Stones of Agony", "Stomp Boots", "Whimsical Rings", "Peril Rings", "Non-gameplay Items", + "Custom Itemclass 01", "Custom Itemclass 02", "Custom Itemclass 03", "Custom Itemclass 04", "Custom Itemclass 05", + "Custom Itemclass 06", "Custom Itemclass 07", "Custom Itemclass 08", "Custom Itemclass 09", "Custom Itemclass 10", + "Custom Itemclass 11", "Custom Itemclass 12", "Custom Itemclass 13", "Custom Itemclass 14", "Custom Itemclass 15", + "Custom Itemclass 16", "Custom Itemclass 17", "Custom Itemclass 18", "Custom Itemclass 19", "Custom Itemclass 20", + "Bow and Arrow (Subscreen Only)", "Letter or Potion (Subscreen Only)" + }; + +const char *familylist(int index, int *list_size); + + +item_class_struct biic[itype_max]; +int biic_cnt=-1; + +void build_biic_list() +{ + int start=biic_cnt=0; + std::map fams; + std::set famnames; + + for(int i=start; i::iterator it = famnames.begin(); it != famnames.end(); ++it) + { + biic[biic_cnt].s = new char[(*it).length() + 1]; + strcpy(biic[biic_cnt].s, it->c_str()); + biic[biic_cnt].i = fams[*it]; + ++biic_cnt; + } +} + +void deallocate_biic_list() +{ + for(int i(0); i < 255; i++) //I don't know what this really is. + { + if(biic[i].s) + delete [] biic[i].s; + } +} + +const char *item_class_list(int index, int *list_size) +{ + if(index<0) + { + *list_size = biic_cnt; + return NULL; + } + + return biic[index].s; +} + + +int doInit(zinitdata *local_zinit) +{ + for(int i=0; i >::iterator it = families.find(family); + + if(it == families.end()) + { + families[family] = std::vector(); + } + + families[family].push_back(Family(family, itemsbuf[i].fam_type,i)); + } + + //family map has been populated, now sort + for(std::map >::iterator it = families.begin(); it != families.end(); it++) + { + sort(it->second.begin(), it->second.end()); + } + + init_dlg[0].dp2=lfont; + + if(biic_cnt==-1) + { + build_biic_list(); + } + + //make the map + int listindex=0; + + for(int i=0; i p(&oldselection,&tempdata); + init_dlg[5].dp3 = &p; + + if(families.size() == 0) + { + doFamily(-1, &tempdata); + oldselection = -1; + } + else + { + doFamily(listidx2biic[0],&tempdata); + oldselection = 0; + } + + // items + char bombstring[5]; + char maxbombstring[5]; + char sbombstring[5]; + char maxsbombstring[5]; + char arrowstring[5]; + char maxarrowstring[5]; + sprintf(bombstring, "%d", local_zinit->bombs); + sprintf(maxbombstring, "%d", local_zinit->max_bombs); + sprintf(sbombstring, "%d", local_zinit->super_bombs); + sprintf(maxsbombstring, "%d", local_zinit->max_bombs/(local_zinit->bomb_ratio > 0 ? local_zinit->bomb_ratio : 4)); + sprintf(arrowstring, "%d", local_zinit->arrows); + sprintf(maxarrowstring, "%d", local_zinit->max_arrows); + + init_dlg[109].dp=bombstring; + init_dlg[110].dp=maxbombstring; + init_dlg[115].dp=sbombstring; + init_dlg[116].dp=maxsbombstring; + init_dlg[119].dp=arrowstring; + init_dlg[120].dp=maxarrowstring; + // dmap items + + char key_list[512][4]; + + for(int i=0; i<256; i++) + { + init_dlg[i+631].flags = get_bit(local_zinit->map,i) ? D_SELECTED : 0; + init_dlg[i+887].flags = get_bit(local_zinit->compass,i) ? D_SELECTED : 0; + init_dlg[i+1143].flags = get_bit(local_zinit->boss_key,i) ? D_SELECTED : 0; + sprintf(key_list[i], "%d", local_zinit->level_keys[i]); + init_dlg[i+1399].dp = key_list[i]; + } + + for(int i=256; i<512; i++) + { + init_dlg[i+2240-256].flags = get_bit(local_zinit->map,i) ? D_SELECTED : 0; + init_dlg[i+2496-256].flags = get_bit(local_zinit->compass,i) ? D_SELECTED : 0; + init_dlg[i+2752-256].flags = get_bit(local_zinit->boss_key,i) ? D_SELECTED : 0; + sprintf(key_list[i], "%d", local_zinit->level_keys[i]); + init_dlg[i+3008-256].dp = key_list[i]; + } + + // misc + char tempbuf[5]; + char hcstring[5]; + char hcpstring[5]; + char hcpperstring[5]; + char sheartstring[5]; + char cheartstring[5]; + char keystring[5]; + char rupiestring[5]; + char magicstring[5]; + char maxmagicstring[5]; + char maxrupeestring[8]; + char maxkeystring[8]; + char bombratiostring[5]; + char gravitystring[5]; + char terminalvstring[8]; + char thresholdstring[8]; + + sprintf(tempbuf, "0"); + sprintf(hcstring, "%d", local_zinit->hc); + sprintf(hcpstring, "%d", local_zinit->hcp); + sprintf(hcpperstring, "%d", local_zinit->hcp_per_hc); + sprintf(sheartstring, "%d", local_zinit->start_heart); + sprintf(cheartstring, "%d", local_zinit->cont_heart); + sprintf(keystring, "%d", local_zinit->keys); + sprintf(rupiestring, "%d", local_zinit->rupies); + sprintf(magicstring, "%d", local_zinit->magic); + sprintf(maxmagicstring, "%d", local_zinit->max_magic); + sprintf(bombratiostring, "%d", local_zinit->bomb_ratio); + sprintf(gravitystring, "%.2f", local_zinit->gravity/100.0); + sprintf(terminalvstring, "%.2f", local_zinit->terminalv/100.0); + sprintf(thresholdstring, "%d", local_zinit->jump_link_layer_threshold); + + init_dlg[1662].dp=hcstring; + init_dlg[1663].dp=sheartstring; + init_dlg[1664].dp=cheartstring; + init_dlg[131].dp=keystring; + init_dlg[125].dp=rupiestring; + init_dlg[1667].flags &= ~D_SELECTED; + init_dlg[1667].flags |= get_bit(local_zinit->misc,idM_CONTPERCENT) ? D_SELECTED : 0; + init_dlg[1669].dp=hcpstring; + init_dlg[1671].dp=hcpperstring; + + for(int i=0; i<8; i++) + { + init_dlg[1676+i].flags = get_bit(&local_zinit->triforce,i) ? D_SELECTED : 0; + } + + init_dlg[1684].flags = get_bit(local_zinit->misc,idM_CANSLASH) ? D_SELECTED : 0; + init_dlg[1689].dp=magicstring; + init_dlg[1690].dp=maxmagicstring; + init_dlg[1691].flags = get_bit(local_zinit->misc,idM_DOUBLEMAGIC) ? D_SELECTED : 0; + + sprintf(maxrupeestring, "%d", local_zinit->max_rupees); + sprintf(maxkeystring, "%d", local_zinit->max_keys); + + + init_dlg[132].dp=maxkeystring; + init_dlg[126].dp=maxrupeestring; + init_dlg[1699].dp=bombratiostring; + init_dlg[1703].dp=gravitystring; + init_dlg[1704].dp=terminalvstring; + init_dlg[1705].dp=thresholdstring; + + if(is_large) + { + large_dialog(init_dlg); + init_dlg[0].d1 = 1; + } + + int ret = zc_popup_dialog(init_dlg,1); + + if(ret==2) + { + + //save old selection + if(oldselection != -1) + { + std::map >::iterator it = families.find(biic[listidx2biic[oldselection]].i); + + if(it != families.end()) + { + std::vector &f = it->second; + std::vector::iterator it2 = f.begin(); + + for(int j=7; it2 != f.end() && jitemid] = 0 != (init_dlg[j].flags & D_SELECTED); + } + } + } + + memcpy(local_zinit, &tempdata, sizeof(zinitdata)); + local_zinit->bombs=atoi(bombstring); + local_zinit->max_bombs=atoi(maxbombstring); + local_zinit->super_bombs=atoi(sbombstring); + local_zinit->arrows=atoi(arrowstring); + local_zinit->max_arrows=atoi(maxarrowstring); + + // dmap items + for(int i=0; i<256; i++) + { + set_bit(local_zinit->map,i,init_dlg[i+631].flags & D_SELECTED); + set_bit(local_zinit->compass,i,init_dlg[i+887].flags & D_SELECTED); + set_bit(local_zinit->boss_key,i,init_dlg[i+1143].flags & D_SELECTED); + local_zinit->level_keys[i]=vbound(atoi(key_list[i]),0,255); + } + + for(int i=256; i<512; i++) + { + set_bit(local_zinit->map,i,init_dlg[i+2240-256].flags & D_SELECTED); + set_bit(local_zinit->compass,i,init_dlg[i+2496-256].flags & D_SELECTED); + set_bit(local_zinit->boss_key,i,init_dlg[i+2752-256].flags & D_SELECTED); + local_zinit->level_keys[i]=vbound(atoi(key_list[i]),0,255); + } + + // misc + local_zinit->start_dmap = init_dlg[1656].d1; + local_zinit->hc = zc_max(atoi(hcstring),0); + local_zinit->start_heart = vbound(atoi(sheartstring),0,local_zinit->hc); + local_zinit->hcp_per_hc = vbound(atoi(hcpperstring),0,255); + local_zinit->hcp = vbound(atoi(hcpstring),0,local_zinit->hcp_per_hc-1); + set_bit(local_zinit->misc,idM_CONTPERCENT,((init_dlg[1667].flags & D_SELECTED) != 0 ? 1 : 0)); + + if(get_bit(local_zinit->misc,idM_CONTPERCENT)) + { + local_zinit->cont_heart = zc_min(atoi(cheartstring),100); + } + else + { + local_zinit->cont_heart = zc_min(atoi(cheartstring),local_zinit->hc); + } + + local_zinit->keys = atoi(keystring); + local_zinit->rupies = vbound(atoi(rupiestring), 0, 0xFFFF); + + // triforce + for(int i=0; i<8; i++) + { + set_bit(&local_zinit->triforce,i,init_dlg[1676+i].flags & D_SELECTED); + } + + + set_bit(local_zinit->misc,idM_CANSLASH,init_dlg[1684].flags & D_SELECTED); + local_zinit->max_magic = atoi(maxmagicstring); + local_zinit->magic = zc_min(atoi(magicstring),local_zinit->max_magic); + set_bit(local_zinit->misc,idM_DOUBLEMAGIC,init_dlg[1691].flags & D_SELECTED); + local_zinit->max_rupees = vbound(atoi(maxrupeestring), 0, 0xFFFF); + local_zinit->max_keys = vbound(atoi(maxkeystring), 0, 0xFFFF); + local_zinit->bomb_ratio = vbound(atoi(bombratiostring),0,255); + local_zinit->gravity = vbound(int(strtod(gravitystring, NULL)*100),1,255); + local_zinit->terminalv = vbound(int(strtod(terminalvstring, NULL)*100), 1, 9999); + local_zinit->jump_link_layer_threshold = vbound(atoi(thresholdstring),0,255); + onInitOK(); + } + + //for(map::iterator it = famnames.begin(); it != famnames.end(); it++) + // delete[] it->second; + //famnames.clear(); + families.clear(); + return D_O_K; +} + + +const char *familylist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)listidx2biic.size(); + return NULL; + } + + return biic[listidx2biic[index]].s; +} + +void doFamily(int biicindx, zinitdata *local_zinit) +{ + if(biicindx == -1 || families.find(biic[biicindx].i) == families.end()) + { + for(int i=7; i &f = families[biic[biicindx].i]; + std::vector::iterator it = f.begin(); + int i; + + for(i=7; i < endEquipField && it != f.end(); i++, it++) + { + init_dlg[i].proc = jwin_checkfont_proc; + init_dlg[i].dp2 = is_large? lfont_l : pfont; + init_dlg[i].dp = (void *)item_string[it->itemid]; + init_dlg[i].flags = local_zinit->items[it->itemid] ? D_SELECTED : 0; + } + + for(; i *p = (std::pair *)(d->dp3); + int *oldselection = p->first; + static int index=-1; + index = d->d1; + + if(*oldselection != d->d1 && d->d1 != -1) + { + //save old selection + if(*oldselection != -1) + { + std::map >::iterator it = families.find(biic[listidx2biic[*oldselection]].i); + + if(it != families.end()) + { + std::vector &f = it->second; + std::vector::iterator it2 = f.begin(); + + for(int j=7; it2 != f.end() && jsecond->items[it2->itemid] = 0 != (init_dlg[j].flags & D_SELECTED); + } + } + } + + *(p->first) = d->d1; + doFamily(listidx2biic[d->d1], p->second); + acquire_screen(); + scare_mouse(); + init_dlg[4].proc(MSG_DRAW, &init_dlg[4], 0); + // broadcast_dialog_message(MSG_DRAW, 0); + unscare_mouse(); + release_screen(); + } + + return rval; +} + +// NOTE: This method has been severely hacked to fix an annoying problem at game start: +// items (ie the Small Wallet) which modify max counter values need to be processed after +// the values for those counters specified in init data, as the author expects these items +// to modify the max counter. BUT the counter value should NOT be updated, ie, starting with +// the bomb item does not give 8 free bombs at quest start. +// I don't like this solution one bit, but can't come up with anything better -DD + +void resetItems(gamedata *game2, zinitdata *zinit2, bool lvlitems) +{ + game2->set_maxlife(zinit2->hc*HP_PER_HEART); + game2->set_maxbombs(zinit2->max_bombs); + game2->set_maxcounter(zinit2->max_bombs/zc_max(1,zinit2->bomb_ratio), 6); + game2->set_maxmagic(zinit2->max_magic); + game2->set_maxarrows(zinit2->max_arrows); + game2->set_maxcounter(zinit2->max_rupees, 1); + game2->set_maxcounter(zinit2->max_keys, 5); + + //set up the items + for(int i=0; iitems[i] && (itemsbuf[i].flags & ITEM_GAMEDATA)) + { + if(!game2->get_item(i)) + getitem(i,true); + } + else + game2->set_item_no_flush(i,false); + + game2->items_off[i] = 0; + + // Fix them DMap items + // Since resetItems() gets called before AND after init_dmap()... + if(get_currdmap() > -1) + game2->items_off[i] |= DMaps[get_currdmap()].disableditems[i]; + } + + flushItemCache(); + + //Then set up the counters + game2->set_bombs(zinit2->bombs); + + if(zinit2->bombs > 0 && zinit2->max_bombs > 0) game2->set_item(iBombs, true); + + game2->set_keys(zinit2->keys); + game2->set_sbombs(zinit2->super_bombs); + + if(zinit2->super_bombs > 0 && (zinit2->max_bombs/zc_max(1,zinit2->bomb_ratio)) > 0) game2->set_item(iSBomb, true); + + game2->set_HCpieces(zinit2->hcp); + game2->set_rupies(zinit2->rupies); + game2->set_hcp_per_hc(zinit2->hcp_per_hc); + game2->set_cont_hearts(zinit2->cont_heart); + game2->set_cont_percent(get_bit(zinit2->misc, idM_CONTPERCENT) != 0); + + for(int i=0; ilvlitems[i]=0; + else + game2->lvlitems[i]&=~(liMAP|liCOMPASS|liBOSSKEY| (i>0 && i<=8 ? liTRIFORCE : 0)); + + game2->lvlitems[i]|=get_bit(zinit2->map,i)?liMAP:0; + game2->lvlitems[i]|=get_bit(zinit2->compass,i)?liCOMPASS:0; + game2->lvlitems[i]|=get_bit(zinit2->boss_key,i)?liBOSSKEY:0; + game2->lvlkeys[i]=zinit2->level_keys[i]; + } + + for(int i=0; i<8; i++) + { + game2->lvlitems[i+1]|=get_bit(&zinit2->triforce,i)?liTRIFORCE:0; + } + + game2->set_magic(zc_min(zinit2->magic,zinit2->max_magic)); + game2->set_magicdrainrate(get_bit(zinit2->misc,idM_DOUBLEMAGIC)?1:2); + game2->set_canslash(get_bit(zinit2->misc,idM_CANSLASH)?1:0); + + game2->set_arrows(zinit2->arrows); + + //flush the cache again (in case bombs became illegal to use by setting bombs to 0) + flushItemCache(); +} + diff --git a/src/init.h b/src/init.h new file mode 100644 index 0000000000..c7cd380c94 --- /dev/null +++ b/src/init.h @@ -0,0 +1,41 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- +#ifndef _INIT_H_ +#define _INIT_H_ + +#include "tab_ctl.h" +#include "zc_alleg.h" + +#define MAXINITTABS 5 + +typedef struct item_class_struct +{ + char *s; + int i; +} item_class_struct; + +extern item_class_struct biic[itype_max]; +extern const char *itype_names[itype_max]; + +extern int biic_cnt; +void build_biic_list(); +void deallocate_biic_list(); +const char *item_class_list(int index, int *list_size); + +int jwin_initlist_proc(int msg,DIALOG *d,int c); +int d_line_proc(int msg, DIALOG *d, int c); +int d_maxbombsedit_proc(int msg,DIALOG *d,int c); +int d_bombratio_proc(int msg,DIALOG *d,int c); +extern DIALOG init_dlg[]; +extern TABPANEL init_tabs[]; +int doInit(zinitdata *zinit); +void resetItems(gamedata *data, zinitdata *zinit, bool lvlitems); +#endif + diff --git a/src/item/clock.cpp b/src/item/clock.cpp new file mode 100644 index 0000000000..613184b73e --- /dev/null +++ b/src/item/clock.cpp @@ -0,0 +1,35 @@ +#include +#include "clock.h" +#include + +extern bool cheat_superman, watch; + +ClockEffect::ClockEffect(LinkClass& l, int time): + ItemEffect(ie_clock), + link(l), + timer((time>0) ? time : -1) +{ +} + +ClockEffect::~ClockEffect() +{ + if(!cheat_superman) + link.setInvincible(false); + watch=false; +} + +void ClockEffect::activate() +{ + watch=true; + link.setInvincible(true); +} + +void ClockEffect::update() +{ + if(timer<0) + return; + + timer--; + if(timer==0) + delete this; +} diff --git a/src/item/clock.h b/src/item/clock.h new file mode 100644 index 0000000000..5d566f577e --- /dev/null +++ b/src/item/clock.h @@ -0,0 +1,20 @@ +#ifndef _ZC_ITEM_WATCH_H_ +#define _ZC_ITEM_WATCH_H_ + +#include "itemEffect.h" +class LinkClass; + +class ClockEffect: public ItemEffect +{ +public: + ClockEffect(LinkClass& link, int time); + ~ClockEffect(); + void activate(); + void update(); + +private: + LinkClass& link; + int timer; +}; + +#endif diff --git a/src/item/dinsFire.cpp b/src/item/dinsFire.cpp new file mode 100644 index 0000000000..ee1b5d174c --- /dev/null +++ b/src/item/dinsFire.cpp @@ -0,0 +1,142 @@ +#include //always first +#include "dinsFire.h" + +#include +#include +#include +#include +#include + +extern LinkClass Link; + +static void dfRocketSparkle(const weapon& wpn) +{ + if((frame&3)!=0) + return; + + int type; + if(wpn.type==pDINSFIREROCKET) + type=pDINSFIREROCKETTRAIL; + else + type=pDINSFIREROCKETTRAILRETURN; + + Lwpns.add(new weapon( + fix((wpn.getX()-3)+(rand()%7)), + fix((wpn.getY()-3)+(rand()%7)), + wpn.getZ(), wPhantom, type, 0, 0, wpn.parentitem, -1)); +} + +DinsFireAction::DinsFireAction(int itemID, LinkClass& l): + phase(0), + timer(0), + link(l), + rocket() +{ + magicitem=itemID; +} + +DinsFireAction::~DinsFireAction() +{ + rocket.del(); + magicitem=-1; +} + +void DinsFireAction::update() +{ + if(timer>0) + { + timer--; + return; + } + + switch(phase) + { + case 0: + rocket.reset(new weapon(LinkX(),LinkY(),LinkZ(),wPhantom,pDINSFIREROCKET,0,up, magicitem, link.getUID())); + rocket->LOADGFX(itemsbuf[magicitem].wpn); + rocket->step=4; + rocket->setSparkleFunc(dfRocketSparkle); + Lwpns.add(rocket.get()); + + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1ROCKETUP, pan(link.getX())); + + linktile(&link.tile, &link.flip, &link.extend, ls_landhold2, link.getDir(), zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + link.tile+=item_tile_mod(); + + phase=1; + timer=64; + break; + + case 1: + rocket->type=pDINSFIREROCKETRETURN; + rocket->y=-32; + rocket->dir=down; + rocket->LOADGFX(itemsbuf[magicitem].wpn2); + rocket->step=4; + + + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1ROCKETDOWN, pan(link.getX())); + + linktile(&link.tile, &link.flip, &link.extend, ls_landhold2, link.getDir(), zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + link.tile+=item_tile_mod(); + + phase=3; + break; + + case 3: + if(rocket->getY()flags7&fSIDEVIEW) ? (flamecounterstep=(itemsbuf[magicitem].misc2/100.0); + flame->angular=true; + flame->angle=(flamecounter*PI/(flamemax/2.0)); + Lwpns.add(flame); + } + + phase=5; + timer=98; + break; + } + + case 5: + // Just waiting for the timer... + phase=6; + break; + } +} + +bool DinsFireAction::isFinished() const +{ + return phase==6; +} + +void DinsFireAction::abort() +{ + rocket.del(); +} diff --git a/src/item/dinsFire.h b/src/item/dinsFire.h new file mode 100644 index 0000000000..817c03cf5a --- /dev/null +++ b/src/item/dinsFire.h @@ -0,0 +1,26 @@ +#ifndef _ZC_ITEM_DINSFIRE_H_ +#define _ZC_ITEM_DINSFIRE_H_ + +#include "itemAction.h" + +#include "../entityPtr.h" +class LinkClass; +class weapon; + +class DinsFireAction: public ItemAction +{ +public: + DinsFireAction(int itemID, LinkClass& link); + ~DinsFireAction(); + void update(); + bool isFinished() const; + void abort(); + +private: + int phase; + int timer; + LinkClass& link; + EntityPtr rocket; +}; + +#endif diff --git a/src/item/faroresWind.cpp b/src/item/faroresWind.cpp new file mode 100644 index 0000000000..823fc6eb65 --- /dev/null +++ b/src/item/faroresWind.cpp @@ -0,0 +1,150 @@ +#include //always first +#include "faroresWind.h" + +#include +#include +#include +#include +#include + +extern sprite_list particles; + +FaroresWindAction::FaroresWindAction(int itemID, LinkClass& l): + phase(0), + timer(0), + link(l), + baseX(l.getX()), + baseY(l.getY()) +{ + magicitem=itemID; +} + +FaroresWindAction::~FaroresWindAction() +{ + magicitem=-1; +} + +void FaroresWindAction::update() +{ + if(timer>0) + { + timer--; + if(phase!=1) // Whatever + return; + } + + int ltile=0; + int lflip=0; + + switch(phase) + { + //if(timer==0) + case 0: + { + linktile(<ile, &lflip, ls_stab, down, zinit.linkanimationstyle); + unpack_tile(newtilebuf, ltile, lflip, true); + memcpy(linkTile, unpackbuf, 256); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + ltile+=item_tile_mod(); + + linktile(&link.tile, &link.flip, &link.extend, ls_pound, down, zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + { + link.tile+=item_tile_mod(); + } + } + phase=1; + timer=64; + // Fall though + + case 1: + link.setX(fix(baseX+((rand()%3)-1))); + link.setY(fix(baseY+((rand()%3)-1))); + if(timer==0) + phase=2; + break; + + case 2: + link.setX(fix(baseX)); + link.setY(fix(baseY)); + linktile(&link.tile, &link.flip, &link.extend, ls_stab, down, zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + link.tile+=item_tile_mod(); + + phase=3; + timer=32; + break; + + case 3: + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(itemsbuf[magicitem].usesound,pan(int(link.getX()))); + + link.setDontDraw(true); + + for(int i=0; i<16; ++i) + { + for(int j=0; j<16; ++j) + { + if(linkTile[i*16+j]) + { + if(itemsbuf[magicitem].misc1==1) // Twilight + { + particles.add(new pTwilight(link.getX()+j, link.getY()-link.getZ()+i, 5, 0, 0, (rand()%8)+i*4)); + int k=particles.Count()-1; + particle *p = (particle*)(particles.spr(k)); + p->step=3; + } + else if(itemsbuf[magicitem].misc1==2) // Sands of Hours + { + particles.add(new pTwilight(link.getX()+j, link.getY()-link.getZ()+i, 5, 1, 2, (rand()%16)+i*2)); + int k=particles.Count()-1; + particle *p = (particle*)(particles.spr(k)); + p->step=4; + + if(rand()%10 < 2) + { + p->color=1; + p->cset=0; + } + } + else + { + particles.add(new pFaroresWindDust(link.getX()+j, link.getY()-link.getZ()+i, 5, 6, linkTile[i*16+j], rand()%96)); + + int k=particles.Count()-1; + particle *p = (particle*)(particles.spr(k)); + p->angular=true; + p->angle=rand(); + p->step=(((double)j)/8); + p->yofs=link.getYOfs(); + } + } + } + } + phase=4; + timer=130; + break; + + case 4: + restart_level(); + magicitem=-1; + link.setDontDraw(false); + link.currentItemAction=this; // This won't do... + phase=5; + + break; + } +} + +bool FaroresWindAction::isFinished() const +{ + return phase==5; +} + +void FaroresWindAction::abort() +{ + link.setDontDraw(false); +} diff --git a/src/item/faroresWind.h b/src/item/faroresWind.h new file mode 100644 index 0000000000..d53faafc41 --- /dev/null +++ b/src/item/faroresWind.h @@ -0,0 +1,26 @@ +#ifndef _ZC_ITEM_FARORESWIND_H_ +#define _ZC_ITEM_FARORESWIND_H_ + +#include "itemAction.h" + +class LinkClass; + +class FaroresWindAction: public ItemAction +{ +public: + FaroresWindAction(int itemID, LinkClass& link); + ~FaroresWindAction(); + void update(); + bool isFinished() const; + void abort(); + +private: + int phase; + int timer; + LinkClass& link; + int baseX, baseY; + unsigned char linkTile[256]; +}; + +#endif + diff --git a/src/item/hookshot.cpp b/src/item/hookshot.cpp new file mode 100644 index 0000000000..7c16e50673 --- /dev/null +++ b/src/item/hookshot.cpp @@ -0,0 +1,355 @@ +#include +#include "hookshot.h" +#include +#include + +HookshotAction::HookshotAction(int itemID, LinkClass& l): + link(l) +{ + int hookitem = itemsbuf[itemID].fam_type; + int hookpower = itemsbuf[itemID].power; + + if(Lwpns.Count()>=SLMAX) + Lwpns.del(0); + + if(Lwpns.Count()>=SLMAX-1) + Lwpns.del(0); + + int dir=link.getDir(); + fix wx=link.getX(); + fix wy=link.getY(); + fix wz=link.getZ(); + + switch(dir) + { + case up: + wy-=16; + break; + + case down: + wy+=16; + break; + + case left: + wx-=16; + break; + + case right: + wx+=16; + break; + } + + if(dir==up) + { + hookshot_used=true; + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wHSHandle,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + Lwpns.add(new weapon((fix)wx,(fix)wy-4,(fix)wz,wHookshot,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + hs_startx=wx; + hs_starty=wy-4; + } + + if(dir==down) + { + int offset=get_bit(quest_rules,qr_HOOKSHOTDOWNBUG)?4:0; + hookshot_used=true; + Lwpns.add(new weapon((fix)wx,(fix)wy+offset,(fix)wz,wHSHandle,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + Lwpns.add(new weapon((fix)wx,(fix)wy+offset,(fix)wz,wHookshot,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + hs_startx=wx; + hs_starty=wy; + } + + if(dir==left) + { + hookshot_used=true; + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wHSHandle,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + Lwpns.add(new weapon((fix)(wx-4),(fix)wy,(fix)wz,wHookshot,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + hs_startx=wx-4; + hs_starty=wy; + } + + if(dir==right) + { + hookshot_used=true; + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wHSHandle,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + Lwpns.add(new weapon((fix)(wx+4),(fix)wy,(fix)wz,wHookshot,hookitem, + hookpower*DAMAGE_MULTIPLIER,dir,itemID,link.getUID())); + hs_startx=wx+4; + hs_starty=wy; + } + + hookshot_frozen=true; +} + +bool HookshotAction::canUse(const LinkClass& link) +{ + int dir=link.getDir(); + fix x=link.getX(); + fix y=link.getY(); + + for(int i=-1; i<2; i++) + { + if(dir==up) + { + if((combobuf[MAPCOMBO2(i,x,y-7)].type==cHSGRAB)|| + (_walkflag(x+2,y+4,1) && !ishookshottable(int(x),int(y+4)))) + return false; + } + else if(dir==down) + { + if((combobuf[MAPCOMBO2(i,x+12,y+23)].type==cHSGRAB)) + return false; + } + else if(dir==left) + { + if((combobuf[MAPCOMBO2(i,x-7,y+12)].type==cHSGRAB)) + return false; + } + else if(dir==right) + { + if((combobuf[MAPCOMBO2(i,x+23,y+12)].type==cHSGRAB)) + return false; + } + } + + return true; +} + +HookshotAction::~HookshotAction() +{ + link.reset_hookshot(); +} + +void HookshotAction::update() +{ + oldUpdate1(); + oldUpdate2(); +} + +void HookshotAction::oldUpdate1() +{ + int hs_x, hs_y, hs_z,hs_dx, hs_dy; + bool check_hs=false; + int dist_bx, dist_by, hs_w; + chainlinks.animate(); + + //find out where the head is and make it + //easy to reference + if(Lwpns.idFirst(wHookshot)>-1) + { + check_hs=true; + } + + if(check_hs) + { + int parentitem = ((weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot)))->parentitem; + hs_x=Lwpns.spr(Lwpns.idFirst(wHookshot))->x; + hs_y=Lwpns.spr(Lwpns.idFirst(wHookshot))->y; + hs_z=Lwpns.spr(Lwpns.idFirst(wHookshot))->z; + hs_dx=hs_x-hs_startx; + hs_dy=hs_y-hs_starty; + + //extending + if(((weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot)))->misc==0) + { + int maxchainlinks=itemsbuf[parentitem].misc2; + + if(chainlinks.Count()=hs_xdist+8) + { + hs_xdist=abs(hs_x-hs_startx); + chainlinks.add(new weapon((fix)hs_x, (fix)hs_y, (fix)hs_z,wHSChain, 0,0,link.getDir(), parentitem,link.getUID())); + } + else if(abs(hs_dy)>=hs_ydist+8) + { + hs_ydist=abs(hs_y-hs_starty); + chainlinks.add(new weapon((fix)hs_x, (fix)hs_y, (fix)hs_z,wHSChain, 0,0,link.getDir(), parentitem,link.getUID())); + } + } //stretching chain + else + { + dist_bx=(abs(hs_dx)-(8*chainlinks.Count()))/(chainlinks.Count()+1); + dist_by=(abs(hs_dy)-(8*chainlinks.Count()))/(chainlinks.Count()+1); + hs_w=8; + + if(hs_dx<0) + { + dist_bx=0-dist_bx; + hs_w=-8; + } + + if(hs_dy<0) + { + dist_by=0-dist_by; + hs_w=-8; + } + + for(int counter=0; counterdown) //chain is moving horizontally + { + chainlinks.spr(counter)->x=hs_startx+hs_w+dist_bx+(counter*(hs_w+dist_bx)); + } + else + { + chainlinks.spr(counter)->y=hs_starty+hs_w+dist_by+(counter*(hs_w+dist_by)); + } + } + } + } //retracting + else if(((weapon*)Lwpns.spr(Lwpns.idFirst(wHookshot)))->misc==1) + { + dist_bx=(abs(hs_dx)-(8*chainlinks.Count()))/(chainlinks.Count()+1); + dist_by=(abs(hs_dy)-(8*chainlinks.Count()))/(chainlinks.Count()+1); + hs_w=8; + + if(hs_dx<0) + { + dist_bx=0-dist_bx; + hs_w=-8; + } + + if(hs_dy<0) + { + dist_by=0-dist_by; + hs_w=-8; + } + + /* With ZScript modification, chains can conceivably move diagonally.*/ + //if (Link.getDir()>down) //chain is moving horizontally + { + if(abs(hs_dx)-(8*chainlinks.Count())>0) //chain is stretched + { + for(int counter=0; counterx=hs_startx+hs_w+dist_bx+(counter*(hs_w+dist_bx)); + } + } + else + { + if(abs(hs_x-hs_startx)<=hs_xdist-8) + { + hs_xdist=abs(hs_x-hs_startx); + + if(pull_link==false) + { + chainlinks.del(chainlinks.idLast(wHSChain)); + } + else + { + chainlinks.del(chainlinks.idFirst(wHSChain)); + } + } + } + } //chain is moving vertically + //else + { + if(abs(hs_dy)-(8*chainlinks.Count())>0) //chain is stretched + { + for(int counter=0; countery=hs_starty+hs_w+dist_by+(counter*(hs_w+dist_by)); + } + else + { + if(abs(hs_y-hs_starty)<=hs_ydist-8) + { + hs_ydist=abs(hs_y-hs_starty); + + if(pull_link==false) + chainlinks.del(chainlinks.idLast(wHSChain)); + else + chainlinks.del(chainlinks.idFirst(wHSChain)); + } + } + } + } + } +} + +void HookshotAction::oldUpdate2() +{ + fix x=link.getX(); + fix y=link.getY(); + + if(hookshot_frozen) + { + if(hookshot_used) + { + link.Freeze(); + + if(pull_link) + { + sprite *t; + int i; + + for(i=0; iid!=wHSHandle); i++) + { + /* do nothing */ + } + + t = Lwpns.spr(i); + + for(i=0; iid==wHookshot) + { + int dx=0, dy=0; + if((s->y)>y) + dy=4; + else if((s->y)x)>x) + dx=4; + else if((s->x)x+=dx; + t->y+=dy; + } + } + } + } + } + else + { + Lwpns.del(Lwpns.idFirst(wHSHandle)); + link.reset_hookshot(); + } + + if(hs_fix) + { + if(link.getDir()==up || link.getDir()==down) + y=int(y+7)&0xF0; + else + x=int(x+7)&0xF0; + + hs_fix=false; + } + } +} + +bool HookshotAction::isFinished() const +{ + return Lwpns.idFirst(wHookshot)<0; +} + +void HookshotAction::abort() +{ + link.reset_hookshot(); +} + diff --git a/src/item/hookshot.h b/src/item/hookshot.h new file mode 100644 index 0000000000..5c0bfe41cb --- /dev/null +++ b/src/item/hookshot.h @@ -0,0 +1,20 @@ +#include "itemAction.h" + +class LinkClass; + +class HookshotAction: public ItemAction +{ +public: + HookshotAction(int itemID, LinkClass& link); + ~HookshotAction(); + static bool canUse(const LinkClass& link); + void update(); + bool isFinished() const; + void abort(); + +private: + LinkClass& link; + + void oldUpdate1(); // Formerly update_hookshot() + void oldUpdate2(); // Formerly part of LinkClass::animate() +}; diff --git a/src/item/itemAction.h b/src/item/itemAction.h new file mode 100644 index 0000000000..67874eaf7e --- /dev/null +++ b/src/item/itemAction.h @@ -0,0 +1,19 @@ +#ifndef _ZC_ITEM_ITEMACTION_H_ +#define _ZC_ITEM_ITEMACTION_H_ + +/** This is the base class for things that happen when an item is used, + * such as the hookshot being fired or a spell being cast. + * This does not include any effects that occur when Link is able + * to move freely again. For instance, this would cover the casting + * sequence of Nayru's Love, but not the spell's effect afterward. + */ +class ItemAction +{ +public: + virtual ~ItemAction() {} + virtual void update()=0; + virtual bool isFinished() const=0; + virtual void abort() {} +}; + +#endif diff --git a/src/item/itemEffect.cpp b/src/item/itemEffect.cpp new file mode 100644 index 0000000000..e81f2d8792 --- /dev/null +++ b/src/item/itemEffect.cpp @@ -0,0 +1,124 @@ +#include "itemEffect.h" +#include +#include +#include +#include + +extern SFXManager sfxMgr; + + +ItemEffect::ItemEffect(itemEffectType t): + type(t), + list(0) +{ +} + +ItemEffect::~ItemEffect() +{ + if(list) + list->remove(this, false); +} + +// ----------------------------------------------------------------------------- + +ItemEffectList::ItemEffectList(): + numEffects(0) +{ +} + +void ItemEffectList::add(ItemEffect* newEffect) +{ + // Remove any effects of the same type before adding the new one. + // Will we ever not want to do this? + remove(newEffect->getType(), true); + + effects[numEffects]=newEffect; + numEffects++; + newEffect->setList(this); + newEffect->activate(); +} + +void ItemEffectList::update() +{ + for(int i=0; iupdate(); +} + +void ItemEffectList::remove(ItemEffect* effect, bool del) +{ + bool found=false; + for(int i=0; isetList(0); // So it won't call remove() recursively + if(del) + delete effects[i]; + found=true; + numEffects--; + effects[i]=effects[i+1]; + } + } + + ZCASSERT(found); +} + +void ItemEffectList::remove(itemEffectType type, bool del) +{ + bool found=false; + for(int i=0; igetType()==type) + { + effects[i]->setList(0); + if(del) + delete effects[i]; + found=true; + numEffects--; + effects[i]=effects[i+1]; + } + } +} + +void ItemEffectList::clear() +{ + for(int i=0; isetList(0); + delete effects[i]; + } + numEffects=0; +} + +// ----------------------------------------------------------------------------- + +// This should all go in a proper factory class, but it can wait +#include "clock.h" +#include "nayrusLove.h" +#include +extern LinkClass Link; + +ItemEffect* getItemEffect(int itemID) +{ + const itemdata& data=itemsbuf[itemID]; + switch(data.family) + { + case itype_clock: + return new ClockEffect(Link, data.misc1); + + case itype_nayruslove: + if(get_bit(quest_rules,qr_MORESOUNDS)) + { + return new NayrusLoveEffect(Link, data.misc1, + sfxMgr.getSFX(data.usesound), sfxMgr.getSFX(data.usesound+1)); + } + else + return new NayrusLoveEffect(Link, data.misc1, SFX(0), SFX(0)); + } + + return 0; +} diff --git a/src/item/itemEffect.h b/src/item/itemEffect.h new file mode 100644 index 0000000000..b73835b539 --- /dev/null +++ b/src/item/itemEffect.h @@ -0,0 +1,46 @@ +#ifndef _ZC_ITEM_ITEMEFFECT_H_ +#define _ZC_ITEM_ITEMEFFECT_H_ + +class ItemEffectList; + +enum itemEffectType { ie_nayrusLove, ie_clock }; + +/** This is the base class for effects that persist independently after + * an item or weapon has been used. + */ +class ItemEffect +{ +public: + ItemEffect(itemEffectType type); + virtual ~ItemEffect(); + virtual void activate()=0; + virtual void update()=0; + inline void setList(ItemEffectList* l) { list=l; } + inline itemEffectType getType() const { return type; } + +private: + itemEffectType type; + ItemEffectList* list; +}; + +/// A set of item effects. +class ItemEffectList +{ +public: + ItemEffectList(); + void add(ItemEffect* newEffect); + void remove(ItemEffect* effect, bool del); + void remove(itemEffectType type, bool del); + void clear(); + void update(); + +private: + ItemEffect* effects[256]; + int numEffects; +}; + +/// Return the ItemEffect the given item should create. +// This will be replaced sooner or later. +ItemEffect* getItemEffect(int itemID); + +#endif diff --git a/src/item/nayrusLove.cpp b/src/item/nayrusLove.cpp new file mode 100644 index 0000000000..981935edd2 --- /dev/null +++ b/src/item/nayrusLove.cpp @@ -0,0 +1,216 @@ +#include //always first +#include "nayrusLove.h" +#include +#include +#include +#include +#include +#include + +extern sprite_list decorations; + +static void nlRocketSparkle(const weapon& wpn) +{ + if((frame&3)!=0) + return; + + int type; + switch(wpn.type) + { + case pNAYRUSLOVEROCKET1: + type=pNAYRUSLOVEROCKETTRAIL1; + break; + + case pNAYRUSLOVEROCKET2: + type=pNAYRUSLOVEROCKETTRAIL2; + break; + + case pNAYRUSLOVEROCKETRETURN1: + type=pNAYRUSLOVEROCKETTRAILRETURN1; + break; + + case pNAYRUSLOVEROCKETRETURN2: + type=pNAYRUSLOVEROCKETTRAILRETURN2; + break; + } + + Lwpns.add(new weapon( + fix((wpn.getX()-3)+(rand()%7)), + fix((wpn.getY()-3)+(rand()%7)), + wpn.getZ(), wPhantom, type, 0, 0, wpn.parentitem, -1)); +} + +NayrusLoveAction::NayrusLoveAction(int itemID, LinkClass& l): + phase(0), + timer(0), + link(l) +{ + magicitem=itemID; +} + +NayrusLoveAction::~NayrusLoveAction() +{ + rocket1.del(); + rocket2.del(); + magicitem=-1; +} + +void NayrusLoveAction::update() +{ + if(timer>0) + { + timer--; + return; + } + + // See also link.cpp, LinkClass::checkhit(). + switch(phase) + { + case 0: + rocket1.reset(new weapon(link.getX(),link.getY(),(fix)0,wPhantom,pNAYRUSLOVEROCKET1,0,left, magicitem, link.getUID())); + rocket1->LOADGFX(itemsbuf[magicitem].wpn); + rocket1->step=4; + rocket1->setSparkleFunc(nlRocketSparkle); + Lwpns.add(rocket1.get()); + + rocket2.reset(new weapon(link.getX(),link.getY(),(fix)0,wPhantom,pNAYRUSLOVEROCKET2,0,right, magicitem, link.getUID())); + rocket2->LOADGFX(itemsbuf[magicitem].wpn6); + rocket2->step=4; + rocket2->setSparkleFunc(nlRocketSparkle); + Lwpns.add(rocket2.get()); + + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1ROCKETUP, pan(link.getX())); + + linktile(&link.tile, &link.flip, &link.extend, ls_cast, link.getDir(), zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + link.tile+=item_tile_mod(); + + phase=1; + timer=64; + break; + + case 1: + rocket1->dir=right; + rocket1->type=pNAYRUSLOVEROCKETRETURN1; + rocket1->LOADGFX(itemsbuf[magicitem].wpn2); + + rocket2->dir=left; + rocket2->type=pNAYRUSLOVEROCKETRETURN2; + rocket2->LOADGFX(itemsbuf[magicitem].wpn7); + + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1ROCKETDOWN, pan(link.getX())); + + linktile(&link.tile, &link.flip, &link.extend, ls_cast, link.getDir(), zinit.linkanimationstyle); + + if(get_bit(quest_rules,qr_EXPANDEDLTM)) + link.tile+=item_tile_mod(); + + phase=3; + break; + + case 3: + if(rocket1->getX()setX(link.getX()); + shieldFront->setY(link.getY()); + shieldBack->setX(link.getX()); + shieldBack->setY(link.getY()); +} + +void NayrusLoveEffect::createShield() +{ + if(!shieldFront) + { + shieldFront.reset(new dNayrusLoveShield(link.getX(), link.getY(), timer)); + shieldFront->misc=0; // I may have front and back mixed up... + decorations.add(shieldFront.get()); + } + if(!shieldBack) + { + shieldBack.reset(new dNayrusLoveShield(link.getX(), link.getY(), timer)); + shieldBack->misc=1; + decorations.add(shieldBack.get()); + } +} diff --git a/src/item/nayrusLove.h b/src/item/nayrusLove.h new file mode 100644 index 0000000000..c5a6f50123 --- /dev/null +++ b/src/item/nayrusLove.h @@ -0,0 +1,47 @@ +#ifndef _ZC_ITEM_NAYRUSLOVE_H_ +#define _ZC_ITEM_NAYRUSLOVE_H_ + +#include "itemAction.h" +#include "itemEffect.h" +#include +#include +class dNayrusLoveShield; +class LinkClass; +class weapon; + +class NayrusLoveAction: public ItemAction +{ +public: + NayrusLoveAction(int itemID, LinkClass& link); + ~NayrusLoveAction(); + void update(); + bool isFinished() const; + void abort(); + +private: + int phase; + int timer; + LinkClass& link; + EntityPtr rocket1; + EntityPtr rocket2; +}; + +class NayrusLoveEffect: public ItemEffect +{ +public: + NayrusLoveEffect(LinkClass& link, int time, const SFX& normal, + const SFX& fading); + ~NayrusLoveEffect(); + void activate(); + void update(); + +private: + LinkClass& link; + int timer; + EntityPtr shieldFront, shieldBack; + SFX normalSFX, fadingSFX; + + void createShield(); +}; + +#endif diff --git a/src/items.cpp b/src/items.cpp new file mode 100644 index 0000000000..bc9f623aae --- /dev/null +++ b/src/items.cpp @@ -0,0 +1,522 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +/**********************************/ +/********** Item Class **********/ +/**********************************/ + +#include "precompiled.h" //always first + +#include "items.h" +#include "maps.h" +#include "zelda.h" +#include "zdefs.h" +#include "mem_debug.h" +#include "sound.h" +#include "angelscript/aszc.h" + +#include + +char *item_string[ITEMCNT]; + +extern zinitdata zinit; + +int fairy_cnt=0; + +item::~item() +{ + if(itemsbuf[id].family==itype_fairy && itemsbuf[id].misc3>0 && misc>0) + killfairy(misc); +} + +void item::setPickupFlags(int newPickup) +{ + pickup=newPickup; + + if(pickup&ipBIGRANGE) + { + hxofs=-8; + hxsz=17; + hyofs=-4; + hysz=20; + } + else if(pickup&ipBIGTRI) + { + hxofs=-8; + hxsz=28; + hyofs=-4; + hysz=20; + } + else + { + hxsz=1; + hyofs=4; + hysz=12; + } +} + +bool item::animate(int) +{ + if(!screenIsScrolling()) // Because subscreen items are items, too. :p + { + if(is_side_view()) + { + if(can_drop(x,y) && !(pickup & ipDUMMY) && !(pickup & ipCHECK)) + { + y+=fall/100; + + if((fall/100)==0 && fall>0) + fall*=(fall>0 ? 2 : 0.5); // That oughta do something about the floatiness. + + if(fall <= (int)zinit.terminalv) + { + fall += zinit.gravity; + } + } + else if(!can_drop(x,y) && !(pickup & ipDUMMY) && !(pickup & ipCHECK)) + { + fall = -fall/2; // LA key bounce. + } + } + else + { + z-=fall/100; + + if(z<0) + { + z = 0; + fall = -fall/2; + } + else if(z <= 1 && abs(fall) < (int)zinit.gravity) + { + z=0; + fall=0; + } + else if(fall <= (int)zinit.terminalv) + { + fall += zinit.gravity; + } + } + } + + // Maybe it fell off the bottom in sideview, or was moved by a script. + if(y>352 || y<-176 || x<-256 || x > 512) + { + return true; + } + + if((++clk)>=0x8000) + { + clk=0x7000; + } + + if(flash) + { + cs = o_cset; + + if(frame&8) + { + cs >>= 4; + } + else + { + cs &= 15; + } + } + + if(anim) + { + int spd = o_speed; + + if(aframe==0) + { + spd *= o_delay+1; + } + + if(++aclk >= spd) + { + aclk=0; + + if(++aframe >= frames) + { + aframe=0; + } + } + + //tile = o_tile + aframe; + if(extend > 2) + { + if(o_tile/TILES_PER_ROW==(o_tile+txsz*aframe)/TILES_PER_ROW) + tile=o_tile+txsz*aframe; + else + tile=o_tile+(txsz*aframe)+((tysz-1)*TILES_PER_ROW)*((o_tile+txsz*aframe)/TILES_PER_ROW)-(o_tile/TILES_PER_ROW); + } + else + tile = o_tile + aframe; + } + + if(itemsbuf[id].family ==itype_fairy && itemsbuf[id].misc3) + { + movefairy(x,y,misc); + } + + if(fadeclk==0 && !subscreenItem) + { + return true; + } + + if(pickup&ipTIMER) + { + if(++clk2 == 512) + { + return true; + } + } + + return false; +} + +void item::draw(BITMAP *dest) +{ + if(pickup&ipNODRAW || tile==0) + return; + + if(!(pickup&ipFADE) || fadeclk<0 || fadeclk&1) + { + if(clk2>32 || (clk2&2)==0 || itemsbuf[id].family == itype_fairy) + { + sprite::draw(dest); + } + } +} + +item::item(int id): + sprite(), + price(0) +{ + init(fix(0), fix(0), fix(0), id, 0, 0, false); +} + +item::item(fix X,fix Y,fix Z,int i,int p,int c, bool isDummy): + sprite(), + price(0) +{ + init(X, Y, Z, i, p, c, isDummy); +} + + +void item::init(fix X,fix Y,fix Z,int i,int p,int c, bool isDummy) +{ + x=X; + y=Y; + z=Z; + id=i; + pickup=p; + clk=c; + misc=clk2=0; + aframe=aclk=0; + anim=flash=twohand=subscreenItem=false; + PriceIndex=-1; + + alsoHaveBow=false; + + if(id<0 || id>iMax) //>, not >= for dummy items such as the HC Piece display in the subscreen + return; + + o_tile = itemsbuf[id].tile; + tile = itemsbuf[id].tile; + cs = itemsbuf[id].csets&15; + o_cset = itemsbuf[id].csets; + o_speed = itemsbuf[id].speed; + o_delay = itemsbuf[id].delay; + frames = itemsbuf[id].frames; + flip = itemsbuf[id].misc>>2; + + if(itemsbuf[id].misc&1) + flash=true; + + if(itemsbuf[id].misc&2) + twohand=true; + + anim = itemsbuf[id].frames>0; + + if(pickup&ipBIGRANGE) + { + hxofs=-8; + hxsz=17; + hyofs=-4; + hysz=20; + } + else if(pickup&ipBIGTRI) + { + hxofs=-8; + hxsz=28; + hyofs=-4; + hysz=20; + } + else + { + hxsz=1; + hyofs=4; + hysz=12; + } + + if(!isDummy && itemsbuf[id].family == itype_fairy && itemsbuf[id].misc3) + { + misc = ++fairy_cnt; + + if(addfairy(x, y, itemsbuf[id].misc3, misc)) + sfx(itemsbuf[id].usesound); + } + + /*for(int j=0;j<8;j++) + { + if(j<2) a[j]=itemsbuf[id].initiala[j]*10000; + d[j]=itemsbuf[id].initiald[j]; + }*/ + + assignItemScript(this, "item"); +} + +// easy way to draw an item + +void putitem(BITMAP *dest,int x,int y,int item_id) +{ + item temp((fix)x,(fix)y,(fix)0,item_id,0,0); + temp.yofs=0; + temp.animate(0); + temp.draw(dest); +} + +void putitem2(BITMAP *dest,int x,int y,int item_id, int &aclk, int &aframe, int flash) +{ + item temp((fix)x,(fix)y,(fix)0,item_id,0,0,true); + temp.yofs=0; + temp.aclk=aclk; + temp.aframe=aframe; + + if(flash) + { + temp.flash=(flash != 0); + } + + temp.animate(0); + temp.draw(dest); + aclk=temp.aclk; + aframe=temp.aframe; +} + +//some methods for dealing with items +int getItemFamily(itemdata* items, int item) +{ + return items[item].family; +} + +void removeItemsOfFamily(gamedata *g, itemdata *items, int family) +{ + for(int i=0; iset_item(i,false); + } +} + +void removeLowerLevelItemsOfFamily(gamedata *g, itemdata *items, int family, int level) +{ + for(int i=0; iset_item(i, false); + } +} + +void removeItemsOfFamily(zinitdata *z, itemdata *items, int family) +{ + for(int i=0; iitems[i]=false; + } +} + +int getHighestLevelOfFamily(zinitdata *source, itemdata *items, int family) +{ + int result = -1; + int highestlevel = -1; + + for(int i=0; iitems[i]) + { + if(items[i].fam_type >= highestlevel) + { + highestlevel = items[i].fam_type; + result=i; + } + } + } + + return result; +} + +int getHighestLevelOfFamily(gamedata *source, itemdata *items, int family, bool checkenabled) +{ + int result = -1; + int highestlevel = -1; + + for(int i=0; iget_item(i) && (checkenabled?(!(source->items_off[i])):1)) + { + if(items[i].fam_type >= highestlevel) + { + highestlevel = items[i].fam_type; + result=i; + } + } + } + + return result; +} + +int getItemID(itemdata *items, int family, int level) +{ + if(level<0) return getCanonicalItemID(items, family); + + for(int i=0; iitems[id]=true; + } + } +} + +int computeOldStyleBitfield(zinitdata *source, itemdata *items, int family) +{ + int rval=0; + + for(int i=0; iitems[i]) + { + if(items[i].fam_type > 0) + rval |= 1<<(items[i].fam_type-1); + } + } + + return rval; +} + +const char *old_item_string[iLast] = +{ + "Rupee (1)", "Rupee (5)", "Heart", "Bomb (Normal)", "Clock", + "Sword 1 (Wooden)", "Sword 2 (White)", "Sword 3 (Magic)", "Shield 2 (Magic)", "Key (Normal)", + "Candle 1 (Blue)", "Candle 2 (Red)", "Letter", "Arrow 1 (Wooden)", "Arrow 2 (Silver)", + "Bow 1 (Short)", "Bait", "Ring 1 (Blue)", "Ring 2 (Red)", "Bracelet 2", + "Triforce (Fragment)", "Map", "Compass", "Boomerang 1 (Wooden)", "Boomerang 2 (Magic)", + "Wand", "Raft", "Ladder 1", "Heart Container", "Potion 1 (Blue)", + "Potion 2 (Red)", "Whistle", "Magic Book", "Key (Magic)", "Fairy (Moving)", + "Boomerang 3 (Fire)", "Sword 4 (Master)", "Shield 3 (Mirror)", "Rupee (20)", "Rupee (50)", + "Rupee (200)", "Wallet 1 (500)", "Wallet 2 (999)", "Dust Pile", + "Triforce (Whole)", "Selection (1)", "Misc 1", "Misc 2", "Bomb (Super)","Heart Container Piece", + "Amulet 1", "Flippers", "Hookshot 1 (Short)", "Lens of Truth", "Hammer", "Boots", + "Bracelet 3", "Arrow 3 (Golden)", "Magic Container", "Magic Jar 1 (Small)", + "Magic Jar 2 (Large)", "Ring 3 (Golden)", "Kill All Enemies", "Amulet 2", + "Din's Fire", "Farore's Wind", "Nayru's Love", "Key (Boss)", "Bow 2 (Long)", "Fairy (Stationary)", + "Arrow Ammunition (1)", "Arrow Ammunition (5)", "Arrow Ammunition (10)", "Arrow Ammunition (30)", + "Quiver 1 (Small)", "Quiver 2 (Medium)", "Quiver 3 (Large)", "Bomb Ammunition (1)", "Bomb Ammunition (4)", "Bomb Ammunition (8)", "Bomb Ammunition (30)", + "Bomb Bag 1 (Small)", "Bomb Bag 2 (Medium)", "Bomb Bag 3 (Large)", "Key (Level Specific)", "Selection (2)", "Rupee (10)", "Rupee (100)", "Cane of Byrna", + "Hookshot 2 (Long)", "Letter (used)", "Roc's Feather", "Hover Boots","Shield 1 (Small)","Scroll: Spin Attack", "Scroll: Cross Beams", "Scroll: Quake Hammer", + "Scroll: Super Quake", "Scroll: Hurricane Spin", "Whisp Ring 1", "Whisp Ring 2", "Charge Ring 1", "Charge Ring 2", "Scroll: Peril Beam", "Wallet 3 (Magic)", + "Quiver 4 (Magic)", "Bomb Bag 4 (Magic)", "Bracelet 1 (Worn-out Glove)", "Ladder 2 (Four-Way)", "Wealth Medal 1 (75%)", "Wealth Medal 2 (50%)", + "Wealth Medal 3 (25%)", "Heart Ring 1 (Slow)", "Heart Ring 2", "Heart Ring 3 (Fast)", "Magic Ring 1 (Slow)", "Magic Ring 2", "Magic Ring 3 (Fast)", + "Magic Ring 4 (Light Force)", "Stone of Agony", "Stomp Boots", "Peril Ring", "Whimsical Ring", + "Custom Item 01", "Custom Item 02", "Custom Item 03", "Custom Item 04", "Custom Item 05", + "Custom Item 06", "Custom Item 07", "Custom Item 08", "Custom Item 09", "Custom Item 10", + "Custom Item 11", "Custom Item 12", "Custom Item 13", "Custom Item 14", "Custom Item 15", + "Custom Item 16", "Custom Item 17", "Custom Item 18", "Custom Item 19", "Custom Item 20" +}; + +const char *old_weapon_string[wLast] = +{ + "Sword 1 (Wooden)", "Sword 2 (White)", "Sword 3 (Magic)", "Sword 4 (Master)", + "Boomerang 1 (Wooden)", "Boomerang 2 (Magic)", "Boomerang 3 (Fire)", "Bomb (Normal)", + "Bomb (Super)", "Explosion (Normal)", "Arrow 1 (Wooden)", "Arrow 2 (Silver)", "Flame", "Whirlwind", + "Bait", "Wand", "Magic (Normal)", "Fireball", "Rock", "Arrow (Enemy)", "Sword (Enemy)", + "Magic (Enemy)", "MISC: Spawn", "MISC: Death", "MISC: ", "Hammer", + "Hookshot 1 (Short) Head", "Hookshot 1 (Short) Chain (Horizontal)", "Hookshot 1 (Short) Handle", "MISC: Arrow 2 (Silver) Sparkle", + "MISC: Arrow 3 (Golden) Sparkle", "MISC: Boomerang 2 (Magic) Sparkle", "MISC: Boomerang 3 (Fire) Sparkle", + "MISC: Hammer Impact", "Arrow 3 (Golden)", "Fire (Enemy)", "Whirlwind (Enemy)", "MISC: Magic Meter", + "Din's Fire (Rising)", "Din's Fire (Falling)","Din's Fire Trail (Rising)", "Din's Fire Trail (Falling)", "Hookshot 1 (Short) Chain (Vertical)", "MISC: More...", + "MISC: ", "MISC: ", "Sword 1 (Wooden) Slash", + "Sword 2 (White) Slash", "Sword 3 (Magic) Slash", "Sword 4 (Master) Slash", "MISC: Shadow (Small)", + "MISC: Shadow (Large)", "MISC: Bush Leaves", "MISC: Flower Clippings", + "MISC: Grass Clippings", "MISC: Tall Grass", "MISC: Ripples", "MISC: ", + "Nayru's Love (Left)", "Nayru's Love (Left, Returning)","Nayru's Love Trail (Left)", "Nayru's Love Trail (Left, Returning)", + "Nayru's Love (Right)", "Nayru's Love (Right, Returning)","Nayru's Love Trail (Right)", "Nayru's Love Trail (Right, Returning)", + "Nayru's Love Shield (Front)", "Nayru's Love Shield (Back)", "MISC: Subscreen Vine", "Cane of Byrna", "Cane of Byrna (Slash)", + "Hookshot 2 (Long) Head", "Hookshot 2 (Long) Chain (Horizontal)", "Hookshot 2 (Long) Handle", "Hookshot 2 (Long) Chain (Vertical)", + "Explosion (Super)", "Bomb (Enemy, Normal)", "Bomb (Enemy, Super)", "Explosion (Enemy, Normal)", "Explosion (Enemy, Super)", + "Fire Trail (Enemy)", "Fire 2 (Enemy)", "Fire 2 Trail (Enemy) ", "Ice Magic (Enemy) ", "MISC: Hover Boots Glow", "Magic (Fire)", "MISC: Quarter Hearts", "Cane of Byrna (Beam)" /*, "MISC: Sideview Ladder", "MISC: Sideview Raft"*/ +}; + +char *weapon_string[WPNCNT]; + diff --git a/src/items.h b/src/items.h new file mode 100644 index 0000000000..9b28b4c60d --- /dev/null +++ b/src/items.h @@ -0,0 +1,88 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- + +#ifndef _ITEMS_H_ +#define _ITEMS_H_ + +#include "sprite.h" +#include "zdefs.h" +#include + +class LinkClass; + +extern char *item_string[ITEMCNT]; + +extern int fairy_cnt; +void movefairy(fix &x,fix &y,int misc); +void killfairy(int misc); +int addenemy(int x,int y,int id,int clk); +bool addfairy(fix x, fix y, int misc3, int id); +bool can_drop(fix x, fix y); +int select_dropitem(int item_set, int x, int y); +bool is_side_view(); + +class item : public sprite +{ +public: + int pickup,clk2; + int aclk,aframe; + char PriceIndex; + bool flash,twohand,anim, subscreenItem; + int o_tile,o_cset, o_speed, o_delay, frames; + + bool alsoHaveBow; // Used in subscreens + + item(int id); + item(fix X,fix Y,fix Z,int i,int p,int c, bool isDummy = false); + virtual ~item(); + + void setPickupFlags(int newPickup); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); + + /// Determines whether Link is able to collect an item. + /** \note ZC only + */ + bool canPickUp(LinkClass* link); + + /// Finds the item that will be added when an upgrading item is collected. + /** \return The ID of the resulting item, or -1 if this is not + * an upgrade item or no suitable upgrade could be found. + * \note ZC only + */ + int getUpgradeResult() const; + + //TODO: These are broken. There should be a less clever way to do this. + // public for now... + void* onGetDummyMoney; // ..WHY?? + void* onPickUp; + + inline void setPrice(int newPrice) + { + price=newPrice; + } + +protected: + void init(fix X,fix Y,fix Z,int i,int p,int c, bool isDummy = false); + +private: + int price; +}; + +// easy way to draw an item +void putitem(BITMAP *dest,int x,int y,int item_id); +void putitem2(BITMAP *dest,int x,int y,int item_id, int &aclk, int &aframe, int flash); +#endif +/*** end of sprite.cc ***/ + diff --git a/src/jmenu.cpp b/src/jmenu.cpp new file mode 100644 index 0000000000..b65358b546 --- /dev/null +++ b/src/jmenu.cpp @@ -0,0 +1,729 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// jmenu.cc +// +// The Allegro menu routines don't support joystick input, so here's +// their code with a little joystick stuff added. +// +//-------------------------------------------------------- + +#include +#include +#include "zc_alleg.h" +#include "zelda.h" +#include "jwin.h" +#include + +typedef struct MENU_INFO /* information about a popup menu */ +{ + MENU *menu; /* the menu itself */ + struct MENU_INFO *parent; /* the parent menu, or NULL for root */ + int bar; /* set if it is a top level menu bar */ + int size; /* number of items in the menu */ + int sel; /* selected item */ + int x, y, w, h; /* screen position of the menu */ + int (*proc)(); /* callback function */ + BITMAP *saved; /* saved what was underneath it */ +} MENU_INFO; + + + +/* get_menu_pos: + * Calculates the coordinates of an object within a top level menu bar. + */ +static void get_menu_pos(MENU_INFO *m, int c, int *x, int *y, int *w) +{ + int c2; + + if(m->bar) + { + *x = m->x+1; + + for(c2=0; c2menu[c2].text) + 16; + + *y = m->y+1; + *w = gui_strlen(m->menu[c].text) + 16; + } + else + { + *x = m->x+1; + *y = m->y+c*(text_height(font)+4)+1; + *w = m->w-2; + } +} + + + +/* draw_menu_item: + * Draws an item from a popup menu onto the screen. + */ +static void draw_menu_item(MENU_INFO *m, int c) +{ + int fg, bg; + int i, x, y, w; + char buf[80], *tok; + + if(m->menu[c].flags & D_DISABLED) + { + if(c == m->sel) + { + fg = gui_mg_color; + bg = gui_fg_color; + } + else + { + fg = gui_mg_color; + bg = gui_bg_color; + } + } + else + { + if(c == m->sel) + { + fg = gui_bg_color; + bg = gui_fg_color; + } + else + { + fg = gui_fg_color; + bg = gui_bg_color; + } + } + + get_menu_pos(m, c, &x, &y, &w); + + rectfill(screen, x, y, x+w-1, y+text_height(font)+3, bg); + text_mode(bg); + + if(m->menu[c].text[0]) + { + for(i=0; (m->menu[c].text[i]) && (m->menu[c].text[i] != '\t'); i++) + buf[i] = m->menu[c].text[i]; + + buf[i] = 0; + + gui_textout(screen, buf, x+8, y+1, fg, FALSE); + + if(m->menu[c].text[i] == '\t') + { + tok = m->menu[c].text+i+1; + gui_textout(screen, tok, x+w-gui_strlen(tok)-8, y+1, fg, FALSE); + } + } + else + hline(screen, x, y+text_height(font)/2+2, x+w, fg); + + if(m->menu[c].flags & D_SELECTED) + { + line(screen, x+1, y+text_height(font)/2+1, x+3, y+text_height(font)+1, fg); + line(screen, x+3, y+text_height(font)+1, x+6, y+2, fg); + } +} + + + +/* draw_menu: + * Draws a popup menu onto the screen. + */ +static void draw_menu(MENU_INFO *m) +{ + int c; + + rect(screen, m->x, m->y, m->x+m->w-1, m->y+m->h-1, gui_fg_color); + vline(screen, m->x+m->w, m->y+1, m->y+m->h, gui_fg_color); + hline(screen, m->x+1, m->y+m->h, m->x+m->w, gui_fg_color); + + for(c=0; m->menu[c].text; c++) + draw_menu_item(m, c); +} + + + +/* menu_mouse_object: + * Returns the index of the object the mouse is currently on top of. + */ +static int menu_mouse_object(MENU_INFO *m) +{ + int c; + int x, y, w; + + for(c=0; csize; c++) + { + get_menu_pos(m, c, &x, &y, &w); + + if((gui_mouse_x() >= x) && (gui_mouse_x() < x+w) && + (gui_mouse_y() >= y) && (gui_mouse_y() < y+(text_height(font)+4))) + return (m->menu[c].text[0]) ? c : -1; + } + + return -1; +} + + + +/* mouse_in_parent_menu: + * Recursively checks if the mouse is inside a menu or any of its parents. + */ +static int mouse_in_parent_menu(MENU_INFO *m) +{ + int c; + + if(!m) + return FALSE; + + c = menu_mouse_object(m); + + if((c >= 0) && (c != m->sel)) + return TRUE; + + return mouse_in_parent_menu(m->parent); +} + + + +/* fill_menu_info: + * Fills a menu info structure when initialising a menu. + */ +static void fill_menu_info(MENU_INFO *m, MENU *menu, MENU_INFO *parent, int bar, int x, int y, int minw, int minh) +{ + int c, i; + int extra = 0; + char buf[80], *tok; + + m->menu = menu; + m->parent = parent; + m->bar = bar; + m->x = x; + m->y = y; + m->w = 2; + m->h = (m->bar) ? (text_height(font)+6) : 2; + m->proc = NULL; + m->sel = -1; + + /* calculate size of the menu */ + for(m->size=0; m->menu[m->size].text; m->size++) + { + for(i=0; (m->menu[m->size].text[i]) && (m->menu[m->size].text[i] != '\t'); i++) + buf[i] = m->menu[m->size].text[i]; + + buf[i] = 0; + + c = gui_strlen(buf); + + if(m->bar) + { + m->w += c+16; + } + else + { + m->h += text_height(font)+4; + m->w = MAX(m->w, c+16); + } + + if(m->menu[m->size].text[i] == '\t') + { + tok = m->menu[m->size].text+i+1; + c = gui_strlen(tok); + extra = MAX(extra, c); + } + } + + if(extra) + m->w += extra+16; + + m->w = MAX(m->w, minw); + m->h = MAX(m->h, minh); +} + + + +/* menu_key_shortcut: + * Returns true if c is indicated as a keyboard shortcut by a '&' character + * in the specified string. + */ +static int menu_key_shortcut(int c, char *s) +{ + while(*s) + { + if(*s == '&') + { + ++s; + + if((*s != '&') && (tolower(*s) == tolower(c & 0xff))) + return TRUE; + } + + ++s; + } + + return FALSE; +} + + + + +/* menu_alt_key: + * Searches a menu for keyboard shortcuts, for the alt+letter to bring + * up a menu. + */ +int menu_alt_key(int k, MENU *m) +{ + char *s; + int c; + + if(k & 0xff) + return 0; + + //k = key_ascii_table[k>>8]; + + for(c=0; m[c].text; c++) + { + s = m[c].text; + + while(*s) + { + if(*s == '&') + { + ++s; + + if((*s != '&') && (tolower(*s) == tolower(k))) + return k; + } + + ++s; + } + } + + return 0; +} + + + +/* _j_do_menu: + * The core menu control function, called by do_menu() and d_menu_proc(). + */ +int _j_do_menu(MENU *menu, MENU_INFO *parent, int bar, int x, int y, int repos, int *dret, int minw, int minh) +{ + MENU_INFO m; + MENU_INFO *i; + int c, c2; + int ret = -1; + int mouse_on = gui_mouse_b(); + int joy_on = joy_left + joy_right + joy_up + joy_down + joy_b1 + joy_b2; + int old_sel; + int mouse_sel; + int _x, _y; + int redraw = TRUE; + + scare_mouse(); + + fill_menu_info(&m, menu, parent, bar, x, y, minw, minh); + + if(repos) + { + m.x = MID(0, m.x, SCREEN_W-m.w-1); + m.y = MID(0, m.y, SCREEN_H-m.h-1); + } + + /* save screen under the menu */ + m.saved = create_bitmap(m.w+1, m.h+1); + + if(m.saved) + blit(screen, m.saved, m.x, m.y, 0, 0, m.w+1, m.h+1); + else + errno = ENOMEM; + + m.sel = mouse_sel = menu_mouse_object(&m); + + if((m.sel < 0) && (!mouse_on) && (!bar)) + m.sel = 0; + + unscare_mouse(); + + do + { + old_sel = m.sel; + + c = menu_mouse_object(&m); + + if((gui_mouse_b()) || (c != mouse_sel)) + m.sel = mouse_sel = c; + + if(gui_mouse_b()) /* if button pressed */ + { + if((gui_mouse_x() < m.x) || (gui_mouse_x() > m.x+m.w) || + (gui_mouse_y() < m.y) || (gui_mouse_y() > m.y+m.h)) + { + if(!mouse_on) /* dismiss menu? */ + break; + + if(mouse_in_parent_menu(m.parent)) /* back to parent? */ + break; + } + + if((m.sel >= 0) && (m.menu[m.sel].child)) /* bring up child? */ + ret = m.sel; + + mouse_on = TRUE; + clear_keybuf(); + } + else /* button not pressed */ + { + if(mouse_on) /* selected an item? */ + ret = m.sel; + + mouse_on = FALSE; + + poll_joystick(); + + if(joy_left + joy_right + joy_up + joy_down + joy_b1 + joy_b2 == 0) + joy_on = FALSE; + + c = 0; + + if(keypressed()) /* keyboard input */ + c = readkey(); + else if(!joy_on) /* joystick input */ + { + if(joy_up) + { + c = KEY_UP << 8; + joy_on = TRUE; + } + + if(joy_down) + { + c = KEY_DOWN << 8; + joy_on = TRUE; + } + + if(joy_left) + { + c = KEY_LEFT << 8; + joy_on = TRUE; + } + + if(joy_right) + { + c = KEY_RIGHT << 8; + joy_on = TRUE; + } + + if(joy_b1 | joy_b2) + { + c = KEY_ENTER << 8; + joy_on = TRUE; + } + } + + if(c) + { + + if((c & 0xff) == 27) + { + ret = -1; + goto getout; + } + + switch(c >> 8) + { + + case KEY_LEFT: + if(m.parent) + { + if(m.parent->bar) + { + simulate_keypress(KEY_LEFT<<8); + simulate_keypress(KEY_DOWN<<8); + } + + ret = -1; + goto getout; + } + + /* fall through */ + + case KEY_UP: + if((((c >> 8) == KEY_LEFT) && (m.bar)) || + (((c >> 8) == KEY_UP) && (!m.bar))) + { + c = m.sel; + + do + { + --c; + + if(c < 0) + c = m.size - 1; + } + while((!(m.menu[c].text[0])) && (c != m.sel)); + + m.sel = c; + } + + break; + + case KEY_RIGHT: + if(((m.sel < 0) || (!m.menu[m.sel].child)) && + (m.parent) && (m.parent->bar)) + { + simulate_keypress(KEY_RIGHT<<8); + simulate_keypress(KEY_DOWN<<8); + ret = -1; + goto getout; + } + + /* fall through */ + + case KEY_DOWN: + if((m.sel >= 0) && (m.menu[m.sel].child) && + ((((c >> 8) == KEY_RIGHT) && (!m.bar)) || + (((c >> 8) == KEY_DOWN) && (m.bar)))) + { + ret = m.sel; + } + else if((((c >> 8) == KEY_RIGHT) && (m.bar)) || + (((c >> 8) == KEY_DOWN) && (!m.bar))) + { + c = m.sel; + + do + { + ++c; + + if(c >= m.size) + c = 0; + } + while((!(m.menu[c].text[0])) && (c != m.sel)); + + m.sel = c; + } + + break; + + case KEY_SPACE: + case KEY_ENTER: + if(m.sel >= 0) + ret = m.sel; + + break; + + default: + if((!m.parent) && ((c & 0xff) == 0)) + c = menu_alt_key(c, m.menu); + + for(c2=0; m.menu[c2].text; c2++) + { + if(menu_key_shortcut(c, m.menu[c2].text)) + { + ret = m.sel = c2; + break; + } + } + + if(m.parent) + { + i = m.parent; + + for(c2=0; i->parent; c2++) + i = i->parent; + + c = menu_alt_key(c, i->menu); + + if(c) + { + while(c2-- > 0) + simulate_keypress(27); + + simulate_keypress(c); + ret = -1; + goto getout; + } + } + + break; + } + } + } + + if((redraw) || (m.sel != old_sel)) /* selection changed? */ + { + scare_mouse(); + + if(redraw) + { + draw_menu(&m); + redraw = FALSE; + } + else + { + if(old_sel >= 0) + draw_menu_item(&m, old_sel); + + if(m.sel >= 0) + draw_menu_item(&m, m.sel); + } + + unscare_mouse(); + } + + if((ret >= 0) && (m.menu[ret].flags & D_DISABLED)) + ret = -1; + + if(ret >= 0) /* child menu? */ + { + if(m.menu[ret].child) + { + if(m.bar) + { + get_menu_pos(&m, ret, &_x, &_y, &c); + _x += 6; + _y += text_height(font)+7; + } + else + { + // _x = m.x+m.w*2/3; + _x = m.x+m.w-4; + _y = m.y + (text_height(font)+4)*ret + text_height(font)/4+2; + } + + c = _j_do_menu(m.menu[ret].child, &m, FALSE, _x, _y, TRUE, NULL, 0, 0); + + if(c < 0) + { + ret = -1; + mouse_on = FALSE; + mouse_sel = menu_mouse_object(&m); + } + } + } + + if((m.bar) && (!gui_mouse_b()) && (!keypressed()) && + ((gui_mouse_x() < m.x) || (gui_mouse_x() > m.x+m.w) || + (gui_mouse_y() < m.y) || (gui_mouse_y() > m.y+m.h))) + break; + + } + while(ret < 0); + +getout: + + if(dret) + *dret = 0; + + /* callback function? */ + if((!m.proc) && (ret >= 0)) + { + active_menu = &m.menu[ret]; + m.proc = active_menu->proc; + } + + if(ret >= 0) + { + if(parent) + parent->proc = m.proc; + else + { + if(m.proc) + { + c = m.proc(); + + if(dret) + *dret = c; + } + } + } + + /* restore screen */ + if(m.saved) + { + scare_mouse(); + blit(m.saved, screen, 0, 0, m.x, m.y, m.w+1, m.h+1); + unscare_mouse(); + destroy_bitmap(m.saved); + } + + return ret; +} + + + +/* j_do_menu: + * Displays and animates a popup menu at the specified screen position, + * returning the index of the item that was selected, or -1 if it was + * dismissed. If the menu crosses the edge of the screen it will be moved. + */ +int j_do_menu(MENU *menu, int x, int y) +{ + int ret = _j_do_menu(menu, NULL, FALSE, x, y, TRUE, NULL, 0, 0); + + do + { + } + while(gui_mouse_b()); + + return ret; +} + + + +/* d_jmenu_proc: + * Dialog procedure for adding drop down menus to a GUI dialog. This + * displays the top level menu items as a horizontal bar (eg. across the + * top of the screen), and pops up child menus when they are clicked. + * When it executes one of the menu callback routines, it passes the + * return value back to the dialog manager, so these can return D_O_K, + * D_CLOSE, D_REDRAW, etc. + */ +int d_jmenu_proc(int msg, DIALOG *d, int c) +{ + MENU_INFO m; + int ret = D_O_K; + int x; + + switch(msg) + { + + case MSG_START: + fill_menu_info(&m, (MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, d->w+2, d->h+2); + d->w = m.w-2; + d->h = m.h-2; + break; + + case MSG_DRAW: + fill_menu_info(&m, (MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, d->w+2, d->h+2); + draw_menu(&m); + break; + + case MSG_XCHAR: + x = menu_alt_key(c, (MENU*)d->dp); + + if(!x) + break; + + ret |= D_USED_CHAR; + simulate_keypress(x); + /* fall through */ + + case MSG_GOTMOUSE: + case MSG_CLICK: + _j_do_menu((MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, FALSE, &x, d->w+2, d->h+2); + ret |= x; + + do + { + } + while(gui_mouse_b()); + + break; + } + + return ret; +} + + + + diff --git a/src/jwin.cpp b/src/jwin.cpp new file mode 100644 index 0000000000..737e379503 --- /dev/null +++ b/src/jwin.cpp @@ -0,0 +1,5369 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.c + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ + +/* This code is not fully tested */ + +#include "precompiled.h" //always first + +#include +#include +#include "zc_alleg.h" +#include +#include "jwin.h" +#include "editbox.h" +#include +#include "zsys.h" +#include +#include "mem_debug.h" + +//#ifndef _MSC_VER +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) +//#endif +//#ifdef _ZQUEST_SCALE_ +extern volatile int myvsync; +extern int zqwin_scale; +extern BITMAP *hw_screen; +//#endif +extern int zq_screen_w, zq_screen_h; +extern int joystick_index; + +extern bool is_zquest(); + +/* ... Included in jwin.h ... + + enum { jcBOX, jcLIGHT, jcMEDLT, jcMEDDARK, jcDARK, jcBOXFG, + jcTITLEL, jcTITLER, jcTITLEFG, jcTEXTBG, jcTEXTFG, jcSELBG, jcSELFG, + jcMAX }; + */ + +int bound(int x,int low,int high) +{ + if(xhigh) x=high; + + return x; +} +/* + float bound(float x,float low,float high) + { + if(xhigh) x=high; + return x; + } + */ + +/* these are provided for external use */ +int jwin_colors[jcMAX] = +{ + 0xC0C0C0,0xF0F0F0,0xD0D0D0,0x808080,0x404040,0x000000, + 0x000080,0x00F0F0,0xFFFFFF,0xFFFFFF,0x000000,0x000080,0xFFFFFF +}; + +int scheme[jcMAX] = +{ + 0xC0C0C0,0xF0F0F0,0xD0D0D0,0x808080,0x404040,0x000000, + 0x000080,0x00F0F0,0xFFFFFF,0xFFFFFF,0x000000,0x000080,0xFFFFFF +}; + +/* jwin_set_colors: + * Loads a set of colors in 0xRRGGBB or 256-color-indexed format + * into the current color scheme using the appropriate color depth + * conversions. + */ +void jwin_set_colors(int *colors) +{ + int i = 0; + + if(bitmap_color_depth(screen) == 8) + { + // use color indices + for(; i>16, (colors[i]>>8)&0xFF, colors[i]&0xFF); + } +} + +/* jwin_set_dialog_color: + * Sets the foreground and background colors of all the objects in a dialog. + * + * Needs work! + */ +void jwin_set_dialog_color(DIALOG *dialog) +{ + int c; + + for(c=0; dialog[c].proc; c++) + { + dialog[c].fg = scheme[jcMEDDARK]; + dialog[c].bg = scheme[jcBOX]; + } +} + +/* jwin_draw_frame: + * Draws a frame using the specified style. + */ +void jwin_draw_frame(BITMAP *dest,int x,int y,int w,int h,int style) +{ + int c1,c2,c3,c4; + + switch(style) + { + case FR_BOX: + c1 = jcLIGHT; + c2 = jcMEDLT; + c3 = jcMEDDARK; + c4 = jcDARK; + break; + + case FR_INV: + c1 = jcDARK; + c2 = jcMEDDARK; + c3 = jcMEDLT; + c4 = jcLIGHT; + break; + + case FR_DEEP: + c1 = jcMEDDARK; + c2 = jcDARK; + c3 = jcMEDLT; + c4 = jcLIGHT; + break; + + case FR_DARK: + c1 = jcDARK; + c2 = jcMEDDARK; + c3 = jcMEDDARK; + c4 = jcDARK; + break; + + case FR_ETCHED: + c1 = jcMEDDARK; + c2 = jcLIGHT; + c3 = jcMEDDARK; + c4 = jcLIGHT; + break; + + case FR_MEDDARK: + c1 = jcMEDDARK; + c2 = jcBOX; + c3 = jcBOX; + c4 = jcMEDDARK; + break; + + case FR_WIN: + default: + c1 = jcMEDLT; + c2 = jcLIGHT; + c3 = jcMEDDARK; + c4 = jcDARK; + break; + } + + _allegro_hline(dest, vbound(x,0,dest->w-1), vbound(y,0,dest->h-1) , vbound(x+w-2, 0,dest->w-1), palette_color[scheme[c1]]); + _allegro_vline(dest, vbound(x,0,dest->w-1), vbound(y+1,0,dest->h-1), vbound(y+h-2, 0, dest->h-1), palette_color[scheme[c1]]); + + _allegro_hline(dest, vbound(x+1,0,dest->w-1), vbound(y+1,0,dest->h-1), vbound(x+w-3,0,dest->w-1), palette_color[scheme[c2]]); + _allegro_vline(dest, vbound(x+1,0,dest->w-1), vbound(y+2,0,dest->h-1), vbound(y+h-3,0,dest->h-1), palette_color[scheme[c2]]); + + _allegro_hline(dest, vbound(x+1,0,dest->w-1), vbound(y+h-2,0,dest->h-1), vbound(x+w-2,0,dest->w-1), palette_color[scheme[c3]]); + _allegro_vline(dest, vbound(x+w-2,0,dest->w-1), vbound(y+1,0,dest->h-1), vbound(y+h-3,0,dest->h-1), palette_color[scheme[c3]]); + + _allegro_hline(dest, vbound(x,0,dest->w-1), vbound(y+h-1,0,dest->h-1), vbound(x+w-1,0, dest->w-1), palette_color[scheme[c4]]); + _allegro_vline(dest, vbound(x+w-1,0,dest->w-1), vbound(y,0,dest->h-1), vbound(y+h-2,0,dest->h-1), palette_color[scheme[c4]]); +} + +/* jwin_draw_win: + * Draws a window -- a box with a frame. + */ +void jwin_draw_win(BITMAP *dest,int x,int y,int w,int h,int frame) +{ + rectfill(dest,zc_max(x+2,0),zc_max(y+2,0),zc_min(x+w-3, dest->w-1),zc_min(y+h-3, dest->h-1),palette_color[scheme[jcBOX]]); + jwin_draw_frame(dest, x, y, w, h, frame); +} + +/* jwin_draw_button: + * Helper function for buttons. + * Draws a box with a frame that depends on "state": + * 0: normal border (slightly different than window border) + * 1: inverted border + * 2: dark border + * 3: medium dark border + */ +void jwin_draw_button(BITMAP *dest,int x,int y,int w,int h,int state,int type) +{ + int frame = FR_BOX; + + if(type==1) + { + frame=FR_WIN; + } + + switch(state) + { + case 1: + frame = FR_INV; + break; + + case 2: + frame = FR_DARK; + break; + + case 3: + frame = FR_MEDDARK; + break; + } + + jwin_draw_win(dest, x, y, w, h, frame); +} + +/* mix_value: + * Returns a mix of the values c1 and c2 with jwinPOS==0 being c1, + * jwinPOS==max being c2, jwinPOS==max/2 being half way between c1 and c2, etc. + */ +int mix_value(int c1,int c2,int jwinPOS,int max) +{ + if(max<=0) + return c1; + + return (c2 - c1) * jwinPOS / max + c1; +} + +/* mix_color: + * Returns a mix of the colors c1 and c2 with jwinPOS==0 being c1, + * jwinPOS==max being c2, jwinPOS==max/2 being half way between c1 and c2, etc. + * + static int mix_color(int c1,int c2,int jwinPOS,int max) + { + int c; + + if(bitmap_color_depth(screen) == 8) + c = mix_value(c1, c2, jwinPOS, max); + else + { + int r = mix_value(getr(c1), getr(c2), jwinPOS, max); + int g = mix_value(getg(c1), getg(c2), jwinPOS, max); + int b = mix_value(getb(c1), getb(c2), jwinPOS, max); + c = makecol(r,g,b); + } + + return c; + } + */ + +char *shorten_string(char *dest, char *src, FONT *usefont, int maxchars, int maxwidth) +{ + strncpy(dest,src,maxchars); + dest[maxchars-1]='\0'; + int len=(int)strlen(dest); + int width=text_length(usefont, dest); + dest[len]=0; + + while(width>maxwidth && len>4) + { + dest[len-4] = '.'; + dest[len-3] = '.'; + dest[len-2] = '.'; + dest[len-1] = 0; + len--; + width=text_length(usefont, dest); + } + + return dest; +} + +void jwin_draw_titlebar(BITMAP *dest, int x, int y, int w, int h, const char *str, bool draw_button) +{ + char buf[512]; + int len = (int)strlen(str); + int length = text_length(font,str); + int height = text_height(font); + + int tx = x + 2; + int ty = y + (h-height)/2; + PALETTE temp_pal; + /* + int i = 0; + for( ; i509) + len=509; + + strncpy(buf,str,len); + buf[len]=0; + + // this part needs work + + if(length>w-20) + { + while(length>w-20 && len>1) + { + buf[len-4] = '.'; + buf[len-3] = '.'; + buf[len-2] = '.'; + buf[len-1] = 0; + len--; + length = text_length(font,buf); + } + } + + textout_ex(dest,font,buf,tx,ty,palette_color[scheme[jcTITLEFG]],-1); + + if(draw_button) + { + draw_x_button(dest, x + w - 18, y+2, 0); + } + +} + +void draw_x_button(BITMAP *dest, int x, int y, int state) +{ + int c = scheme[jcDARK]; + + jwin_draw_button(dest,x,y,16,14,state,0); + x += 4 + (state?1:0); + y += 3 + (state?1:0); + + line(dest,x, y, x+6,y+6,palette_color[c]); + line(dest,x+1,y, x+7,y+6,palette_color[c]); + line(dest,x, y+6,x+6,y, palette_color[c]); + line(dest,x+1,y+6,x+7,y, palette_color[c]); +} + +void draw_arrow_button(BITMAP *dest, int x, int y, int w, int h, int up, int state) +{ + int c = scheme[jcDARK]; + int ah = zc_min(h/3, 5); + int i = 0; + + jwin_draw_button(dest,x,y,w,h,state,1); + x += w/2 - (state?0:1); + y += (h-ah)/2 + (state?1:0); + + for(; i= x) && (gui_mouse_y() >= y) && + (gui_mouse_x() < x + w) && (gui_mouse_y() < y + h)); +} + +static int jwin_do_x_button(BITMAP *dest, int x, int y) +{ + int down=0, last_draw = 0; + + while(gui_mouse_b()) + { + down = mouse_in_rect(x,y,16,14); + + if(down!=last_draw) + { + scare_mouse(); + draw_x_button(dest,x,y,down); + unscare_mouse(); + last_draw = down; + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + } + + if(down) + { + scare_mouse(); + draw_x_button(dest,x,y,0); + unscare_mouse(); + } + + return down; +} + +/* dotted_rect: + * Draws a dotted rectangle, for showing an object has the input focus. + */ +void dotted_rect(BITMAP *dest, int x1, int y1, int x2, int y2, int fg, int bg) +{ + int x = ((x1+y1) & 1) ? 1 : 0; + int c; + + //acquire the bitmap ourselves, because locking a surface within each call is *SLOW AS BALLS* -DD + acquire_bitmap(dest); + + for(c=x1; c<=x2; c++) + { + putpixel(dest, c, y1, (((c+y1) & 1) == x) ? fg : bg); + putpixel(dest, c, y2, (((c+y2) & 1) == x) ? fg : bg); + } + + for(c=y1+1; c= 0) + { + int i; + i = tmp[hline_pos]; + tmp[hline_pos] = 0; + hline_pos = text_length(f, tmp); + tmp[0] = i; + tmp[1] = 0; + i = text_length(f, tmp); + _allegro_hline(bmp, x+hline_pos, y+text_height(f)-gui_font_baseline, x+hline_pos+i-1, color); + } + } + + y += text_height(f); + } + + return pix_len; +} + +int gui_textout_ln(BITMAP *bmp, unsigned char *s, int x, int y, int color, int bg, int jwinPOS) +{ + return gui_textout_ln(bmp, font, s, x, y, color, bg, jwinPOS); +} + + +/*******************************/ +/***** Misc Dialog Procs *****/ +/*******************************/ + +/* typedef for the listbox callback functions */ +typedef char *(*getfuncptr)(int, int *); + +/* event handler that closes a dialog */ +int close_dlg() +{ + return D_CLOSE; +} + +int jwin_frame_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg == MSG_DRAW) + { + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1); + } + + return D_O_K; +} + +int jwin_guitest_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg == MSG_DRAW) + { + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1); + } + + return D_O_K; +} + +/* jwin_win_proc: + * Draws a box with a frame. Use dp for a title string. If dp is NULL, + * it won't draw a title bar. If the D_EXIT flag is set, it will also + * draw an "X" button on the title bar that can be used to close the + * dialog. + */ +int jwin_win_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + rest(1); + + switch(msg) + { + case MSG_DRAW: + jwin_draw_win(screen, d->x, d->y, d->w, d->h, FR_WIN); + + if(d->dp) + { + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + jwin_draw_titlebar(screen, d->x+3, d->y+3, d->w-6, 18, (char*)d->dp, d->flags & D_EXIT); + font = oldfont; + } + + /* + if(d->flags & D_EXIT) + { + draw_x_button(screen, d->x + d->w - 21, d->y+5, 0); + } + */ + break; + + case MSG_CLICK: + if((d->flags & D_EXIT) && mouse_in_rect(d->x+d->w-21, d->y+5, 16, 14)) + { + if(jwin_do_x_button(screen, d->x+d->w-21, d->y+5)) + return D_CLOSE; + } + + break; + } + + return D_O_K; +} + +/* jwin_text_proc: + * Simple dialog procedure: draws the text string which is pointed to by dp. + * + * Handles '\n' characters. + */ +int jwin_text_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + ASSERT(d); + static BITMAP *dummy=create_bitmap_ex(8, 1, 1); + + switch(msg) + { + case MSG_START: + d->w=gui_textout_ln(dummy, (unsigned char *)d->dp, 0, 0, scheme[jcMEDDARK], -1, 0); + break; + + case MSG_DRAW: + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x+1, d->y+1, palette_color[scheme[jcLIGHT]], palette_color[scheme[jcBOX]], 0); + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcMEDDARK]], -1, 0); + } + else + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcBOXFG]], palette_color[scheme[jcBOX]], 0); + } + + font = oldfont; + break; + } + + return D_O_K; +} + +int jwin_ctext_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + ASSERT(d); + static BITMAP *dummy=create_bitmap_ex(8, 320, 240); + + switch(msg) + { + case MSG_START: + d->w=gui_textout_ln(dummy, (unsigned char *)d->dp, 0, 0, scheme[jcMEDDARK], -1, 0); + break; + + case MSG_DRAW: + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x+1, d->y+1, palette_color[scheme[jcLIGHT]], palette_color[scheme[jcBOX]], 1); + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcMEDDARK]], -1, 1); + } + else + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcBOXFG]], palette_color[scheme[jcBOX]], 1); + } + + font = oldfont; + break; + } + + return D_O_K; +} + +int jwin_rtext_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + ASSERT(d); + static BITMAP *dummy=create_bitmap_ex(8, 1, 1); + + switch(msg) + { + case MSG_START: + d->w=gui_textout_ln(dummy, (unsigned char *)d->dp, 0, 0, scheme[jcMEDDARK], -1, 2); + break; + + case MSG_DRAW: + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x+1, d->y+1, palette_color[scheme[jcLIGHT]], palette_color[scheme[jcBOX]], 2); + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcMEDDARK]], -1, 2); + } + else + { + gui_textout_ln(screen, (unsigned char*)d->dp, d->x, d->y, palette_color[scheme[jcBOXFG]], palette_color[scheme[jcBOX]], 2); + } + + font = oldfont; + break; + } + + return D_O_K; +} + +/* draw_text_button: + * Helper for jwin_button_proc. + */ +void jwin_draw_text_button(BITMAP *dest, int x, int y, int w, int h, const char *str, int flags, bool show_dotted_rect) +{ + int g = (flags & D_SELECTED) ? 1 : 0; + + if(flags & D_SELECTED) + jwin_draw_button(dest, x, y, w, h, 2, 0); + else if(!(flags & D_GOTFOCUS)) + jwin_draw_button(dest, x, y, w, h, 0, 0); + else + { + rect(dest, x, y, x+w-1, y+h-1, palette_color[scheme[jcDARK]]); + jwin_draw_button(dest, x+1, y+1, w-2, h-2, 0, 0); + } + + if(!(flags & D_DISABLED)) + gui_textout_ex(dest, str, x+w/2+g, y+h/2-text_height(font)/2+g, palette_color[scheme[jcBOXFG]], -1, TRUE); + else + { + gui_textout_ex(dest, str, x+w/2+1,y+h/2-text_height(font)/2+1, palette_color[scheme[jcLIGHT]], -1, TRUE); + gui_textout_ex(dest, str, x+w/2, y+h/2-text_height(font)/2, palette_color[scheme[jcMEDDARK]], -1, TRUE); + } + + if(show_dotted_rect&&(flags & D_GOTFOCUS)) + dotted_rect(dest, x+4, y+4, x+w-5, y+h-5, palette_color[scheme[jcDARK]], palette_color[scheme[jcBOX]]); +} + +/* draw_graphics_button: + * Helper for jwin_button_proc. + */ +void jwin_draw_graphics_button(BITMAP *dest, int x, int y, int w, int h, BITMAP *bmp, BITMAP *bmp2, int flags, bool show_dotted_rect, bool overlay) +{ + int g = (flags & D_SELECTED) ? 1 : 0; + + if(flags & D_SELECTED) + jwin_draw_button(dest, x, y, w, h, 2, 0); + else if(!(flags & D_GOTFOCUS)) + jwin_draw_button(dest, x, y, w, h, 0, 0); + else + { + rect(dest, x, y, x+w-1, y+h-1, scheme[jcDARK]); + jwin_draw_button(dest, x+1, y+1, w-2, h-2, 0, 0); + } + + if(!(flags & D_DISABLED)) + { +// gui_textout_ex(dest, str, x+w/2+g, y+h/2-text_height(font)/2+g, scheme[jcBOXFG], -1, TRUE); + if(bmp!=NULL) + { + if(overlay) + { + masked_blit(bmp, dest, 0, 0, x+w/2-bmp->w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w); + } + else + { + blit(bmp, dest, 0, 0, x+w/2-bmp->w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w); + } + } + } + else + { +// gui_textout_ex(dest, str, x+w/2+1,y+h/2-text_height(font)/2+1, scheme[jcLIGHT], -1, TRUE); +// gui_textout_ex(dest, str, x+w/2, y+h/2-text_height(font)/2, scheme[jcMEDDARK], -1, TRUE); + if(bmp2!=NULL) + { + if(overlay) + { + masked_blit(bmp2, dest, 0, 0, x+w/2-bmp2->w/2+g, y+h/2-bmp2->h/2+g, bmp2->h, bmp2->w); + } + else + { + blit(bmp2, dest, 0, 0, x+w/2-bmp2->w/2+g, y+h/2-bmp2->h/2+g, bmp2->h, bmp2->w); + } + } + } + + if(show_dotted_rect&&(flags & D_GOTFOCUS)) + dotted_rect(dest, x+4, y+4, x+w-5, y+h-5, scheme[jcDARK], scheme[jcBOX]); +} + +/* jwin_button_proc: + * A button object (the dp field points to the text string). This object + * can be selected by clicking on it with the mouse or by pressing its + * keyboard shortcut. If the D_EXIT flag is set, selecting it will close + * the dialog, otherwise it will toggle on and off. + */ +int jwin_button_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int down=0; + int selected=(d->flags&D_SELECTED)?1:0; + int last_draw; + + switch(msg) + { + + case MSG_DRAW: + { + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + jwin_draw_text_button(screen, d->x, d->y, d->w, d->h, (char*)d->dp, d->flags, true); + font = oldfont; + } + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + + /* close dialog? */ + if(d->flags & D_EXIT) + { + return D_CLOSE; + } + + /* or just toggle */ + d->flags ^= D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + break; + + case MSG_CLICK: + last_draw = 0; + + /* track the mouse until it is released */ + while(gui_mouse_b()) + { + down = mouse_in_rect(d->x, d->y, d->w, d->h); + + /* redraw? */ + if(last_draw != down) + { + if(down != selected) + d->flags |= D_SELECTED; + else + d->flags &= ~D_SELECTED; + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + last_draw = down; + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + /* redraw in normal state */ + if(down) + { + if(d->flags&D_EXIT) + { + d->flags &= ~D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + } + } + + /* should we close the dialog? */ + if(down && (d->flags & D_EXIT)) + return D_CLOSE; + + break; + } + + return D_O_K; +} + +/* jwin_edit_proc: + * An editable text object (the dp field points to the string). When it + * has the input focus (obtained by clicking on it with the mouse), text + * can be typed into this object. The d1 field specifies the maximum + * number of characters that it will accept, and d2 is the text cursor + * position within the string. + */ +int jwin_edit_proc(int msg, DIALOG *d, int c) +{ + int f, l, p, w, x, y, fg, bg; + int b; + int scroll; + char *s; + char buf[2]; + char nullbuf[2]; + sprintf(nullbuf, " "); + + if(d->dp==NULL) + { + d->dp=(void *)nullbuf; + } + + s = (char*)d->dp; + l = (int)strlen(s); + + if(d->d2 > l) + d->d2 = l; + + /* calculate maximal number of displayable characters */ + b = x = 0; + + if(d->d2 == l) + { + buf[0] = ' '; + buf[1] = 0; + + if(d->dp2) + x = text_length((FONT*)d->dp2, buf); + else + x = text_length(font, buf); + } + + buf[1] = 0; + + for(p=d->d2; p>=0; p--) + { + buf[0] = s[p]; + b++; + + if(d->dp2) + x += text_length((FONT*)d->dp2, buf); + else + x += text_length(font, buf); + + if(x > d->w-6) + break; + } + + if(x <= d->w-6) + { + b = l; + scroll = FALSE; + } + else + { + b--; + scroll = TRUE; + } + + FONT *oldfont = font; + + switch(msg) + { + + case MSG_START: + d->d2 = (int)strlen((char*)d->dp);; + break; + + case MSG_DRAW: + if(d->dp2) + { + font = (FONT*)d->dp2; + } + + fg = (d->flags & D_DISABLED) || (d->flags & D_READONLY) ? scheme[jcMEDDARK] : scheme[jcTEXTFG]; + bg = (d->flags & D_DISABLED) || (d->flags & D_READONLY) ? scheme[jcBOX] : scheme[jcTEXTBG]; + x = 3; + y = (d->h - text_height(font)) / 2 + d->y; + + /* first fill in the edges */ + + if(y > d->y+2) + rectfill(screen, d->x+2, d->y+2, d->x+d->w-3, y-1, bg); + + if(y+text_height(font)-1 < d->y+d->h-2) + rectfill(screen, d->x+2, y+text_height(font)-1, d->x+d->w-3, d->y+d->h-3, bg); + + _allegro_vline(screen, d->x+2, d->y+2, d->y+d->h-3, bg); + + /* now the text */ + + if(scroll) + { + p = d->d2-b+1; + b = d->d2; + } + else + p = 0; + + for(; p<=b; p++) + { + buf[0] = s[p] ? s[p] : ' '; + w = text_length(font, buf); + + if(x+w > d->w) + break; + + f = ((p == d->d2) && (d->flags & D_GOTFOCUS)); + textout_ex(screen, font, buf, d->x+x, y, f ? bg : fg,f ? fg : bg); + x += w; + } + + if(x < d->w-2) + rectfill(screen, d->x+x, y, d->x+d->w-3, y+text_height(font)-1, bg); + + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, FR_DEEP); + font = oldfont; + break; + + case MSG_CLICK: + x = d->x+3; + + if(scroll) + { + p = d->d2-b+1; + b = d->d2; + } + else + p = 0; + + for(; pdp2) ? (FONT*)d->dp2 : font, buf); + + if(x > gui_mouse_x()) + break; + } + + d->d2 = MID(0, p, l); + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + break; + + case MSG_WANTFOCUS: + case MSG_LOSTFOCUS: + case MSG_KEY: + return D_WANTFOCUS; + + case MSG_CHAR: + if((c >> 8) == KEY_LEFT) + { + if(d->d2 > 0) d->d2--; + } + else if((c >> 8) == KEY_RIGHT) + { + if(d->d2 < l) d->d2++; + } + else if((c >> 8) == KEY_HOME) + { + d->d2 = 0; + } + else if((c >> 8) == KEY_END) + { + d->d2 = l; + } + else if((c >> 8) == KEY_DEL) + { + if(d->d2 < l) + for(p=d->d2; s[p]; p++) + s[p] = s[p+1]; + } + else if((c >> 8) == KEY_BACKSPACE) + { + if(d->d2 > 0) + { + d->d2--; + + for(p=d->d2; s[p]; p++) + s[p] = s[p+1]; + } + } + else if((c >> 8) == KEY_ENTER) + { + if(d->flags & D_EXIT) + { + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + return D_CLOSE; + } + else + return D_O_K; + } + else if((c >> 8) == KEY_TAB) + { + return D_O_K; + } + else if(!(d->flags & D_READONLY)) + { + c &= 0xFF; + + if((c >= 32) && (c <= 255)) + { + if(l < d->d1) + { + while(l >= d->d2) + { + s[l+1] = s[l]; + l--; + } + + s[d->d2] = c; + d->d2++; + } + } + else + return D_O_K; + } + + /* if we changed something, jwinBETTER redraw... */ + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + return D_USED_CHAR; + } + + return D_O_K; +} + +int jwin_hexedit_proc_old(int msg,DIALOG *d,int c) +{ + if(msg==MSG_CHAR) + if(((isalpha(c&255) && !isxdigit(c&255))) || ispunct(c&255)) + return D_USED_CHAR; + + return jwin_edit_proc(msg,d,isalpha(c&255)?c&0xDF:c); +} + +int jwin_hexedit_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_CHAR) + if((isalpha(c&255) && !isxdigit(c&255)) || ispunct(c&255)) + return D_O_K; + + return jwin_edit_proc(msg,d,c); +} + +int jwin_numedit_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_CHAR) + if((isalnum(c&255) && !isdigit(c&255)) && ((c&255)!='-')) + return D_O_K; + + return jwin_edit_proc(msg,d,c); +} + +/* _calc_scroll_bar: + * Helps find positions of buttons on the scroll bar. + */ +void _calc_scroll_bar(int h, int height, int listsize, int offset, + int *bh, int *len, int *jwinPOS) +{ + *bh = zc_max(zc_min((h-4)/2, 14), 0); + *len = zc_max(((h - 32) * height + listsize/2) / listsize , 6); + *jwinPOS = ((h - 32 - *len) * offset) / (listsize-height); +} + +/* _handle_scrollable_click: + * Helper to process a click on a scrollable object. + */ + +void _handle_jwin_scrollable_scroll_click(DIALOG *d, int listsize, int *offset, FONT *fnt) +{ + enum { top_btn, bottom_btn, bar, top_bar, bottom_bar }; + + int xx, yy; + int height = (d->h-3) / text_height(fnt); + int hh = d->h - 32; + int obj = bar; + int bh, len, jwinPOS; + int down = 1, last_draw = 0; + int redraw = 0, mouse_delay = 0; + + _calc_scroll_bar(d->h, height, listsize, *offset, &bh, &len, &jwinPOS); + + xx = d->x + d->w - 18; + + // find out which object is being clicked + + yy = gui_mouse_y(); + + if(yy <= d->y+2+bh) + { + obj = top_btn; + yy = d->y+2; + } + else if(yy >= d->y+d->h-2-bh) + { + obj = bottom_btn; + yy = d->y+d->h-2-bh; + } + else if(d->h > 32+6) + { + if(yy < d->y+2+bh+jwinPOS) + obj = top_bar; + else if(yy >= d->y+2+bh+jwinPOS+len) + obj = bottom_bar; + } + + while(gui_mouse_b()) + { + _calc_scroll_bar(d->h, height, listsize, *offset, &bh, &len, &jwinPOS); + + switch(obj) + { + case top_btn: + case bottom_btn: + down = mouse_in_rect(xx, yy, 16, bh); + + if(!down) + mouse_delay = 0; + else + { + if((mouse_delay&1)==0) + { + if(obj==top_btn && *offset>0) + { + (*offset)--; + redraw = 1; + } + + if(obj==bottom_btn && *offsetproc(MSG_DRAW, d, 0); + draw_arrow_button(screen, xx, yy, 16, bh, obj==top_btn, down*3); + unscare_mouse(); + last_draw = down; + } + + break; + + case top_bar: + case bottom_bar: + if(mouse_in_rect(xx, d->y+2, 16, d->h-4)) + { + if(obj==top_bar) + { + if(gui_mouse_y() < d->y+2+bh+jwinPOS) + yy = *offset - height; + } + else + { + if(gui_mouse_y() >= d->y+2+bh+jwinPOS+len) + yy = *offset + height; + } + + if(yy < 0) + yy = 0; + + if(yy > listsize-height) + yy = listsize-height; + + if(yy != *offset) + { + *offset = yy; + vsync(); + scare_mouse(); + d->proc(MSG_DRAW, d, 0); + unscare_mouse(); + } + } + + _calc_scroll_bar(d->h, height, listsize, *offset, &bh, &len, &jwinPOS); + + if(!mouse_in_rect(xx, d->y+2+bh+jwinPOS, 16, len)) + break; + + // fall through + + case bar: + default: + xx = gui_mouse_y() - jwinPOS; + + while(gui_mouse_b()) + { + yy = (listsize * (gui_mouse_y() - xx) + hh/2) / hh; + + if(yy > listsize-height) + yy = listsize-height; + + if(yy < 0) + yy = 0; + + if(yy != *offset) + { + *offset = yy; + scare_mouse(); + d->proc(MSG_DRAW, d, 0); + unscare_mouse(); + } + + // let other objects continue to animate + broadcast_dialog_message(MSG_IDLE, 0); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + break; + + } // switch(obj) + + redraw = 0; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + // let other objects continue to animate + broadcast_dialog_message(MSG_IDLE, 0); + } + + if(last_draw==1) + { + scare_mouse(); + draw_arrow_button(screen, xx, yy, 16, bh, obj==top_btn, 0); + unscare_mouse(); + } +} + +/* _handle_scrollable_scroll: + * Helper function to scroll through a scrollable object. + */ + +static void _handle_jwin_scrollable_scroll(DIALOG *d, int listsize, int *index, int *offset, FONT *fnt) +{ + int height = (d->h-3) / text_height(fnt); + + if(listsize <= 0) + { + *index = *offset = 0; + return; + } + + // check selected item + if(*index < 0) + *index = 0; + else if(*index >= listsize) + *index = listsize - 1; + + // check scroll position + while((*offset > 0) && (*offset + height > listsize)) + (*offset)--; + + if(*offset >= *index) + { + if(*index < 0) + *offset = 0; + else + *offset = *index; + } + else + { + while((*offset + height - 1) < *index) + (*offset)++; + } +} + +/* idle_cb: + * rest_callback() routine to keep dialogs animating nice and smoothly. + */ + +static void idle_cb() +{ + broadcast_dialog_message(MSG_IDLE, 0); +} + +/* _handle_listbox_click: + * Helper to process a click on a listbox, doing hit-testing and moving + * the selection. + */ + +static void _handle_jwin_listbox_click(DIALOG *d) +{ + ListData *data = (ListData *)d->dp; + char *sel = (char *)d->dp2; + int listsize, height; + int i, j; + + (*data->listFunc)(-1, &listsize); + + if(!listsize) + return; + + height = (d->h-3) / text_height(*data->font); + + i = MID(0, ((gui_mouse_y() - d->y - 4) / text_height(*data->font)), + ((d->h-3) / text_height(*data->font) - 1)); + i += d->d2; + + if(i < d->d2) + i = d->d2; + else + { + if(i > d->d2 + height-1) + i = d->d2 + height-1; + + if(i >= listsize) + i = listsize-1; + } + + if(gui_mouse_y() <= d->y) + i = MAX(i-1, 0); + else if(gui_mouse_y() >= d->y+d->h) + i = MIN(i+1, listsize-1); + + if(i != d->d1) + { + if(sel) + { + if(key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG)) + { + if((key_shifts & KB_SHIFT_FLAG) || (d->flags & D_INTERNAL)) + { + for(j=MIN(i, d->d1); j<=MAX(i, d->d1); j++) + sel[j] = TRUE; + } + else + sel[i] = TRUE; + } + } + + d->d1 = i; + i = d->d2; + _handle_jwin_scrollable_scroll(d, listsize, &d->d1, &d->d2, *data->font); + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + + if(i != d->d2) + rest_callback(MID(10, text_height(font)*16-d->h, 100), idle_cb); + } +} + +/* _jwin_draw_scrollable_frame: + * Helper function to draw a frame for all objects with vertical scrollbars. + */ +void _jwin_draw_scrollable_frame(DIALOG *d, int listsize, int offset, int height, int type) +{ + int jwinPOS, len; + int xx, yy, hh, bh; + static BITMAP *pattern = NULL; // just create it once + + /* draw frame */ + if(type) + // for droplists + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, FR_DARK); + else + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, FR_DEEP); + + /* possibly draw scrollbar */ + if(listsize > height) + { + _calc_scroll_bar(d->h, height, listsize, offset, &bh, &len, &jwinPOS); + + xx = d->x + d->w - 18; + + draw_arrow_button(screen, xx, d->y+2, 16, bh, 1, 0); + draw_arrow_button(screen, xx, d->y+d->h-2-bh, 16, bh, 0, 0); + + if(d->h > 32) + { + yy = d->y + 16; + hh = (d->h-32); + + /* create and draw the scrollbar */ + if(!pattern) + pattern = create_bitmap_ex(bitmap_color_depth(screen),2,2); + + putpixel(pattern, 0, 1, scheme[jcLIGHT]); + putpixel(pattern, 1, 0, scheme[jcLIGHT]); + putpixel(pattern, 0, 0, scheme[jcBOX]); + putpixel(pattern, 1, 1, scheme[jcBOX]); + + drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0); + rectfill(screen, xx, yy, xx+15, yy+hh-1, 0); + solid_mode(); + + if(d->h > 32+6) + { + jwin_draw_button(screen, xx, yy+jwinPOS, 16, len, 0, 1); + } + } + + if(d->flags & D_GOTFOCUS) + _dotted_rect(d->x+2, d->y+2, d->x+d->w-19, d->y+d->h-3, scheme[jcTEXTFG], scheme[jcTEXTBG]); + } + else if(d->flags & D_GOTFOCUS) + _dotted_rect(d->x+2, d->y+2, d->x+d->w-3, d->y+d->h-3, scheme[jcTEXTFG], scheme[jcTEXTBG]); +} + +/* _jwin_draw_listbox: + * Helper function to draw a listbox object. + */ +void _jwin_draw_listbox(DIALOG *d) +{ + int height, listsize, i, len, bar, x, y, w; + int fg_color, bg_color, fg, bg; + char *sel = (char*)d->dp2; + char s[1024]; + ListData *data = (ListData *)d->dp; + + (*data->listFunc)(-1, &listsize); + height = (d->h-3) / text_height(*data->font); + bar = (listsize > height); + w = (bar ? d->w-21 : d->w-5); + fg_color = (d->flags & D_DISABLED) ? scheme[jcMEDDARK] : (d->fg ? d->fg : scheme[jcTEXTFG]); + bg_color = (d->flags & D_DISABLED) ? scheme[jcBOX] : (d->bg ? d->bg : scheme[jcTEXTBG]); + + rectfill(screen, d->x+2, d->y+2, d->x+w+2, d->y+3, bg_color); + _allegro_vline(screen, d->x+2, d->y+4, d->y+d->h-3, bg_color); + _allegro_vline(screen, d->x+3, d->y+4, d->y+d->h-3, bg_color); + _allegro_vline(screen, d->x+w+1, d->y+4, d->y+d->h-3, bg_color); + _allegro_vline(screen, d->x+w+2, d->y+4, d->y+d->h-3, bg_color); + + /* draw box contents */ + for(i=0; id2+i < listsize) + { + if(d->d2+i == d->d1 && !(d->flags & D_DISABLED)) + { + fg = scheme[jcSELFG]; + bg = scheme[jcSELBG]; + } + else if((sel) && (sel[d->d2+i])) + { + fg = scheme[jcMEDDARK]; + bg = scheme[jcSELBG]; + } + else + { + fg = fg_color; + bg = bg_color; + } + + strncpy(s, (*data->listFunc)(i+d->d2, NULL), 1023); + x = d->x + 4; + y = d->y + 4 + i*text_height(*data->font); + // text_mode(bg); + rectfill(screen, x, y, x+7, y+text_height(*data->font)-1, bg); + x += 8; + len = (int)strlen(s); + + while(text_length(*data->font, s) >= d->w - (bar ? 26 : 10)) + { + len--; + s[len] = 0; + } + + textout_ex(screen, *data->font, s, x, y, fg,bg); + x += text_length(*data->font, s); + + if(x <= d->x+w) + rectfill(screen, x, y, d->x+w, y+text_height(*data->font)-1, bg); + } + else + rectfill(screen, d->x+2, d->y+4+i*text_height(*data->font), + d->x+w+2, d->y+3+(i+1)*text_height(*data->font), bg_color); + } + + if(d->y+4+i*text_height(font) <= d->y+d->h-3) + rectfill(screen, d->x+2, d->y+4+i*text_height(*data->font), + d->x+w+2, d->y+d->h-3, bg_color); + + /* draw frame, maybe with scrollbar */ + _jwin_draw_scrollable_frame(d, listsize, d->d2, height, (d->flags&D_USER)?1:0); +} + +/* jwin_list_proc: + * A list box object. The dp field points to a ListData struct containing + * a function which it will call + * to obtain information about the list. This should follow the form: + * char * (int index, int *list_size); + * If index is zero or positive, the function should return a pointer to + * the string which is to be displayed at position index in the list. If + * index is negative, it should return null and list_size should be set + * to the number of items in the list. The list box object will allow the + * user to scroll through the list and to select items list by clicking + * on them, and if it has the input focus also by using the arrow keys. If + * the D_EXIT flag is set, double clicking on a list item will cause it to + * close the dialog. The index of the selected item is held in the d1 + * field, and d2 is used to store how far it has scrolled through the list. + */ +int jwin_list_proc(int msg, DIALOG *d, int c) +{ + ListData *data = (ListData *)d->dp; + int listsize, i, bottom, height, bar, orig; + char *sel = (char *)d->dp2; + int redraw = FALSE; + + switch(msg) + { + + case MSG_START: + (*data->listFunc)(-1, &listsize); + _handle_jwin_scrollable_scroll(d, listsize, &d->d1, &d->d2, *data->font); + break; + + case MSG_DRAW: + _jwin_draw_listbox(d); + break; + + case MSG_CLICK: + (*data->listFunc)(-1, &listsize); + height = (d->h-3) / text_height(*data->font); + bar = (listsize > height); + + if((!bar) || (gui_mouse_x() < d->x+d->w-18)) + { + if((sel) && (!(key_shifts & KB_CTRL_FLAG))) + { + for(i=0; iflags |= D_INTERNAL; + _handle_jwin_listbox_click(d); + d->flags &= ~D_INTERNAL; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + if(rightClicked && (d->flags&(D_USER<<1))!=0 && d->dp3) + { + typedef void (*funcType)(int /* index */, int /* x */, int /* y */); + funcType func=reinterpret_cast(d->dp3); + func(d->d1, gui_mouse_x(), gui_mouse_y()); + } + + if(d->flags & D_USER) + { + if(listsize) + { + clear_keybuf(); + return D_CLOSE; + } + } + } + else + { + _handle_jwin_scrollable_scroll_click(d, listsize, &d->d2, *data->font); + } + + break; + + case MSG_DCLICK: + // Ignore double right-click + if((gui_mouse_b()&2)!=0) + break; + + (*data->listFunc)(-1, &listsize); + height = (d->h-3) / text_height(*data->font); + bar = (listsize > height); + + if((!bar) || (gui_mouse_x() < d->x+d->w-18)) + { + if(d->flags & D_EXIT) + { + if(listsize) + { + i = d->d1; + object_message(d, MSG_CLICK, 0); + + if(i == d->d1) + return D_CLOSE; + } + } + } + + break; + + case MSG_KEY: + (*data->listFunc)(-1, &listsize); + + if((listsize) && (d->flags & D_EXIT)) + return D_CLOSE; + + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_WHEEL: + (*data->listFunc)(-1, &listsize); + height = (d->h-4) / text_height(*data->font); + + if(height < listsize) + { + int delta = (height > 3) ? 3 : 1; + + if(c > 0) + { + i = MAX(0, d->d2-delta); + } + else + { + i = MIN(listsize-height, d->d2+delta); + } + + if(i != d->d2) + { + d->d2 = i; + object_message(d, MSG_DRAW, 0); + } + } + + break; + + case MSG_CHAR: + (*data->listFunc)(-1,&listsize); + + if(listsize) + { + c >>= 8; + + bottom = d->d2 + (d->h-3)/text_height(*data->font) - 1; + + if(bottom >= listsize-1) + bottom = listsize-1; + + orig = d->d1; + + if(c == KEY_UP) + d->d1--; + else if(c == KEY_DOWN) + d->d1++; + else if(c == KEY_HOME) + d->d1 = 0; + else if(c == KEY_END) + d->d1 = listsize-1; + else if(c == KEY_PGUP) + { + if(d->d1 > d->d2) + d->d1 = d->d2; + else + d->d1 -= (bottom - d->d2); + } + else if(c == KEY_PGDN) + { + if(d->d1 < bottom) + d->d1 = bottom; + else + d->d1 += (bottom - d->d2); + } + else + return D_O_K; + + if(sel) + { + if(!(key_shifts & (KB_SHIFT_FLAG | KB_CTRL_FLAG))) + { + for(i=0; id1); i<=MAX(orig, d->d1); i++) + { + if(key_shifts & KB_CTRL_FLAG) + sel[i] = (i != d->d1); + else + sel[i] = TRUE; + } + } + } + + /* if we changed something, jwinBETTER redraw... */ + _handle_jwin_scrollable_scroll(d, listsize, &d->d1, &d->d2, *data->font); + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + return D_USED_CHAR; + } + + break; + } + + return D_O_K; +} + +/* _jwin_draw_textbox: + * Helper function to draw a textbox object. + */ +void _jwin_draw_textbox(char *thetext, int *listsize, int draw, int offset, + int wword, int tabsize, int x, int y, int w, int h, + int disabled) +{ + int fg = scheme[jcTEXTFG]; + int bg = scheme[jcTEXTBG]; + int y1 = y+4; + int x1; + int len; + int ww = w-10; + char s[16]; + char text[16]; + char space[16]; + char *printed = text; + char *scanned = text; + char *oldscan = text; + char *ignore = NULL; + char *tmp, *ptmp; + int width; + int line = 0; + int i = 0; + int noignore; + // int rtm; + + usetc(s+usetc(s, '.'), 0); + usetc(text+usetc(text, ' '), 0); + usetc(space+usetc(space, ' '), 0); + + /* find the correct text */ + if(thetext != NULL) + { + printed = thetext; + scanned = thetext; + } + + /* choose the text color */ + if(disabled) + { + fg = scheme[jcMEDDARK]; + bg = scheme[jcBOX]; + } + + /* do some drawing setup */ + if(draw) + { + /* initial start blanking at the top */ + rectfill(screen, x+2, y+2, x+w-2, y1-1, bg); + } + + // rtm = text_mode(bg); + + /* loop over the entire string */ + for(;;) + { + width = 0; + + /* find the next break */ + while(ugetc(scanned)) + { + /* check for a forced break */ + if(ugetc(scanned) == '\n') + { + scanned += uwidth(scanned); + + /* we are done parsing the line end */ + break; + } + + /* the next character length */ + usetc(s+usetc(s, ugetc(scanned)), 0); + len = text_length(font, s); + + /* modify length if its a tab */ + if(ugetc(s) == '\t') + len = tabsize * text_length(font, space); + + /* check for the end of a line by excess width of next char */ + if(width+len >= ww) + { + /* we have reached end of line do we go back to find start */ + if(wword) + { + /* remember where we were */ + oldscan = scanned; + noignore = FALSE; + + /* go backwards looking for start of word */ + while(!uisspace(ugetc(scanned))) + { + /* don't wrap too far */ + if(scanned == printed) + { + /* the whole line is filled, so stop here */ + tmp = ptmp = scanned; + + while(ptmp != oldscan) + { + ptmp = tmp; + tmp += uwidth(tmp); + } + + scanned = ptmp; + noignore = TRUE; + break; + } + + /* look further backwards to wrap */ + tmp = ptmp = printed; + + while(tmp < scanned) + { + ptmp = tmp; + tmp += uwidth(tmp); + } + + scanned = ptmp; + } + + /* put the space at the end of the line */ + if(!noignore) + { + ignore = scanned; + scanned += uwidth(scanned); + } + else + ignore = NULL; + + /* check for endline at the convenient place */ + if(ugetc(scanned) == '\n') + scanned += uwidth(scanned); + } + + /* we are done parsing the line end */ + break; + } + + /* the character can be added */ + scanned += uwidth(scanned); + width += len; + } + + /* check if we are to print it */ + if((draw) && (line >= offset) && (y1+text_height(font) < (y+h-3))) + { + x1 = x+4; + + /* the initial blank bit */ + rectfill(screen, x+2, y1, x1-1, y1+text_height(font), bg); + + /* print up to the marked character */ + while(printed != scanned) + { + /* do special stuff for each character */ + switch(ugetc(printed)) + { + + case '\r': + case '\n': + /* don't print endlines in the text */ + break; + + /* possibly expand the tabs */ + case '\t': + for(i=0; iflags & D_DISABLED) ? gui_mg_color : d->fg; + + FONT *oldfont=NULL; + + if(d->dp2!=NULL) + { + oldfont=font; + font=(FONT*)d->dp2; + } + + /* calculate the actual height */ + height = (d->h-4) / text_height(font); + + switch(msg) + { + + case MSG_START: + /* measure how many lines of text we contain */ + _jwin_draw_textbox((char*)d->dp, &d->d1, + 0, /* DONT DRAW anything */ + d->d2, !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w, d->h, + (d->flags & D_DISABLED)); + break; + + case MSG_DRAW: + /* tell the object to sort of draw, but only calculate the listsize */ + _jwin_draw_textbox((char*)d->dp, &d->d1, + 0, /* DONT DRAW anything */ + d->d2, !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w, d->h, + (d->flags & D_DISABLED)); + + if(d->d1 > height) + { + bar = 16; + } + else + { + bar = 0; + d->d2 = 0; + } + + /* now do the actual drawing */ + _jwin_draw_textbox((char*)d->dp, &d->d1, 1, d->d2, + !(d->flags & D_SELECTED), 8, + d->x, d->y, d->w-bar-1, d->h, + (d->flags & D_DISABLED)); + + /* draw the frame around */ + _jwin_draw_scrollable_frame(d, d->d1, d->d2, height, 0); + break; + + case MSG_CLICK: + /* figure out if it's on the text or the scrollbar */ + bar = (d->d1 > height); + + if((!bar) || (gui_mouse_x() < d->x+d->w-18)) + { + /* clicked on the text area */ + ret = D_O_K; + } + else + { + /* clicked on the scroll area */ + _handle_jwin_scrollable_scroll_click(d, d->d1, &d->d2, font); + } + + break; + + case MSG_WHEEL: + l = (d->h-8)/text_height(font); + delta = (l > 3) ? 3 : 1; + + // scroll, making sure that the list stays in bounds + start = d->d2; + d->d2 = (c > 0) ? MAX(0, d->d2-delta) : MIN(d->d1-l, d->d2+delta); + + // if we changed something, jwinBETTER redraw... + if(d->d2 != start) + { + d->flags |= D_DIRTY; + } + + ret = D_O_K; + break; + + case MSG_CHAR: + start = d->d2; + used = D_USED_CHAR; + + if(d->d1 > 0) + { + if(d->d2 > 0) + top = d->d2+1; + else + top = 0; + + l = (d->h-3)/text_height(font); + + bottom = d->d2 + l - 1; + + if(bottom >= d->d1-1) + bottom = d->d1-1; + else + bottom--; + + if((c>>8) == KEY_UP) + d->d2--; + else if((c>>8) == KEY_DOWN) + d->d2++; + else if((c>>8) == KEY_HOME) + d->d2 = 0; + else if((c>>8) == KEY_END) + d->d2 = d->d1-l; + else if((c>>8) == KEY_PGUP) + d->d2 = d->d2-(bottom-top); + else if((c>>8) == KEY_PGDN) + d->d2 = d->d2+(bottom-top); + else + used = D_O_K; + + /* make sure that the list stays in bounds */ + if(d->d2 > d->d1-l) + d->d2 = d->d1-l; + + if(d->d2 < 0) + d->d2 = 0; + } + else + used = D_O_K; + + /* if we changed something, jwinBETTER redraw... */ + if(d->d2 != start) + { + scare_mouse(); + d->proc(MSG_DRAW, d, 0); + unscare_mouse(); + } + + ret = used; + break; + + case MSG_WANTFOCUS: + + /* if we don't have a scrollbar we can't do anything with the focus */ + if(d->d1 > height) + ret = D_WANTFOCUS; + + break; + + default: + ret = D_O_K; + } + + if(d->dp2!=NULL) + { + font=oldfont; + } + + return ret; +} + +/* jwin_slider_proc: + * A slider control object. This object returns a value in d2, in the + * range from 0 to d1. It will display as a vertical slider if h is + * greater than or equal to w; otherwise, it will display as a horizontal + * slider. dp can contain an optional bitmap to use for the slider handle; + * dp2 can contain an optional callback function, which is called each + * time d2 changes. The callback function should have the following + * prototype: + * + * int function(void *dp3, int d2); + * + * The d_slider_proc object will return the value of the callback function. + */ +int jwin_slider_proc(int msg, DIALOG *d, int c) +{ + BITMAP *slhan = NULL; + int sfg; /* slider foreground color */ + int vert = TRUE; /* flag: is slider vertical? */ + int hh = 7; /* handle height (width for horizontal sliders) */ + int hmar; /* handle margin */ + int slp; /* slider position */ + int irange; + int slx, sly, slh, slw; + fixed slratio, slmax, slpos; + ASSERT(d); + + /* check for slider direction */ + if(d->h < d->w) + { + vert = FALSE; + } + + /* set up the metrics for the control */ + if(d->dp != NULL) + { + slhan = (BITMAP *)d->dp; + + if(vert) + { + hh = slhan->h; + } + else + { + hh = slhan->w; + } + } + + hmar = hh/2; + irange = (vert) ? d->h : d->w; + slmax = itofix(irange-hh); + slratio = slmax / (d->d1); + slpos = slratio * d->d2; + slp = fixtoi(slpos); + + switch(msg) + { + case MSG_DRAW: + // sfg = (d->flags & D_DISABLED) ? gui_mg_color : scheme[jcBOXFG]; + sfg = (d->flags & D_DISABLED) ? scheme[jcMEDDARK] : scheme[jcBOXFG]; + + if(vert) + { + rectfill(screen, d->x, d->y, d->x+d->w/2-2, d->y+d->h, scheme[jcBOX]); + rectfill(screen, d->x+d->w/2-1, d->y, d->x+d->w/2+1, d->y+d->h, sfg); + rectfill(screen, d->x+d->w/2+2, d->y, d->x+d->w, d->y+d->h, scheme[jcBOX]); + } + else + { + rectfill(screen, d->x, d->y, d->x+d->w, d->y+d->h/2-2, scheme[jcBOX]); + rectfill(screen, d->x, d->y+d->h/2-1, d->x+d->w, d->y+d->h/2+1, sfg); + rectfill(screen, d->x, d->y+d->h/2+2, d->x+d->w, d->y+d->h, scheme[jcBOX]); + } + + if(d->flags & D_GOTFOCUS) + { + _dotted_rect(d->x, d->y, d->x+d->w, d->y+d->h, sfg, scheme[jcBOX]); + } + + /* okay, background and slot are drawn, now draw the handle */ + if(slhan) + { + if(vert) + { + slx = d->x+(d->w/2)-(slhan->w/2); + sly = d->y+d->h-(hh+slp); + } + else + { + slx = d->x+slp; + sly = d->y+(d->h/2)-(slhan->h/2); + } + + draw_sprite(screen, slhan, slx, sly); + } + else + { + /* draw default handle */ + if(vert) + { + slx = d->x; + sly = d->y+d->h-(hh+slp); + slw = d->w; + slh = hh; + } + else + { + slx = d->x+slp; + sly = d->y; + slw = hh; + slh = d->h; + } + + jwin_draw_button(screen, slx, sly, slw+1, slh+1, d->flags&D_DISABLED?3:0, 0); + } + + break; + + default: + return d_jslider_proc(msg, d, c); + } + + return D_O_K; +} + +/*********************/ +/***** Menus *****/ +/*********************/ + +typedef struct MENU_INFO /* information about a popup menu */ +{ + MENU *menu; /* the menu itself */ + struct MENU_INFO *parent; /* the parent menu, or NULL for root */ + int bar; /* set if it is a top level menu bar */ + int size; /* number of items in the menu */ + int sel; /* selected item */ + int hover; /* set if is bar and child menu not down */ + int x, y, w, h; /* screen position of the menu */ + int (*proc)(); /* callback function */ + BITMAP *saved; /* saved what was underneath it */ +} MENU_INFO; + +/* get_menu_pos: + * Calculates the coordinates of an object within a top level menu bar. + */ +static void get_menu_pos(MENU_INFO *m, int c, int *x, int *y, int *w) +{ + int c2; + + *x = m->x + ((m->bar) ? 1 : 3); + + if(m->bar) + { + for(c2=0; c2menu[c2].text) + 16; + + *y = m->y+1; + *w = gui_strlen(m->menu[c].text) + 16; + } + else + { + *y = m->y + c*(text_height(font)+4) + 3; + *w = m->w - 6; + } +} + +/* draw_menu_item: + * Draws an item from a popup menu onto the screen. + */ +static void draw_menu_item(MENU_INFO *m, int c) +{ + int fg, bg; + int i, x, y, w, d=0; + int yofs = (m->bar) ? 1 : 0; + int h = text_height(font) + 4 + yofs; + int g = 0; + char buf[80], *tok; + int my; + + fg = scheme[jcBOXFG]; + bg = scheme[jcBOX]; + + if(m->menu[c].flags & D_DISABLED) + { + fg = scheme[jcMEDDARK]; + d = 1; + } + + if(c == m->sel) + { + if(m->bar) + g = !m->hover; + else + { + if(d) + d = 0; + else + fg = scheme[jcSELFG]; + + bg = scheme[jcSELBG]; + } + } + + get_menu_pos(m, c, &x, &y, &w); + + rectfill(screen, x, y, x+w-1, y+h-1, bg); + // text_mode(-1); + + if(m->menu[c].text[0] == 0) + { + _allegro_hline(screen, x+1, y+text_height(font)/2+2, x+w-2, scheme[jcMEDDARK]); + _allegro_hline(screen, x+1, y+text_height(font)/2+3, x+w-2, scheme[jcLIGHT]); + } + else + { + for(i=0; (m->menu[c].text[i]) && (m->menu[c].text[i] != '\t'); i++) + buf[i] = m->menu[c].text[i]; + + buf[i] = 0; + + if(d) + gui_textout_ex(screen, buf, x+9, y+yofs+2, scheme[jcLIGHT], -1, FALSE); + + gui_textout_ex(screen, buf, x+8+g, y+yofs+1+g, fg, -1, FALSE); + + if(m->menu[c].text[i] == '\t') + { + tok = m->menu[c].text+i+1; + + if(d) + gui_textout_ex(screen, tok, x+w-gui_strlen(tok)-7, y+yofs+2, scheme[jcLIGHT], -1, FALSE); + + gui_textout_ex(screen, tok, x+w-gui_strlen(tok)-8+g, y+yofs+1+g, fg, -1, FALSE); + } + + if(((m->menu[c].child) && (!m->bar))) + { + my = y + text_height(font)/2; + putpixel(screen, x+w-7, my-2, fg); + _allegro_hline(screen, x+w-7, my-1, x+w-6, fg); + _allegro_hline(screen, x+w-7, my+0, x+w-5, fg); + _allegro_hline(screen, x+w-7, my+1, x+w-4, fg); + _allegro_hline(screen, x+w-7, my+2, x+w-5, fg); + _allegro_hline(screen, x+w-7, my+3, x+w-6, fg); + putpixel(screen, x+w-7, my+4, fg); + + if(d) + { + line(screen, x+w-6, my+5, x+w-3, my+2, scheme[jcLIGHT]); + line(screen, x+w-6, my+4, x+w-4, my+2, scheme[jcLIGHT]); + } + } + } + + if((c == m->sel) && m->bar) + { + int c1 = scheme[jcLIGHT]; + int c2 = scheme[jcMEDDARK]; + + if(m->hover == 0) + { + c1 = scheme[jcMEDDARK]; + c2 = scheme[jcLIGHT]; + } + + _allegro_hline(screen, x, y, x+w-2, c1); + _allegro_vline(screen, x, y+1, y+h-2, c1); + _allegro_hline(screen, x, y+h-1, x+w-1, c2); + _allegro_vline(screen, x+w-1, y, y+h-2, c2); + } + + if(m->menu[c].flags & D_SELECTED) + { + line(screen, x+1, y+text_height(font)/2+1, x+3, y+text_height(font)+1, fg); + line(screen, x+3, y+text_height(font)+1, x+6, y+2, fg); + } +} + +/* draw_menu: + * Draws a popup menu onto the screen. + */ +static void draw_menu(MENU_INFO *m) +{ + int c; + + if(m->bar) + rectfill(screen, zc_max(0,m->x), zc_max(0,m->y), zc_min(m->x+m->w-1, screen->w), zc_min(m->y+m->h-1, screen->h), scheme[jcBOX]); + else + jwin_draw_win(screen, m->x, m->y, m->w, m->h, FR_WIN); + + for(c=0; m->menu[c].text; c++) + draw_menu_item(m, c); +} + +/* menu_mouse_object: + * Returns the index of the object the mouse is currently on top of. + */ +static int menu_mouse_object(MENU_INFO *m) +{ + int c; + int x, y, w; + + for(c=0; csize; c++) + { + get_menu_pos(m, c, &x, &y, &w); + + if((gui_mouse_x() >= x) && (gui_mouse_x() < x+w) && + (gui_mouse_y() >= y) && (gui_mouse_y() < y+(text_height(font)+4))) + return (m->menu[c].text[0]) ? c : -1; + } + + return -1; +} + +/* mouse_in_parent_menu: + * Recursively checks if the mouse is inside a menu or any of its parents. + */ +static int mouse_in_parent_menu(MENU_INFO *m) +{ + int c; + + if(!m) + return FALSE; + + c = menu_mouse_object(m); + + if((c >= 0) && (c != m->sel)) + return TRUE; + + return mouse_in_parent_menu(m->parent); +} + +/* fill_menu_info: + * Fills a menu info structure when initialising a menu. + */ +static void fill_menu_info(MENU_INFO *m, MENU *menu, MENU_INFO *parent, int bar, int x, int y, int minw, int minh) +{ + int c, i; + int extra = 0; + char buf[80], *tok; + int border = (bar)?0:1; + + m->menu = menu; + m->parent = parent; + m->bar = bar; + m->x = x - border*2; + m->y = y - border*2; + m->w = 2 + border*4; + + m->h = (m->bar) ? (text_height(font)+7) : 2 + border*4; + + m->proc = NULL; + m->sel = -1; + m->hover = 0; + + /* calculate size of the menu */ + for(m->size=0; m->menu[m->size].text; m->size++) + { + for(i=0; (m->menu[m->size].text[i]) && (m->menu[m->size].text[i] != '\t'); i++) + buf[i] = m->menu[m->size].text[i]; + + buf[i] = 0; + + c = gui_strlen(buf); + + if(m->bar) + { + m->w += c+16; + } + else + { + m->h += text_height(font)+4; + m->w = MAX(m->w, c+16); + } + + if(m->menu[m->size].text[i] == '\t') + { + tok = m->menu[m->size].text+i+1; + c = gui_strlen(tok); + extra = MAX(extra, c); + } + } + + if(extra) + m->w += extra+16; + + m->w = MAX(m->w, minw); + m->h = MAX(m->h, minh); +} + +/* menu_key_shortcut: + * Returns true if c is indicated as a keyboard shortcut by a '&' character + * in the specified string. + */ +static int menu_key_shortcut(int c, AL_CONST char *s) +{ + int d; + + while((d = ugetxc(&s)) != 0) + { + if(d == '&') + { + d = ugetc(s); + + if((d != '&') && (utolower(d) == utolower(c & 0xFF))) + return TRUE; + } + } + + return FALSE; +} + +/* menu_alt_key: + * Searches a menu for keyboard shortcuts, for the alt+letter to bring + * up a menu. + */ + +//#ifdef ALLEGRO_DOS +//int menu_alt_key(int k, MENU *m); +//#elif defined ALLEGRO_WINDOWS + +int menu_alt_key(int k, MENU *m) +{ + static unsigned char alt_table[] = + { + KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, + KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, + KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z + }; + + AL_CONST char *s; + int c, d; + + if(k & 0xFF) + return 0; + + k >>= 8; + + c = scancode_to_ascii(k); + + if(c) + { + k = c; + } + else + { + for(c=0; c<(int)sizeof(alt_table); c++) + { + if(k == alt_table[c]) + { + k = c + 'a'; + break; + } + } + + if(c >= (int)sizeof(alt_table)) + return 0; + } + + for(c=0; m[c].text; c++) + { + s = m[c].text; + + while((d = ugetxc(&s)) != 0) + { + if(d == '&') + { + d = ugetc(s); + + if((d != '&') && (utolower(d) == utolower(k))) + return k; + } + } + } + + return 0; +} + + +//#elif defined ALLEGRO_LINUX +//int menu_alt_key(int k, MENU *m); +//#elif defined ALLEGRO_MACOSX +//int menu_alt_key(int k, MENU *m); +//#endif + +/* _jwin_do_menu: + * The core menu control function, called by jwin_do_menu() and jwin_menu_proc(). + * + * I added joystick support. + */ +int _jwin_do_menu(MENU *menu, MENU_INFO *parent, int bar, int x, int y, int repos, int *dret, int minw, int minh) +{ + MENU_INFO m; + MENU_INFO *i; + int c, c2; + int ret = -1; + int mouse_on = gui_mouse_b(); + int joy_on = joy[joystick_index].stick[0].axis[0].d1 + joy[joystick_index].stick[0].axis[0].d2 + + joy[joystick_index].stick[0].axis[1].d1 + joy[joystick_index].stick[0].axis[1].d2 + + joy[joystick_index].button[0].b + joy[joystick_index].button[1].b; + int old_sel; + int mouse_sel; + int cur_sel=0; + int _x, _y; + int redraw = TRUE; + + scare_mouse(); + + fill_menu_info(&m, menu, parent, bar, x, y, minw, minh); + + if(repos) + { + m.x = MID(0, m.x, zq_screen_w-m.w-1); + m.y = MID(0, m.y, zq_screen_h-m.h-1); + } + + /* save screen under the menu */ + m.saved = create_bitmap_ex(bitmap_color_depth(screen),m.w+1, m.h+1); + + if(m.saved) + blit(screen, m.saved, m.x, m.y, 0, 0, m.w+1, m.h+1); + else + errno = ENOMEM; + + m.sel = mouse_sel = menu_mouse_object(&m); + + if(bar && !mouse_on) + m.hover = 1; + + if((m.sel < 0) && (!mouse_on) && (!bar)) + m.sel = 0; + + unscare_mouse(); + + do + { + rest(1); + old_sel = m.sel; + + c = menu_mouse_object(&m); + + if((gui_mouse_b()) || (c != mouse_sel)) + m.sel = mouse_sel = c; + + if(gui_mouse_b()) /* if button pressed */ + { + if((gui_mouse_x() < m.x) || (gui_mouse_x() > m.x+m.w) || + (gui_mouse_y() < m.y) || (gui_mouse_y() > m.y+m.h)) + { + if(!mouse_on) /* dismiss menu? */ + break; + + if(mouse_in_parent_menu(m.parent)) /* back to parent? */ + break; + } + + if((m.sel >= 0) && (m.menu[m.sel].child)) /* bring up child? */ + ret = m.sel; + + if(!mouse_on) cur_sel=m.sel; + + mouse_on = TRUE; + } + else /* button not pressed */ + { + if(mouse_on) /* selected an item? */ + { + //if(cur_sel == m.sel) + ret = m.sel; + } + + mouse_on = FALSE; + + poll_joystick(); + + if(joy[joystick_index].stick[0].axis[0].d1 + joy[joystick_index].stick[0].axis[0].d2 + + joy[joystick_index].stick[0].axis[1].d1 + joy[joystick_index].stick[0].axis[1].d2 + + joy[joystick_index].button[0].b + joy[joystick_index].button[1].b == 0) + joy_on = FALSE; + + c = 0; + + if(keypressed()) /* keyboard input */ + c = readkey(); + else if(!joy_on) /* joystick input */ + { + if(joy[joystick_index].stick[0].axis[1].d1) + { + c = KEY_UP << 8; + joy_on = TRUE; + } + + if(joy[joystick_index].stick[0].axis[1].d2) + { + c = KEY_DOWN << 8; + joy_on = TRUE; + } + + if(joy[joystick_index].stick[0].axis[0].d1) + { + c = KEY_LEFT << 8; + joy_on = TRUE; + } + + if(joy[joystick_index].stick[0].axis[0].d2) + { + c = KEY_RIGHT << 8; + joy_on = TRUE; + } + + if(joy[joystick_index].button[0].b | joy[joystick_index].button[1].b) + { + c = KEY_ENTER << 8; + joy_on = TRUE; + } + } + + if(c) + { + + if((c & 0xff) == 27) + { + ret = -1; + goto getout; + } + + switch(c >> 8) + { + + case KEY_LEFT: + if(m.parent) + { + if(m.parent->bar) + { + simulate_keypress(KEY_LEFT<<8); + simulate_keypress(KEY_DOWN<<8); + } + + ret = -1; + goto getout; + } + + /* fall through */ + + case KEY_UP: + if((((c >> 8) == KEY_LEFT) && (m.bar)) || + (((c >> 8) == KEY_UP) && (!m.bar))) + { + c = m.sel; + + do + { + c--; + + if(c < 0) + c = m.size - 1; + } + while((!(m.menu[c].text[0])) && (c != m.sel)); + + m.sel = c; + } + + break; + + case KEY_RIGHT: + if(((m.sel < 0) || (!m.menu[m.sel].child)) && + (m.parent) && (m.parent->bar)) + { + simulate_keypress(KEY_RIGHT<<8); + simulate_keypress(KEY_DOWN<<8); + ret = -1; + goto getout; + } + + /* fall through */ + + case KEY_DOWN: + if((m.sel >= 0) && (m.menu[m.sel].child) && + ((((c >> 8) == KEY_RIGHT) && (!m.bar)) || + (((c >> 8) == KEY_DOWN) && (m.bar)))) + { + ret = m.sel; + } + else if((((c >> 8) == KEY_RIGHT) && (m.bar)) || + (((c >> 8) == KEY_DOWN) && (!m.bar))) + { + c = m.sel; + + do + { + c++; + + if(c >= m.size) + c = 0; + } + while((!(m.menu[c].text[0])) && (c != m.sel)); + + m.sel = c; + } + + break; + + case KEY_SPACE: + case KEY_ENTER: + if(m.sel >= 0) + ret = m.sel; + + break; + + default: + if((!m.parent) && ((c & 0xff) == 0)) + c = menu_alt_key(c, m.menu); + + for(c2=0; m.menu[c2].text; c2++) + { + if(menu_key_shortcut(c, m.menu[c2].text)) + { + ret = m.sel = c2; + break; + } + } + + if(m.parent) + { + i = m.parent; + + for(c2=0; i->parent; c2++) + i = i->parent; + + c = menu_alt_key(c, i->menu); + + if(c) + { + while(c2-- > 0) + simulate_keypress(27); + + simulate_keypress(c); + ret = -1; + goto getout; + } + } + + break; + } + } + } + + if((redraw) || (m.sel != old_sel)) /* selection changed? */ + { + scare_mouse(); + + if(redraw) + { + draw_menu(&m); + redraw = FALSE; + } + else + { + if(old_sel >= 0) + draw_menu_item(&m, old_sel); + + if(m.sel >= 0) + draw_menu_item(&m, m.sel); + } + + unscare_mouse(); + } + + if((ret >= 0) && (m.menu[ret].flags & D_DISABLED)) + ret = -1; + + if(ret >= 0) /* child menu? */ + { + if(m.menu[ret].child) + { + if(m.bar) + { + if(m.hover) + { + m.hover = 0; + scare_mouse(); + draw_menu(&m); + unscare_mouse(); + } + + get_menu_pos(&m, ret, &_x, &_y, &c); + _x += 2; + _y += text_height(font)+7; + } + else + { + _x = m.x+m.w-3; + _y = m.y + (text_height(font)+4)*ret + text_height(font)/4; + } + + c = _jwin_do_menu(m.menu[ret].child, &m, FALSE, _x, _y, TRUE, NULL, 0, 0); + + if(c < 0) + { + ret = -1; + mouse_on = FALSE; + mouse_sel = menu_mouse_object(&m); + } + } + } + + if((m.bar) && (!gui_mouse_b()) && (!keypressed()) && + ((gui_mouse_x() < m.x) || (gui_mouse_x() > m.x+m.w) || + (gui_mouse_y() < m.y) || (gui_mouse_y() > m.y+m.h))) + break; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + + } + while(ret < 0); + +getout: + + if(dret) + *dret = 0; + + /* callback function? */ + if((!m.proc) && (ret >= 0)) + { + active_menu = &m.menu[ret]; + m.proc = active_menu->proc; + } + + if(ret >= 0) + { + if(parent) + parent->proc = m.proc; + else + { + if(m.proc) + { + c = m.proc(); + + if(dret) + *dret = c; + + clear_keybuf(); + } + } + } + + /* restore screen */ + if(m.saved) + { + scare_mouse(); + blit(m.saved, screen, 0, 0, m.x, m.y, m.w+1, m.h+1); + unscare_mouse(); + destroy_bitmap(m.saved); + } + + return ret; +} + +/* jwin_do_menu: + * Displays and animates a popup menu at the specified screen position, + * returning the index of the item that was selected, or -1 if it was + * dismissed. If the menu crosses the edge of the screen it will be moved. + */ +int jwin_do_menu(MENU *menu, int x, int y) +{ + int ret = _jwin_do_menu(menu, NULL, FALSE, x, y, TRUE, NULL, 0, 0); + + do + { + } + while(gui_mouse_b()); + + return ret; +} + +/* jwin_menu_proc: + * Dialog procedure for adding drop down menus to a GUI dialog. This + * displays the top level menu items as a horizontal bar (eg. across the + * top of the screen), and pops up child menus when they are clicked. + * When it executes one of the menu callback routines, it passes the + * return value back to the dialog manager, so these can return D_O_K, + * D_CLOSE, D_REDRAW, etc. + * + * Set the D_USER flag in d->flags to have it draw a frame around a bar menu. + */ +int jwin_menu_proc(int msg, DIALOG *d, int c) +{ + MENU_INFO m; + int ret = D_O_K; + int x; + + rest(1); + + switch(msg) + { + + case MSG_START: + fill_menu_info(&m, (MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, d->w+2, d->h+2); + d->w = m.w-2; + d->h = m.h-2; + break; + + case MSG_DRAW: + fill_menu_info(&m, (MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, d->w+2, d->h+2); + draw_menu(&m); + + if(d->flags&D_USER) + jwin_draw_frame(screen, d->x-3, d->y-3, d->w+6, d->h+6, FR_WIN); + + break; + + case MSG_XCHAR: + x = menu_alt_key(c, (MENU*)d->dp); + + if(!x) + break; + + ret |= D_USED_CHAR; + simulate_keypress(x); + /* fall through */ + + case MSG_GOTMOUSE: + case MSG_CLICK: + _jwin_do_menu((MENU*)d->dp, NULL, TRUE, d->x-1, d->y-1, FALSE, &x, d->w+2, d->h+2); + ret |= x; + + do + { + } + while(gui_mouse_b()); + + break; + } + + return ret; +} + +static DIALOG alert_dialog[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ctext_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +#define A_S1 1 +#define A_S2 2 +#define A_S3 3 +#define A_B1 4 +#define A_B2 5 +#define A_B3 6 + +/* jwin_alert3: + * Displays a simple alert box, containing three lines of text (s1-s3), + * and with either one, two, or three buttons. The text for these buttons + * is passed in b1, b2, and b3 (NULL for buttons which are not used), and + * the keyboard shortcuts in c1 and c2. Returns 1, 2, or 3 depending on + * which button was selected. + */ +int jwin_alert3(const char *title, const char *s1, const char *s2, const char *s3, const char *b1, const char *b2, const char *b3, int c1, int c2, int c3, FONT *title_font) +{ + int maxlen = 0; + int len1, len2, len3; + int avg_w = text_length(font, " "); + int avg_h = text_height(font)+is_large; + int buttons = 0; + int yofs = (title ? 22 : 0); + int b[3]; + int c; + +#define SORT_OUT_BUTTON(x) { \ + if (b##x) \ + { \ + alert_dialog[A_B##x].flags &= ~D_HIDDEN; \ + alert_dialog[A_B##x].key = c##x; \ + alert_dialog[A_B##x].dp = (void *)b##x; \ + len##x = gui_strlen(b##x); \ + b[buttons++] = A_B##x; \ + } \ + else \ + { \ + alert_dialog[A_B##x].flags |= D_HIDDEN; \ + len##x = 0; \ + } \ + } + + if(title_font) + { + alert_dialog[0].dp2=title_font; + } + + alert_dialog[A_S1].dp = alert_dialog[A_S2].dp = alert_dialog[A_S3].dp = + alert_dialog[A_B1].dp = alert_dialog[A_B2].dp = (void*)""; + + if(s1) + { + alert_dialog[A_S1].dp = (void *)s1; + maxlen = text_length(font, s1); + } + + if(s2) + { + alert_dialog[A_S2].dp = (void *)s2; + len1 = text_length(font, s2); + + if(len1 > maxlen) + maxlen = len1; + } + + if(s3) + { + alert_dialog[A_S3].dp = (void *)s3; + len1 = text_length(font, s3); + + if(len1 > maxlen) + maxlen = len1; + } + + SORT_OUT_BUTTON(1); + SORT_OUT_BUTTON(2); + SORT_OUT_BUTTON(3); + + len1 = MAX(len1, MAX(len2, len3)) + avg_w*3; + + if(len1*buttons > maxlen) + maxlen = len1*buttons; + + maxlen += avg_w*4; + maxlen=zc_max(text_length(title_font?title_font:font,title)+29,maxlen); + alert_dialog[0].w = maxlen; + alert_dialog[A_S1].x = alert_dialog[A_S2].x = alert_dialog[A_S3].x = + alert_dialog[0].x + maxlen/2; + + alert_dialog[A_B1].w = alert_dialog[A_B2].w = alert_dialog[A_B3].w = len1; + + alert_dialog[A_B1].x = alert_dialog[A_B2].x = alert_dialog[A_B3].x = + alert_dialog[0].x + maxlen/2 - len1/2; + + if(buttons == 3) + { + alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1*3/2 - avg_w; + alert_dialog[b[2]].x = alert_dialog[0].x + maxlen/2 + len1/2 + avg_w; + } + else if(buttons == 2) + { + alert_dialog[b[0]].x = alert_dialog[0].x + maxlen/2 - len1 - avg_w; + alert_dialog[b[1]].x = alert_dialog[0].x + maxlen/2 + avg_w; + } + + alert_dialog[0].h = avg_h*7 + 13 + yofs; + alert_dialog[A_S1].y = alert_dialog[0].y + avg_h + yofs; + alert_dialog[A_S2].y = alert_dialog[0].y + avg_h*2 + yofs; + alert_dialog[A_S3].y = alert_dialog[0].y + avg_h*3 + yofs; + alert_dialog[A_S1].h = alert_dialog[A_S2].h = alert_dialog[A_S3].h = avg_h; + + alert_dialog[A_B1].y = alert_dialog[A_B2].y = alert_dialog[A_B3].y = + alert_dialog[0].y + avg_h*5 + yofs; + + alert_dialog[A_B1].h = alert_dialog[A_B2].h = alert_dialog[A_B3].h = avg_h+13; + + alert_dialog[0].dp = (void *)title; + alert_dialog[0].flags = (title) ? D_EXIT : 0; + + jwin_center_dialog(alert_dialog); + set_dialog_color(alert_dialog, scheme[jcTEXTFG], scheme[jcBOX]); + + clear_keybuf(); + + do + { + } + while(gui_mouse_b()); + + if(is_large) + { + large_dialog(alert_dialog); + alert_dialog[0].d1 = 0; + } + + c = popup_zqdialog(alert_dialog, A_B1); + + if(c == A_B1) + return 1; + else if(c == A_B2) + return 2; + else + return 3; +} + +/* jwin_alert: + * Displays a simple alert box, containing three lines of text (s1-s3), + * and with either one or two buttons. The text for these buttons is passed + * in b1 and b2 (b2 may be null), and the keyboard shortcuts in c1 and c2. + * Returns 1 or 2 depending on which button was selected. + */ +int jwin_alert(const char *title, const char *s1, const char *s2, const char *s3, const char *b1, const char *b2, int c1, int c2, FONT *title_font) +{ + int ret; + + ret = jwin_alert3(title, s1, s2, s3, b1, b2, NULL, c1, c2, 0, title_font); + + if(ret > 2) + ret = 2; + + return ret; +} + +/*****************************************/ +/*********** drop list proc ************/ +/*****************************************/ + +static int d_dropcancel_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + d=d; + c=c; + + if(msg==MSG_CLICK || msg==MSG_DCLICK) + return D_CLOSE; + + return D_O_K; +} + +static DIALOG droplist_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3)*/ + { d_dropcancel_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_list_proc, 0, 0, 0, 0, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void*)close_dlg, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static int droplist(DIALOG *d) +{ + ListData *data = (ListData *)d->dp; + int d1 = d->d1; + int listsize, x, y, w, h, max_w; + + (*data->listFunc)(-1, &listsize); + y = d->y + d->h; + h = zc_min(listsize,8) * text_height(*data->font) + 8; + + if(y+h >= zq_screen_h) + { + y = d->y - h; + } + + x = d->x; + w = d->w; + max_w = zc_max(d->x+d->w, zq_screen_w-d->x); + + for(int i=0; ifont,(*data->listFunc)(i, NULL))+39)); + } + + if(x+w >= zq_screen_w) + { + x = d->x + d->w - w; + } + + droplist_dlg[1] = *d; + droplist_dlg[1].proc = &jwin_abclist_proc; + droplist_dlg[1].flags = D_EXIT + D_USER; + droplist_dlg[1].x = x; + droplist_dlg[1].y = y; + droplist_dlg[1].w = w; + droplist_dlg[1].h = h; + droplist_dlg[1].d2 = listsize<=8 ? 0 : zc_max(d1-3,0); + + // cancel + droplist_dlg[0].x = 0; + droplist_dlg[0].y = 0; + droplist_dlg[0].w = zq_screen_w; + droplist_dlg[0].h = zq_screen_h; + + /*if (is_large) + { + large_dialog(droplist_dlg); + alert_dialog[0].d1 = 0; + }*/ + if(popup_zqdialog(droplist_dlg,1)==1) + { + position_mouse_z(0); + return droplist_dlg[1].d1; + } + + position_mouse_z(0); + return d1; +} + +/* jwin_droplist_proc: + * A drop list... + */ +int jwin_droplist_proc(int msg,DIALOG *d,int c) +{ + int ret; + int down=0, last_draw=0; + int d1; + + switch(msg) + { + case MSG_CLICK: + if(mouse_in_rect(d->x+d->w-18,d->y+2,16,d->h)) + goto dropit; + + break; + + case MSG_KEY: + goto dropit; + break; + } + + d1 = d->d1; + ret = jwin_list_proc(msg,d,c); + + if(d->d1!=d->d2) + { + d->d1=d->d2; + scare_mouse(); + jwin_droplist_proc(MSG_DRAW, d, 0); + unscare_mouse(); + } + + if((d1 != d->d1) && (d->flags&D_EXIT)) + ret |= D_CLOSE; + + if(msg == MSG_DRAW) + { + draw_arrow_button(screen, d->x+d->w-18, d->y+2,16, d->h-4, 0, 0); + } + + return ret; + +dropit: + last_draw = 0; + + while(gui_mouse_b()) + { + down = mouse_in_rect(d->x+d->w-18,d->y+2,16,d->h); + + if(down!=last_draw) + { + scare_mouse(); + draw_arrow_button(screen, d->x+d->w-18, d->y+2,16, d->h-4, 0, down*3); + unscare_mouse(); + last_draw = down; + } + + clear_keybuf(); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + if(!down) + { + return D_O_K; + } + + scare_mouse(); + draw_arrow_button(screen, d->x+d->w-18, d->y+2,16, d->h-4, 0, 0); + unscare_mouse(); + + d1 = d->d1; + d->d2 = d->d1 = droplist(d); + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + + while(gui_mouse_b()) + clear_keybuf(); + + return ((d1 != d->d1) && (d->flags&D_EXIT)) ? D_CLOSE : D_O_K; +} + +/*****************************************/ +/************ ABC list proc ************/ +/*****************************************/ + +int jwin_abclist_proc(int msg,DIALOG *d,int c) +{ + ListData *data = (ListData *)d->dp; + + if(msg==MSG_CHAR && (isalpha(c&0xFF) || isdigit(c&0xFF))) + { + int max,dummy,h,i; + + h = (d->h-3) / text_height(*data->font); + c = toupper(c&0xFF); + + (*data->listFunc)(-1, &max); + + for(i=0; ilistFunc)(i,&dummy))[0]) == c) + { + d->d1 = i; + d->d2 = zc_max(zc_min(i-(h>>1), max-h), 0); + goto gotit; + } + } + +gotit: + scare_mouse(); + jwin_list_proc(MSG_DRAW,d,0); + unscare_mouse(); + return D_USED_CHAR; + } + + return jwin_list_proc(msg,d,c); +} + +int jwin_checkfont_proc(int msg, DIALOG *d, int c) +{ + + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT *)d->dp2; + } + + int rval = jwin_check_proc(msg, d, c); + font = oldfont; + return rval; +} + +/* jwin_check_proc: + * Who needs C++ after all? This is derived from d_button_proc, + * but overrides the drawing routine to provide a check box. + */ +int jwin_check_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + int x; + int bx=0, tl=0; + int tx=d->x; + ASSERT(d); + + switch(msg) + { + case MSG_DRAW: + x = d->x; + + if(!(d->d1)) + { + if(d->dp) + { + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char *)d->dp, tx+1, d->y+1+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcLIGHT], scheme[jcBOX], 0); + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcMEDDARK], -1, 0); + bx=tl+text_height(font)/2; + } + else + { + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcBOXFG], scheme[jcBOX], 0); + bx=tl+text_height(font)/2; + } + } + } + + jwin_draw_frame(screen, x+bx, d->y, d->h, d->h, FR_DEEP); + + if(!(d->flags & D_DISABLED)) + { + rectfill(screen, x+bx+2, d->y+2, x+bx+d->h-3, d->y+d->h-3, scheme[jcLIGHT]); + } + + if(d->d1) + { + tx=x+bx+d->h-1+(text_height(font)/2); + + if(d->dp) + { + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char *)d->dp, tx+1, d->y+1+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcLIGHT], scheme[jcBOX], 0); + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcMEDDARK], -1, 0); + } + else + { + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcBOXFG], scheme[jcBOX], 0); + } + } + } + + if(d->flags & D_SELECTED) + { + line(screen, x+bx+2, d->y+2, x+bx+d->h-3, d->y+d->h-3, scheme[jcDARK]); + line(screen, x+bx+2, d->y+d->h-3, x+bx+d->h-3, d->y+2, scheme[jcDARK]); + } + + d->w=int(text_height(font)*1.5); + + if(d->dp) + { +// dotted_rect(screen, tx-1, d->y-1, tx+tl, d->y+d->h-1, (d->flags & D_GOTFOCUS)?scheme[jcDARK]:scheme[jcBOX], scheme[jcBOX]); + dotted_rect(screen, tx-1, d->y-1, tx+tl, d->y+(text_height(font)), (d->flags & D_GOTFOCUS)?scheme[jcDARK]:scheme[jcBOX], scheme[jcBOX]); + d->w+=tl+1; + } + + return D_O_K; + break; + } + + return d_jwinbutton_proc(msg, d, 0); +} + +int jwin_radiofont_proc(int msg, DIALOG *d, int c) +{ + FONT *oldfont = font; + + if(d->dp2) + { + font = (FONT *)d->dp2; + } + + int rval = jwin_radio_proc(msg, d, c); + font = oldfont; + return rval; +} + +/* jwin_radio_proc: + * GUI procedure for radio buttons. + * Parameters: d1-button group number; d2-button style (0=circle,1=square); + * dp-text to appear as label to the right of the button. + */ +int jwin_radio_proc(int msg, DIALOG *d, int c) +{ + int x, center, r, ret, tl=0, tx; + ASSERT(d); + + switch(msg) + { + case MSG_DRAW: + // tx=d->x+d->h-1+text_height(font); + tx=d->x+int(text_height(font)*1.5); + + if(d->dp) + { + if(d->flags & D_DISABLED) + { + gui_textout_ln(screen, (unsigned char *)d->dp, tx+1, d->y+1+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcLIGHT], scheme[jcBOX], 0); + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcMEDDARK], -1, 0); + } + else + { + tl=gui_textout_ln(screen, (unsigned char *)d->dp, tx, d->y+(d->h-(text_height(font)-gui_font_baseline))/2, scheme[jcBOXFG], scheme[jcBOX], 0); + } + } + + x = d->x; + r = d->h/2; + + center = x+r; + rectfill(screen, x, d->y, x+d->h-1, d->y+d->h-1, scheme[jcBOX]); + + switch(d->d2) + { + case 1: + jwin_draw_frame(screen, x, d->y, d->h, d->h, FR_DEEP); + + if(!(d->flags & D_DISABLED)) + { + rectfill(screen, x+2, d->y+2, x+d->h-3, d->y+d->h-3, scheme[jcLIGHT]); + } + + if(d->flags & D_SELECTED) + { + rectfill(screen, x+r/2, d->y+r/2, x+d->h-1-r/2, d->y+d->h-1-r/2, scheme[jcDARK]); + //line(screen, x+2, d->y+2, x+d->h-3, d->y+d->h-3, scheme[jcDARK]); + //line(screen, x+2, d->y+d->h-3, x+d->h-3, d->y+2, scheme[jcDARK]); + } + + break; + + default: + circlefill(screen, center, d->y+r, r, scheme[jcLIGHT]); + arc(screen, center, d->y+r, itofix(32), itofix(160), r, scheme[jcMEDDARK]); + circlefill(screen, center, d->y+r, r-1, scheme[jcMEDLT]); + arc(screen, center, d->y+r, itofix(32), itofix(160), r-1, scheme[jcDARK]); + circlefill(screen, center, d->y+r, r-2, (d->flags & D_DISABLED)?scheme[jcBOX]:scheme[jcLIGHT]); + + if(d->flags & D_SELECTED) + { + circlefill(screen, center, d->y+r, r-3, scheme[jcDARK]); + } + + break; + } + + if(d->dp) + { +// dotted_rect(screen, tx-1, d->y-1, tx+tl, d->y+d->h-1, (d->flags & D_GOTFOCUS)?scheme[jcDARK]:scheme[jcBOX], scheme[jcBOX]); + dotted_rect(screen, tx-1, d->y-1, tx+tl, d->y+(text_height(font)), (d->flags & D_GOTFOCUS)?scheme[jcDARK]:scheme[jcBOX], scheme[jcBOX]); + d->w=tl+int(text_height(font)*1.5)+1; + } + + return D_O_K; + + case MSG_KEY: + case MSG_CLICK: + if(d->flags & D_SELECTED) + { + return D_O_K; + } + + break; + + case MSG_RADIO: + if((c == d->d1) && (d->flags & D_SELECTED)) + { + d->flags &= ~D_SELECTED; + object_message(d, MSG_DRAW, 0); + } + + break; + } + + ret = d_jwinbutton_proc(msg, d, 0); + + if(((msg==MSG_KEY) || (msg==MSG_CLICK)) && (d->flags & D_SELECTED) && (!(d->flags & D_EXIT))) + { + d->flags &= ~D_SELECTED; + broadcast_dialog_message(MSG_RADIO, d->d1); + d->flags |= D_SELECTED; + } + + return ret; +} + + +/* 1.5k lookup table for color matching */ +unsigned int col_diff[3*128]; + +/* bestfit_init: + * Color matching is done with weighted squares, which are much faster + * if we pregenerate a little lookup table... + */ +void bestfit_init(void) +{ + int i; + + col_diff[0] = col_diff[128] = col_diff[256] = 0; + + for(i=1; i<64; i++) + { + int k = i * i; + col_diff[0 +i] = col_diff[0 +128-i] = k * (59 * 59); + col_diff[128+i] = col_diff[128+128-i] = k * (30 * 30); + col_diff[256+i] = col_diff[256+128-i] = k * (11 * 11); + } +} + + + +/* bestfit_color: + * Searches a palette for the color closest to the requested R, G, B value. + */ +int bestfit_color_range(AL_CONST PALETTE pal, int r, int g, int b, unsigned char start, unsigned char end) +{ + int i, coldiff, lowest, bestfit; + + if(col_diff[1] == 0) + bestfit_init(); + + bestfit = start; + lowest = INT_MAX; + + i = start; + + while(ig - g) & 0x7F ]; + + if(coldiff < lowest) + { + coldiff += (col_diff + 128) [(rgb->r - r) & 0x7F ]; + + if(coldiff < lowest) + { + coldiff += (col_diff + 256) [(rgb->b - b) & 0x7F ]; + + if(coldiff < lowest) + { + bestfit = rgb - pal; /* faster than `bestfit = i;' */ + + if(coldiff == 0) + { + return bestfit; + } + + lowest = coldiff; + } + } + } + + i++; + } + + return bestfit; +} + + +/* makecol8: + * Converts R, G, and B values (ranging 0-255) to an 8 bit paletted color. + * If the global rgb_map table is initialised, it uses that, otherwise + * it searches through the current palette to find the best match. + */ +int makecol8_map(int r, int g, int b, RGB_MAP *table) +{ + return table->data[r>>3][g>>3][b>>3]; +} + + +/* create_rgb_table: + * Fills an RGB_MAP lookup table with conversion data for the specified + * palette. This is the faster version by Jan Hubicka. + * + * Uses alg. similar to floodfill - it adds one seed per every color in + * palette to its best position. Then areas around seed are filled by + * same color because it is best approximation for them, and then areas + * about them etc... + * + * It does just about 80000 tests for distances and this is about 100 + * times jwinBETTER than normal 256*32000 tests so the calculation time + * is now less than one second at all computers I tested. + */ +void create_rgb_table_range(RGB_MAP *table, AL_CONST PALETTE pal, unsigned char start, unsigned char end, void (*callback)(int jwinPOS)) +{ +#define jwinUNUSED 65535 +#define jwinLAST 65532 + + /* macro jwinADD adds to single linked list */ +#define jwinADD(i) (next[(i)] == jwinUNUSED ? (next[(i)] = jwinLAST, \ + (first != jwinLAST ? (next[last] = (i)) : (first = (i))), \ + (last = (i))) : 0) + + /* same but w/o checking for first element */ +#define jwinADD1(i) (next[(i)] == jwinUNUSED ? (next[(i)] = jwinLAST, \ + next[last] = (i), \ + (last = (i))) : 0) + + /* calculates distance between two colors */ +#define jwinDIST(a1, a2, a3, b1, b2, b3) \ + (col_diff[ ((a2) - (b2)) & 0x7F] + \ + (col_diff + 128)[((a1) - (b1)) & 0x7F] + \ + (col_diff + 256)[((a3) - (b3)) & 0x7F]) + + /* converts r,g,b to position in array and back */ +#define jwinPOS(r, g, b) \ + (((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2)) + +#define jwinDEPOS(pal, r, g, b) \ + ((b) = ((pal) & 31) * 2, \ + (g) = (((pal) >> 5) & 31) * 2, \ + (r) = (((pal) >> 10) & 31) * 2) + + /* is current color jwinBETTER than pal1? */ +#define jwinBETTER(r1, g1, b1, pal1) \ + (((int)jwinDIST((r1), (g1), (b1), \ + (pal1).r, (pal1).g, (pal1).b)) > (int)dist2) + + /* checking of position */ +#define jwinDOPOS(rp, gp, bp, ts) \ + if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \ + (gp > -1 || g > 0) && (gp < 1 || g < 61) && \ + (bp > -1 || b > 0) && (bp < 1 || b < 61)) { \ + i = first + rp * 32 * 32 + gp * 32 + bp; \ + if (!data[i]) { \ + data[i] = val; \ + jwinADD1(i); \ + } \ + else if ((ts) && (data[i] != val)) { \ + dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \ + (gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \ + (bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \ + if (jwinBETTER((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) { \ + data[i] = val; \ + jwinADD1(i); \ + } \ + } \ + } + + int i, curr, r, g, b, val, dist2; + unsigned int r2, g2, b2; + unsigned short next[32*32*32]; + unsigned char *data; + int first = jwinLAST; + int last = jwinLAST; + int count = 0; + int cbcount = 0; + +#define AVERAGE_COUNT 18000 + + if(col_diff[1] == 0) + bestfit_init(); + + memset(next, 255, sizeof(next)); + memset(table->data, 0, sizeof(char)*32*32*32); + + data = (unsigned char *)table->data; + + /* jwinADD starting seeds for floodfill */ + for(i=start; i 0) && (data[first-1] == val)) + { + b -= 2; + first--; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + jwinDOPOS(-1, 0, 0, 0); + jwinDOPOS(1, 0, 0, 0); + jwinDOPOS(0,-1, 0, 0); + jwinDOPOS(0, 1, 0, 0); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + first++; + } + + /* get next from list */ + i = first; + first = next[first]; + next[i] = jwinUNUSED; + + /* second version of loop */ + if(first != jwinLAST) + { + jwinDEPOS(first, r, g, b); + + val = data[first]; + r2 = (col_diff+128)[((pal[val].r)-(r)) & 0x7F]; + g2 = (col_diff)[((pal[val].g)-(g)) & 0x7F]; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + jwinDOPOS(0, 0, 1, 1); + jwinDOPOS(0, 0,-1, 1); + jwinDOPOS(1, 0, 0, 1); + jwinDOPOS(-1, 0, 0, 1); + jwinDOPOS(0, 1, 0, 1); + jwinDOPOS(0,-1, 0, 1); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + if((b < 61) && (data[first + 1] == val)) + { + b += 2; + first++; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7f]; + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + jwinDOPOS(-1, 0, 0, 0); + jwinDOPOS(1, 0, 0, 0); + jwinDOPOS(0,-1, 0, 0); + jwinDOPOS(0, 1, 0, 0); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + first--; + } + + i = first; + first = next[first]; + next[i] = jwinUNUSED; + } + + count++; + + if(count == (cbcount+1)*AVERAGE_COUNT/256) + { + if(cbcount < 256) + { + if(callback) + callback(cbcount); + + cbcount++; + } + } + } + + if(callback) + while(cbcount < 256) + callback(cbcount++); +} + +int short_bmp_avg(BITMAP *bmp, int i) +{ + int j=((short *)bmp->line[0])[i]; + int r=getr15(j); + int g=getg15(j); + int b=getb15(j); + int k=1; + + if(i>0) + { + j=((short *)bmp->line[0])[i-1]; + r+=getr15(j); + g+=getg15(j); + b+=getb15(j); + ++k; + } + + if(i<(bmp->w-2)) + { + j=((short *)bmp->line[0])[i+1]; + r+=getr15(j); + g+=getg15(j); + b+=getb15(j); + ++k; + } + + r/=k; + g/=k; + b/=k; + return makecol15(r, g, b); +} +void dither_rect(BITMAP *bmp, PALETTE *pal, int x1, int y1, int x2, int y2, + int src_color1, int src_color2, unsigned char dest_color1, + unsigned char dest_color2) +{ + BITMAP *src_bmp=create_bitmap_ex(15, abs(x2-x1)+1, 1); + BITMAP *dest_bmp=create_bitmap_ex(8, abs(x2-x1)+1, abs(y2-y1)+1); + int r, g, b, direction=1; + register int c; + int r1, r2, g1, g2, b1, b2; + // int diff[2][x2-x1+3][3]; + int (*diff[2])[3]; + diff[0] = new int[x2-x1+3][3]; + diff[1] = new int[x2-x1+3][3]; + int cdiff[3]; + RGB_MAP table; + int temp; + int red_rand_strength=0, green_rand_strength=0, blue_rand_strength=0; + + clear_bitmap(dest_bmp); + + if(x1>x2) + { + temp=x1; + x1=x2; + x2=temp; + } + + if(y1>y2) + { + temp=y1; + y1=y2; + y2=temp; + } + + if(src_color1>src_color2) + { + temp=src_color1; + src_color1=src_color2; + src_color2=temp; + } + + if(dest_color1>dest_color2) + { + temp=dest_color1; + dest_color1=dest_color2; + dest_color2=temp; + } + + create_rgb_table_range(&table, *pal, dest_color1, dest_color2, NULL); + r1=getr15(src_color1); + r2=getr15(src_color2); + g1=getg15(src_color1); + g2=getg15(src_color2); + b1=getb15(src_color1); + b2=getb15(src_color2); + red_rand_strength=getr8(dest_color1+1)-getr8(dest_color1); + green_rand_strength=getg8(dest_color1+1)-getg8(dest_color1); + blue_rand_strength=getb8(dest_color1+1)-getb8(dest_color1); + memset(cdiff,0,3*sizeof(float)); + memset(diff[0],0,(x2-x1+3)*3*sizeof(int)); + memset(diff[1],0,(x2-x1+3)*3*sizeof(int)); + int mc, mr, mg, mb; + + for(int i=0; iw; i++) + { + r = mix_value(r1, r2, i, src_bmp->w-1); + g = mix_value(g1, g2, i, src_bmp->w-1); + b = mix_value(b1, b2, i, src_bmp->w-1); + c = makecol15(r,g,b); + ((short *)src_bmp->line[0])[i] = c; + } + + unsigned char tempcolor, origcolor; + + for(int j=0; j<=y2-y1; ++j) + { + if(direction==1) + { + for(int i=0; i<=x2-x1; ++i) + { + mc=((short *)src_bmp->line[0])[i]; + mr=bound(getr15(mc)+rand()%(red_rand_strength*2+1)-(red_rand_strength*1),0,255); + mg=bound(getg15(mc)+rand()%(green_rand_strength*2+1)-(green_rand_strength*1),0,255); + mb=bound(getb15(mc)+rand()%(blue_rand_strength*2+1)-(blue_rand_strength*1),0,255); + cdiff[0]=bound(mr+ + diff[0][i][0]+ + diff[0][i+1][0]+ + diff[0][i+2][0]+ + cdiff[0],0,255); + cdiff[1]=bound(mg+ + diff[0][i][1]+ + diff[0][i+1][1]+ + diff[0][i+2][1]+ + cdiff[1],0,255); + cdiff[2]=bound(mb+ + diff[0][i][2]+ + diff[0][i+1][2]+ + diff[0][i+2][2]+ + cdiff[2],0,255); + // bmp->line[j][i+x1]=bound(makecol8_map(int(cdiff[0]),int(cdiff[1]),int(cdiff[2]),&table),dest_color1,dest_color2); + origcolor=makecol8_map(mr,mg,mb,&table); + // tempcolor=bound(makecol8_map(cdiff[0],cdiff[1],cdiff[2],&table),origcolor-1,origcolor+1); + tempcolor=makecol8_map(cdiff[0],cdiff[1],cdiff[2],&table); + dest_bmp->line[j][i]=tempcolor; + r=getr8(tempcolor); + g=getg8(tempcolor); + b=getb8(tempcolor); + diff[1][i][0]=(cdiff[0]-r)*3/16; + diff[1][i][1]=(cdiff[1]-g)*3/16; + diff[1][i][2]=(cdiff[2]-b)*3/16; + diff[1][i+1][0]=(cdiff[0]-r)*5/16; + diff[1][i+1][1]=(cdiff[1]-g)*5/16; + diff[1][i+1][2]=(cdiff[2]-b)*5/16; + diff[1][i+2][0]=(cdiff[0]-r)*1/16; + diff[1][i+2][1]=(cdiff[1]-g)*1/16; + diff[1][i+2][2]=(cdiff[2]-b)*1/16; + cdiff[0]=(cdiff[0]-r)*7/16; + cdiff[1]=(cdiff[1]-g)*7/16; + cdiff[2]=(cdiff[2]-b)*7/16; + } + + memcpy(diff[0],diff[1],(x2-x1+3)*3*sizeof(int)); + memset(diff[1],0,(x2-x1+3)*3*sizeof(int)); + direction=-1; + } + else + { + for(int i=x2-x1; i>=0; --i) + { + mc=((short *)src_bmp->line[0])[i]; + mr=getr15(mc); + mg=getg15(mc); + mb=getb15(mc); + cdiff[0]=bound(mr+ + diff[0][i][0]+ + diff[0][i+1][0]+ + diff[0][i+2][0]+ + cdiff[0],0,255); + cdiff[1]=bound(mg+ + diff[0][i][1]+ + diff[0][i+1][1]+ + diff[0][i+2][1]+ + cdiff[1],0,255); + cdiff[2]=bound(mb+ + diff[0][i][2]+ + diff[0][i+1][2]+ + diff[0][i+2][2]+ + cdiff[2],0,255); + // bmp->line[j][i+x1]=bound(makecol8_map(int(cdiff[0]),int(cdiff[1]),int(cdiff[2]),&table),dest_color1,dest_color2); + origcolor=makecol8_map(mr,mg,mb,&table); + // tempcolor=bound(makecol8_map(cdiff[0],cdiff[1],cdiff[2],&table),origcolor-1,origcolor+1); + tempcolor=makecol8_map(cdiff[0],cdiff[1],cdiff[2],&table); + dest_bmp->line[j][i]=tempcolor; + r=getr8(tempcolor); + g=getg8(tempcolor); + b=getb8(tempcolor); + diff[1][i][0]=(cdiff[0]-r)*3/16; + diff[1][i][1]=(cdiff[1]-g)*3/16; + diff[1][i][2]=(cdiff[2]-b)*3/16; + diff[1][i+1][0]=(cdiff[0]-r)*5/16; + diff[1][i+1][1]=(cdiff[1]-g)*5/16; + diff[1][i+1][2]=(cdiff[2]-b)*5/16; + diff[1][i+2][0]=(cdiff[0]-r)*1/16; + diff[1][i+2][1]=(cdiff[1]-g)*1/16; + diff[1][i+2][2]=(cdiff[2]-b)*1/16; + cdiff[0]=(cdiff[0]-r)*7/16; + cdiff[1]=(cdiff[1]-g)*7/16; + cdiff[2]=(cdiff[2]-b)*7/16; + } + + memcpy(diff[0],diff[1],(x2-x1+3)*3*sizeof(float)); + memset(diff[1],0,(x2-x1+3)*3*sizeof(float)); + direction=1; + } + } + + blit(dest_bmp, bmp, 0, 0, x1, y1, x2-x1+1, y2-y1+1); + delete[] diff[1]; + delete[] diff[0]; + destroy_bitmap(src_bmp); + destroy_bitmap(dest_bmp); + return; +} + +bool do_text_button(int x,int y,int w,int h,const char *text) +{ + bool over=false; + + while(gui_mouse_b()) + { + //vsync(); + if(mouse_in_rect(x,y,w,h)) + { + if(!over) + { + vsync(); + scare_mouse(); + jwin_draw_text_button(screen, x, y, w, h, text, D_SELECTED, true); + unscare_mouse(); + over=true; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + } + else + { + if(over) + { + vsync(); + scare_mouse(); + jwin_draw_text_button(screen, x, y, w, h, text, 0, true); + unscare_mouse(); + over=false; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + } + } + + return over; +} + +bool do_text_button_reset(int x,int y,int w,int h,const char *text) +{ + bool over=false; + + while(gui_mouse_b()) + { + //vsync(); + if(mouse_in_rect(x,y,w,h)) + { + if(!over) + { + vsync(); + scare_mouse(); + jwin_draw_text_button(screen, x, y, w, h, text, D_SELECTED, true); + unscare_mouse(); + over=true; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + } + else + { + if(over) + { + vsync(); + scare_mouse(); + jwin_draw_text_button(screen, x, y, w, h, text, 0, true); + unscare_mouse(); + over=false; + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + } + + } + + if(over) + { + vsync(); + scare_mouse(); + jwin_draw_text_button(screen, x, y, w, h, text, 0, true); + unscare_mouse(); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + return over; +} + +int jwin_tab_proc(int msg, DIALOG *d, int c) +{ + int i; + int tx; + int sd=2; //selected delta + TABPANEL *panel=(TABPANEL *)d->dp; + DIALOG *panel_dialog=NULL, *current_object=NULL; + int selected=0; + int counter=0; + ASSERT(d); + int temp_d, temp_d2; + + if(d->dp==NULL) return D_O_K; + + panel_dialog=(DIALOG *)d->dp3; + + for(i=0; panel[i].text; ++i) + { + if((panel[i].flags&D_SELECTED) && !(d->flags & D_HIDDEN)) + { + for(counter=0; counterflags&=~D_HIDDEN; + } + } + else + { + for(counter=0; counterflags|=D_HIDDEN; + + if(current_object->proc == &jwin_tab_proc) + object_message(current_object,0,c); + } + } + + /*if (d->flags & D_HIDDEN) + { + for(counter=0; counterx=zq_screen_w*3; + current_object->y=zq_screen_h*3; + } + }*/ + } + + switch(msg) + { + case MSG_DRAW: + { + FONT *oldfont = font; + + if(d->xydp2) + { + font = (FONT *)d->dp2; + } + + panel_dialog=(DIALOG *)d->dp3; + rectfill(screen, d->x, d->y, d->x+d->w-1, d->y+8+text_height(font), scheme[jcBOX]); //tab area + rectfill(screen, d->x+1, d->y+sd+text_height(font)+7, d->x+d->w-2, d->y+sd+d->h-2, scheme[jcBOX]); //panel + _allegro_vline(screen, d->x, d->y+sd+7+text_height(font), d->y+sd+d->h-2, scheme[jcLIGHT]); + _allegro_vline(screen, d->x+1, d->y+sd+7+text_height(font), d->y+sd+d->h-3, scheme[jcMEDLT]); + _allegro_vline(screen, d->x+d->w-2, d->y+sd+7+text_height(font), d->y+sd+d->h-2, scheme[jcMEDDARK]); + _allegro_vline(screen, d->x+d->w-1, d->y+sd+7+text_height(font)-1, d->y+sd+d->h-1, scheme[jcDARK]); + _allegro_hline(screen, d->x+1, d->y+sd+d->h-2, d->x+d->w-3, scheme[jcMEDDARK]); + _allegro_hline(screen, d->x, d->y+sd+d->h-1, d->x+d->w-2, scheme[jcDARK]); + tx=d->x; + + if(d->dp) + { + if(!(panel[((d->d1&0xFF00)>>8)].flags&D_SELECTED)) + { + _allegro_hline(screen, tx+1, d->y+sd+6+text_height(font)+1, tx+2, scheme[jcMEDLT]); //initial bottom + _allegro_hline(screen, tx, d->y+sd+6+text_height(font), tx+1, scheme[jcLIGHT]); //initial bottom + } + + tx+=2; + + for(i=0; panel[i].text; ++i) + { + if(panel[i].flags&D_SELECTED) + { + selected=i; + } + } + + for(i=((d->d1&0xFF00)>>8); panel[i].text&&i<=last_visible_tab(panel,((d->d1&0xFF00)>>8),d->w); ++i) + { + sd=(panel[i].flags&D_SELECTED)?0:2; + + if((i==((d->d1&0xFF00)>>8)) || (!(panel[i-1].flags&D_SELECTED))) + { + _allegro_vline(screen, tx-(2-sd), d->y+sd+2, d->y+8+text_height(font), scheme[jcLIGHT]); //left side + _allegro_vline(screen, tx-(2-sd)+1, d->y+sd+2, d->y+8+text_height(font), scheme[jcMEDLT]); //left side + putpixel(screen, tx+1-(2-sd), d->y+sd+1, scheme[jcLIGHT]); //left angle + } + + _allegro_hline(screen, tx+2-(2-sd), d->y+sd, tx+12+(2-sd)+text_length(font, (char *)panel[i].text), scheme[jcLIGHT]); //top + _allegro_hline(screen, tx+2-(2-sd), d->y+sd+1, tx+12+(2-sd)+text_length(font, (char *)panel[i].text), scheme[jcMEDLT]); //top + + if(!(panel[i].flags&D_SELECTED)) + { + _allegro_hline(screen, tx+1, d->y+sd+6+text_height(font), tx+13+text_length(font, (char *)panel[i].text)+1, scheme[jcLIGHT]); //bottom + _allegro_hline(screen, tx, d->y+sd+6+text_height(font)+1, tx+13+text_length(font, (char *)panel[i].text)+1, scheme[jcMEDLT]); //bottom + } + + tx+=4; + gui_textout_ln(screen, (unsigned char*)panel[i].text, tx+4, d->y+sd+4, scheme[jcBOXFG], scheme[jcBOX], 0); + tx+=text_length(font, (char *)panel[i].text)+10; + + if(!(panel[i+1].text) || (!(panel[i+1].flags&D_SELECTED))) + { + putpixel(screen, tx-1+(2-sd), d->y+sd+1, scheme[jcDARK]); //right angle + _allegro_vline(screen, tx+(2-sd), d->y+sd+2, d->y+8+text_height(font)-1, scheme[jcDARK]); //right side + _allegro_vline(screen, tx+(2-sd)-1, d->y+sd+2, d->y+8+text_height(font)-(sd?1:0), scheme[jcMEDDARK]); //right side + } + + tx++; + } + + if(((d->d1&0xFF00)>>8)!=0||last_visible_tab(panel,((d->d1&0xFF00)>>8),d->w)+1x+d->w-14,d->y+2, 14, 14, "\x8B", 0, true); + jwin_draw_text_button(screen,d->x+d->w-28,d->y+2, 14, 14, "\x8A", 0, true); + } + } + + if((tx+(2-sd))<(d->x+d->w)) + { + _allegro_hline(screen, tx+(2-sd)-1, d->y+8+text_height(font), d->x+d->w-1, scheme[jcLIGHT]); //ending bottom + _allegro_hline(screen, tx+(2-sd)-2, d->y+8+text_height(font)+1, d->x+d->w-2, scheme[jcMEDLT]); //ending bottom + } + + font = oldfont; + + //what dialog is this tab control in (programmer must set manually) + panel_dialog=(DIALOG *)d->dp3; + + //for each object handled by the currently selected tab... + for(counter=0; counterx=panel[selected].xy[counter*2]; + current_object->y=panel[selected].xy[counter*2+1]; + object_message(current_object, MSG_DRAW, 0); + } + + //if there was a previously selected tab... + if((d->d1&0x00FF)!=0x00FF) + { + //for each object handled by the tab + for(counter=0; counterd1&0xFF].objects; counter++) + { + //assign current_object to one of the controls handled by the tab + current_object=panel_dialog+(panel[d->d1&0xFF].dialog[counter]); + // //remember the x and y positions of the control + // panel[d->d1].xy[counter*2]=current_object->x; + // panel[d->d1].xy[counter*2+1]=current_object->y; + current_object->x=zq_screen_w*3; + current_object->y=zq_screen_h*3; + } + } + } + } + break; + + case MSG_CLICK: + { + d->d1&=0xFF00; + d->d1|=0x00FF; + + // is the mouse on one of the tab arrows (if visible) or in the tab area? + if(uses_tab_arrows(panel, d->w)&&(mouse_in_rect(d->x+d->w-28, d->y+2, 28, 14))) + { + if(mouse_in_rect(d->x+d->w-28, d->y+2, 14, 14)) + { + if(do_text_button_reset(d->x+d->w-28, d->y+2, 14, 14, "\x8A")) + { + temp_d=((d->d1&0xFF00)>>8); + temp_d2=(d->d1&0x00FF); + + if(temp_d>0) + { + --temp_d; + } + + d->d1=(temp_d<<8)|temp_d2; + d->flags|=D_DIRTY; + } + } + else if(mouse_in_rect(d->x+d->w-14, d->y+2, 14, 14)) + { + if(do_text_button_reset(d->x+d->w-14, d->y+2, 14, 14, "\x8B")) + { + temp_d=((d->d1&0xFF00)>>8); + temp_d2=(d->d1&0x00FF); + + if(last_visible_tab(panel, temp_d, d->w)<(tab_count(panel)-1)) + { + ++temp_d; + } + + d->d1=(temp_d<<8)|temp_d2; + d->flags|=D_DIRTY; + } + } + } + else + { + d_tab_proc(msg, d, c); + } + } + break; + + default: + return d_tab_proc(msg, d, c); + break; + } + + panel_dialog=(DIALOG *)d->dp3; + + if(d->flags & D_HIDDEN) + { + for(i=0; panel[i].text; ++i) + { + for(counter=0; counterx=zq_screen_w*3; + current_object->y=zq_screen_h*3; + } + } + + //d->x=zq_screen_w*3; + //d->y=zq_screen_h*3; + } + else + { + for(i=0; panel[i].text; ++i) + { + for(counter=0; counterx=panel[i].xy[counter*2]; + current_object->y=panel[i].xy[counter*2+1]; + } + } + + // d->x=zq_screen_w*3; + //d->y=zq_screen_h*3; + } + + return D_O_K; +} + + + + +int jwin_hline_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + ASSERT(d); + + if(msg==MSG_DRAW) + { + _allegro_hline(screen, d->x, d->y, d->x+d->w-1, scheme[jcMEDDARK]); + _allegro_hline(screen, d->x, d->y+1, d->x+d->w-1, scheme[jcLIGHT]); + } + + return D_O_K; +} + +int jwin_vline_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + ASSERT(d); + + if(msg==MSG_DRAW) + { + _allegro_vline(screen, d->x, d->y, d->y+d->h-1, scheme[jcMEDDARK]); + _allegro_vline(screen, d->x+1, d->y, d->y+d->h-1, scheme[jcLIGHT]); + } + + return D_O_K; +} + +int jwin_editbox_proc(int msg, DIALOG *d, int c) +{ + return d_editbox_proc(msg, d, c); +} + +//centers dialog based on first object, which should be the containing window +void jwin_center_dialog(DIALOG *dialog) +{ + int xc, yc; + int c; + ASSERT(dialog); + + /* how much to move by? */ + xc = (zq_screen_w - dialog[0].w) / 2 - dialog[0].x; + yc = (zq_screen_h - dialog[0].h) / 2 - dialog[0].y; + + /* move it */ + for(c=0; dialog[c].proc; c++) + { + dialog[c].x += xc; + dialog[c].y += yc; + } +} + +//Custom slider proc +int d_jslider_proc(int msg, DIALOG *d, int c) +{ + BITMAP *gui_bmp = gui_get_screen(); + BITMAP *slhan = NULL; + int oldpos, newpos; + int sfg; /* slider foreground color */ + int vert = TRUE; /* flag: is slider vertical? */ + int hh = 7; /* handle height (width for horizontal sliders) */ + int hmar; /* handle margin */ + int slp; /* slider position */ + int mp; /* mouse position */ + int irange; + int slx, sly, slh, slw; + int msx, msy; + int retval = D_O_K; + int upkey, downkey; + int pgupkey, pgdnkey; + int homekey, endkey; + int delta; + fixed slratio, slmax, slpos; + typedef int (*SLIDER_TYPE)(void*, int); + SLIDER_TYPE proc = NULL; + //int (*proc)(void *cbpointer, int d2value); + int oldval; + ASSERT(d); + + /* check for slider direction */ + if(d->h < d->w) + vert = FALSE; + + /* set up the metrics for the control */ + if(d->dp != NULL) + { + slhan = (BITMAP *)d->dp; + + if(vert) + hh = slhan->h; + else + hh = slhan->w; + } + + hmar = hh/2; + irange = (vert) ? d->h : d->w; + slmax = itofix(irange-hh); + slratio = slmax / (d->d1); + slpos = slratio * d->d2; + slp = fixtoi(slpos); + + switch(msg) + { + + case MSG_DRAW: + sfg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + + if(vert) + { + rectfill(gui_bmp, d->x, d->y, d->x+d->w/2-2, d->y+d->h-1, d->bg); + rectfill(gui_bmp, d->x+d->w/2-1, d->y, d->x+d->w/2+1, d->y+d->h-1, sfg); + rectfill(gui_bmp, d->x+d->w/2+2, d->y, d->x+d->w-1, d->y+d->h-1, d->bg); + } + else + { + rectfill(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h/2-2, d->bg); + rectfill(gui_bmp, d->x, d->y+d->h/2-1, d->x+d->w-1, d->y+d->h/2+1, sfg); + rectfill(gui_bmp, d->x, d->y+d->h/2+2, d->x+d->w-1, d->y+d->h-1, d->bg); + } + + /* okay, background and slot are drawn, now draw the handle */ + if(slhan) + { + if(vert) + { + slx = d->x+(d->w/2)-(slhan->w/2); + sly = d->y+(d->h-1)-(hh+slp); + } + else + { + slx = d->x+slp; + sly = d->y+(d->h/2)-(slhan->h/2); + } + + draw_sprite(gui_bmp, slhan, slx, sly); + } + else + { + /* draw default handle */ + if(vert) + { + slx = d->x; + sly = d->y+(d->h)-(hh+slp); + slw = d->w-1; + slh = hh-1; + } + else + { + slx = d->x+slp; + sly = d->y; + slw = hh-1; + slh = d->h-1; + } + + /* draw body */ + rectfill(gui_bmp, slx+2, sly, slx+(slw-2), sly+slh, sfg); + vline(gui_bmp, slx+1, sly+1, sly+slh-1, sfg); + vline(gui_bmp, slx+slw-1, sly+1, sly+slh-1, sfg); + vline(gui_bmp, slx, sly+2, sly+slh-2, sfg); + vline(gui_bmp, slx+slw, sly+2, sly+slh-2, sfg); + vline(gui_bmp, slx+1, sly+2, sly+slh-2, d->bg); + hline(gui_bmp, slx+2, sly+1, slx+slw-2, d->bg); + putpixel(gui_bmp, slx+2, sly+2, d->bg); + } + + if(d->flags & D_GOTFOCUS) + dotted_rect(gui_bmp, d->x, d->y, d->x+d->w-1, d->y+d->h-1, sfg, d->bg); + + break; + + case MSG_WANTFOCUS: + case MSG_LOSTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + if(!(d->flags & D_GOTFOCUS)) + return D_WANTFOCUS; + else + return D_O_K; + + case MSG_CHAR: + /* handle movement keys to move slider */ + c >>= 8; + + if(vert) + { + upkey = KEY_UP; + downkey = KEY_DOWN; + pgupkey = KEY_PGUP; + pgdnkey = KEY_PGDN; + homekey = KEY_END; + endkey = KEY_HOME; + } + else + { + upkey = KEY_RIGHT; + downkey = KEY_LEFT; + pgupkey = KEY_PGDN; + pgdnkey = KEY_PGUP; + homekey = KEY_HOME; + endkey = KEY_END; + } + + if(c == upkey) + delta = 1; + else if(c == downkey) + delta = -1; + else if(c == pgdnkey) + delta = -d->d1 / 16; + else if(c == pgupkey) + delta = d->d1 / 16; + else if(c == homekey) + delta = -d->d2; + else if(c == endkey) + delta = d->d1 - d->d2; + else + delta = 0; + + if(delta) + { + oldpos = slp; + oldval = d->d2; + + //while (true) { + for(; ;) //thank you, MSVC ~pkmnfrk + { + d->d2 = d->d2+delta; + slpos = slratio*d->d2; + slp = fixtoi(slpos); + + if((slp != oldpos) || (d->d2 <= 0) || (d->d2 >= d->d1)) + break; + } + + if(d->d2 < 0) + d->d2 = 0; + + if(d->d2 > d->d1) + d->d2 = d->d1; + + retval = D_USED_CHAR; + + if(d->d2 != oldval) + { + /* call callback function here */ + if(d->dp2) + { + proc = (SLIDER_TYPE)(d->dp2); + retval |= (*proc)(d->dp3, d->d2); + } + + object_message(d, MSG_DRAW, 0); + } + } + + break; + + case MSG_WHEEL: + oldval = d->d2; + d->d2 = MID(0, d->d2+c, d->d1); + + if(d->d2 != oldval) + { + /* call callback function here */ + if(d->dp2) + { + proc = (SLIDER_TYPE)(d->dp2); + retval |= (*proc)(d->dp3, d->d2); + } + + object_message(d, MSG_DRAW, 0); + } + + break; + + case MSG_CLICK: + /* track the mouse until it is released */ + mp = slp; + + while(gui_mouse_b()) + { + msx = gui_mouse_x(); + msy = gui_mouse_y(); + oldval = d->d2; + + if(vert) + mp = (d->y+d->h-hmar)-msy; + else + mp = msx-(d->x+hmar); + + if(mp < 0) + mp = 0; + + if(mp > irange-hh) + mp = irange-hh; + + slpos = itofix(mp); + slmax = fixdiv(slpos, slratio); + newpos = fixtoi(slmax); + + if(newpos != oldval) + { + d->d2 = newpos; + + /* call callback function here */ + if(d->dp2 != NULL) + { + proc = (SLIDER_TYPE)(d->dp2); + retval |= (*proc)(d->dp3, d->d2); + } + + object_message(d, MSG_DRAW, 0); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + } + + break; + } + + return retval; +} + +int d_jwinbutton_proc(int msg, DIALOG *d, int) +{ + BITMAP *gui_bmp; + int state1, state2; + int black; + int swap; + int g; + ASSERT(d); + + gui_bmp = gui_get_screen(); + + switch(msg) + { + + case MSG_DRAW: + if(d->flags & D_SELECTED) + { + g = 1; + state1 = d->bg; + state2 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + } + else + { + g = 0; + state1 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + state2 = d->bg; + } + + rectfill(gui_bmp, d->x+1+g, d->y+1+g, d->x+d->w-3+g, d->y+d->h-3+g, state2); + rect(gui_bmp, d->x+g, d->y+g, d->x+d->w-2+g, d->y+d->h-2+g, state1); + gui_textout_ex(gui_bmp, (char *)d->dp, d->x+d->w/2+g, d->y+d->h/2-text_height(font)/2+g, state1, -1, TRUE); + + if(d->flags & D_SELECTED) + { + vline(gui_bmp, d->x, d->y, d->y+d->h-2, d->bg); + hline(gui_bmp, d->x, d->y, d->x+d->w-2, d->bg); + } + else + { + black = makecol(0,0,0); + vline(gui_bmp, d->x+d->w-1, d->y+1, d->y+d->h-2, black); + hline(gui_bmp, d->x+1, d->y+d->h-1, d->x+d->w-1, black); + } + + if((d->flags & D_GOTFOCUS) && + (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) + dotted_rect(gui_bmp, d->x+1+g, d->y+1+g, d->x+d->w-3+g, d->y+d->h-3+g, state1, state2); + + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + + /* close dialog? */ + if(d->flags & D_EXIT) + { + return D_CLOSE; + } + + /* or just toggle */ + d->flags ^= D_SELECTED; + object_message(d, MSG_DRAW, 0); + break; + + case MSG_CLICK: + /* what state was the button originally in? */ + state1 = d->flags & D_SELECTED; + + if(d->flags & D_EXIT) + swap = FALSE; + else + swap = state1; + + /* track the mouse until it is released */ + while(gui_mouse_b()) + { + state2 = ((gui_mouse_x() >= d->x) && (gui_mouse_y() >= d->y) && + (gui_mouse_x() < d->x + d->w) && (gui_mouse_y() < d->y + d->h)); + + if(swap) + state2 = !state2; + + /* redraw? */ + if(((state1) && (!state2)) || ((state2) && (!state1))) + { + d->flags ^= D_SELECTED; + state1 = d->flags & D_SELECTED; + object_message(d, MSG_DRAW, 0); + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + /* should we close the dialog? */ + if((d->flags & D_SELECTED) && (d->flags & D_EXIT)) + { + d->flags ^= D_SELECTED; + return D_CLOSE; + } + + break; + } + + return D_O_K; +} + + + +/*** The End ***/ + diff --git a/src/jwin.h b/src/jwin.h new file mode 100644 index 0000000000..096c4a69a8 --- /dev/null +++ b/src/jwin.h @@ -0,0 +1,170 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.h + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + * How to use: + * + * - include jwin.c in your project + * - include this header in your code + * + * - do the same for jwinfsel.* if you want to use the file selector + * + * - call jwin_set_colors() at program start up + * (send jwin_colors for default colors or make your own array + * of colors and send them to jwin_set_colors()... see jwin.c) + * + * - use the DIALOG procs the same way you use the default Allegro ones + * + */ + +/* This code is not fully tested */ + +#ifndef _JWIN_H_ +#define _JWIN_H_ + +#include "zc_alleg.h" +#include "tab_ctl.h" + +struct ListData +{ + ListData(const char *(*lf)(int, int*), FONT **f) : listFunc(lf), font(f) {} + const char *(*listFunc)(int, int *); + FONT **font; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* read only flag for jwin_edit_proc */ +#define D_READONLY D_USER + +/* Disable click to select combo for d_combo_proc */ +#define D_NOCLICK D_USER + +/* frame styles */ +enum { + FR_WIN, FR_BOX, FR_INV, FR_DEEP, FR_DARK, FR_ETCHED, FR_MEDDARK +}; + +/* todo: (maybe) put the colors into a struct */ + +/* color indices */ +enum +{ + jcBOX, jcLIGHT, jcMEDLT, jcMEDDARK, jcDARK, jcBOXFG, + jcTITLEL, jcTITLER, jcTITLEFG, jcTEXTBG, jcTEXTFG, jcSELBG, jcSELFG, + jcMAX +}; + +/* a copy of the default color scheme; do what you want with this */ +extern int jwin_colors[jcMAX]; + +extern int mix_value(int c1,int c2,int pos,int max); + +/* 1.5k lookup table for color matching */ +extern unsigned int col_diff[3*128]; + +/* you should call this before using the other procedures */ +void jwin_set_colors(int *colors); + +/* drawing routines */ +void jwin_draw_frame(BITMAP *dest,int x,int y,int w,int h,int style); +void jwin_draw_win(BITMAP *dest,int x,int y,int w,int h,int frame); +void jwin_draw_button(BITMAP *dest,int x,int y,int w,int h,int state,int type); +void draw_x_button(BITMAP *dest, int x, int y, int state); +char *shorten_string(char *dest, char *src, FONT *usefont, int maxchars, int maxwidth); +void jwin_draw_titlebar(BITMAP *dest, int x, int y, int w, int h, const char *str, bool draw_button); +void jwin_draw_text_button(BITMAP *dest, int x, int y, int w, int h, const char *str, int flags, bool show_dotted_rect); +void jwin_draw_graphics_button(BITMAP *dest, int x, int y, int w, int h, BITMAP *bmp, BITMAP *bmp2, int flags, bool show_dotted_rect, bool overlay); + +/* Allegro DIALOG procedures */ +int jwin_win_proc(int msg, DIALOG *d, int c); +int jwin_frame_proc(int msg, DIALOG *d, int c); +int jwin_guitest_proc(int msg, DIALOG *d, int c); +int jwin_button_proc(int msg, DIALOG *d, int c); +int jwin_text_proc(int msg, DIALOG *d, int c); +int jwin_ctext_proc(int msg, DIALOG *d, int c); +int jwin_rtext_proc(int msg, DIALOG *d, int c); +int jwin_edit_proc(int msg, DIALOG *d, int c); +int jwin_hexedit_proc(int msg,DIALOG *d,int c); +int jwin_numedit_proc(int msg,DIALOG *d,int c); +int jwin_list_proc(int msg, DIALOG *d, int c); +int jwin_textbox_proc(int msg, DIALOG *d, int c); +int jwin_slider_proc(int msg, DIALOG *d, int c); +int jwin_menu_proc(int msg, DIALOG *d, int c); +int jwin_droplist_proc(int msg, DIALOG *d, int c); +int jwin_abclist_proc(int msg, DIALOG *d, int c); +int jwin_check_proc(int msg, DIALOG *d, int c); +int jwin_checkfont_proc(int msg, DIALOG *d, int c); +int jwin_radio_proc(int msg, DIALOG *d, int c); +int jwin_radiofont_proc(int msg, DIALOG *d, int c); +int jwin_tab_proc(int msg, DIALOG *d, int c); +int jwin_hline_proc(int msg, DIALOG *d, int c); +int jwin_vline_proc(int msg, DIALOG *d, int c); + +/* other GUI procedures */ +void jwin_set_dialog_color(DIALOG *dialog); + +int gui_textout_ln(BITMAP *bmp, FONT *f, unsigned char *s, int x, int y, int color, int bg, int pos); + +int jwin_do_menu(MENU *menu, int x, int y); + +int jwin_alert3(const char *title, const char *s1, const char *s2, const char *s3, const char *b1, const char *b2, const char *b3, int c1, int c2, int c3, FONT *title_font); +int jwin_alert(const char *title, const char *s1, const char *s2, const char *s3, const char *b1, const char *b2, int c1, int c2, FONT *title_font); + +/* event handler that closes a dialog */ +int close_dlg(); +int mouse_in_rect(int x,int y,int w,int h); + +void bestfit_init(void); +int bestfit_color_range(AL_CONST PALETTE pal, int r, int g, int b, unsigned char start, unsigned char end); +int makecol8_map(int r, int g, int b, RGB_MAP *table); +void create_rgb_table_range(RGB_MAP *table, AL_CONST PALETTE pal, unsigned char start, unsigned char end, void (*callback)(int pos)); +int short_bmp_avg(BITMAP *bmp, int i); +void dither_rect(BITMAP *bmp, PALETTE *pal, int x1, int y1, int x2, int y2, + int src_color1, int src_color2, unsigned char dest_color1, + unsigned char dest_color2); +void jwin_center_dialog(DIALOG *dialog); + +void _calc_scroll_bar(int h, int height, int listsize, int offset, + int *bh, int *len, int *pos); +void draw_arrow_button(BITMAP *dest, int x, int y, int w, int h, int up, int state); +void draw_arrow_button_horiz(BITMAP *dest, int x, int y, int w, int h, int up, int state); + + +void dotted_rect(BITMAP *dest, int x1, int y1, int x2, int y2, int fg, int bg); +void _jwin_draw_scrollable_frame(DIALOG *d, int listsize, int offset, int height, int type); +void _handle_jwin_scrollable_scroll_click(DIALOG *d, int listsize, int *offset, FONT *fnt); + +extern int popup_zqdialog(DIALOG *dialog, int focus_obj); +extern int do_zqdialog(DIALOG *dialog, int focus_obj); + +int d_jslider_proc(int msg, DIALOG *d, int c); +int d_jwinbutton_proc(int msg, DIALOG *d, int c); + + +#ifdef __cplusplus +} +#endif +#endif // _JWIN_H_ + diff --git a/src/jwinfsel.cpp b/src/jwinfsel.cpp new file mode 100644 index 0000000000..a1415a24f6 --- /dev/null +++ b/src/jwinfsel.cpp @@ -0,0 +1,1366 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwinfsel.c + * + * The file selector. + * + * By Shawn Hargreaves. + * + * Guilherme Silveira and Theuzifan Sumachingun both independently + * modified it to only list valid drive letters. + * + * Peter Pavlovic modified it not to list the logical drives, such + * as the b: drive assigned as a logical drive for a: on single + * floppy disk drive equipped systems and improved the browsing + * through directories. + * + * Peter Wang and Eric Botcazou modified it to stretch to screen and + * font sizes. + * + * Annie Testes modified it so that buffer overflows cannot occur + * anymore. + * + * Eric Botcazou optimized the handling of the extension string. + * + * Adapted to "jwin" style by Jeremy Craner. Also added the "browser". + * + * Version: 8/2/03 + * Allegro version: 4.x + * + * See readme.txt for copyright information. + */ + +#include "precompiled.h" //always first + +#include + +#include +#include +#include + +#include "jwin.h" +#include "jwinfsel.h" +#include "zsys.h" +#include "zc_malloc.h" + +extern FONT *lfont_l; + +#if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0') +#define HAVE_DIR_LIST +#endif + + +static int fs_edit_proc(int, DIALOG *, int); +static int fs_flist_proc(int, DIALOG *, int); +static int fs_elist_proc(int, DIALOG *, int); +static const char *fs_flist_getter(int, int *); +static const char *fs_elist_getter(int, int *); + +#ifdef HAVE_DIR_LIST + +static int fs_dlist_proc(int, DIALOG *, int); +static const char *fs_dlist_getter(int, int *); +#endif + +#define FLIST_SIZE 2048 + +typedef struct FLIST +{ + char dir[1024]; + int size; + char *name[FLIST_SIZE]; +} FLIST; + +static FLIST *flist = NULL; + +/* file extensions */ +static char *fext = NULL; /* tokenized extension string (dynamically allocated) */ +static EXT_LIST *fext_list = NULL; +static char **fext_p = NULL; /* list of pointers to the tokens (dynamically allocated) */ +static int fext_size = 0; /* size of the list */ + +/* file attributes (rhsda order) */ +#define ATTRB_MAX 5 /* number of attributes */ +#define ATTRB_DIREC 3 /* index of FA_DIREC */ + +typedef enum { ATTRB_ABSENT, ATTRB_UNSET, ATTRB_SET } +attrb_state_t; + +#define DEFAULT_ATTRB_STATE { ATTRB_ABSENT, ATTRB_UNSET, ATTRB_UNSET, ATTRB_ABSENT, ATTRB_ABSENT } + +static int attrb_flag[ATTRB_MAX] = { FA_RDONLY, FA_HIDDEN, FA_SYSTEM, FA_DIREC, FA_ARCH }; +static attrb_state_t attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; + +static char updir[1024]; + +static int fs_dummy_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + msg=msg; + d=d; + c=c; + + return D_O_K; +} + +static ListData fs_flist__getter(fs_flist_getter, &font); +static ListData fs_elist__getter(fs_elist_getter, &font); +#ifdef HAVE_DIR_LIST //Needed to compile. -L +static ListData fs_dlist__getter(fs_dlist_getter, &font); +#endif + +static DIALOG file_selector[] = +{ +#ifdef HAVE_DIR_LIST + + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 0, 0, 305, 161, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 208, 107, 81, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 208, 129, 81, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, + { fs_edit_proc, 16, 28, 272, 8, 0, 0, 0, 0, 79, 0, NULL, NULL, NULL }, + { fs_elist_proc, 16, 154, 176, 16, 0, 0, 0, D_EXIT, 0, 0, (void *) &fs_elist__getter, NULL, NULL }, + { fs_flist_proc, 16, 46, 177, 100, 0, 0, 0, D_EXIT, 0, 0, (void *) &fs_flist__getter, NULL, NULL }, + { fs_dlist_proc, 208, 46, 81, 52, 0, 0, 0, D_EXIT, 0, 0, (void *) &fs_dlist__getter, NULL, NULL }, + { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + +#else + + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 0, 0, 305, 189, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 64, 160, 81, 17, 0, 0, 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 160, 160, 81, 17, 0, 0, 27, D_EXIT, 0, 0, NULL, NULL, NULL }, + { fs_edit_proc, 16, 28, 272, 8, 0, 0, 0, 0, 79, 0, NULL, NULL, NULL }, + { fs_elist_proc, 16, 154, 176, 16, 0, 0, 0, D_EXIT, 0, 0, (void *) &fs_elist__getter, NULL, NULL }, + { fs_flist_proc, 16, 46, 273, 100, 0, 0, 0, D_EXIT, 0, 0, (void *) &fs_flist__getter, NULL, NULL }, + { d_yield_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, +#endif + + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +#define FS_WIN 0 +#define FS_OK 1 +#define FS_CANCEL 2 +#define FS_EDIT 3 +#define FS_TYPES 4 +#define FS_FILES 5 + +#ifdef HAVE_DIR_LIST /* not all platforms need a directory list */ + +#define FS_DISKS 6 +#define FS_YIELD 7 + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +/* count_disks: + * Counts the number of valid drives. + */ +static int count_disks(void) +{ + int c, i; + + c = 0; + + for(i=0; i<26; i++) + if(_al_drive_exists(i)) + c++; + + return c; +} + +/* get_x_drive: + * Returns the drive letter matching the specified list index. + */ +static int get_x_drive(int index) +{ + int c, i; + + c = 0; + + for(i=0; i<26; i++) + { + if(_al_drive_exists(i)) + { + c++; + + if(c==index) + return i; + } + } + + return -1; +} + +/* fs_dlist_getter: + * Listbox data getter routine for the file selector disk list. + */ +static const char *fs_dlist_getter(int index, int *list_size) +{ + static char d[8]; + int pos, c; + + if(index < 0) + { + if(list_size) + *list_size = count_disks(); + + return NULL; + } + + c = 'A' + get_x_drive(index+1); + + if((c < 'A') || (c > 'Z')) + c = 'C'; + + pos = usetc(d, c); + pos += usetc(d+pos, DEVICE_SEPARATOR); + pos += usetc(d+pos, OTHER_PATH_SEPARATOR); + usetc(d+pos, 0); + + return d; +} + +/* fs_dlist_proc: + * Dialog procedure for the file selector disk list. + */ +static int fs_dlist_proc(int msg, DIALOG *d, int c) +{ + char *s = (char *) file_selector[FS_EDIT].dp; + int ret, i, temp; + + if(msg == MSG_START) + { + d->d1 = d->d2 = 0; + temp = utoupper(ugetc(s)); + + if(((temp >= 'A') && (temp <= 'Z')) && (ugetat(s, 1) == DEVICE_SEPARATOR)) + { + temp -= 'A'; + + for(i=0; id1++; + } + } + + ret = jwin_droplist_proc(msg, d, c); + + if(ret & D_CLOSE) + { + temp = 'A' + get_x_drive(d->d1+1); + + if((temp < 'A') || (temp > 'Z')) + temp = 'C'; + + s += usetc(s, temp); + s += usetc(s, DEVICE_SEPARATOR); + s += usetc(s, OTHER_PATH_SEPARATOR); + usetc(s, 0); + + object_message(file_selector+FS_FILES, MSG_START, 0); + object_message(file_selector+FS_FILES, MSG_DRAW, 0); + object_message(file_selector+FS_EDIT, MSG_START, 0); + object_message(file_selector+FS_EDIT, MSG_DRAW, 0); + + return ret - D_CLOSE + D_O_K; + } + + return ret; +} + +#else + +#define FS_YIELD 6 +#endif /* HAVE_DIR_LIST */ + +/* fs_edit_proc: + * Dialog procedure for the file selector editable string. + */ +static int fs_edit_proc(int msg, DIALOG *d, int c) +{ + char *s = (char *) d->dp; + int size = (d->d1 + 1) * uwidth_max(U_CURRENT); /* of s (in bytes) */ + int list_size; + int found = 0; + char b[1024], tmp[16]; + int ch, attr; + int i; + + if(msg == MSG_START) + { + canonicalize_filename(b, s, sizeof(b)); + ustrzcpy(s, size, b); + } + + if(msg == MSG_KEY) + { + if((!ugetc(s)) || (ugetat(s, -1) == DEVICE_SEPARATOR)) + ustrzcat(s, size, uconvert_ascii("./", tmp)); + + canonicalize_filename(b, s, sizeof(b)); + ustrzcpy(s, size - ucwidth(OTHER_PATH_SEPARATOR), b); + + ch = ugetat(s, -1); + + if((ch != '/') && (ch != OTHER_PATH_SEPARATOR)) + { + if(file_exists(s, FA_RDONLY | FA_HIDDEN | FA_DIREC, &attr)) + { + if(attr & FA_DIREC) + put_backslash(s); + else + return D_CLOSE; + } + else + return D_CLOSE; + } + + object_message(file_selector+FS_FILES, MSG_START, 0); + + /* did we `cd ..' ? */ + if(ustrlen(updir)) + { + /* now we have to find a directory name equal to updir */ + for(i = 0; isize; i++) + { + if(!ustrcmp(updir, flist->name[i])) /* we got it ! */ + { + file_selector[FS_FILES].d1 = i; + /* we have to know the number of visible lines in the filelist */ + /* -1 to avoid an off-by-one problem */ + list_size = (file_selector[FS_FILES].h-4) / text_height(font) - 1; + + if(i>list_size) + file_selector[FS_FILES].d2 = i-list_size; + else + file_selector[FS_FILES].d2 = 0; + + found = 1; + break; /* ok, our work is done... */ + } + } + + /* by some strange reason, we didn't find the old directory... */ + if(!found) + { + file_selector[FS_FILES].d1 = 0; + file_selector[FS_FILES].d2 = 0; + } + } + + /* and continue... */ + object_message(file_selector+FS_FILES, MSG_DRAW, 0); + object_message(d, MSG_START, 0); + object_message(d, MSG_DRAW, 0); + + return D_O_K; + } + + int allegro_lfn = ALLEGRO_LFN; //removes compiler warning + + if(msg == MSG_UCHAR) + { + if((c >= 'a') && (c <= 'z')) + { + if(!allegro_lfn) + c = utoupper(c); + } + else if(c == '/') + { + c = OTHER_PATH_SEPARATOR; + } + else if(allegro_lfn) + { + if((c > 127) || (c < 32)) + return D_O_K; + } + else + { + if((c != OTHER_PATH_SEPARATOR) && (c != '_') && + (c != DEVICE_SEPARATOR) && (c != '.') && + ((c < 'A') || (c > 'Z')) && ((c < '0') || (c > '9'))) + return D_O_K; + } + } + + // return _gui_edit_proc(msg, d, c); + return jwin_edit_proc(msg, d, c); +} + +/* ustrfilecmp: + * ustricmp for filenames: makes sure that eg "foo.bar" comes before + * "foo-1.bar", and also that "foo9.bar" comes before "foo10.bar". + */ +static int ustrfilecmp(AL_CONST char *s1, AL_CONST char *s2) +{ + int c1, c2; + int x1, x2; + char *t1, *t2; + + for(;;) + { + c1 = utolower(ugetxc(&s1)); + c2 = utolower(ugetxc(&s2)); + + if((c1 >= '0') && (c1 <= '9') && (c2 >= '0') && (c2 <= '9')) + { + x1 = ustrtol(s1 - ucwidth(c1), &t1, 10); + x2 = ustrtol(s2 - ucwidth(c2), &t2, 10); + + if(x1 != x2) + return x1 - x2; + else if(t1 - s1 != t2 - s2) + return (t2 - s2) - (t1 - s1); + + s1 = t1; + s2 = t2; + } + else if(c1 != c2) + { + if(!c1) + return -1; + else if(!c2) + return 1; + else if(c1 == '.') + return -1; + else if(c2 == '.') + return 1; + + return c1 - c2; + } + + if(!c1) + return 0; + } +} + +/* fs_flist_putter: + * Callback routine for for_each_file() to fill the file selector listbox. + */ +static int fs_flist_putter(AL_CONST char *str, int attrib, void *check_attrib) +{ + char *s, *ext, *name; + int c, c2; + + s = get_filename(str); + fix_filename_case(s); + + if(!(attrib & FA_DIREC)) + { + /* Check if file extension matches. */ + if(fext_p) + { + ext = get_extension(s); + + for(c=0; csize < FLIST_SIZE) && ((ugetc(s) != '.') || (ugetat(s, 1)))) + { + int size = ustrsizez(s) + ((attrib & FA_DIREC) ? ucwidth(OTHER_PATH_SEPARATOR) : 0); + name = (char *) zc_malloc(size); + + if(!name) + return -1; + + ustrzcpy(name, size, s); + + if(attrib & FA_DIREC) + put_backslash(name); + + /* Sort alphabetically with directories first. */ + for(c=0; csize; c++) + { + if(ugetat(flist->name[c], -1) == OTHER_PATH_SEPARATOR) + { + if(attrib & FA_DIREC) + if(ustrfilecmp(name, flist->name[c]) < 0) + break; + } + else + { + if(attrib & FA_DIREC) + break; + + if(ustrfilecmp(name, flist->name[c]) < 0) + break; + } + } + + /* Shift in preparation for inserting the new entry. */ + for(c2=flist->size; c2>c; c2--) + flist->name[c2] = flist->name[c2-1]; + + /* Insert the new entry. */ + flist->name[c] = name; + flist->size++; + } + + return 0; +} + +/* fs_flist_getter: + * Listbox data getter routine for the file selector list. + */ +static const char *fs_flist_getter(int index, int *list_size) +{ + if(index < 0) + { + if(list_size) + *list_size = flist->size; + + return NULL; + } + + return flist->name[index]; +} + +/* build_attrb_flag: + * Returns the cumulative flag for all attributes in state STATE. + */ +static int build_attrb_flag(attrb_state_t state) +{ + int i, flag = 0; + + for(i = 0; i < ATTRB_MAX; i++) + { + if(attrb_state[i] == state) + flag |= attrb_flag[i]; + } + + return flag; +} + +/* fs_flist_proc: + * Dialog procedure for the file selector list. + */ +static int fs_flist_proc(int msg, DIALOG *d, int c) +{ + static int recurse_flag = 0; + char *s = (char *) file_selector[FS_EDIT].dp; + char tmp[32]; + /* of s (in bytes) */ + int size = (file_selector[FS_EDIT].d1 + 1) * uwidth_max(U_CURRENT); + int sel = d->d1; + int i, ret; + int ch, count; + + if(msg == MSG_START) + { + if(!flist) + { + flist = (FLIST *) zc_malloc(sizeof(FLIST)); + + if(!flist) + { + *allegro_errno = ENOMEM; + return D_CLOSE; + } + } + else + { + for(i=0; isize; i++) + if(flist->name[i]) + zc_free(flist->name[i]); + } + + flist->size = 0; + + replace_filename(flist->dir, s, uconvert_ascii("*.*", tmp), sizeof(flist->dir)); + + /* The semantics of the attributes passed to file_select_ex() is + * different from that of for_each_file_ex() in one case: when + * the 'd' attribute is not mentioned in the set of characters, + * the other attributes are not taken into account for directories, + * i.e the directories are all included. So we can't filter with + * for_each_file_ex() in that case. + */ + if(attrb_state[ATTRB_DIREC] == ATTRB_ABSENT) + /* accept all dirs */ + for_each_file_ex(flist->dir, 0 , FA_LABEL, fs_flist_putter, (void *)1UL /* check */); + else + /* don't check */ + for_each_file_ex(flist->dir, build_attrb_flag(ATTRB_SET), build_attrb_flag(ATTRB_UNSET) | FA_LABEL, fs_flist_putter, (void *)0UL); + + usetc(get_filename(flist->dir), 0); + d->d1 = d->d2 = 0; + sel = 0; + } + + if(msg == MSG_END) + { + if(flist) + { + for(i=0; isize; i++) + if(flist->name[i]) + zc_free(flist->name[i]); + + zc_free(flist); + flist = NULL; + } + } + + recurse_flag++; + ret = jwin_abclist_proc(msg,d,c); /* call the parent procedure */ + + recurse_flag--; + + if(((sel != d->d1) || (ret == D_CLOSE)) && (recurse_flag == 0)) + { + replace_filename(s, flist->dir, flist->name[d->d1], size); + + /* check if we want to `cd ..' */ + if((!ustrncmp(flist->name[d->d1], uconvert_ascii("..", tmp), 2)) && (ret == D_CLOSE)) + { + /* let's remember the previous directory */ + usetc(updir, 0); + i = ustrlen(flist->dir); + count = 0; + + while(i>0) + { + ch = ugetat(flist->dir, i); + + if((ch == '/') || (ch == OTHER_PATH_SEPARATOR)) + { + if(++count == 2) + break; + } + + uinsert(updir, 0, ch); + i--; + } + + /* ok, we have the dirname in updir */ + } + else + { + usetc(updir, 0); + } + + object_message(file_selector+FS_EDIT, MSG_START, 0); + object_message(file_selector+FS_EDIT, MSG_DRAW, 0); + + if(ret == D_CLOSE) + return object_message(file_selector+FS_EDIT, MSG_KEY, 0); + } + + return ret; +} + +/* parse_extension_string: + * Parses the extension string, possibly containing attribute characters. + */ +static void parse_extension_string(AL_CONST char *ext) +{ + attrb_state_t state; + char ext_tokens[32], attrb_char[32]; + char *last, *p, *attrb_p; + int c, c2, i; + + i = 0; + fext_size = 0; + fext_p = NULL; + attrb_p = NULL; + + if(!ext) + return; + + fext = ustrdup(ext); + + /* Tokenize the extension string and record the pointers to the + * beginning of each token in a dynamically growing array. + * ???? We rely on the implementation of ustrtok_r() which writes + * null characters in the string to delimit the tokens. Yuck. + */ + c = usetc(ext_tokens, ' '); + c += usetc(ext_tokens+c, ','); + c += usetc(ext_tokens+c, ';'); + usetc(ext_tokens+c, 0); + + p = ustrtok_r(fext, ext_tokens, &last); + + if(p == NULL || !ugetc(p)) + return; + + do + { + /* Set of attribute characters. */ + if(ugetc(p) == '/') + { + attrb_p = p + ucwidth('/'); + continue; + } + + /* Dynamically grow the array if needed. */ + if(i >= fext_size) + { + fext_size = (fext_size ? fext_size*2 : 2); + fext_p = (char **)_al_sane_realloc(fext_p, fext_size * sizeof(char *)); + } + + /* Record a pointer to the beginning of the token. */ + fext_p[i++] = p; + + } + while((p = ustrtok_r(NULL, ext_tokens, &last))!=NULL); + + /* This is the meaningful size now. */ + fext_size = i; + + if(attrb_p) + { + state = ATTRB_SET; + c = usetc(attrb_char, 'r'); + c += usetc(attrb_char+c, 'h'); + c += usetc(attrb_char+c, 's'); + c += usetc(attrb_char+c, 'd'); + c += usetc(attrb_char+c, 'a'); + c += usetc(attrb_char+c, '+'); + c += usetc(attrb_char+c, '-'); + usetc(attrb_char+c, 0); + + /* Scan the string. */ + while((c = utolower(ugetx(&attrb_p)))!=0) + { + p = attrb_char; + + for(i = 0; (c2 = ugetx(&p))!=0; i++) + { + if(c == c2) + { + if(i < ATTRB_MAX) + attrb_state[i] = state; + else + state = (i == ATTRB_MAX) ? ATTRB_SET : ATTRB_UNSET; + + break; + } + } + } + } +} + +/* stretch_dialog: + * Stretch the dialog horizontally and vertically to the specified + * size and the font in use. + * (all the magic numbers come from the "historical" file selector) + */ +static void stretch_dialog(DIALOG *d, int width, int height, int show_extlist) +{ + int font_w, font_h, hpad, vpad; + char tmp[16]; + +#ifdef HAVE_DIR_LIST + + /* horizontal settings */ + font_w = text_length(font, uconvert_ascii("A", tmp)); + + if(width == 0) + width = (int)(0.95*SCREEN_W); + + hpad = (int)(0.05*width); + + d[FS_WIN].w = width; + d[FS_WIN].x = 0; + d[FS_EDIT].w = d[FS_WIN].w - 2*hpad; + d[FS_EDIT].x = hpad; + d[FS_CANCEL].w = 10*font_w; + d[FS_CANCEL].x = d[FS_WIN].w - hpad - d[FS_CANCEL].w; + d[FS_OK].w = d[FS_CANCEL].w; + d[FS_OK].x = d[FS_CANCEL].x; + d[FS_TYPES].x = hpad; + d[FS_TYPES].w = d[FS_OK].x - 2*hpad; + d[FS_FILES].w = d[FS_TYPES].w; + d[FS_FILES].x = d[FS_TYPES].x; + d[FS_DISKS].w = d[FS_OK].w; + d[FS_DISKS].x = d[FS_OK].x; + d[FS_YIELD].x = 0; + + /* vertical settings */ + font_h = text_height(font); + + if(height == 0) + height = (int)(0.80*SCREEN_H); + + vpad = (int)(0.05*height); + + d[FS_WIN].h = height; + d[FS_WIN].y = 0; + d[FS_EDIT].h = font_h+6; + d[FS_EDIT].y = 2*vpad + font_h + 4; + d[FS_CANCEL].h = font_h + 13; + d[FS_CANCEL].y = d[FS_WIN].h - vpad - d[FS_CANCEL].h; + d[FS_OK].h = d[FS_CANCEL].h; + d[FS_OK].y = d[FS_CANCEL].y - vpad/2 - d[FS_OK].h; + d[FS_TYPES].h = show_extlist?font_h+8:0; + d[FS_TYPES].y = d[FS_WIN].h-d[FS_TYPES].h-vpad; + d[FS_FILES].h = ((((d[FS_WIN].h - 2*vpad - d[FS_EDIT].y - d[FS_EDIT].h - (show_extlist?(d[FS_TYPES].h+vpad):0))-8)/font_h)*font_h)+8; + d[FS_FILES].y = (show_extlist?d[FS_TYPES].y:d[FS_WIN].h)-vpad-d[FS_FILES].h; + d[FS_DISKS].y = d[FS_FILES].y; + d[FS_DISKS].h = font_h+8; + d[FS_YIELD].y = 0; + +#else + + /* horizontal settings */ + font_w = text_length(font, uconvert_ascii("A", tmp)); + + if(width == 0) + width = (int)(0.95*SCREEN_W); + + hpad = (int)(0.05*width); + + d[FS_WIN].w = width; + d[FS_WIN].x = 0; + d[FS_EDIT].w = d[FS_WIN].w - 2*hpad; + d[FS_EDIT].x = hpad; + d[FS_OK].w = 10*font_w; + d[FS_OK].x = (d[FS_WIN].w - 2*d[FS_OK].w - hpad + 1)/2; + d[FS_CANCEL].w = d[FS_OK].w; + d[FS_CANCEL].x = d[FS_WIN].w - d[FS_OK].x - d[FS_CANCEL].w; + d[FS_TYPES].x = hpad; + d[FS_TYPES].w = d[FS_WIN].w - 2*hpad; + d[FS_FILES].x = d[FS_TYPES].x; + d[FS_FILES].w = d[FS_TYPES].w; + d[FS_YIELD].x = 0; + + /* vertical settings */ + font_h = text_height(font); + + if(height == 0) + height = (int)(0.95*SCREEN_H); + + vpad = (int)(0.04*height); + + d[FS_WIN].h = height; + d[FS_WIN].y = 0; + d[FS_EDIT].h = font_h+6; + d[FS_EDIT].y = 2*vpad + font_h + 4; + d[FS_OK].h = font_h + 13; + d[FS_OK].y = d[FS_WIN].h - vpad - d[FS_OK].h; + d[FS_CANCEL].h = d[FS_OK].h; + d[FS_CANCEL].y = d[FS_OK].y; + d[FS_TYPES].h = show_extlist?font_h+8:0; + d[FS_TYPES].y = d[FS_OK].y-d[FS_TYPES].h-vpad; + d[FS_FILES].h = ((((d[FS_OK].y - 2*vpad - d[FS_EDIT].y - d[FS_EDIT].h - (show_extlist?(d[FS_TYPES].h+vpad):0))-8)/font_h)*font_h)+8; + d[FS_FILES].y = (show_extlist?d[FS_TYPES].y:d[FS_OK].y)-vpad-d[FS_FILES].h; + d[FS_YIELD].y = 0; +#endif +} + +/* enlarge_file_selector: + * Enlarges the dialog for Large Mode. -L + */ +void enlarge_file_selector(int width, int height) +{ + if(file_selector[0].d1==0) + { + stretch_dialog(file_selector, width, height, 1); + } + + jwin_center_dialog(file_selector); + bool show_extlist = file_selector[FS_TYPES].proc != fs_dummy_proc; + + if(is_large) + { + large_dialog(file_selector); + int bottom = +#ifndef HAVE_DIR_LIST + file_selector[FS_OK].y; +#else + file_selector[FS_WIN].y+file_selector[FS_WIN].h-8; +#endif + file_selector[FS_FILES].dp2=NULL; + file_selector[FS_TYPES].y = bottom-file_selector[FS_TYPES].h-5; + file_selector[FS_FILES].h=show_extlist ? 152 : 168; + file_selector[FS_FILES].y = (show_extlist ? file_selector[FS_TYPES].y:bottom)-(file_selector[FS_FILES].h+5); + file_selector[FS_EDIT].y = file_selector[FS_FILES].y-26; + ((ListData *)file_selector[FS_FILES].dp)->font = &lfont_l; + file_selector[FS_TYPES].dp2=NULL; + file_selector[FS_TYPES].h=20; + ((ListData *)file_selector[FS_TYPES].dp)->font = &lfont_l; +#ifdef HAVE_DIR_LIST + file_selector[FS_DISKS].dp2=NULL; + file_selector[FS_DISKS].h=20; + ((ListData *)file_selector[FS_DISKS].dp)->font = &lfont_l; +#endif + } +} + +/* jwin_file_select_ex: + * Displays the JWin file selector, with the message as caption. + * Allows the user to select a file, and stores the selection in the + * path buffer, whose length in bytes is given by size and should have + * room for at least 80 characters. The files are filtered according to + * the file extensions in ext. Passing NULL includes all files, "PCX;BMP" + * includes only files with .PCX or .BMP extensions. Returns zero if it + * was closed with the Cancel button or non-zero if it was OK'd. + */ +int jwin_file_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height, FONT *title_font) +{ + static attrb_state_t default_attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; + int ret; + char *p; + char tmp[32]; + ASSERT(message); + ASSERT(path); + + if(title_font) + { + file_selector[0].dp2=title_font; + } + + if(width == OLD_FILESEL_WIDTH) + width = 304; + +#ifdef HAVE_DIR_LIST + + if(height == OLD_FILESEL_HEIGHT) + height = 160; + +#else + + if(height == OLD_FILESEL_HEIGHT) + height = 188; + +#endif + + /* for fs_dlist_proc() */ + ASSERT(size >= 4 * uwidth_max(U_CURRENT)); + + usetc(updir, 0); + file_selector[FS_WIN].dp = (char *)message; + file_selector[FS_EDIT].d1 = size/uwidth_max(U_CURRENT) - 1; + file_selector[FS_EDIT].dp = path; + file_selector[FS_OK].dp = (void*)get_config_text("OK"); + file_selector[FS_CANCEL].dp = (void*)get_config_text("Cancel"); + + /* Set default attributes. */ + memcpy(attrb_state, default_attrb_state, sizeof(default_attrb_state)); + + /* Parse extension string. */ +// if (ext)// && ugetc(ext)) + { + parse_extension_string(ext); + } + + if(!ugetc(path)) + { + +#ifdef HAVE_DIR_LIST + + int drive = _al_getdrive(); + +#else + + int drive = 0; +#endif + + _al_getdcwd(drive, path, size - ucwidth(OTHER_PATH_SEPARATOR)); + fix_filename_case(path); + fix_filename_slashes(path); + put_backslash(path); + } + + clear_keybuf(); + + do + { + } + while(gui_mouse_b()); + + file_selector[FS_TYPES].proc = fs_dummy_proc; + enlarge_file_selector(width, height); + ret = popup_zqdialog(file_selector, FS_EDIT); + + if(fext) + { + zc_free(fext); + fext = NULL; + } + + if(fext_p) + { + _al_free(fext_p); + fext_p = NULL; + } + + if((ret == FS_CANCEL) || (ret == FS_WIN) || (!ugetc(get_filename(path)))) + return FALSE; + + p = get_extension(path); + + if((!ugetc(p)) && (ext) && (!ustrpbrk(ext, uconvert_ascii(" ,;", tmp)))) + { + size -= ((long)(size_t)p - (long)(size_t)path + ucwidth('.')); + + if(size >= uwidth_max(U_CURRENT) + ucwidth(0)) /* do not end with '.' */ + { + p += usetc(p, '.'); + ustrzcpy(p, size, ext); + } + } + + return TRUE; +} + +static int count_ext_list() +{ + int c = 0; + + if(fext_list) + { + while(fext_list[c].text) + c++; + } + + return c; +} + +/* fs_elist_getter: + * Listbox data getter routine for the file selector disk list. + */ +static const char *fs_elist_getter(int index, int *list_size) +{ + if(index < 0) + { + if(list_size) + *list_size = count_ext_list(); + + return NULL; + } + + return fext_list[index].text; +} + +/* fs_elist_proc: + * Dialog procedure for the file selector disk list. + */ +static int fs_elist_proc(int msg, DIALOG *d, int c) +{ + int ret; + int sel = d->d1; + char *s, *tok; + char tmp[80], ext[80]; + static char ext_tokens[] = " ,;"; + + s = (char *) file_selector[FS_EDIT].dp; + + if(msg == MSG_START) + { + d->d2 = 0; + } + + ret = jwin_droplist_proc(msg, d, c); + + if((sel != d->d1) || (ret & D_CLOSE)) + { + // change the extension(s) + fext = fext_list[d->d1].ext; +// if (fext)// && ugetc(fext)) + { + parse_extension_string(fext); + } + + // check whether the extension on the current file name is still valid + if((fext) && (strlen(get_filename(s)))) + { + strcpy(tmp, fext); + strcpy(ext, get_extension(s)); + tok = strtok(tmp, ext_tokens); + + while(tok) + { + if(stricmp(ext, tok) == 0) + break; + + tok = strtok(NULL, ext_tokens); + } + + // not valid, replace file name + if(!tok) + replace_filename(s, flist->dir, "", 256); + } + + scare_mouse(); + SEND_MESSAGE(file_selector+FS_FILES, MSG_START, 0); + SEND_MESSAGE(file_selector+FS_FILES, MSG_DRAW, 0); + SEND_MESSAGE(file_selector+FS_EDIT, MSG_START, 0); + SEND_MESSAGE(file_selector+FS_EDIT, MSG_DRAW, 0); + unscare_mouse(); + + if(ret & D_CLOSE) + return (ret | SEND_MESSAGE(file_selector+FS_EDIT, MSG_KEY, 0)) & ~D_CLOSE; + } + + return ret; +} + +/* jwin_dfile_select_ex: + * Same as jwin_file_select_ex except that it returns TRUE on OK, even + * if the selected path doesn't include a file name. + * This is for getting directories instead of files, so a blank filename isn't an issue. + */ +int jwin_dfile_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height, FONT *title_font) +{ + static attrb_state_t default_attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; + int ret; + char *p; + char tmp[32]; + ASSERT(message); + ASSERT(path); + + if(title_font) + { + file_selector[0].dp2=title_font; + } + + if(width == OLD_FILESEL_WIDTH) + width = 304; + +#ifdef HAVE_DIR_LIST + + if(height == OLD_FILESEL_HEIGHT) + height = 160; + +#else + + if(height == OLD_FILESEL_HEIGHT) + height = 188; + +#endif + + /* for fs_dlist_proc() */ + ASSERT(size >= 4 * uwidth_max(U_CURRENT)); + + usetc(updir, 0); + file_selector[FS_WIN].dp = (char *)message; + file_selector[FS_EDIT].d1 = size/uwidth_max(U_CURRENT) - 1; + file_selector[FS_EDIT].dp = path; + file_selector[FS_OK].dp = (void*)get_config_text("OK"); + file_selector[FS_CANCEL].dp = (void*)get_config_text("Cancel"); + + /* Set default attributes. */ + memcpy(attrb_state, default_attrb_state, sizeof(default_attrb_state)); + + /* Parse extension string. */ +// if (ext)// && ugetc(ext)) + { + parse_extension_string(ext); + } + + if(!ugetc(path)) + { + +#ifdef HAVE_DIR_LIST + + int drive = _al_getdrive(); + +#else + + int drive = 0; +#endif + + _al_getdcwd(drive, path, size - ucwidth(OTHER_PATH_SEPARATOR)); + fix_filename_case(path); + fix_filename_slashes(path); + put_backslash(path); + } + + clear_keybuf(); + + do + { + } + while(gui_mouse_b()); + + file_selector[FS_TYPES].proc = fs_dummy_proc; + enlarge_file_selector(width, height); + ret = popup_zqdialog(file_selector, FS_EDIT); + + if(fext) + { + zc_free(fext); + fext = NULL; + } + + if(fext_p) + { + _al_free(fext_p); + fext_p = NULL; + } + + if((ret == FS_CANCEL) || (ret == FS_WIN)) + return FALSE; + + if(!ugetc(get_filename(path))) + return TRUE; + + p = get_extension(path); + + if((!ugetc(p)) && (ext) && (!ustrpbrk(ext, uconvert_ascii(" ,;", tmp)))) + { + size -= ((long)(size_t)p - (long)(size_t)path + ucwidth('.')); + + if(size >= uwidth_max(U_CURRENT) + ucwidth(0)) /* do not end with '.' */ + { + p += usetc(p, '.'); + ustrzcpy(p, size, ext); + } + } + + return TRUE; +} + +/* jwin_file_browse_ex: + * Same as jwin_file_select but it lets you give it a list of + * possible extensions to choose from. + */ +int jwin_file_browse_ex(AL_CONST char *message, char *path, EXT_LIST *list, int *list_sel, int size, int width, int height, FONT *title_font) +{ + static attrb_state_t default_attrb_state[ATTRB_MAX] = DEFAULT_ATTRB_STATE; + int ret; + char *p; + char tmp[32]; + ASSERT(message); + ASSERT(path); + + if(title_font) + { + file_selector[0].dp2=title_font; + } + + if(width == OLD_FILESEL_WIDTH) + width = 304; + +#ifdef HAVE_DIR_LIST + + if(height == OLD_FILESEL_HEIGHT) + height = 160; + +#else + + if(height == OLD_FILESEL_HEIGHT) + height = 188; + +#endif + + /* for fs_dlist_proc() */ + ASSERT(size >= 4 * uwidth_max(U_CURRENT)); + + usetc(updir, 0); + file_selector[FS_WIN].dp = (char *)message; + file_selector[FS_EDIT].d1 = size/uwidth_max(U_CURRENT) - 1; + file_selector[FS_EDIT].dp = path; + file_selector[FS_OK].dp = (void*)get_config_text("OK"); + file_selector[FS_CANCEL].dp = (void*)get_config_text("Cancel"); + + fext_list = list; + fext = list[*list_sel].ext; + file_selector[FS_TYPES].d1 = *list_sel; + + /* Set default attributes. */ + memcpy(attrb_state, default_attrb_state, sizeof(default_attrb_state)); + + /* Parse extension string. */ +// if (fext)// && ugetc(fext)) + { + parse_extension_string(fext); + } + + if(!ugetc(path)) + { + +#ifdef HAVE_DIR_LIST + + int drive = _al_getdrive(); + +#else + + int drive = 0; +#endif + + _al_getdcwd(drive, path, size - ucwidth(OTHER_PATH_SEPARATOR)); + fix_filename_case(path); + fix_filename_slashes(path); + put_backslash(path); + } + + clear_keybuf(); + + do + { + } + while(gui_mouse_b()); + + file_selector[FS_TYPES].proc = fs_elist_proc; + enlarge_file_selector(width,height); + ret = popup_zqdialog(file_selector, FS_EDIT); + + if(fext) + { + zc_free(fext); + fext = NULL; + } + + if(fext_p) + { + _al_free(fext_p); + fext_p = NULL; + } + + if((ret == FS_CANCEL) || (ret == FS_WIN) || (!ugetc(get_filename(path)))) + return FALSE; + + *list_sel = file_selector[FS_TYPES].d1; + + p = get_extension(path); + + if((!ugetc(p)) && (fext) && (!ustrpbrk(fext, uconvert_ascii(" ,;", tmp)))) + { + size -= ((long)(size_t)p - (long)(size_t)path + ucwidth('.')); + + if(size >= uwidth_max(U_CURRENT) + ucwidth(0)) /* do not end with '.' */ + { + p += usetc(p, '.'); + ustrzcpy(p, size, fext); + } + } + + return TRUE; +} + diff --git a/src/jwinfsel.h b/src/jwinfsel.h new file mode 100644 index 0000000000..6617e8919a --- /dev/null +++ b/src/jwinfsel.h @@ -0,0 +1,76 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwinfsel.h + * + * The file selector. + * + * By Shawn Hargreaves. + * + * Guilherme Silveira and Theuzifan Sumachingun both independently + * modified it to only list valid drive letters. + * + * Adapted to "jwin" style by Jeremy Craner. Also added the "browser". + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ + +#ifndef _JWIN_FSEL_H_ +#define _JWIN_FSEL_H_ + +#include "jwin.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* jwin_file_select: + * Displays the Allegro file selector, with the message as caption. + * Allows the user to select a file, and stores the selection in path + * (which should have room for at least 80 characters). The files are + * filtered according to the file extensions in ext. Passing NULL + * includes all files, "PCX;BMP" includes only files with .PCX or .BMP + * extensions. Returns zero if it was closed with the Cancel button or + * if the path has no file name, or non-zero if it was OK'd. + */ +//int jwin_file_select(char *message, char *path, char *ext); +int jwin_file_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height, FONT *title_font); + +/* jwin_dfile_select: + * Same as jwin_file_select except that it returns TRUE on OK even + * if the selected path doesn't include a file name. + */ +//int jwin_dfile_select(char *message, char *path, char *ext); +int jwin_dfile_select_ex(AL_CONST char *message, char *path, AL_CONST char *ext, int size, int width, int height, FONT *title_font); + +typedef struct EXT_LIST +{ + char *text; // appears in drop list + char *ext; // same as *ext in file_select() +} EXT_LIST; + +/* jwin_file_browse: + * Same as jwin_file_select except that it takes a list of possible + * extensions and lets the user select from them. The list should be + * an array of EXT_LIST structures terminated by one with text==NULL. + * list_sel is the index of the current selection in the EXT_LIST. + */ +//int jwin_file_browse(char *message, char *path, EXT_LIST *list, int *list_sel); +int jwin_file_browse_ex(AL_CONST char *message, char *path, EXT_LIST *list, int *list_sel, int size, int width, int height, FONT *title_font); + +#ifdef __cplusplus +} +#endif +#endif // _JWIN_FSEL_H_ + diff --git a/src/link.cpp b/src/link.cpp new file mode 100644 index 0000000000..a5c19cc656 --- /dev/null +++ b/src/link.cpp @@ -0,0 +1,12417 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// link.cc +// +// Link's class: LinkClass +// Handles a lot of game play stuff as well as Link's +// movement, attacking, etc. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include + +#include "link.h" +#include "ffc.h" +#include "guys.h" +#include "zc_subscr.h" +#include "zelda.h" +#include "zc_sys.h" +#include "decorations.h" +#include "gamedata.h" +#include "zc_custom.h" +#include "title.h" +#include "messageManager.h" +#include "screenWipe.h" +#include "sequence.h" +#include "sound.h" +#include "angelscript/scriptData.h" + +#include "item/dinsFire.h" +#include "item/faroresWind.h" +#include "item/hookshot.h" +#include "item/nayrusLove.h" + +using std::set; + +extern MessageManager messageMgr; + +//extern bool draw_screen_clip_rect_show_link; +extern bool global_wait; + +int link_count = -1; +int link_animation_speed = 1; //lower is faster animation +int z3step = 2; +bool did_scripta=false; +bool did_scriptb=false; +bool did_scriptl=false; +byte lshift = 0; +int dowpn = -1; +int directItem = -1; //Is set if Link is currently using an item directly +int directItemA = -1; +int directItemB = -1; +int directWpn = -1; +int whistleitem=-1; +extern word g_doscript; + +void playLevelMusic(); + +const byte lsteps[8] = { 1, 1, 2, 1, 1, 2, 1, 1 }; + +extern LinkClass Link; +void showCurrentDMapIntro() +{ + if(game->visited[currdmap]!=1 || (DMaps[currdmap].flags&dmfALWAYSMSG)!=0) + { + game->visited[currdmap]=1; + + // Only show the intro if it isn't blank + bool showIntro=false; + const char* intro=DMaps[currdmap].intro; + for(int i=0; intro[i]!=0; i++) + { + if(intro[i]!=' ') + { + showIntro=true; + break; + } + } + + if(showIntro) + { + Link.Freeze(); + messageMgr.showDMapIntro(currdmap); + } + } +} + +int LinkClass::DrunkClock() +{ + return drunkclk; +} +void LinkClass::setDrunkClock(int newdrunkclk) +{ + drunkclk=newdrunkclk; +} + +LinkClass::LinkClass(): sprite() +{ + init(); +} + +//void LinkClass::linkstep() { lstep = lstep<(BSZ?27:11) ? lstep+1 : 0; } +void LinkClass::linkstep() +{ + lstep = lstep<((zinit.linkanimationstyle==las_bszelda)?27:11) ? lstep+1 : 0; +} + +bool is_moving() +{ + return DrunkUp()||DrunkDown()||DrunkLeft()||DrunkRight(); +} + +// called by ALLOFF() +void LinkClass::resetflags(bool all) +{ + refilling=REFILL_NONE; + inwallm=false; + inlikelike=blowcnt=whirlwind=specialcave=hclk=fairyclk=refill_why=didstuff=0; + + if(swordclk>0 || all) + swordclk=0; + + if(itemclk>0 || all) + itemclk=0; + + if(all) + { + itemEffects.clear(); + hoverclk=jumping=0; + } + + hopclk=0; + hopdir=-1; + attackclk=0; + stomping=false; + reset_swordcharge(); + diveclk=drownclk=0; + action=none; + conveyor_flags=0; + magicitem=-1; +} + +void LinkClass::Freeze() +{ + if(action!=inwind) action=freeze; +} +void LinkClass::unfreeze() +{ + if(action==freeze && fairyclk<1) action=none; +} + +void LinkClass::Drown() +{ + asIScriptFunction* func=scriptData->getFunction("void Drown()"); + scriptData->runFunction(func); +} + +void LinkClass::finishedmsg() +{ + //these are to cancel out any keys that Link may + //be pressing so he doesn't attack at the end of + //a message if he was scrolling through it quickly. + rAbtn(); + rBbtn(); + unfreeze(); + + if(action == landhold1 || + action == landhold2 || + action == waterhold1 || + action == waterhold2) + { + holdclk = 1; + } +} +fix LinkClass::getFall() +{ + return fall; +} + +int LinkClass::getHitDir() +{ + return hitdir; +} + +fix LinkClass::getXOfs() +{ + return xofs; +} +fix LinkClass::getYOfs() +{ + return yofs; +} +void LinkClass::setXOfs(int newxofs) +{ + xofs=newxofs; +} +void LinkClass::setYOfs(int newyofs) +{ + yofs=newyofs; +} +fix LinkClass::getClimbCoverX() +{ + return climb_cover_x; +} +fix LinkClass::getClimbCoverY() +{ + return climb_cover_y; +} + +int LinkClass::getLStep() +{ + return lstep; +} +void LinkClass::onMeleeWeaponHit() +{ + if(charging>0) + attackclk=attackclk+1; //Cancel charging +} +bool LinkClass::isCharged() +{ + return spins>0; +} + +void LinkClass::cancelAttack() +{ + attackclk=0; +} + +int LinkClass::getSwordClk() +{ + return swordclk; +} +int LinkClass::getItemClk() +{ + return itemclk; +} +void LinkClass::setSwordClk(int newclk) +{ + swordclk=newclk; +} +void LinkClass::setItemClk(int newclk) +{ + itemclk=newclk; +} + +void LinkClass::setHitDir(int newdir) +{ + hitdir = newdir; +} +int LinkClass::getClk() +{ + return clk; +} +int LinkClass::getPushing() +{ + return pushing; +} +void LinkClass::Catch() +{ + if(!inwallm && (action==none || action==walking)) + { + action=attacking; + attackclk=0; + attack=wCatching; + } +} + +bool LinkClass::getClock() +{ + return superman; +} +void LinkClass::setClock(bool state) +{ + superman=state; +} +int LinkClass::getAction() // Used by ZScript +{ + if(spins > 0) + return isspinning; + else if(charging > 0) + return ischarging; + else if(diveclk > 0) + return isdiving; + + return action; +} + +void LinkClass::setAction(actiontype new_action) +{ + if(currentItemAction) + { + currentItemAction->abort(); + delete currentItemAction; + currentItemAction=0; + } + + if(action==inwind) // Remove from whirlwind + { + xofs=0; + whirlwind=0; + lstep=0; + dontdraw=false; + } + else if(action==freeze) // Might be in enemy wind + { + sprite* wind=0; + bool foundWind=false; + for(int i=0; iid==ewWind && ((weapon*)wind)->hasLink()) + { + foundWind=true; + break; + } + } + + if(foundWind) + { + xofs=0; + dontdraw=false; + wind->misc=-1; + x=wind->x; + y=wind->y; + } + } + + if(new_action != attacking) + { + attackclk=0; + + if(attack==wHookshot) + reset_hookshot(); + } + if(new_action != isspinning) + { + charging = 0; + spins = 0; + } + + switch(new_action) + { + case isspinning: + if(attack==wSword) + { + attackclk = SWORDCHARGEFRAME+1; + charging = 0; + + if(spins==0) + spins = 5; + } + return; + + case isdiving: + if(action==swimming && diveclk==0) + diveclk = 80; // Who cares about qr_NODIVING? It's the questmaker's business. + return; + + case drowning: + if(!drownclk) + Drown(); + + break; + + case gothit: + case swimhit: + if(!hclk) + hclk=48; + + break; + + case landhold1: + case landhold2: + case waterhold1: + case waterhold2: + if(!holdclk) + holdclk=130; + + attack=none; + break; + + case attacking: + attack=none; + break; + + default: + break; + } + + action=new_action; +} + +void LinkClass::setHeldItem(int newitem) +{ + holditem=newitem; +} +int LinkClass::getHeldItem() +{ + return holditem; +} +bool LinkClass::isDiving() +{ + return (diveclk>30); +} +bool LinkClass::isSwimming() +{ + return ((action==swimming)||(action==swimhit)|| + (action==waterhold1)||(action==waterhold2)|| + (hopclk==0xFF)); +} + +void LinkClass::setDontDraw(bool new_dontdraw) +{ + dontdraw=new_dontdraw; +} + +bool LinkClass::getDontDraw() +{ + return dontdraw; +} + +void LinkClass::setHitTimer(int newhclk) +{ + hclk=newhclk; +} + +int LinkClass::getHClk() +{ + return hclk; +} + +int LinkClass::getSpecialCave() +{ + return specialcave; // used only by maps.cpp +} + +void LinkClass::init() +{ + currentItemAction=0; + hookshot_used=false; + hookshot_frozen=false; + dir = up; + shiftdir = -1; + holddir = -1; + landswim = 0; + sdir = up; + ilswim=true; + walkable=false; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + x=tmpscr->warpreturnx[0]; + y=tmpscr->warpreturny[0]; + } + else + { + x=tmpscr->warparrivalx; + y=tmpscr->warparrivaly; + } + + z=fall=0; + hzsz = 12; // So that flying peahats can still hit him. + + if(x==0) dir=right; + + if(x==240) dir=left; + + if(y==0) dir=down; + + if(y==160) dir=up; + + lstep=0; + skipstep=0; + autostep=false; + attackclk=holdclk=hoverclk=jumping=0; + attack=wNone; + attackid=-1; + action=none; + xofs=0; + yofs=playing_field_offset; + cs=6; + pushing=fairyclk=0; + id=0; + inlikelike=0; + superman=inwallm=false; + scriptcoldet=1; + blowcnt=whirlwind=specialcave=0; + hopclk=diveclk=0; + hopdir=-1; + conveyor_flags=0; + drunkclk=0; + drawstyle=3; + stepoutindex=stepoutwr=stepoutdmap=stepoutscr=0; + stepnext=stepsecret=-1; + entry_x=x; + entry_y=y; + falling_oldy = y; + magicitem = -1; + nayrusLoveActive=false; + + for(int i=0; i<16; i++) miscellaneous[i] = 0; + + bigHitbox=get_bit(quest_rules, qr_LTTPCOLLISION); + diagonalMovement=get_bit(quest_rules,qr_LTTPWALK); +} + +void LinkClass::scriptInit() +{ + asUpdate=scriptData->getFunction("int Update()"); +} + +void LinkClass::draw_under(BITMAP* dest) +{ + int c_raft=current_item_id(itype_raft); + int c_ladder=current_item_id(itype_ladder); + + if(action==rafting && c_raft >-1) + { + if(((dir==left) || (dir==right)) && (get_bit(quest_rules,qr_RLFIX))) + { + overtile16(dest, itemsbuf[c_raft].tile, x, y+playing_field_offset+4, + itemsbuf[c_raft].csets&15, rotate_value((itemsbuf[c_raft].misc>>2)&3)^3); + } + else + { + overtile16(dest, itemsbuf[c_raft].tile, x, y+playing_field_offset+4, + itemsbuf[c_raft].csets&15, (itemsbuf[c_raft].misc>>2)&3); + } + } + + if(ladderx+laddery && c_ladder >-1) + { + if((ladderdir>=left) && (get_bit(quest_rules,qr_RLFIX))) + { + overtile16(dest, itemsbuf[c_ladder].tile, ladderx, laddery+playing_field_offset, + itemsbuf[c_ladder].csets&15, rotate_value((itemsbuf[iRaft].misc>>2)&3)^3); + } + else + { + overtile16(dest, itemsbuf[c_ladder].tile, ladderx, laddery+playing_field_offset, + itemsbuf[c_ladder].csets&15, (itemsbuf[c_ladder].misc>>2)&3); + } + } +} + +void LinkClass::drawshadow(BITMAP* dest, bool translucent) +{ + int tempy=yofs; + yofs+=8; + shadowtile = wpnsbuf[iwShadow].tile; + sprite::drawshadow(dest,translucent); + yofs=tempy; +} + +// The Stone of Agony reacts to these flags. +bool LinkClass::agonyflag(int flag) +{ + switch(flag) + { + case mfWHISTLE: + case mfBCANDLE: + case mfARROW: + case mfBOMB: + case mfSBOMB: + case mfBRANG: + case mfMBRANG: + case mfFBRANG: + case mfSARROW: + case mfGARROW: + case mfRCANDLE: + case mfWANDFIRE: + case mfDINSFIRE: + case mfWANDMAGIC: + case mfREFMAGIC: + case mfREFFIREBALL: + case mfSWORD: + case mfWSWORD: + case mfMSWORD: + case mfXSWORD: + case mfSWORDBEAM: + case mfWSWORDBEAM: + case mfMSWORDBEAM: + case mfXSWORDBEAM: + case mfHOOKSHOT: + case mfWAND: + case mfHAMMER: + case mfSTRIKE: + return true; + } + + return false; +} + + +// Find the attack power of the current melee weapon. +// The Whimsical Ring is applied on a target-by-target basis. +int LinkClass::weaponattackpower() +{ + asIScriptFunction* func=scriptData->getFunction("int weaponattackpower()"); + scriptData->runFunction(func); + return scriptData->getLastResult(); +} + +// Must only be called once per frame! +void LinkClass::positionSword(weapon *w, int itemid) +{ + asIScriptFunction* func=scriptData->getFunction("void positionSword(weapon@ w, int itemid)"); + scriptData->runFunction(func, w->getScriptObject(), itemid); +} + +void LinkClass::draw(BITMAP* dest) +{ + /*{ + char buf[36]; + //sprintf(buf,"%d %d %d %d %d %d %d",dir, action, attack, attackclk, charging, spins, tapping); + textout_shadowed_ex(framebuf,font, buf, 2,72,WHITE,BLACK,-1); + }*/ + int oxofs, oyofs; + bool shieldModify = false; + + bool invisible=dontdraw || (tmpscr->flags3&fINVISLINK); + + if(action==dying) + { + if(!invisible) + { + sprite::draw(dest); + } + + return; + } + + bool useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0); + + oxofs=xofs; + oyofs=yofs; + + if(!invisible) + yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_LINKDUNGEONPOSFIX)) ? 2 : 0); + + // Stone of Agony + bool agony=false; + int agonyid = current_item_id(itype_agony); + + if(invisible) + goto attack; + + if(agonyid>-1) + { + // Stolen some code from checkdamagecombos()... + int power = itemsbuf[agonyid].power; + int dx1 = (int)x+8-power; + int dx2 = (int)x+8+(power-1); + int dy1 = (int)y+(bigHitbox?8:12)-(bigHitbox?power:(power+1)/2); + int dy2 = (int)y+(bigHitbox?8:12)+(bigHitbox?power:(power+1)/2)-1; + + agony = (agonyflag(MAPFLAG(dx1,dy1)) || agonyflag(MAPFLAG(dx1,dy2)) + || agonyflag(MAPFLAG(dx2,dy1)) || agonyflag(MAPFLAG(dx2,dy2)) + || agonyflag(MAPCOMBOFLAG(dx1,dy1)) || agonyflag(MAPCOMBOFLAG(dx1,dy2)) + || agonyflag(MAPCOMBOFLAG(dx2,dy1)) || agonyflag(MAPCOMBOFLAG(dx2,dy2))); + } + + cs = 6; + + if(!get_bit(quest_rules,qr_LINKFLICKER)) + { + if(superman) + { + cs += (((~frame)>>1)&3); + } + else if(hclk && !nayrusLoveActive) + { + cs += ((hclk>>1)&3); + } + } + +attack: + + if(attackclk || action==attacking) + { + /* Spaghetti code constants! + * - Link.attack contains a weapon type... + * - which must be converted to an itype... + * - which must be converted to an item ID... + * - which is used to acquire a wpn ID! Aack! + */ + int itype = (attack==wFire ? itype_candle : attack==wCByrna ? itype_cbyrna : attack==wWand ? itype_wand : attack==wHammer ? itype_hammer : itype_sword); + int itemid = (directWpn>-1 && itemsbuf[directWpn].family==itype) ? directWpn : current_item_id(itype); + itemid=vbound(itemid, 0, MAXITEMS-1); + + if(attackclk>4||(attack==wSword&&game->get_canslash())) + { + if((attack==wSword || attack==wWand || ((attack==wFire || attack==wCByrna) && itemsbuf[itemid].wpn)) && wpnsbuf[itemsbuf[itemid].wpn].tile) + { + // Create a sword weapon at the right spot. + weapon *w=NULL; + bool found = false; + + // Look for pre-existing sword + for(int i=0; iid == (attack==wSword ? wSword : wWand)) + { + found = true; + break; + } + } + + if(!found) // Create one if sword nonexistant + { + Lwpns.add(new weapon((fix)0,(fix)0,(fix)0,(attack==wSword ? wSword : wWand),0,0,dir,itemid,getUID())); + w = (weapon*)Lwpns.spr(Lwpns.Count()-1); + + positionSword(w,itemid); + + // Stone of Agony + if(agony) + { + w->y-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,2)); + } + } + + // These are set by positionSword(), above or in checkstab() + yofs += slashyofs; + xofs += slashxofs; + slashyofs = slashxofs = 0; + } + } + + if(attackclk<7 + || (attack==wSword && + (attackclk<(game->get_canslash()?15:13) || (charging>0 && attackclk!=SWORDCHARGEFRAME))) + || ((attack==wWand || attack==wFire || attack==wCByrna) && attackclk<13) + || (attack==wHammer && attackclk<=30)) + { + if(!invisible) + { + linktile(&tile, &flip, &extend, ls_stab, dir, zinit.linkanimationstyle); + + if((game->get_canslash() && (attack==wSword || attack==wWand || attack==wFire || attack==wCByrna)) && itemsbuf[itemid].flags&ITEM_FLAG4 && (attackclk<7)) + { + linktile(&tile, &flip, &extend, ls_slash, dir, zinit.linkanimationstyle); + } + + if((attack==wHammer) && (attackclk<13)) + { + linktile(&tile, &flip, &extend, ls_pound, dir, zinit.linkanimationstyle); + } + + if(useltm) + { + tile+=item_tile_mod(shieldModify); + } + + tile+=dmap_tile_mod(); + + // Stone of Agony + if(agony) + { + yofs-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3)); + } + + if(!(get_bit(quest_rules,qr_LINKFLICKER)&&((superman||hclk)&&(frame&1)))) + { + masked_draw(dest); + } + } + + if(attack!=wHammer) + { + xofs=oxofs; + yofs=oyofs; + return; + } + } + + if(attack==wHammer) // To do: possibly abstract this out to a positionHammer routine? + { + int wy=1; + int wx=1; + int f=0,t,cs2; + weapon *w=NULL; + bool found = false; + + for(int i=0; iid == wHammer) + { + found = true; + break; + } + } + + if(!found) + { + Lwpns.add(new weapon((fix)0,(fix)0,(fix)0,wHammer,0,0,dir,itemid,getUID())); + w = (weapon*)Lwpns.spr(Lwpns.Count()-1); + found = true; + } + + t = w->o_tile; + cs2 = w->o_cset; + + switch(dir) + { + case up: + wx=-1; + wy=-15; + + if(attackclk>=13) + { + wx-=1; + wy+=1; + ++t; + } + + if(attackclk>=15) + { + ++t; + } + + break; + + case down: + wx=3; + wy=-14; + t+=3; + + if(attackclk>=13) + { + wy+=16; + ++t; + } + + if(attackclk>=15) + { + wx-=1; + wy+=12; + ++t; + } + + break; + + case left: + wx=0; + wy=-14; + t+=6; + f=1; + + if(attackclk>=13) + { + wx-=7; + wy+=8; + ++t; + } + + if(attackclk>=15) + { + wx-=8; + wy+=8; + ++t; + } + + break; + + case right: + wx=0; + wy=-14; + t+=6; + + if(attackclk>=13) + { + wx+=7; + wy+=8; + ++t; + } + + if(attackclk>=15) + { + wx+=8; + wy+=8; + ++t; + } + + break; + } + + if(BSZ || ((isdungeon() && currscr<128) && !get_bit(quest_rules,qr_LINKDUNGEONPOSFIX))) + { + wy+=2; + } + + // Stone of Agony + if(agony) + { + wy-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3)); + } + + w->x = x+wx; + w->y = y+wy-(54-yofs); + w->z = (z+zofs); + w->tile = t; + w->flip = f; + w->hxsz=20; + w->hysz=20; + + if(dir>down) + { + w->hysz-=6; + } + else + { + w->hxsz-=6; + w->hyofs=4; + } + + w->power = weaponattackpower(); + + if(attackclk==15 && z==0 && (sideviewhammerpound() || !(tmpscr->flags7&fSIDEVIEW))) + { + sfx(((iswater(MAPCOMBO(x+wx+8,y+wy)) || COMBOTYPE(x+wx+8,y+wy)==cSHALLOWWATER) && get_bit(quest_rules,qr_MORESOUNDS)) ? WAV_ZN1SPLASH : itemsbuf[itemid].usesound,pan(int(x))); + } + + xofs=oxofs; + yofs=oyofs; + return; + } + } + else if(!charging && !spins) // remove the sword + { + for(int i=0; iid == wSword || w->id == wHammer || w->id==wWand) + w->dead=1; + } + } + + if(invisible) + { + xofs=oxofs; + yofs=oyofs; + return; + } + + if(action != casting) + { + // Keep this consistent with checkspecial2, line 7800-ish... + bool inwater = iswater(MAPCOMBO(x+4,y+9)) && iswater(MAPCOMBO(x+4,y+15)) && iswater(MAPCOMBO(x+11,y+9)) && iswater(MAPCOMBO(x+11,y+15)); + + int jumping2 = int(jumping*(zinit.gravity/16.0)); + + //if (jumping!=0) al_trace("%d %d %f %d\n",jumping,zinit.gravity,zinit.gravity/16.0,jumping2); + switch(zinit.linkanimationstyle) + { + case las_original: //normal + if(action==drowning) + { + if(inwater) + { + linktile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_dive, dir, zinit.linkanimationstyle); + tile+=((frame>>3) & 1)*(extend==2?2:1); + } + else + { + xofs=oxofs; + yofs=oyofs; + return; + } + } + else if(action==swimming || action==swimhit || hopclk==0xFF) + { + linktile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.linkanimationstyle); + + if(lstep>=6) + { + if(dir==up) + { + ++flip; + } + else + { + extend==2?tile+=2:++tile; + } + } + + if(diveclk>30) + { + linktile(&tile, &flip, &extend, ls_dive, dir, zinit.linkanimationstyle); + tile+=((frame>>3) & 1)*(extend==2?2:1); + } + } + else if(charging > 0 && attack != wHammer) + { + linktile(&tile, &flip, &extend, ls_charge, dir, zinit.linkanimationstyle); + + if(lstep>=6) + { + if(dir==up) + { + ++flip; + } + else + { + extend==2?tile+=2:++tile; + } + } + } + else if((z>0 || (tmpscr->flags7&fSIDEVIEW)) && jumping2>0 && jumping2<24 && game->get_life()>0 && action!=rafting) + { + linktile(&tile, &flip, &extend, ls_jump, dir, zinit.linkanimationstyle); + tile+=((int)jumping2/8)*(extend==2?2:1); + } + else + { + linktile(&tile, &flip, &extend, ls_walk, dir, zinit.linkanimationstyle); + + if(dir>up) + { + useltm=true; + shieldModify=true; + } + + if(lstep>=6) + { + if(dir==up) + { + ++flip; + } + else + { + extend==2?tile+=2:++tile; + } + } + } + + break; + + case las_bszelda: //BS + if(action==drowning) + { + if(inwater) + { + linktile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_dive, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + else + { + xofs=oxofs; + yofs=oyofs; + return; + } + } + else if(action==swimming || action==swimhit || hopclk==0xFF) + { + linktile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + + if(diveclk>30) + { + linktile(&tile, &flip, &extend, ls_dive, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + } + else if(charging > 0 && attack != wHammer) + { + linktile(&tile, &flip, &extend, ls_charge, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + else if((z>0 || (tmpscr->flags7&fSIDEVIEW)) && jumping2>0 && jumping2<24 && game->get_life()>0) + { + linktile(&tile, &flip, &extend, ls_jump, dir, zinit.linkanimationstyle); + tile+=((int)jumping2/8)*(extend==2?2:1); + } + else + { + linktile(&tile, &flip, &extend, ls_walk, dir, zinit.linkanimationstyle); + + if(dir>up) + { + useltm=true; + shieldModify=true; + } + + /* + else if (dir==up) + { + useltm=true; + } + */ + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + + break; + + case las_zelda3slow: //8-frame Zelda 3 (slow) + case las_zelda3: //8-frame Zelda 3 + if(action == drowning) + { + if(inwater) + { + linktile(&tile, &flip, &extend, (drownclk > 60) ? ls_float : ls_dive, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + else + { + xofs=oxofs; + yofs=oyofs; + return; + } + } + else if(action == swimming || action==swimhit || hopclk==0xFF) + { + linktile(&tile, &flip, &extend, is_moving()?ls_swim:ls_float, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + + if(diveclk>30) + { + linktile(&tile, &flip, &extend, ls_dive, dir, zinit.linkanimationstyle); + tile += anim_3_4(lstep,7)*(extend==2?2:1); + } + } + else if(charging > 0 && attack != wHammer) + { + linktile(&tile, &flip, &extend, ls_charge, dir, zinit.linkanimationstyle); + tile+=(extend==2?2:1); +// int l=link_count/link_animation_speed; + int l=(link_count/link_animation_speed)&15; + //int l=((p[lt_clock]/link_animation_speed)&15); + l-=((l>3)?1:0)+((l>12)?1:0); + tile+=(l/2)*(extend==2?2:1); + } + else if((z>0 || (tmpscr->flags7&fSIDEVIEW)) && jumping2>0 && jumping2<24 && game->get_life()>0) + { + linktile(&tile, &flip, &extend, ls_jump, dir, zinit.linkanimationstyle); + tile+=((int)jumping2/8)*(extend==2?2:1); + } + else + { + linktile(&tile, &flip, &extend, ls_walk, dir, zinit.linkanimationstyle); + + if(action == walking || action == climbcoverbottom || action == climbcovertop) + { + tile += (extend == 2 ? 2 : 1); + } + + if(dir>up) + { + useltm=true; + shieldModify=true; + } + + if(action == walking || action == hopping || action == climbcoverbottom || action == climbcovertop) + { + //tile+=(extend==2?2:1); + //tile+=(((active_count>>2)%8)*(extend==2?2:1)); + int l = link_count / link_animation_speed; + l -= ((l > 3) ? 1 : 0) + ((l > 12) ? 1 : 0); + tile += (l / 2) * (extend == 2 ? 2 : 1); + } + } + + break; + + default: + break; + } + } + + yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_LINKDUNGEONPOSFIX)) ? 2 : 0); + + if(action==won) + { + yofs=playing_field_offset - 2; + } + + if(action==landhold1 || action==landhold2) + { + useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0); + yofs = oyofs-((!BSZ && isdungeon() && currscr<128 && !get_bit(quest_rules,qr_LINKDUNGEONPOSFIX)) ? 2 : 0); + linktile(&tile, &flip, &extend, (action==landhold1)?ls_landhold1:ls_landhold2, dir, zinit.linkanimationstyle); + } + else if(action==waterhold1 || action==waterhold2) + { + useltm=(get_bit(quest_rules,qr_EXPANDEDLTM) != 0); + linktile(&tile, &flip, &extend, (action==waterhold1)?ls_waterhold1:ls_waterhold2, dir, zinit.linkanimationstyle); + } + + if(action!=casting) + { + if(useltm) + { + tile+=item_tile_mod(shieldModify); + } + } + + tile+=dmap_tile_mod(); + + // Stone of Agony + if(agony) + { + yofs-=!(frame%zc_max(60-itemsbuf[agonyid].misc1,3)); + } + + if(!(get_bit(quest_rules,qr_LINKFLICKER)&&((superman||hclk)&&(frame&1)))) + { + masked_draw(dest); + } + + //draw held items after Link so they don't go behind his head + if(action==landhold1 || action==landhold2) + { + if(holditem > -1) + { + if(get_bit(quest_rules,qr_HOLDITEMANIMATION)) + { + putitem2(dest,x-((action==landhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET)),holditem,lens_hint_item[holditem][0], lens_hint_item[holditem][1], 0); + } + else + { + putitem(dest,x-((action==landhold1)?4:0),y+yofs-16-(get_bit(quest_rules, qr_NOITEMOFFSET)),holditem); + } + } + } + else if(action==waterhold1 || action==waterhold2) + { + if(holditem > -1) + { + if(get_bit(quest_rules,qr_HOLDITEMANIMATION)) + { + putitem2(dest,x-((action==waterhold1)?4:0),y+yofs-12-(get_bit(quest_rules, qr_NOITEMOFFSET)),holditem,lens_hint_item[holditem][0], lens_hint_item[holditem][1], 0); + } + else + { + putitem(dest,x-((action==waterhold1)?4:0),y+yofs-12-(get_bit(quest_rules, qr_NOITEMOFFSET)),holditem); + } + } + } + + if(fairyclk==0||(get_bit(quest_rules,qr_NOHEARTRING))) + { + xofs=oxofs; + yofs=oyofs; + return; + } + + double a2 = fairyclk*2*PI/80 + (PI/2); + int hearts=0; + // int htile = QHeader.dat_flags[ZQ_TILES] ? 2 : 0; + int htile = 2; + + do + { + int nx=125; + + if(get_bit(quest_rules,qr_HEARTRINGFIX)) + { + nx=x; + } + + int ny=88; + + if(get_bit(quest_rules,qr_HEARTRINGFIX)) + { + ny=y; + } + + double tx = cos(a2)*53 +nx; + double ty = -sin(a2)*53 +ny+playing_field_offset; + overtile8(dest,htile,int(tx),int(ty),1,0); + a2-=PI/4; + ++hearts; + } + while(a2>PI/2 && hearts<8); + + xofs=oxofs; + yofs=oyofs; +} + +void LinkClass::masked_draw(BITMAP* dest) +{ + if(isdungeon() && currscr<128 && (x<16 || x>224 || y<18 || y>146) && !get_bit(quest_rules,qr_FREEFORM)) + { + // clip under doorways + BITMAP *sub=create_sub_bitmap(dest,16,playing_field_offset+16,224,144); + + if(sub!=NULL) + { + yofs -= (playing_field_offset+16); + xofs -= 16; + sprite::draw(sub); + xofs=0; + yofs += (playing_field_offset+16); + destroy_bitmap(sub); + } + } + else + { + sprite::draw(dest); + } + + return; +} + +// separate case for sword/wand/hammer/slashed weapons only +// the main weapon checking is in the global function check_collisions() +void LinkClass::checkstab() +{ + asIScriptFunction* func=scriptData->getFunction("void checkstab()"); + scriptData->runFunction(func); +} + +int LinkClass::EwpnHit() +{ + for(int i=0; ihit(x+7,y+7,z,2,2,1)) + { + weapon *ew = (weapon*)(Ewpns.spr(i)); + bool hitshield=false; + + if((ew->ignoreLink)==true) + break; + + if(ew->id==ewWind) + { + xofs=1000; + action=freeze; + ew->pickUpLink(); + attackclk=0; + return -1; + } + + switch(dir) + { + case up: + if(ew->dir==down || ew->dir==l_down || ew->dir==r_down) + hitshield=true; + + break; + + case down: + if(ew->dir==up || ew->dir==l_up || ew->dir==r_up) + hitshield=true; + + break; + + case left: + if(ew->dir==right || ew->dir==r_up || ew->dir==r_down) + hitshield=true; + + break; + + case right: + if(ew->dir==left || ew->dir==l_up || ew->dir==l_down) + hitshield=true; + + break; + } + + switch(ew->id) + { + case ewLitBomb: + case ewBomb: + case ewLitSBomb: + case ewSBomb: + return i; + } + + if(!hitshield || action==attacking || action==swimming || charging > 0 || spins > 0 || hopclk==0xFF) + { + return i; + } + + int itemid = current_item_id(itype_shield); + + if(itemid<0 || !checkmagiccost(itemid)) return i; + + paymagiccost(itemid); + + bool reflect = false; + + switch(ew->id) + { + case ewFireball2: + case ewFireball: + if(ew->type & 1) //Boss fireball + { + if(!(itemsbuf[itemid].misc1 & (shFIREBALL2))) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shFIREBALL2) != 0); + } + else + { + if(!(itemsbuf[itemid].misc1 & (shFIREBALL))) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shFIREBALL) != 0); + } + + break; + + case ewMagic: + if(!(itemsbuf[itemid].misc1 & shMAGIC)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shMAGIC) != 0); + break; + + case ewSword: + if(!(itemsbuf[itemid].misc1 & shSWORD)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shSWORD) != 0); + break; + + case ewFlame: + if(!(itemsbuf[itemid].misc1 & shFLAME)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shFLAME) != 0); // Actually isn't reflected. + break; + + case ewRock: + if(!(itemsbuf[itemid].misc1 & shROCK)) + return i; + + reflect = (itemsbuf[itemid].misc2 & shROCK); + break; + + case ewArrow: + if(!(itemsbuf[itemid].misc1 & shARROW)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shARROW) != 0); // Actually isn't reflected. + break; + + case ewBrang: + if(!(itemsbuf[itemid].misc1 & shBRANG)) + return i; + + break; + + default: // Just throw the script weapons in here... + if(ew->id>=wScript1 && ew->id<=wScript10) + { + if(!(itemsbuf[itemid].misc1 & shSCRIPT)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shSCRIPT) != 0); + } + + break; + } + + int oldid = ew->id; + ew->onhit(false, reflect ? 2 : 1, dir); + + if(ew->id != oldid) // changed type from ewX to wX + { + // ew->power*=DAMAGE_MULTIPLIER; + Lwpns.add(ew); + Ewpns.remove(ew); + } + + if(ew->id==wRefMagic) + { + ew->ignoreLink=true; + ew->ignorecombo=-1; + } + + sfx(itemsbuf[itemid].usesound,pan(int(x))); + } + } + + return -1; +} + +int LinkClass::LwpnHit() // Check for reflected weapons +{ + for(int i=0; ihit(x+7,y+7,z,2,2,1)) + { + weapon *lw = (weapon*)(Lwpns.spr(i)); + bool hitshield=false; + + if((lw->ignoreLink)==true) + break; + + switch(dir) + { + case up: + if(lw->dir==down || lw->dir==l_down || lw->dir==r_down) + hitshield=true; + + break; + + case down: + if(lw->dir==up || lw->dir==l_up || lw->dir==r_up) + hitshield=true; + + break; + + case left: + if(lw->dir==right || lw->dir==r_up || lw->dir==r_down) + hitshield=true; + + break; + + case right: + if(lw->dir==left || lw->dir==l_up || lw->dir==l_down) + hitshield=true; + + break; + } + + int itemid = current_item_id(itype_shield); + bool reflect = false; + + switch(lw->id) + { + case wRefFireball: + if(itemid<0) + return i; + + if(lw->type & 1) //Boss fireball + return i; + + if(!(itemsbuf[itemid].misc1 & (shFIREBALL))) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shFIREBALL) != 0); + break; + + case wRefMagic: + if(itemid<0) + return i; + + if(!(itemsbuf[itemid].misc1 & shMAGIC)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shMAGIC) != 0); + break; + + case wRefBeam: + if(itemid<0) + return i; + + if(!(itemsbuf[itemid].misc1 & shSWORD)) + return i; + + reflect = ((itemsbuf[itemid].misc2 & shSWORD) != 0); + break; + + case wRefRock: + if(itemid<0) + return i; + + if(!(itemsbuf[itemid].misc1 & shROCK)) + return i; + + reflect = (itemsbuf[itemid].misc2 & shROCK); + break; + + default: + return -1; + } + + if(!hitshield || action==attacking || action==swimming || hopclk==0xFF) + return i; + + if(itemid<0 || !checkmagiccost(itemid)) return i; + + paymagiccost(itemid); + + lw->onhit(false, 1+reflect, dir); + lw->ignoreLink=true; + lw->ignorecombo=-1; + sfx(itemsbuf[itemid].usesound,pan(int(x))); + } + + return -1; +} + +void LinkClass::checkhit() +{ + if(checklink && hclk>0) + hclk--; + + if(hclk<39 && action==gothit) + action=none; + + if(hclk<39 && action==swimhit) + action=swimming; + + if(hclk>=40 && action==gothit) + { + if(((ladderx+laddery) && ((hitdir&2)==ladderdir))||(!(ladderx+laddery))) + { + for(int i=0; i<4; i++) + { + switch(hitdir) + { + case up: + if(hit_walkflag(x,y+(bigHitbox?-1:7),2)||(int(x)&7?hit_walkflag(x+16,y+(bigHitbox?-1:7),1):0)) action=none; + else --y; + + break; + + case down: + if(hit_walkflag(x,y+16,2)||(int(x)&7?hit_walkflag(x+16,y+16,1):0)) action=none; + else ++y; + + break; + + case left: + if(hit_walkflag(x-1,y+(bigHitbox?0:8),1)||hit_walkflag(x-1,y+8,1)||(int(y)&7?hit_walkflag(x-1,y+16,1):0)) action=none; + else --x; + + break; + + case right: + if(hit_walkflag(x+16,y+(bigHitbox?0:8),1)||hit_walkflag(x+16,y+8,1)||(int(y)&7?hit_walkflag(x+16,y+16,1):0)) action=none; + else ++x; + + break; + } + } + } + } + + if(hclk>0 || inlikelike == 1 || action==inwind || action==drowning || inwallm || diveclk>30 || (action==hopping && hopclk<255)) + { + return; + } + + for(int i=0; iparentitem; + + if(s->id==wFire && (superman ? (diagonalMovement?s->hit(x+4,y+4,z,7,7,1):s->hit(x+7,y+7,z,2,2,1)) : s->hit(this))&& + (itemid < 0 || itemsbuf[itemid].family!=itype_dinsfire)) + { + if(!nayrusLoveActive) + { + int ringpow = ringpower(lwpn_dp(i)); + game->set_life(zc_max(game->get_life()-ringpow,0)); + } + + hitdir = s->hitdir(x,y,16,16,dir); + + if(action!=rafting && action!=freeze) + action=gothit; + + if(action==swimming || hopclk==0xFF) + action=swimhit; + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + hclk=48; + sfx(WAV_OUCH,pan(int(x))); + return; + } + } + + // check enemy weapons true, 1, -1 + // + if(get_bit(quest_rules,qr_Z3BRANG_HSHOT)) + { + if(s->id==wBrang || s->id==wHookshot) + { + int itemid = ((weapon*)s)->parentitem>-1 ? ((weapon*)s)->parentitem : + directWpn>-1 ? directWpn : current_item_id(s->id==wHookshot ? itype_hookshot : itype_brang); + itemid = vbound(itemid, 0, MAXITEMS-1); + + for(int j=0; jhit(t->x+7,t->y+7,t->z,2,2,1)) + { + bool reflect = false; + + switch(t->id) + { + case ewBrang: + if(!(itemsbuf[itemid].misc3 & shBRANG)) break; + + reflect = ((itemsbuf[itemid].misc4 & shBRANG) != 0); + goto killweapon; + + case ewArrow: + if(!(itemsbuf[itemid].misc3 & shARROW)) break; + + reflect = ((itemsbuf[itemid].misc4 & shARROW) != 0); + goto killweapon; + + case ewRock: + if(!(itemsbuf[itemid].misc3 & shROCK)) break; + + reflect = ((itemsbuf[itemid].misc4 & shROCK) != 0); + goto killweapon; + + case ewFireball2: + case ewFireball: + { + int mask = (((weapon*)t)->type&1 ? shFIREBALL2 : shFIREBALL); + + if(!(itemsbuf[itemid].misc3 & mask)) break; + + reflect = ((itemsbuf[itemid].misc4 & mask) != 0); + goto killweapon; + } + + case ewSword: + if(!(itemsbuf[itemid].misc3 & shSWORD)) break; + + reflect = ((itemsbuf[itemid].misc4 & shSWORD) != 0); + goto killweapon; + + case wRefMagic: + case ewMagic: + if(!(itemsbuf[itemid].misc3 & shMAGIC)) break; + + reflect = ((itemsbuf[itemid].misc4 & shMAGIC) != 0); + goto killweapon; + + case wScript1: + case wScript2: + case wScript3: + case wScript4: + case wScript5: + case wScript6: + case wScript7: + case wScript8: + case wScript9: + case wScript10: + if(!(itemsbuf[itemid].misc3 & shSCRIPT)) break; + + reflect = ((itemsbuf[itemid].misc4 & shSCRIPT) != 0); + goto killweapon; + + case ewLitBomb: + case ewLitSBomb: +killweapon: + ((weapon*)s)->dead=1; + weapon *ew = ((weapon*)t); + int oldid = ew->id; + ew->onhit(true, reflect ? 2 : 1, s->dir); + + + if(ew->id != oldid || (ew->id>=wScript1 && ew->id<=wScript10)) // changed type from ewX to wX... Except for script weapons + { + Lwpns.add(ew); + Ewpns.remove(ew); + } + + if(ew->id==wRefMagic) + { + ew->ignoreLink=true; + ew->ignorecombo=-1; + } + + break; + } + + break; + } + } + } + } + + if(get_bit(quest_rules,qr_OUCHBOMBS)) + { + // if(((s->id==wBomb)||(s->id==wSBomb)) && (superman ? s->hit(x+7,y+7,z,2,2,1) : s->hit(this))) + if(((s->id==wBomb)||(s->id==wSBomb)) && s->hit(this) && !superman && (scriptcoldet&1)) + { + if(!nayrusLoveActive) + { + int ringpow = ringpower(((((weapon*)s)->parentitem>-1 ? itemsbuf[((weapon*)s)->parentitem].misc3 : ((weapon*)s)->power) *HP_PER_HEART)); + game->set_life(zc_min(game->get_maxlife(), zc_max(game->get_life()-ringpow,0))); + } + + hitdir = s->hitdir(x,y,16,16,dir); + + if(action!=rafting && action!=freeze) + action=gothit; + + if(action==swimming || hopclk==0xFF) + action=swimhit; + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + hclk=48; + sfx(WAV_OUCH,pan(int(x))); + return; + } + } + + if(hclk==0 && s->id==wWind && s->hit(x+7,y+7,z,2,2,1) && !fairyclk) + { + reset_hookshot(); + xofs=1000; + action=inwind; + dir=s->dir; + spins = charging = attackclk = 0; + + // In case Link used two whistles in a row, summoning two whirlwinds, + // check which whistle's whirlwind picked him up so the correct + // warp ring will be used + int whistle=((weapon*)s)->parentitem; + + if(whistle>-1 && itemsbuf[whistle].family==itype_whistle) + whistleitem=whistle; + + return; + } + } + + if(action==rafting || action==freeze || + action==casting || action==drowning || superman || !(scriptcoldet&1)) + return; + + int hit2 = diagonalMovement?GuyHit(x+4,y+4,z,8,8,hzsz):GuyHit(x+7,y+7,z,2,2,hzsz); + + if(hit2!=-1) + { + hitlink(hit2); + return; + } + + hit2 = LwpnHit(); + + if(hit2!=-1) + { + if(!nayrusLoveActive) + { + int ringpow = ringpower(lwpn_dp(hit2)); + game->set_life(zc_max(game->get_life()-ringpow,0)); + } + + hitdir = Lwpns.spr(hit2)->hitdir(x,y,16,16,dir); + ((weapon*)Lwpns.spr(hit2))->onhit(false); + + if(action==swimming || hopclk==0xFF) + action=swimhit; + else + action=gothit; + + hclk=48; + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + sfx(WAV_OUCH,pan(int(x))); + return; + } + + hit2 = EwpnHit(); + + if(hit2!=-1) + { + if(!nayrusLoveActive) + { + int ringpow = ringpower(ewpn_dp(hit2)); + game->set_life(zc_max(game->get_life()-ringpow,0)); + } + + hitdir = Ewpns.spr(hit2)->hitdir(x,y,16,16,dir); + ((weapon*)Ewpns.spr(hit2))->onhit(false); + + if(action==swimming || hopclk==0xFF) + action=swimhit; + else + action=gothit; + + hclk=48; + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + sfx(WAV_OUCH,pan(int(x))); + return; + } + + // The rest of this method deals with damage combos, which can be jumped over. + if(z>0 && !(tmpscr->flags2&fAIRCOMBOS)) return; + + int dx1 = (int)x+8-(tmpscr->csensitive); + int dx2 = (int)x+8+(tmpscr->csensitive-1); + int dy1 = (int)y+(bigHitbox?8:12)-(bigHitbox?tmpscr->csensitive:(tmpscr->csensitive+1)/2); + int dy2 = (int)y+(bigHitbox?8:12)+(bigHitbox?tmpscr->csensitive-1:((tmpscr->csensitive+1)/2)-1); + + for(int i=get_bit(quest_rules, qr_DMGCOMBOLAYERFIX) ? 1 : -1; i>=-1; i--) // Layers 0, 1 and 2!! + (void)checkdamagecombos(dx1,dx2,dy1,dy2,i); +} + +bool LinkClass::checkdamagecombos(int dx, int dy) +{ + return checkdamagecombos(dx,dx,dy,dy); +} + +bool LinkClass::checkdamagecombos(int dx1, int dx2, int dy1, int dy2, int layer, bool solid) //layer = -1, solid = false +{ + if(hclk || superman) + return false; + + int hp_mod[4]; + + hp_mod[0]=combo_class_buf[combobuf[layer>-1?MAPCOMBO2(layer,dx1,dy1):MAPCOMBO(dx1,dy1)].type].modify_hp_amount; + hp_mod[1]=combo_class_buf[combobuf[layer>-1?MAPCOMBO2(layer,dx1,dy2):MAPCOMBO(dx1,dy2)].type].modify_hp_amount; + hp_mod[2]=combo_class_buf[combobuf[layer>-1?MAPCOMBO2(layer,dx2,dy1):MAPCOMBO(dx2,dy1)].type].modify_hp_amount; + hp_mod[3]=combo_class_buf[combobuf[layer>-1?MAPCOMBO2(layer,dx2,dy2):MAPCOMBO(dx2,dy2)].type].modify_hp_amount; + + int hp_modtotal=0; + + for(int i=0; i<4; i++) + { + if(get_bit(quest_rules,qr_DMGCOMBOPRI)) + { + if(hp_modtotal >= 0) + hp_modtotal = zc_min(hp_modtotal, hp_mod[i]); + else if(hp_mod[i] < 0) + hp_modtotal = zc_max(hp_modtotal, hp_mod[i]); + } + else + hp_modtotal = zc_min(hp_modtotal, hp_mod[i]); + } + + hp_mod[0]=combo_class_buf[combobuf[MAPFFCOMBO(dx1,dy1)].type].modify_hp_amount; + hp_mod[1]=combo_class_buf[combobuf[MAPFFCOMBO(dx1,dy2)].type].modify_hp_amount; + hp_mod[2]=combo_class_buf[combobuf[MAPFFCOMBO(dx2,dy1)].type].modify_hp_amount; + hp_mod[3]=combo_class_buf[combobuf[MAPFFCOMBO(dx2,dy2)].type].modify_hp_amount; + int hp_modtotalffc = 0; + + for(int i=0; i<4; i++) + { + if(get_bit(quest_rules,qr_DMGCOMBOPRI)) + { + if(hp_modtotalffc >= 0) + hp_modtotalffc = zc_min(hp_modtotalffc, hp_mod[i]); + else if(hp_mod[i] < 0) + hp_modtotalffc = zc_max(hp_modtotalffc, hp_mod[i]); + } + else + hp_modtotalffc = zc_min(hp_modtotalffc, hp_mod[i]); + } + + int hp_modmin = zc_min(hp_modtotal, hp_modtotalffc); + + bool global_ring = (get_bit(quest_rules,qr_RINGAFFECTDAMAGE) != 0); + bool current_ring = ((tmpscr->flags6&fTOGGLERINGDAMAGE) != 0); + + int itemid = current_item_id(itype_boots); + + bool bootsnosolid = itemid >= 0 && 0 != (itemsbuf[itemid].flags & ITEM_FLAG1); + + if(hp_modmin<0) + { + if((itemid<0) || (tmpscr->flags5&fDAMAGEWITHBOOTS) || (4<set_life(zc_max(game->get_life()-(global_ring!=current_ring ? ringpow:-hp_modmin),0)); + } + + hitdir = (dir^1); + + if(action!=rafting && action!=freeze) + action=gothit; + + if(action==swimming || hopclk==0xFF) + action=swimhit; + + hclk=48; + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + sfx(WAV_OUCH,pan(int(x))); + return true; + } + else paymagiccost(itemid); // Boots are successful + } + + return false; +} + +void LinkClass::hitlink(int hit2) +{ + if(current_item(itype_stompboots) && checkmagiccost(current_item(itype_stompboots)) && (stomping || + (z > (((enemy*)guys.spr(hit2))->z)) || + (((tmpscr->flags7&fSIDEVIEW) && (y+16)-(((enemy*)guys.spr(hit2))->y)<=14) && falling_oldyset_item(itemid,false); + + // Stomp Boots script + if(itemsbuf[itemid].script != 0) + { + ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[itemid].script, itemid & 0xFFF); + } + + return; + } + else if(superman || !(scriptcoldet&1)) + return; + else if(!nayrusLoveActive) + { + int ringpow = ringpower(enemy_dp(hit2)); + game->set_life(zc_max(game->get_life()-ringpow,0)); + } + + hitdir = guys.spr(hit2)->hitdir(x,y,16,16,dir); + + if(action==swimming || hopclk==0xFF) + action=swimhit; + else + action=gothit; + + hclk=48; + sfx(WAV_OUCH,pan(int(x))); + + if(charging > 0 || spins > 0 || attack == wSword || attack == wHammer) + { + spins = charging = attackclk = 0; + attack=none; + tapping = false; + } + + enemy_scored(hit2); + int dm7 = ((enemy*)guys.spr(hit2))->dmisc7; + int dm8 = ((enemy*)guys.spr(hit2))->dmisc8; + + switch(((enemy*)guys.spr(hit2))->family) + { + case eeWALLM: + if(((enemy*)guys.spr(hit2))->hp>0) + { + GrabLink(hit2); + inwallm=true; + action=none; + } + + break; + + //case eBUBBLEST: + //case eeBUBBLE: + case eeWALK: + { + int itemid = current_item_id(itype_whispring); + //I can only assume these are supposed to be int, not bool ~pkmnfrk + int sworddivisor = ((itemid>-1 && itemsbuf[itemid].misc1 & 1) ? itemsbuf[itemid].power : 1); + int itemdivisor = ((itemid>-1 && itemsbuf[itemid].misc1 & 2) ? itemsbuf[itemid].power : 1); + + switch(dm7) + { + case e7tTEMPJINX: + if(dm8==0 || dm8==2) + if(swordclk>=0 && !(sworddivisor==0)) + swordclk=150; + + if(dm8==1 || dm8==2) + if(itemclk>=0 && !(itemdivisor==0)) + itemclk=150; + + break; + + case e7tPERMJINX: + if(dm8==0 || dm8==2) + if(sworddivisor) swordclk=(itemid >-1 && itemsbuf[itemid].flags & ITEM_FLAG1)? int(150/sworddivisor) : -1; + + if(dm8==1 || dm8==2) + if(itemdivisor) itemclk=(itemid >-1 && itemsbuf[itemid].flags & ITEM_FLAG1)? int(150/itemdivisor) : -1; + + break; + + case e7tUNJINX: + if(dm8==0 || dm8==2) + swordclk=0; + + if(dm8==1 || dm8==2) + itemclk=0; + + break; + + case e7tTAKEMAGIC: + game->change_dmagic(-dm8*game->get_magicdrainrate()); + break; + + case e7tTAKERUPEES: + game->change_drupy(-dm8); + break; + + case e7tDRUNK: + drunkclk += dm8; + break; + } + + if(dm7 >= e7tEATITEMS) + { + EatLink(hit2); + inlikelike=(dm7 == e7tEATHURT ? 2:1); + action=none; + } + } + } +} + +static void byrnaSparkle(const weapon& wpn) +{ + const itemdata& data=itemsbuf[wpn.parentitem]; + + int wpn2=data.wpn4; + int wpn3=data.wpn5; + int newWpn; + // Either one (wpn2) or the other (wpn3). If both are present, randomise. + if(wpn2!=0) + { + if(wpn3==0) + newWpn=wpn2; + else + newWpn=((rand()&1)==0) ? wpn2 : wpn3; + } + else + newWpn=wpn3; + + Lwpns.add(new weapon( + fix(wpn.getX()+2), fix(wpn.getY()+2), wpn.getZ(), + newWpn==wpn3 ? wFSparkle : wSSparkle, + newWpn, 0, wpn.getDir(), wpn.parentitem, -1)); +} + +static void standardSparkle(const weapon& wpn) +{ + if((frame&3)!=0) + return; + + const itemdata& data=itemsbuf[wpn.parentitem]; + int wpn2=data.wpn2; + int wpn3=data.wpn3; + int newWpn; + // Either one (wpn2) or the other (wpn3). If both are present, randomise. + if(wpn2!=0) + { + if(wpn3==0) + newWpn=wpn2; + else + newWpn=((rand()&1)==0) ? wpn2 : wpn3; + } + else + newWpn=wpn3; + + if(newWpn) + { + int h=0; + int v=0; + int dir=wpn.getDir(); + + if(dir==right || dir==r_up || dir==r_down) + h=-4; + + if(dir==left || dir==l_up || dir==l_down) + h=4; + + if(dir==down || dir==l_down || dir==r_down) + v=-4; + + if(dir==up || dir==l_up || dir==r_up) + v=4; + + // Damaging boomerang sparkle? + if(newWpn==wpn3 && data.family==itype_brang) + { + // If the boomerang just bounced, flip the sparkle direction so it doesn't hit + // whatever it just bounced off of if it's shielded from that direction. + if(wpn.misc==1 && wpn.clk2>256 && wpn.clk2<272) + dir=oppositeDir[dir]; + } + + Lwpns.add(new weapon( + fix(wpn.getX()+rand()%4)+h, fix(wpn.getY()+rand()%4)+v, wpn.getZ(), + newWpn==wpn3 ? wFSparkle : wSSparkle, + newWpn, 0, dir, wpn.parentitem, -1)); + } +} + +void LinkClass::updateGravity() +{ + if(tmpscr->flags7&fSIDEVIEW) // Sideview gravity + { + // Fall, unless on a ladder, rafting, using the hookshot, drowning or cheating. + if(!(toogam && Up()) && !drownclk && action!=rafting && !pull_link && !((ladderx || laddery) && fall>0)) + { + int ydiff = fall/(spins && fall<0 ? 200:100); + falling_oldy = y; // Stomp Boots-related variable + y+=ydiff; + hs_starty+=ydiff; + + for(int j=0; jy+=ydiff; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=ydiff; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=ydiff; + } + } + + // Stop hovering/falling if you land on something. + if(ON_SIDEPLATFORM && !(pull_link && dir==down) && action!=rafting) + { + stop_item_sfx(itype_hoverboots); + fall = hoverclk = jumping = 0; + y-=(int)y%8; //fix position + + if(y>=160 && currscr>=0x70 && !(tmpscr->flags2&wfDOWN)) // Landed on the bottommost screen. + y = 160; + } + // Stop hovering if you press down. + else if((hoverclk || ladderx || laddery) && DrunkDown()) + { + stop_item_sfx(itype_hoverboots); + hoverclk = 0; + reset_ladder(); + fall = zinit.gravity; + } + // Continue falling. + else if(fall <= (int)zinit.terminalv) + { + if(fall != 0 || hoverclk) + jumping++; + + // Bump head if: hit a solid combo from beneath, or hit a solid combo in the screen above this one. + if((_walkflag(x+4,y-(bigHitbox?9:1),0) + || (y<=(bigHitbox?9:1) && + // Extra checks if Smart Screen Scrolling is enabled + (nextcombo_wf(up) || ((get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE)) && + !(tmpscr->flags2&wfUP)) && (nextcombo_solid(up)))))) + && fall < 0) + { + fall = 0; // Bumped his head + + // ... maybe on spikes + checkdamagecombos(x+4, x+12, y-1, y-1); + } + + if(hoverclk) + { + if(hoverclk > 0) + { + hoverclk--; + } + + if(!hoverclk && !ladderx && !laddery) + { + fall += zinit.gravity; + } + } + else if(fall+int(zinit.gravity) > 0 && fall<=0 && can_use_item(itype_hoverboots,i_hoverboots) && !ladderx && !laddery) + { + fall = jumping = 0; + int itemid = current_item_id(itype_hoverboots); + hoverclk = itemsbuf[itemid].misc1 ? itemsbuf[itemid].misc1 : -1; + } + else if(!ladderx && !laddery) + { + fall += zinit.gravity; + } + } + } + else // Topdown gravity + { + z-=fall/(spins && fall>0 ? 200:100); + + if(z>0) + { + switch(action) + { + case swimming: + diveclk=0; + action=walking; + break; + + case waterhold1: + action=landhold1; + break; + + case waterhold2: + action=landhold2; + break; + + default: + break; + } + } + + for(int j=0; jz=z; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->z=z; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->z=z; + } + + if(z<=0) + { + if(fall > 0) + { + if((iswater(MAPCOMBO(x,y+8)) && ladderx<=0 && laddery<=0) || COMBOTYPE(x,y+8)==cSHALLOWWATER) + sfx(WAV_ZN1SPLASH,int(x)); + + stomping = true; + } + + z = fall = jumping = hoverclk = 0; + } + else if(fall <= (int)zinit.terminalv) + { + if(fall != 0 || hoverclk) + jumping++; + + if(hoverclk) + { + if(hoverclk > 0) + { + hoverclk--; + } + + if(!hoverclk) + { + fall += zinit.gravity; + } + } + else if(fall+(int)zinit.gravity > 0 && fall<=0 && can_use_item(itype_hoverboots,i_hoverboots)) + { + fall = 0; + int itemid = current_item_id(itype_hoverboots); + hoverclk = itemsbuf[itemid].misc1 ? itemsbuf[itemid].misc1 : -1; + } + else fall += zinit.gravity; + } + } +} + +void LinkClass::checkLadderRemoval() +{ + if(diagonalMovement) + { + if(ladderx+laddery) + { + if(ladderdir==up) + { + if((laddery-int(y)>=(16+(ladderstart==dir?ladderstart==down?1:0:0))) || (laddery-int(y)<=(-16-(ladderstart==dir?ladderstart==up?1:0:0))) || (abs(ladderx-int(x))>8)) + { + reset_ladder(); + } + } + else + { + if((abs(laddery-int(y))>8) || (ladderx-int(x)>=(16+(ladderstart==dir?ladderstart==right?1:0:0))) || (ladderx-int(x)<=(-16-(ladderstart==dir?ladderstart==left?1:0:0)))) + { + reset_ladder(); + } + } + } + } + else + { + if((abs(laddery-int(y))>=16) || (abs(ladderx-int(x))>=16)) + { + reset_ladder(); + } + } +} + +// returns true when game over +bool LinkClass::animate(int) +{ + itemEffects.update(); + int lsave=0; + + scriptData->runFunction(asUpdate); + int asRet=scriptData->getLastResult(); + if(asRet==1) + return true; + else if(asRet==2) + return false; + + // This needs to be undone first. :p + if(currentItemAction) + { + currentItemAction->update(); + if(currentItemAction->isFinished()) + { + delete currentItemAction; + currentItemAction=0; + } + return false; + } + + updateGravity(); + + if(drunkclk) + { + --drunkclk; + } + + if(!is_on_conveyor && !diagonalMovement && (fall==0 || z>0) && charging==0 && spins<=5 + && action != gothit) + { + switch(dir) + { + case up: + case down: + x=(int(x)+4)&0xFFF8; + break; + + case left: + case right: + y=(int(y)+4)&0xFFF8; + break; + } + } + + // Pay magic cost for Byrna beams + if(Lwpns.idCount(wCByrna)) + { + weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wCByrna))); + int itemid = ew->parentitem; + + if(!checkmagiccost(itemid)) + { + for(int i=0; iid==wCByrna) + w->dead=1; + } + } + else paymagiccost(itemid); + } + + checkhit(); + + if(game->get_life()<=0) + { + // So scripts can have one frame to handle hp zero events + if(false == (last_hurrah = !last_hurrah)) + { + drunkclk=0; + return true; + } + } + else + last_hurrah=false; + + if(swordclk>0) + --swordclk; + + if(itemclk>0) + --itemclk; + + if(inwallm) + { + attackclk=0; + linkstep(); + + if(CarryLink()==false) + restart_level(); + + return false; + } + + if(hopclk) + action = hopping; + + // get user input or do other animation + freeze_guys=false; // reset this flag, set it again if holding + + if(action != landhold1 && action != landhold2 && action != waterhold1 && action != waterhold2 && fairyclk==0 && holdclk>0) + { + holdclk=0; + } + + switch(action) + { + case gothit: + if(attackclk) + if(!doattack()) + { + attackclk=spins=0; + tapping=false; + } + + break; + + case drowning: + linkstep(); // maybe this line should be elsewhere? + + if(--drownclk==0) + { + action=none; + x=entry_x; + y=entry_y; + warpx=x; + warpy=y; + hclk=48; + game->set_life(zc_max(game->get_life()-(HP_PER_HEART/4),0)); + } + + break; + + case swimhit: + case freeze: + case scrolling: + break; + + case casting: + if(magicitem==-1) + { + action=none; + } + + break; + + case landhold1: + case landhold2: + if(--holdclk <= 0) + { + //restart music + if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0 && (specialcave < GUYCAVE)) + playLevelMusic(); + + action=none; + } + else + freeze_guys=true; + + break; + + case waterhold1: + case waterhold2: + diveclk=0; + + if(--holdclk <= 0) + { + //restart music + if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0 && (specialcave < GUYCAVE)) + playLevelMusic(); + + action=swimming; + } + else + freeze_guys=true; + + break; + + case hopping: + if(DRIEDLAKE) + { + action = none; + hopclk = 0; + diveclk = 0; + break; + } + + do_hopping(); + break; + + case inwind: + { + int i=Lwpns.idFirst(wWind); + + if(i<0) + { + bool exit=false; + + if(whirlwind==255) + { + exit=true; + } + else if(y<=0 && dir==up) y=-1; + else if(y>=160 && dir==down) y=161; + else if(x<=0 && dir==left) x=-1; + else if(x>=240 && dir==right) x=241; + else exit=true; + + if(exit) + { + action=none; + xofs=0; + whirlwind=0; + lstep=0; + dontdraw=false; + entry_x=x; + entry_y=y; + } + } + /* + else if (((weapon*)Lwpns.spr(i))->dead==1) + { + whirlwind=255; + } + */ + else + { + x=Lwpns.spr(i)->x; + y=Lwpns.spr(i)->y; + dir=Lwpns.spr(i)->dir; + } + } + break; + + case swimming: + if(DRIEDLAKE) + { + action=none; + hopclk=0; + break; + } + + if(frame&1) + linkstep(); + + // fall through + + default: + movelink(); // call the main movement routine + } + + checkLadderRemoval(); + + if(ilswim) + landswim++; + else landswim=0; + + if(hopclk!=0xFF) ilswim=false; + + if(action!=inwind && action!=drowning) + { + checkspecial(); + checkitems(); + checklocked(); + checklockblock(); + checkbosslockblock(); + checkchest(cCHEST); + checkchest(cLOCKEDCHEST); + checkchest(cBOSSCHEST); + checkpushblock(); + checkswordtap(); + + if(hookshot_frozen==false) + { + checkspecial2(&lsave); + } + + if(action==won) + { + return true; + } + } + + // Somehow Link was displaced from the fairy flag... + if(fairyclk && action != freeze) + { + fairyclk = holdclk = refill_why = 0; + } + + if((!activated_timed_warp) && (tmpscr->timedwarptics>0)) + { + tmpscr->timedwarptics--; + + if(tmpscr->timedwarptics==0) + { + activated_timed_warp=true; + + if(tmpscr->flags4 & fTIMEDDIRECT) + { + didpit=true; + pitx=x; + pity=y; + } + + int index2 = 0; + + if(tmpscr->flags5 & fRANDOMTIMEDWARP) index2=rand()%4; + + sdir = dir; + dowarp(1,index2); + } + } + + bool awarp = false; + + for(int i=0; i<176; i++) + { + + int ind=0; + + if(!awarp) + { + if(combobuf[tmpscr->data[i]].type==cAWARPA) + { + awarp=true; + ind=0; + } + else if(combobuf[tmpscr->data[i]].type==cAWARPB) + { + awarp=true; + ind=1; + } + else if(combobuf[tmpscr->data[i]].type==cAWARPC) + { + awarp=true; + ind=2; + } + else if(combobuf[tmpscr->data[i]].type==cAWARPD) + { + awarp=true; + ind=3; + } + else if(combobuf[tmpscr->data[i]].type==cAWARPR) + { + awarp=true; + ind=rand()%4; + } + + if(awarp) + { + if(tmpscr->flags5&fDIRECTAWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir = dir; + dowarp(1,ind); + } + } + + } + + awarp=false; + + for(int i=0; i<32; i++) + { + int ind=0; + + if(!awarp) + { + byte ffcType=combobuf[tmpscr->ffcs[i].getCombo()].type; + if(ffcType>=cAWARPA && ffcType<=cAWARPD) + { + awarp=true; + ind=ffcType-cAWARPA; // 0..3 + } + else if(ffcType==cAWARPR) + { + awarp=true; + ind=rand()&3; + } + + if(awarp) + { + if(tmpscr->flags5&fDIRECTAWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir = dir; + dowarp(1,ind); + } + } + + } + + // walk through bombed doors and fake walls + bool walk=false; + int dtype=dBOMBED; + + if(pushing>=24) dtype=dWALK; + + if(isdungeon() && action!=freeze && loaded_guys && !inlikelike && !diveclk && action!=rafting) + { + if(((dtype==dBOMBED)?DrunkUp():dir==up) && (diagonalMovement?x>112&&x<128:x==120) && y<=32 && tmpscr->door[0]==dtype) + { + walk=true; + dir=up; + } + + if(((dtype==dBOMBED)?DrunkDown():dir==down) && (diagonalMovement?x>112&&x<128:x==120) && y>=128 && tmpscr->door[1]==dtype) + { + walk=true; + dir=down; + } + + if(((dtype==dBOMBED)?DrunkLeft():dir==left) && x<=32 && (diagonalMovement?y>72&&y<88:y==80) && tmpscr->door[2]==dtype) + { + walk=true; + dir=left; + } + + if(((dtype==dBOMBED)?DrunkRight():dir==right) && x>=208 && (diagonalMovement?y>72&&y<88:y==80) && tmpscr->door[3]==dtype) + { + walk=true; + dir=right; + } + } + + if(walk) + { + hclk=0; + drawguys=false; + + if(dtype==dWALK) + { + sfx(tmpscr->secretsfx); + } + + action=none; + stepforward(29, true); + action=scrolling; + pushing=false; + } + + if(rSbtn()) + { + int tmp_subscr_clk = frame; + + switch(lsave) + { + case 0: + conveyclk=3; + dosubscr(&QMisc); + newscr_clk += frame - tmp_subscr_clk; + break; + + case 1: + save_game((tmpscr->flags4&fSAVEROOM) != 0, 0); + break; + + case 2: + save_game((tmpscr->flags4&fSAVEROOM) != 0, 1); + break; + } + } + + checkstab(); + + check_conveyor(); + return false; +} + +// A routine used exclusively by startwpn, +// to switch Link's weapon if his current weapon (bombs) was depleted. +void LinkClass::deselectbombs(int super) +{ + if(getItemFamily(itemsbuf,Bwpn&0x0FFF)==(super? itype_sbomb : itype_bomb) && (directWpn<0 || Bwpn==directWpn)) + { + int temp = selectWpn_new(SEL_VERIFY_LEFT, game->bwpn, game->awpn); + Bwpn = Bweapon(temp); + directItemB = directItem; + game->bwpn = temp; + } + else + { + int temp = selectWpn_new(SEL_VERIFY_LEFT, game->awpn, game->bwpn); + Awpn = Bweapon(temp); + directItemA = directItem; + game->awpn = temp; + } +} + +int potion_life=0; +int potion_magic=0; + +bool LinkClass::startwpn(int itemid) +{ + if(itemid < 0) return false; + + if(((dir==up && y<24) || (dir==down && y>128) || + (dir==left && x<32) || (dir==right && x>208)) && !(get_bit(quest_rules,qr_ITEMSONEDGES) || inlikelike)) + return false; + + int wx=x; + int wy=y; + int wz=z; + bool ret = true; + + + switch(dir) + { + case up: + wy-=16; + break; + + case down: + wy+=16; + break; + + case left: + wx-=16; + break; + + case right: + wx+=16; + break; + } + + bool use_hookshot=true; + + switch(itemsbuf[itemid].family) + { + case itype_potion: + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + beginSpecialSequence(seq_potion, itemid); + ret=false; + + break; + + case itype_rocs: + { + if(!inlikelike && z==0 && charging==0 && !(tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM && !ladderx && !laddery) && hoverclk==0) + { + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + fall -= FEATHERJUMP*(itemsbuf[itemid].power+2); + + // Reset the ladder, unless on an unwalkable combo + if((ladderx || laddery) && !(_walkflag(ladderx,laddery,0))) + reset_ladder(); + + sfx(itemsbuf[itemid].usesound,pan(int(x))); + } + + ret = false; + } + break; + + case itype_letter: + { + if(current_item(itype_letter)==i_letter && + tmpscr[currscr<128?0:1].room==rP_SHOP && + tmpscr[currscr<128?0:1].guy && + ((currscr<128&&!(DMaps[currdmap].flags&dmfGUYCAVES))||(currscr>=128&&DMaps[currdmap].flags&dmfGUYCAVES)) + ) + { + int usedid = getItemID(itemsbuf, itype_letter,i_letter+1); + + if(usedid != -1) + getitem(usedid, true); + + sfx(tmpscr[currscr<128?0:1].secretsfx); + setupscreen(); + action=none; + } + + ret = false; + } + break; + + case itype_whistle: + { + bool whistleflag; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + beginSpecialSequence(seq_whistle, itemid); + } + ret=false; + break; + + case itype_bomb: + { + //Remote detonation + if(Lwpns.idCount(wLitBomb) >= zc_max(itemsbuf[itemid].misc2,1)) + { + weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitBomb))); + + while(Lwpns.idCount(wLitBomb) && ew->misc == 0) + { + ew->activateRemoteBomb(); + ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitBomb))); + } + + deselectbombs(false); + return false; + } + + //Remote bombs: + //Even if you have no bombs, the icon remains so that you can detonate laid bombs. + //But the remaining code requires at least one bomb. + if(!game->get_bombs() && !current_item_power(itype_bombbag)) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + + if(!get_debug() && !current_item_power(itype_bombbag)) + game->change_bombs(-1); + + if(itemsbuf[itemid].misc1>0) // If not remote bombs + deselectbombs(false); + + if(isdungeon()) + { + wy=zc_max(wy,16); + } + + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wLitBomb,itemsbuf[itemid].fam_type, + itemsbuf[itemid].power*DAMAGE_MULTIPLIER,dir,itemid,getUID())); + sfx(WAV_PLACE,pan(wx)); + } + break; + + case itype_sbomb: + { + //Remote detonation + if(Lwpns.idCount(wLitSBomb) >= zc_max(itemsbuf[itemid].misc2,1)) + { + weapon *ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitSBomb))); + + while(Lwpns.idCount(wLitSBomb) && ew->misc == 0) + { + ew->activateRemoteBomb(); + ew = (weapon*)(Lwpns.spr(Lwpns.idFirst(wLitSBomb))); + } + + deselectbombs(true); + return false; + } + + //Remote bombs: + //Even if you have no bombs, the icon remains so that you can detonate laid bombs. + //But the remaining code requires at least one bomb. + bool magicbag = (current_item_power(itype_bombbag) + && itemsbuf[current_item_id(itype_bombbag)].flags & ITEM_FLAG1); + + if(!game->get_sbombs() && !magicbag) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + + if(!get_debug() && !magicbag) + game->change_sbombs(-1); + + if(itemsbuf[itemid].misc1>0) // If not remote bombs + deselectbombs(true); + + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wLitSBomb,itemsbuf[itemid].fam_type,itemsbuf[itemid].power*DAMAGE_MULTIPLIER,dir, itemid,getUID())); + sfx(WAV_PLACE,pan(wx)); + } + break; + + case itype_wand: + { + if(Lwpns.idCount(wMagic)) + return false; + + int bookid = current_item_id(itype_book); + bool paybook = (bookid>-1 && checkmagiccost(bookid)); + + if(!(itemsbuf[itemid].flags&ITEM_FLAG1) && !paybook) //Can the wand shoot without the book? + return false; + + if(!checkmagiccost(itemid)) + return false; + + if(Lwpns.idCount(wBeam)) + Lwpns.del(Lwpns.idFirst(wBeam)); + + int type = bookid != -1 ? current_item(itype_book) : itemsbuf[itemid].fam_type; + int pow = (bookid != -1 ? current_item_power(itype_book) : itemsbuf[itemid].power)*DAMAGE_MULTIPLIER; + + for(int i=(spins==1?up:dir); i<=(spins==1 ? right:dir); i++) + if(dir!=(i^1)) + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wMagic,type,pow,i, itemid,getUID())); + + paymagiccost(itemid); + + if(paybook) + paymagiccost(current_item_id(itype_book)); + + if(bookid != -1) + sfx(itemsbuf[bookid].usesound,pan(wx)); + else + sfx(itemsbuf[itemid].usesound,pan(wx)); + } + break; + + case itype_sword: + { + if(!checkmagiccost(itemid)) + return false; + + if((Lwpns.idCount(wBeam) && spins==0)||Lwpns.idCount(wMagic)) + return false; + + paymagiccost(itemid); + float temppower; + + if(itemsbuf[itemid].flags & ITEM_FLAG2) + { + temppower=DAMAGE_MULTIPLIER*itemsbuf[itemid].power; + temppower=temppower*itemsbuf[itemid].misc2; + temppower=temppower/100; + } + else + { + temppower = DAMAGE_MULTIPLIER*itemsbuf[itemid].misc2; + } + + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wBeam,itemsbuf[itemid].fam_type,int(temppower),dir,itemid,getUID())); + sfx(WAV_BEAM,pan(wx)); + } + break; + + case itype_candle: + { + if(itemsbuf[itemid].flags&ITEM_FLAG1 && didstuff&did_candle) + { + return false; + } + + if(Lwpns.idCount(wFire)>=2) + { + return false; + } + + if(!checkmagiccost(itemid)) + { + return false; + } + + paymagiccost(itemid); + + if(itemsbuf[itemid].flags&ITEM_FLAG1) didstuff|=did_candle; + + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wFire, + (itemsbuf[itemid].fam_type > 1), //To do with combo flags + itemsbuf[itemid].power*DAMAGE_MULTIPLIER,dir,itemid,getUID())); + sfx(itemsbuf[itemid].usesound,pan(wx)); + attack=wFire; + } + break; + + case itype_arrow: + { + if(Lwpns.idCount(wArrow) > itemsbuf[itemid].misc2) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + + if(get_bit(quest_rules,qr_TRUEARROWS) && !current_item_power(itype_quiver)) + { + if(game->get_arrows()<=0) + return false; + + game->change_arrows(-1); + } + else if(!current_item_power(itype_quiver) && !current_item_power(itype_wallet)) + { + if(game->get_drupy()+game->get_rupies()<=0) + return false; + + game->change_drupy(-1); + } + + weapon* wpn=new weapon((fix)wx,(fix)wy,(fix)wz,wArrow,itemsbuf[itemid].fam_type,DAMAGE_MULTIPLIER*itemsbuf[itemid].power,dir,itemid,getUID()); + if(itemsbuf[itemid].wpn2!=0 || itemsbuf[itemid].wpn3!=0) + wpn->setSparkleFunc(standardSparkle); + Lwpns.add(wpn); + ((weapon*)Lwpns.spr(Lwpns.Count()-1))->step*=(current_item_power(itype_bow)+1)/2; + sfx(itemsbuf[itemid].usesound,pan(wx)); + } + break; + + case itype_bait: + if(Lwpns.idCount(wBait)) //TODO: More than one Bait per screen? + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + sfx(itemsbuf[itemid].usesound,pan(wx)); + + if(tmpscr->room==rGRUMBLE && !getmapflag()) + { + items.add(new item((fix)wx,(fix)wy,(fix)0,iBait,ipDUMMY+ipFADE,0)); + fadeclk=66; + messageMgr.clear(true); + // putscr(scrollbuf,0,0,tmpscr); + setmapflag(); + removeItemsOfFamily(game,itemsbuf,itype_bait); + verifyBothWeapons(); + sfx(tmpscr->secretsfx); + return false; + } + + Lwpns.add(new weapon((fix)wx,(fix)wy,(fix)wz,wBait,0,0,dir,itemid,getUID())); + break; + + case itype_brang: + { + if(Lwpns.idCount(wBrang) > itemsbuf[itemid].misc2) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + current_item_power(itype_brang); + weapon* wpn=new weapon((fix)wx,(fix)wy,(fix)wz,wBrang, + itemsbuf[itemid].fam_type,(itemsbuf[itemid].power*DAMAGE_MULTIPLIER), + dir,itemid,getUID()); + if(itemsbuf[itemid].wpn2!=0 || itemsbuf[itemid].wpn3!=0) + wpn->setSparkleFunc(standardSparkle); + Lwpns.add(wpn); + } + break; + + case itype_hookshot: + if(!HookshotAction::canUse(*this)) + break; + + if(inlikelike || Lwpns.idCount(wHookshot)) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + currentItemAction=new HookshotAction(itemid, *this); + break; + + case itype_dinsfire: + if(z!=0 || (tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM)) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + action=casting; + currentItemAction=new DinsFireAction(itemid, *this); + break; + + case itype_faroreswind: + if(z!=0 || (tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM)) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + action=casting; + currentItemAction=new FaroresWindAction(itemid, *this); + break; + + case itype_nayruslove: + if(z!=0 || (tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM)) + return false; + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + action=casting; + currentItemAction=new NayrusLoveAction(itemid, *this); + break; + + case itype_cbyrna: + { + //Beams already deployed + if(Lwpns.idCount(wCByrna)) + { + stopCaneOfByrna(); + return false; + } + + if(!checkmagiccost(itemid)) + return false; + + paymagiccost(itemid); + + for(int i=0; isetSparkleFunc(byrnaSparkle); + Lwpns.add(wpn); + } + } + break; + + default: + ret = false; + } + + if(itemsbuf[itemid].flags & ITEM_DOWNGRADE) + { + game->set_item(itemid,false); + + // Maybe Item Override has allowed the same item in both slots? + if(Bwpn == itemid) + { + Bwpn = 0; + verifyBWpn(); + } + + if(Awpn == itemid) + { + Awpn = 0; + verifyAWpn(); + } + } + + return ret; +} + +bool LinkClass::doattack() +{ + //int s = BSZ ? 0 : 11; + int s = (zinit.linkanimationstyle==las_bszelda) ? 0 : 11; + + // Abort attack if attackclk has run out and: + // * the attack is not Hammer, Sword with Spin Scroll, Candle, or Wand, OR + // * you aren't holding down the A button, you're not charging, and/or you're still spinning + + if(attackclk>=(spins>0?8:14) && attack!=wHammer && + (((attack!=wSword || !current_item(itype_spinscroll) || inlikelike) && attack!=wWand && attack!=wFire && attack!=wCByrna) || !((attack==wSword && isWpnPressed(itype_sword) && spins==0) || charging>0))) + { + tapping=false; + return false; + } + + if(attackclk>29) + { + tapping=false; + return false; + } + + int candleid = (directWpn>-1 && itemsbuf[directWpn].family==itype_candle) ? directWpn : current_item_id(itype_candle); + int byrnaid = (directWpn>-1 && itemsbuf[directWpn].family==itype_cbyrna) ? directWpn : current_item_id(itype_cbyrna); + + // An attack can be "walked out-of" after 8 frames, unless it's: + // * a sword stab + // * a hammer pound + // * a wand thrust + // * a candle thrust + // * a cane thrust + // In which case it should continue. + if((attack==wCatching && attackclk>4)||(attack!=wWand && attack!=wSword && attack!=wHammer + && (attack!=wFire || (candleid!=-1 && !(itemsbuf[candleid].wpn))) + && (attack!=wCByrna || (byrnaid!=-1 && !(itemsbuf[byrnaid].wpn))) && attackclk>7)) + { + if(DrunkUp()||DrunkDown()||DrunkLeft()||DrunkRight()) + { + lstep = s; + return false; + } + } + + if(charging==0) + { + lstep=0; + } + + // Work out the sword charge-up delay + int magiccharge = 192, normalcharge = 64; + int itemid = current_item_id(itype_chargering); + + if(itemid>=0) + { + normalcharge = itemsbuf[itemid].misc1; + magiccharge = itemsbuf[itemid].misc2; + } + + // Now work out the magic cost + itemid = current_item_id(attack==wHammer ? itype_quakescroll : itype_spinscroll); + + // charging up weapon... + // + if(((attack==wSword && attackclk==SWORDCHARGEFRAME && itemid>=0 && isWpnPressed(itype_sword)) || +#if 0 + (attack==wWand && attackclk==WANDCHARGEFRAME && itemid>=0 isWpnPressed(itype_wand)) || +#endif + (attack==wHammer && attackclk==HAMMERCHARGEFRAME && itemid>=0 && isWpnPressed(itype_hammer))) && z==0 && checkmagiccost(itemid)) + { + // Increase charging while holding down button. + if(spins==0 && charging-1 && charging==magiccharge && checkmagiccost(itemid)) + { + paymagiccost(itemid); + charging++; // charging>magiccharge signifies a successful supercharge. + sfx(WAV_ZN1CHARGE2,pan(int(x))); + } + } + } + else if(attack==wCByrna && byrnaid!=-1) + { + if(!(itemsbuf[byrnaid].wpn)) + { + attack = wNone; + return startwpn(attackid); // Beam if the Byrna stab animation WASN'T used. + } + + bool beamcount = false; + + for(int i=0; iid==wCByrna) + { + beamcount = true; + break; + } + } + + // If beams already deployed, remove them + if(!attackclk && beamcount) + { + return startwpn(attackid); // Remove beams instantly + } + + // Otherwise, continue + ++attackclk; + } + else + { + ++attackclk; + + if(attackclk==SWORDCHARGEFRAME && charging>0 && !tapping) //Signifies a tapped enemy + { + ++attackclk; // Won't continue charging + charging=0; + } + + // Faster if spinning. + if(spins>0) + ++attackclk; + + // Even faster if hurricane spinning. + if(spins>5) + attackclk+=2; + + // If at a charging threshold, do a charged attack. + if(charging>=normalcharge && (attack!=wSword || attackclk>=SWORDCHARGEFRAME) && !tapping) + { + if(attack==wSword) + { + spins=(charging>magiccharge ? (itemsbuf[current_item_id(itype_spinscroll2)].misc1*4)-3 + : (itemsbuf[current_item_id(itype_spinscroll)].misc1*4)+1); + attackclk=1; + sfx(itemsbuf[current_item_id(spins>5 ? itype_spinscroll2 : itype_spinscroll)].usesound,pan(int(x))); + } + /* + else if(attack==wWand) + { + //Not reachable.. yet + spins=1; + } + */ + else if(attack==wHammer && sideviewhammerpound()) + { + spins=1; //signifies the quake hammer + bool super = (charging>magiccharge && current_item(itype_quakescroll2)); + sfx(itemsbuf[current_item_id(super ? itype_quakescroll2 : itype_quakescroll)].usesound,pan(int(x))); + quakeclk=(itemsbuf[current_item_id(super ? itype_quakescroll2 : itype_quakescroll)].misc1); + + // general area stun + for(int i=0; i=SWORDCHARGEFRAME) + tapping = false; + } + + if(attackclk==1 && attack==wFire && candleid!=-1 && !(itemsbuf[candleid].wpn)) + { + return startwpn(attackid); // Flame if the Candle stab animation WASN'T used. + } + + int crossid = current_item_id(itype_crossscroll); //has Cross Beams scroll + + if(attackclk==13 || (attackclk==7 && spins>1 && crossid >=0 && checkmagiccost(crossid))) + { + + int wpnid = (directWpn>-1 && itemsbuf[directWpn].family==itype_sword) ? directWpn : current_item_id(itype_sword); + long long templife = wpnid>=0? itemsbuf[wpnid].misc1 : 0; + + if(wpnid>=0 && itemsbuf[wpnid].flags & ITEM_FLAG1) + { + templife=templife*game->get_maxlife(); + templife=templife/100; + } + else + { + templife*=HP_PER_HEART; + } + + bool normalbeam = (game->get_life()+(get_bit(quest_rules,qr_QUARTERHEART)?((HP_PER_HEART/4)-1):((HP_PER_HEART/2)-1))>=templife); + int perilid = current_item_id(itype_perilscroll); + bool perilbeam = (perilid>=0 && wpnid>=0 && game->get_life()<=itemsbuf[perilid].misc1*HP_PER_HEART + && checkmagiccost(perilid) + // Must actually be able to shoot sword beams + && ((itemsbuf[wpnid].flags & ITEM_FLAG1) + || itemsbuf[wpnid].misc1 <= game->get_maxlife()/HP_PER_HEART)); + + if(attack==wSword && !tapping && (perilbeam || normalbeam)) + { + if(attackclk==7) + paymagiccost(crossid); // Pay the Cross Beams magic cost. + + if(perilbeam && !normalbeam) + paymagiccost(perilid); // Pay the Peril Beam magic cost. + + // TODO: Something that would be cheap but disgraceful to hack in at this point is + // a way to make the peril/cross beam item's power stat influence the strength + // of the peril/cross beam... + startwpn(attackid); + } + + if(attack==wWand) + startwpn(attackid); // Flame if the Wand stab animation WAS used (it always is). + + if(attack==wFire && candleid!=-1 && itemsbuf[candleid].wpn) // Flame if the Candle stab animation WAS used. + startwpn(attackid); + + if(attack==wCByrna && byrnaid!=-1 && itemsbuf[byrnaid].wpn) // Beam if the Byrna stab animation WAS used. + startwpn(attackid); + } + + if(attackclk==14) + lstep = s; + + return true; +} + +bool LinkClass::can_attack() +{ + if(action==hopping || action==swimming || action==freeze || + (action==attacking && (attack!=wSword || attack!=wWand || !get_bit(quest_rules,qr_QUICKSWORD)) && charging!=0) || spins>0) + { + return false; + } + + int r = (isdungeon()) ? 16 : 0; + int r2 = get_bit(quest_rules, qr_NOBORDER) ? 0 : 8; + + if(!get_bit(quest_rules, qr_ITEMSONEDGES)) switch(dir) + { + case up: + case down: + return !(y<(r2+r) || y>(160-r-r2)); + + case left: + case right: + return !(x<(r2+r) || x>(240-r-r2)); + } + + return true; +} + +bool isRaftFlag(int flag) +{ + return (flag==mfRAFT || flag==mfRAFT_BRANCH || flag==mfRAFT_BOUNCE); +} + +void do_lens() +{ + int itemid = lensid >= 0 ? lensid : directWpn>-1 ? directWpn : current_item_id(itype_lens); + + if(itemid<0) + return; + + if(isWpnPressed(itype_lens) && !LinkItemClk() && !lensclk && checkmagiccost(itemid)) + { + if(lensid<0) + { + lensid=itemid; + + if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(itemsbuf[itemid].usesound); + } + + paymagiccost(itemid); + + if(dowpn>=0 && itemsbuf[dowpn].script != 0 && !did_scriptl) + { + ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn & 0xFFF); + did_scriptl=true; + } + + lensclk = 12; + } + else + { + did_scriptl=false; + + if(lensid>-1 && !(isWpnPressed(itype_lens) && !LinkItemClk() && checkmagiccost(itemid))) + { + lensid=-1; + lensclk = 0; + + if(get_bit(quest_rules,qr_MORESOUNDS)) sfx(WAV_ZN1LENSOFF); + } + } +} + +void LinkClass::do_hopping() +{ + do_lens(); + + if((hopclk==0xFF)) // swimming + { + if(diveclk>0) + --diveclk; + else if(DrunkrAbtn()) + { + bool global_diving=(get_bit(quest_rules,qr_NODIVING) != 0); + bool screen_diving=(tmpscr->flags5&fTOGGLEDIVING) != 0; + + if(global_diving==screen_diving) + diveclk=80; + } + + if((!(int(x)&7) && !(int(y)&7)) || diagonalMovement) + { + action = swimming; + hopclk = 0; + charging = attackclk = 0; + tapping = false; + } + else + { + linkstep(); + + if(diveclk<=30 || (frame&1)) + { + switch(dir) + { + case up: + y -= 1; + break; + + case down: + y += 1; + break; + + case left: + x -= 1; + break; + + case right: + x += 1; + break; + } + } + } + } + else // hopping in or out (need to separate the cases...) + { + if(diagonalMovement) + { + if(hopclk==1) //hopping out + { + if(hopdir!=-1) dir=hopdir; + + landswim=0; + + if(dir==up) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(iswater(MAPCOMBO(x,y+(bigHitbox?0:8)-1)) && !iswater(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1)) && !iswater(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1))) + sidestep=1; + else if(!iswater(MAPCOMBO(x,y+(bigHitbox?0:8)-1)) && !iswater(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1)) && iswater(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1))) + sidestep=2; + + if(sidestep==1) x++; + else if(sidestep==2) x--; + else y--; + + if(!iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&!iswater(MAPCOMBO(int(x),int(y)+15))) + { + hopclk=0; + diveclk=0; + action=none; + hopdir=-1; + } + } + + if(dir==down) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(iswater(MAPCOMBO(x,y+16)) && !iswater(MAPCOMBO(x+8,y+16)) && !iswater(MAPCOMBO(x+15,y+16))) + sidestep=1; + else if(!iswater(MAPCOMBO(x,y+16)) && !iswater(MAPCOMBO(x+7,y+16)) && iswater(MAPCOMBO(x+15,y+16))) + sidestep=2; + + if(sidestep==1) x++; + else if(sidestep==2) x--; + else y++; + + if(!iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&!iswater(MAPCOMBO(int(x),int(y)+15))) + { + hopclk=0; + diveclk=0; + action=none; + hopdir=-1; + } + } + + if(dir==left) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(iswater(MAPCOMBO(x-1,y+(bigHitbox?0:8))) && !iswater(MAPCOMBO(x-1,y+(bigHitbox?8:12))) && !iswater(MAPCOMBO(x-1,y+15))) + sidestep=1; + else if(!iswater(MAPCOMBO(x-1,y+(bigHitbox?0:8))) && !iswater(MAPCOMBO(x-1,y+(bigHitbox?7:11))) && iswater(MAPCOMBO(x-1,y+15))) + sidestep=2; + + if(sidestep==1) y++; + else if(sidestep==2) y--; + else x--; + + if(!iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&!iswater(MAPCOMBO(int(x)+15,int(y)+8))) + { + hopclk=0; + diveclk=0; + action=none; + hopdir=-1; + } + } + + if(dir==right) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(iswater(MAPCOMBO(x+16,y+(bigHitbox?0:8))) && !iswater(MAPCOMBO(x+16,y+(bigHitbox?8:12))) && !iswater(MAPCOMBO(x+16,y+15))) + sidestep=1; + else if(!iswater(MAPCOMBO(x+16,y+(bigHitbox?0:8))) && !iswater(MAPCOMBO(x+16,y+(bigHitbox?7:11))) && iswater(MAPCOMBO(x+16,y+15))) + sidestep=2; + + if(sidestep==1) y++; + else if(sidestep==2) y--; + else x++; + + if(!iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&!iswater(MAPCOMBO(int(x)+15,int(y)+8))) + { + hopclk=0; + diveclk=0; + action=none; + hopdir=-1; + } + } + } + + if(hopclk==2) //hopping in + { + landswim=0; + + if(dir==up) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(!iswater(MAPCOMBO(x,y+(bigHitbox?0:8)-1)) && iswater(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1)) && iswater(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1))) + sidestep=1; + else if(iswater(MAPCOMBO(x,y+(bigHitbox?0:8)-1)) && iswater(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1)) && !iswater(MAPCOMBO(x+15,y+(bigHitbox?0:8)-1))) + sidestep=2; + + if(sidestep==1) x++; + else if(sidestep==2) x--; + else y--; + + if(iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&iswater(MAPCOMBO(int(x),int(y)+15))) + { + hopclk=0xFF; + diveclk=0; + action=swimming; + } + } + + if(dir==down) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(!iswater(MAPCOMBO(x,y+16)) && iswater(MAPCOMBO(x+8,y+16)) && iswater(MAPCOMBO(x+15,y+16))) + sidestep=1; + else if(iswater(MAPCOMBO(x,y+16)) && iswater(MAPCOMBO(x+7,y+16)) && !iswater(MAPCOMBO(x+15,y+16))) + sidestep=2; + + if(sidestep==1) x++; + else if(sidestep==2) x--; + else y++; + + if(iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&iswater(MAPCOMBO(int(x),int(y)+15))) + { + hopclk=0xFF; + diveclk=0; + reset_swordcharge(); + action=swimming; + } + } + + if(dir==left) + { + linkstep(); + linkstep(); + int sidestep=0; + + if(!iswater(MAPCOMBO(x-1,y+(bigHitbox?0:8))) && iswater(MAPCOMBO(x-1,y+(bigHitbox?8:12))) && iswater(MAPCOMBO(x-1,y+15))) + sidestep=1; + else if(iswater(MAPCOMBO(x-1,y+(bigHitbox?0:8))) && iswater(MAPCOMBO(x-1,y+(bigHitbox?7:11))) && !iswater(MAPCOMBO(x-1,y+15))) + sidestep=2; + + if(sidestep==1) y++; + else if(sidestep==2) y--; + else x--; + + if(iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&iswater(MAPCOMBO(int(x)+15,int(y)+8))) + { + hopclk=0xFF; + diveclk=0; + action=swimming; + } + } + + if(dir==right) + { + linkstep(); + linkstep(); + + int sidestep=0; + + if(!iswater(MAPCOMBO(x+16,y+(bigHitbox?0:8))) && iswater(MAPCOMBO(x+16,y+(bigHitbox?8:12))) && iswater(MAPCOMBO(x+16,y+15))) + sidestep=1; + else if(iswater(MAPCOMBO(x+16,y+(bigHitbox?0:8))) && iswater(MAPCOMBO(x+16,y+(bigHitbox?7:11))) && !iswater(MAPCOMBO(x+16,y+15))) + sidestep=2; + + if(sidestep==1) y++; + else if(sidestep==2) y--; + else x++; + + if(iswater(MAPCOMBO(int(x),int(y)+(bigHitbox?0:8)))&&iswater(MAPCOMBO(int(x)+15,int(y)+8))) + { + hopclk=0xFF; + diveclk=0; + action=swimming; + } + } + } + + } + else + { + if(dir(16*link_animation_speed)) + link_count=0; + + int xofs2 = int(x)&15; + int yofs2 = int(y)&15; + int s = 1 + (frame&1); + + switch(dir) + { + case up: + if(yofs2<3 || yofs2>13) --y; + else y-=s; + + break; + + case down: + if(yofs2<3 || yofs2>13) ++y; + else y+=s; + + break; + + case left: + if(xofs2<3 || xofs2>13) --x; + else x-=s; + + break; + + case right: + if(xofs2<3 || xofs2>13) ++x; + else x+=s; + + break; + } + } + } + } +} + +void LinkClass::do_rafting() +{ + + if(toogam) + { + action=none; + return; + } + + do_lens(); + + linkstep(); + + if(!(int(x)&15) && !(int(y)&15)) + { + // this sections handles switching to raft branches + if((MAPFLAG(x,y)==mfRAFT_BRANCH||MAPCOMBOFLAG(x,y)==mfRAFT_BRANCH)) + { + if(dir!=down && DrunkUp() && (isRaftFlag(nextflag(x,y,up,false))||isRaftFlag(nextflag(x,y,up,true)))) + { + dir = up; + goto skip; + } + + if(dir!=up && DrunkDown() && (isRaftFlag(nextflag(x,y,down,false))||isRaftFlag(nextflag(x,y,down,true)))) + { + dir = down; + goto skip; + } + + if(dir!=right && DrunkLeft() && (isRaftFlag(nextflag(x,y,left,false))||isRaftFlag(nextflag(x,y,left,true)))) + { + dir = left; + goto skip; + } + + if(dir!=left && DrunkRight() && (isRaftFlag(nextflag(x,y,right,false))||isRaftFlag(nextflag(x,y,right,true)))) + { + dir = right; + goto skip; + } + } + else if((MAPFLAG(x,y)==mfRAFT_BOUNCE||MAPCOMBOFLAG(x,y)==mfRAFT_BOUNCE)) + { + if(dir == left) dir = right; + else if(dir == right) dir = left; + else if(dir == up) dir = down; + else if(dir == down) dir = up; + } + + + if(!isRaftFlag(nextflag(x,y,dir,false))&&!isRaftFlag(nextflag(x,y,dir,true))) + { + if(dir0 && y<160) + action=none; + } + else //going left or right + { + if((isRaftFlag(nextflag(x,y,down,false))||isRaftFlag(nextflag(x,y,down,true)))) + dir=down; + else if((isRaftFlag(nextflag(x,y,up,false))||isRaftFlag(nextflag(x,y,up,true)))) + dir=up; + else if(x>0 && x<240) + action=none; + } + } + } + +skip: + + switch(dir) + { + case up: + if(int(x)&15) + { + if(int(x)&8) + x++; + else x--; + } + else --y; + + break; + + case down: + if(int(x)&15) + { + if(int(x)&8) + x++; + else x--; + } + else ++y; + + break; + + case left: + if(int(y)&15) + { + if(int(y)&8) + y++; + else y--; + } + else --x; + + break; + + case right: + if(int(y)&15) + { + if(int(y)&8) + y++; + else y--; + } + else ++x; + + break; + } +} + +void LinkClass::movelink() +{ + int xoff=int(x)&7; + int yoff=int(y)&7; + int push=pushing; + int oldladderx=-1000, oldladdery=-1000; // moved here because linux complains "init crosses goto ~Koopa + pushing=0; + + if(diveclk>0) + { + --diveclk; + } + else if(action==swimming) + { + bool global_diving=(get_bit(quest_rules,qr_NODIVING) != 0); + bool screen_diving=(tmpscr->flags5&fTOGGLEDIVING) != 0; + + if(DrunkrAbtn()&&(global_diving==screen_diving)) + { + diveclk=80; + } + } + + if(action==rafting) + { + do_rafting(); + + if(action==rafting) + { + return; + } + + setEntryPoints(x,y); + } + + int olddirectwpn = directWpn; // To be reinstated if startwpn() fails + int btnwpn = -1; + + //&0xFFF removes the "bow & arrows" bitmask + //The Quick Sword is allowed to interrupt attacks. + if((!attackclk && action!=attacking) || ((attack==wSword || attack==wWand) && get_bit(quest_rules,qr_QUICKSWORD))) + { + if(DrunkrBbtn()) + { + btnwpn=getItemFamily(itemsbuf,Bwpn&0xFFF); + dowpn = Bwpn&0xFFF; + directWpn = directItemB; + } + else if(DrunkrAbtn()) + { + btnwpn=getItemFamily(itemsbuf,Awpn&0xFFF); + dowpn = Awpn&0xFFF; + directWpn = directItemA; + } + + if(directWpn > 255) directWpn = 0; + + // The Quick Sword only allows repeated sword or wand swings. + if(action==attacking && ((attack==wSword && btnwpn!=itype_sword) || (attack==wWand && btnwpn!=itype_wand))) + btnwpn=-1; + } + + if(can_attack() && (directWpn>-1 ? itemsbuf[directWpn].family==itype_sword : current_item(itype_sword)) && swordclk==0 && btnwpn==itype_sword && charging==0) + { + action=attacking; + attack=wSword; + attackid=directWpn>-1 ? directWpn : current_item_id(itype_sword); + attackclk=0; + sfx(itemsbuf[directWpn>-1 ? directWpn : current_item_id(itype_sword)].usesound, pan(int(x))); + + if(dowpn>-1 && itemsbuf[dowpn].script!=0 && !did_scripta && checkmagiccost(dowpn)) + { + ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn & 0xFFF); + did_scripta=true; + } + } + else + { + did_scripta=false; + } + + int wx=x; + int wy=y; + + switch(dir) + { + case up: + wy-=16; + break; + + case down: + wy+=16; + break; + + case left: + wx-=16; + break; + + case right: + wx+=16; + break; + } + + do_lens(); + + WalkflagInfo info; + + if(can_attack() && itemclk==0 && btnwpn>itype_sword && charging==0 && btnwpn!=itype_rupee) // This depends on item 0 being a rupee... + { + bool paidmagic = false; + + if(btnwpn==itype_wand && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_wand : false) : current_item(itype_wand))) + { + action=attacking; + attack=wWand; + attackid=directWpn>-1 ? directWpn : current_item_id(itype_wand); + attackclk=0; + } + else if((btnwpn==itype_hammer)&&!(action==attacking && attack==wHammer) + && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_hammer : false) : current_item(itype_hammer)) && checkmagiccost(dowpn)) + { + paymagiccost(dowpn); + paidmagic = true; + action=attacking; + attack=wHammer; + attackid=directWpn>-1 ? directWpn : current_item_id(itype_hammer); + attackclk=0; + } + else if((btnwpn==itype_candle)&&!(action==attacking && attack==wFire) + && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_candle : false) : current_item(itype_candle))) + { + action=attacking; + attack=wFire; + attackid=directWpn>-1 ? directWpn : current_item_id(itype_candle); + attackclk=0; + } + else if((btnwpn==itype_cbyrna)&&!(action==attacking && attack==wCByrna) + && (directWpn>-1 ? (!item_disabled(directWpn) ? itemsbuf[directWpn].family==itype_cbyrna : false) : current_item(itype_cbyrna))) + { + action=attacking; + attack=wCByrna; + attackid=directWpn>-1 ? directWpn : current_item_id(itype_cbyrna); + attackclk=0; + } + else + { + paidmagic = startwpn(directWpn>-1 ? directWpn : current_item_id(btnwpn)); + + if(paidmagic) + { + if(action==casting || action==drowning) + { + ; + } + else + { + action=attacking; + attackclk=0; + attack=none; + + if(btnwpn==itype_brang) + { + attack=wBrang; + } + } + } + else + { + // Weapon not started: directWpn should be reset to prev. value. + directWpn = olddirectwpn; + } + } + + if(dowpn>-1 && itemsbuf[dowpn].script!=0 && !did_scriptb && (paidmagic || checkmagiccost(dowpn))) + { + // Only charge for magic if item's magic cost wasn't already charged + // for the item's main use. + if(!paidmagic && attack!=wWand) + paymagiccost(dowpn); + + ZScriptVersion::RunScript(SCRIPT_ITEM, itemsbuf[dowpn].script, dowpn & 0xFFF); + did_scriptb=true; + } + + if(action==casting || action==drowning) + { + return; + } + } + else + { + did_scriptb=false; + } + + if(attackclk || action==attacking) + { + bool attacked = doattack(); + + // This section below interferes with script-setting Link->Dir, so it comes after doattack + if(!inlikelike && attackclk>4 && (attackclk&3)==0 && charging==0 && spins==0) + { + if((xoff==0)||diagonalMovement) + { + if(DrunkUp()) dir=up; + + if(DrunkDown()) dir=down; + } + + if((yoff==0)||diagonalMovement) + { + if(DrunkLeft()) dir=left; + + if(DrunkRight()) dir=right; + } + } + + if(attacked && (charging==0 && spins<=5) && jumping<1) + { + return; + } + else if(!(attacked)) + { + // Spin attack - change direction + if(spins>1) + { + spins--; + + if(spins%5==0) + sfx(itemsbuf[current_item_id(spins >5 ? itype_spinscroll2 : itype_spinscroll)].usesound,pan(int(x))); + + attackclk=1; + + switch(dir) + { + case up: + dir=left; + break; + + case right: + dir=up; + break; + + case down: + dir=right; + break; + + case left: + dir=down; + break; + } + + return; + } + else + { + spins=0; + } + + action=none; + attackclk=0; + charging=0; + } + } + + if(action==walking) //still walking + { + if(!DrunkUp() && !DrunkDown() && !DrunkLeft() && !DrunkRight() && !autostep) + { + action=(attackclk>0 ? attacking : none); + link_count=-1; + return; + } + + autostep=false; + + if(!diagonalMovement) + { + if(dir==up&&yoff) + { + info = walkflag(x,y+(bigHitbox?0:8)-int(lsteps[int(y)&7]),2,up); + if(blockmoving) + info = info || walkflagMBlock(x+8,y+(bigHitbox?0:8)-int(lsteps[int(y)&7])); + execute(info); + + if(!info.isUnwalkable()) + { + move(up); + } + else + { + action=none; + } + + return; + } + + if(dir==down&&yoff) + { + info = walkflag(x,y+15+int(lsteps[int(y)&7]),2,down); + if(blockmoving) + info = info || walkflagMBlock(x+8,y+15+int(lsteps[int(y)&7])); + execute(info); + + if(!info.isUnwalkable()) + { + move(down); + } + else + { + action=none; + } + + return; + } + + if(dir==left&&xoff) + { + info = walkflag(x-int(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,left) || walkflag(x-int(lsteps[int(x)&7]),y+8,1,left); + execute(info); + + if(!info.isUnwalkable()) + { + move(left); + } + else + { + action=none; + } + + return; + } + + if(dir==right&&xoff) + { + info = walkflag(x+15+int(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,right) || walkflag(x+15+int(lsteps[int(x)&7]),y+8,1,right); + execute(info); + + if(!info.isUnwalkable()) + { + move(right); + } + else + { + action=none; + } + + return; + } + } + } // endif (action==walking) + + if((action!=swimming)&&(action!=casting)&&(action!=drowning) && charging==0 && spins==0 && jumping<1) + { + action=none; + } + + if(diagonalMovement) + { + switch(holddir) + { + case up: + if(!Up()) + { + holddir=-1; + } + + break; + + case down: + if(!Down()) + { + holddir=-1; + } + + break; + + case left: + if(!Left()) + { + holddir=-1; + } + + break; + + case right: + if(!Right()) + { + holddir=-1; + } + + break; + + default: + break; + } //end switch + + if(DrunkUp()&&(holddir==-1||holddir==up)) + { + if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + } + else + { + if(charging==0 && spins==0) + { + dir=up; + } + + holddir=up; + + if(DrunkRight()&&shiftdir!=left) + { + shiftdir=right; + } + else if(DrunkLeft()&&shiftdir!=right) + { + shiftdir=left; + } + else + { + shiftdir=-1; + } + + //walkable if Ladder can be placed or is already placed vertically + if(tmpscr->flags7&fSIDEVIEW && !toogam && !(can_deploy_ladder() || (ladderx && laddery && ladderdir==up))) + { + walkable=false; + } + else + { + info = walkflag(x,y+(bigHitbox?0:8)-z3step,2,up); + + if(int(x) & 7) + info = info || walkflag(x+16,y+(bigHitbox?0:8)-z3step,1,up); + else if(blockmoving) + info = info || walkflagMBlock(x+16, y+(bigHitbox?0:8)-z3step); + + execute(info); + + if(info.isUnwalkable()) + { + if(z3step==2) + { + z3step=1; + info = walkflag(x,y+(bigHitbox?0:8)-z3step,2,up); + + if(int(x)&7) + info = info || walkflag(x+16,y+(bigHitbox?0:8)-z3step,1,up); + else if(blockmoving) + info = info || walkflagMBlock(x+16, y+(bigHitbox?0:8)-z3step); + + execute(info); + + if(info.isUnwalkable()) + { + walkable = false; + } + else + { + walkable=true; + } + } + else + { + walkable=false; + } + } + else + { + walkable = true; + } + } + + int s=shiftdir; + + if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM)) + { + shiftdir=-1; + } + else + { + if(s==left) + { + info = (walkflag(x-1,y+(bigHitbox?0:8),1,left)||walkflag(x-1,y+15,1,left)); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x-1,y+(bigHitbox?0:8)-1,1,left); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + else if(s==right) + { + info = walkflag(x+16,y+(bigHitbox?0:8),1,right)||walkflag(x+16,y+15,1,right); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x+16,y+(bigHitbox?0:8)-1,1,right); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + } + + move(up); + shiftdir=s; + + if(!walkable) + { + if(shiftdir==-1) + { + if(!_walkflag(x, y+(bigHitbox?0:8)-1,1) && + !_walkflag(x+8, y+(bigHitbox?0:8)-1,1) && + _walkflag(x+15,y+(bigHitbox?0:8)-1,1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+(bigHitbox?0:8)-1)) + sprite::move((fix)-1,(fix)0); + } + else + { + if(_walkflag(x, y+(bigHitbox?0:8)-1,1) && + !_walkflag(x+7, y+(bigHitbox?0:8)-1,1) && + !_walkflag(x+15,y+(bigHitbox?0:8)-1,1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+(bigHitbox?0:8)-1)) + sprite::move((fix)1,(fix)0); + } + else + { + pushing=push+1; + } + } + + z3step=2; + } + else + { + pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work. + z3step=2; + } + } + + return; + } + } + + if(DrunkDown()&&(holddir==-1||holddir==down)) + { + if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + } + else + { + if(charging==0 && spins==0) + { + dir=down; + } + + holddir=down; + + if(DrunkRight()&&shiftdir!=left) + { + shiftdir=right; + } + else if(DrunkLeft()&&shiftdir!=right) + { + shiftdir=left; + } + else + { + shiftdir=-1; + } + + //bool walkable; + if(tmpscr->flags7&fSIDEVIEW && !toogam) + { + walkable=false; + } + else + { + info = walkflag(x,y+15+z3step,2,down); + + if(int(x)&7) + info = info || walkflag(x+16,y+15+z3step,1,down); + else if(blockmoving) + info = info || walkflagMBlock(x+16, y+15+z3step); + + execute(info); + + if(info.isUnwalkable()) + { + if(z3step==2) + { + z3step=1; + info = walkflag(x,y+15+z3step,2,down); + + if(int(x)&7) + info = info || walkflag(x+16,y+15+z3step,1,down); + else if(blockmoving) + info = info || walkflagMBlock(x+16, y+15+z3step); + + execute(info); + + if(info.isUnwalkable()) + { + walkable = false; + } + else + { + walkable=true; + } + } + else + { + walkable=false; + } + } + else + { + walkable = true; + } + } + + int s=shiftdir; + + if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM)) + { + shiftdir=-1; + } + else + { + if(s==left) + { + info = walkflag(x-1,y+(bigHitbox?0:8),1,left)||walkflag(x-1,y+15,1,left); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x-1,y+16,1,left); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + else if(s==right) + { + info = walkflag(x+16,y+(bigHitbox?0:8),1,right)||walkflag(x+16,y+15,1,right); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x+16,y+16,1,right); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + } + + move(down); + shiftdir=s; + + if(!walkable) + { + if(shiftdir==-1) + { + if(!_walkflag(x, y+15+1,1)&& + !_walkflag(x+8, y+15+1,1)&& + _walkflag(x+15,y+15+1,1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+15,y+15+1)) + sprite::move((fix)-1,(fix)0); + } + else if(_walkflag(x, y+15+1,1)&& + !_walkflag(x+7, y+15+1,1)&& + !_walkflag(x+15,y+15+1,1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x,y+15+1)) + sprite::move((fix)1,(fix)0); + } + else //if(shiftdir==-1) + { + pushing=push+1; + + if(action!=swimming) + { + } + } + + z3step=2; + } + else + { + pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work. + + if(action!=swimming) + { + } + + z3step=2; + } + } + + return; + } + } + + if(DrunkLeft()&&(holddir==-1||holddir==left)) + { + if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + } + else + { + if(charging==0 && spins==0) + { + dir=left; + } + + holddir=left; + + if(DrunkUp()&&shiftdir!=down) + { + shiftdir=up; + } + else if(DrunkDown()&&shiftdir!=up) + { + shiftdir=down; + } + else + { + shiftdir=-1; + } + + //bool walkable; + info = walkflag(x-z3step,y+(bigHitbox?0:8),1,left)||walkflag(x-z3step,y+8,1,left); + + if(int(y)&7) + info = info || walkflag(x-z3step,y+16,1,left); + + execute(info); + + if(info.isUnwalkable()) + { + if(z3step==2) + { + z3step=1; + info = walkflag(x-z3step,y+(bigHitbox?0:8),1,left)||walkflag(x-z3step,y+8,1,left); + + if(int(y)&7) + info = info || walkflag(x-z3step,y+16,1,left); + + execute(info); + + if(info.isUnwalkable()) + { + walkable = false; + } + else + { + walkable=true; + } + } + else + { + walkable=false; + } + } + else + { + walkable = true; + } + + int s=shiftdir; + + if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || tmpscr->flags7&fSIDEVIEW) + { + shiftdir=-1; + } + else + { + if(s==up) + { + info = walkflag(x,y+(bigHitbox?0:8)-1,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-1,1,up); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x-1,y+(bigHitbox?0:8)-1,1,up); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + else if(s==down) + { + info = walkflag(x,y+16,2,down)||walkflag(x+15,y+16,1,down); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x-1,y+16,1,down); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + } + + move(left); + shiftdir=s; + + if(!walkable) + { + if(shiftdir==-1) + { + int v1=bigHitbox?0:8; + int v2=bigHitbox?8:12; + + if(!_walkflag(x-1,y+v1,1)&& + !_walkflag(x-1,y+v2,1)&& + _walkflag(x-1,y+15,1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+15)) + sprite::move((fix)0,(fix)-1); + } + else if(_walkflag(x-1,y+v1, 1)&& + !_walkflag(x-1,y+v2-1,1)&& + !_walkflag(x-1,y+15, 1)) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x-1,y+v1)) + sprite::move((fix)0,(fix)1); + } + else //if(shiftdir==-1) + { + pushing=push+1; + + if(action!=swimming) + { + } + } + + z3step=2; + } + else + { + pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work. + + if(action!=swimming) + { + } + + z3step=2; + } + } + + return; + } + } + + if(DrunkRight()&&(holddir==-1||holddir==right)) + { + if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + } + else + { + if(charging==0 && spins==0) + { + dir=right; + } + + holddir=right; + + if(DrunkUp()&&shiftdir!=down) + { + shiftdir=up; + } + else if(DrunkDown()&&shiftdir!=up) + { + shiftdir=down; + } + else + { + shiftdir=-1; + } + + //bool walkable; + info = walkflag(x+15+z3step,y+(bigHitbox?0:8),1,right)||walkflag(x+15+z3step,y+8,1,right); + + if(int(y)&7) + info = info || walkflag(x+15+z3step,y+16,1,right); + + execute(info); + + if(info.isUnwalkable()) + { + if(z3step==2) + { + z3step=1; + info = walkflag(x+15+z3step,y+(bigHitbox?0:8),1,right)||walkflag(x+15+z3step,y+8,1,right); + + if(int(y)&7) + info = info || walkflag(x+15+z3step,y+16,1,right); + + execute(info); + + if(info.isUnwalkable()) + { + walkable = false; + } + else + { + walkable=true; + } + } + else + { + walkable=false; + } + } + else + { + walkable = true; + } + + int s=shiftdir; + + if((isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM)) || tmpscr->flags7&fSIDEVIEW) + { + shiftdir=-1; + } + else + { + if(s==up) + { + info = walkflag(x,y+(bigHitbox?0:8)-1,2,up)||walkflag(x+15,y+(bigHitbox?0:8)-1,1,up); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x+16,y+(bigHitbox?0:8)-1,1,up); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + else if(s==down) + { + info = walkflag(x,y+16,2,down)||walkflag(x+15,y+16,1,down); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + else if(walkable) + { + info = walkflag(x+16,y+16,1,down); + execute(info); + + if(info.isUnwalkable()) + { + shiftdir=-1; + } + } + } + } + + move(right); + shiftdir=s; + + if(!walkable) + { + if(shiftdir==-1) + { + int v1=bigHitbox?0:8; + int v2=bigHitbox?8:12; + + info = !walkflag(x+16,y+v1,1,right)&& + !walkflag(x+16,y+v2,1,right)&& + walkflag(x+16,y+15,1,right); + + //do NOT execute these + if(info.isUnwalkable()) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+15)) + sprite::move((fix)0,(fix)-1); + } + else + { + info = walkflag(x+16,y+v1, 1,right)&& + !walkflag(x+16,y+v2-1,1,right)&& + !walkflag(x+16,y+15, 1,right); + + if(info.isUnwalkable()) + { + if(hclk || (z>0 && !(tmpscr->flags2&fAIRCOMBOS)) || !checkdamagecombos(x+16,y+v1)) + sprite::move((fix)0,(fix)1); + } + else //if(shiftdir==-1) + { + pushing=push+1; + z3step=2; + + if(action!=swimming) + { + } + } + } + + z3step=2; + } + else + { + pushing=push+1; // L: This makes solid damage combos and diagonal-triggered Armoses work. + + if(action!=swimming) + { + } + + z3step=2; + } + } + + return; + } + } + + bool wtry = iswater(MAPCOMBO(x,y+15)); + bool wtry8 = iswater(MAPCOMBO(x+15,y+15)); + bool wtrx = iswater(MAPCOMBO(x,y+(bigHitbox?0:8))); + bool wtrx8 = iswater(MAPCOMBO(x+15,y+(bigHitbox?0:8))); + + if(can_use_item(itype_flippers,i_flippers)&&!(ladderx+laddery)&&z==0) + { + if(wtrx&&wtrx8&&wtry&&wtry8 && !DRIEDLAKE) + { + //action=swimming; + if(action !=none && action != swimming) + { + hopclk = 0xFF; + } + } + } + + return; + } //endif (LTTPWALK) + + if(isdungeon() && (x<=26 || x>=214) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + goto LEFTRIGHT; + } + + // make it easier to get in left & right doors + + //ignore ladder for this part. sigh sigh sigh -DD + oldladderx = ladderx; + oldladdery = laddery; + info = walkflag(x-int(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,left) || + walkflag(x-int(lsteps[int(x)&7]),y+8,1,left); + + if(isdungeon() && DrunkLeft() && x==32 && y==80 && !info.isUnwalkable()) + { + //ONLY process the side-effects of the above walkflag if Link will actually move + //sigh sigh sigh... walkflag is a horrible mess :-/ -DD + execute(info); + move(left); + return; + } + + info = walkflag(x+15+int(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,right) || + walkflag(x+15+int(lsteps[int(x)&7]),y+8,1,right); + + if(isdungeon() && DrunkRight() && x==208 && y==80 && !info.isUnwalkable()) + { + execute(info); + move(right); + return; + } + + ladderx = oldladderx; + laddery = oldladdery; + + if(DrunkUp()) + { + if(xoff && !is_on_conveyor && action != swimming && jumping<1) + { + if(dir!=up && dir!=down) + { + if(xoff>2&&xoff<6) + { + move(dir); + } + else if(xoff>=6) + { + move(right); + } + else if(xoff>=1) + { + move(left); + } + } + else + { + if(xoff>=4) + { + move(right); + } + else if(xoff<4) + { + move(left); + } + } + } + else + { + if(action==swimming) + { + info = walkflag(x,y+(bigHitbox?0:8)-int(lsteps[int(y)&7]),2,up); + + if(_walkflag(x+15, y+(bigHitbox?0:8)-int(lsteps[int(y)&7]), 1) && + !(iswater(MAPCOMBO(x, y+(bigHitbox?0:8)-int(lsteps[int(y)&7]))) && + iswater(MAPCOMBO(x+15, y+(bigHitbox?0:8)-int(lsteps[int(y)&7]))))) + info.setUnwalkable(true); + } + else + { + info = walkflag(x,y+(bigHitbox?0:8)-int(lsteps[int(y)&7]),2,up); + if(blockmoving) + info = info || walkflagMBlock(x+8,y+(bigHitbox?0:8)-int(lsteps[int(y)&7])); + } + + execute(info); + + if(!info.isUnwalkable()) + { + move(up); + return; + } + + if(!DrunkLeft() && !DrunkRight()) + { + pushing=push+1; + + if(charging==0 && spins==0) + { + dir=up; + } + + if(action!=swimming) + { + linkstep(); + } + + return; + } + else + { + goto LEFTRIGHT; + } + } + + return; + } + + if(DrunkDown()) + { + if(xoff && !is_on_conveyor && action != swimming && jumping<1) + { + if(dir!=up && dir!=down) + { + if(xoff>2&&xoff<6) + { + move(dir); + } + else if(xoff>=6) + { + move(right); + } + else if(xoff>=1) + { + move(left); + } + } + else + { + if(xoff>=4) + { + move(right); + } + else if(xoff<4) + { + move(left); + } + } + } + else + { + if(action==swimming) + { + info=walkflag(x,y+15+int(lsteps[int(y)&7]),2,down); + + if(_walkflag(x+15, y+15+int(lsteps[int(y)&7]), 1) && + !(iswater(MAPCOMBO(x, y+15+int(lsteps[int(y)&7]))) && + iswater(MAPCOMBO(x+15, y+15+int(lsteps[int(y)&7]))))) + info.setUnwalkable(true); + } + else + { + info=walkflag(x,y+15+int(lsteps[int(y)&7]),2,down); + if(blockmoving) + info = info || walkflagMBlock(x+8,y+15+int(lsteps[int(y)&7])); + } + + execute(info); + + if(!info.isUnwalkable()) + { + move(down); + return; + } + + if(!DrunkLeft() && !DrunkRight()) + { + pushing=push+1; + + if(charging==0 && spins==0) + { + dir=down; + } + + if(action!=swimming) + { + linkstep(); + } + + return; + } + else goto LEFTRIGHT; + } + + return; + } + +LEFTRIGHT: + + if(isdungeon() && (y<=26 || y>=134) && !get_bit(quest_rules,qr_FREEFORM) && !toogam) + { + return; + } + + if(DrunkLeft()) + { + if(yoff && !is_on_conveyor && action != swimming && jumping<1) + { + if(dir!=left && dir!=right) + { + if(yoff>2&&yoff<6) + { + move(dir); + } + else if(yoff>=6) + { + move(down); + } + else if(yoff>=1) + { + move(up); + } + } + else + { + if(yoff>=4) + { + move(down); + } + else if(yoff<4) + { + move(up); + } + } + } + else + { + info = walkflag(x-int(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,left) || + walkflag(x-int(lsteps[int(x)&7]),y+(tmpscr->flags7&fSIDEVIEW ?0:8), 1,left); + execute(info); + + if(!info.isUnwalkable()) + { + move(left); + return; + } + + if(!DrunkUp() && !DrunkDown()) + { + pushing=push+1; + + if(charging==0 && spins==0) + { + dir=left; + } + + if(action!=swimming) + { + linkstep(); + } + + return; + } + } + + return; + } + + if(DrunkRight()) + { + if(yoff && !is_on_conveyor && action != swimming && jumping<1) + { + if(dir!=left && dir!=right) + { + if(yoff>2&&yoff<6) + { + move(dir); + } + else if(yoff>=6) + { + move(down); + } + else if(yoff>=1) + { + move(up); + } + } + else + { + if(yoff>=4) + { + move(down); + } + else if(yoff<4) + { + move(up); + } + } + } + else + { + info = walkflag((int)x+15+(lsteps[int(x)&7]),y+(bigHitbox?0:8),1,right) || walkflag((int)x+15+(lsteps[int(x)&7]),y+(tmpscr->flags7&fSIDEVIEW ?0:8), 1,right); + execute(info); + + if(!info.isUnwalkable()) + { + move(right); + return; + } + + if(!DrunkUp() && !DrunkDown()) + { + pushing=push+1; + + if(charging==0 && spins==0) + { + dir=right; + } + + if(action!=swimming) + { + linkstep(); + } + + return; + } + } + } +} + +void LinkClass::move(int d2) +{ +//al_trace("%s\n",d2==up?"up":d2==down?"down":d2==left?"left":d2==right?"right":"?"); + static bool totalskip = false; + + if(inlikelike) + return; + + int dx=0,dy=0; + int xstep=lsteps[int(x)&7]; + int ystep=lsteps[int(y)&7]; + int z3skip=0; + int z3diagskip=0; + // xstep=ystep=0; + // if((combobuf[MAPCOMBO(x+7,y+8)].type==cOLD_WALKSLOW && z==0) || + // (tmpscr->flags7&fSIDEVIEW && _walkflag(x+7,y+16,0) && combobuf[MAPCOMBO(x+7,y+16)].type==cOLD_WALKSLOW) || + bool slowcombo = (combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement && (z==0 || tmpscr->flags2&fAIRCOMBOS)) || + (tmpscr->flags7&fSIDEVIEW && ON_SIDEPLATFORM && combo_class_buf[combobuf[MAPCOMBO(x+7,y+8)].type].slow_movement); + bool slowcharging = get_bit(quest_rules,qr_SLOWCHARGINGWALK) && charging>0; + bool is_swimming = (action == swimming); + + //slow walk combo, or charging, moves at 2/3 speed +// if(!is_swimming && (slowcharging ^ slowcombo)) + if( + (!is_swimming && (slowcharging ^ slowcombo))|| + (is_swimming && (zinit.link_swim_speed>60)) + ) + { + totalskip = false; + + if(diagonalMovement) + { + skipstep=(skipstep+1)%6; + + if(skipstep%2==0) z3skip=1; + else z3skip=0; + + if(skipstep%3==0) z3diagskip=1; + else z3diagskip=0; + } + else + { + if(d21) + { + skipstep^=1; + ystep=skipstep; + } + } + else + { + if(xstep>1) + { + skipstep^=1; + xstep=skipstep; + } + } + } + } +// else if(is_swimming || (slowcharging && slowcombo)) + else if( + (is_swimming && (zinit.link_swim_speed<60))|| + (slowcharging && slowcombo) + ) + { + //swimming, or charging on a slow combo, moves at 1/2 speed + totalskip = !totalskip; + + if(diagonalMovement) + { + skipstep=0; + } + } + else + { + totalskip = false; + + if(diagonalMovement) + { + skipstep=0; + } + } + + if(!totalskip) + { + if(diagonalMovement) + { + switch(d2) + { + case up: + if(shiftdir==left) + { + if(walkable) + { + dy-=1-z3diagskip; + dx-=1-z3diagskip; + z3step=2; + } + else + { + dx-=1-z3diagskip; + z3step=2; + } + } + else if(shiftdir==right) + { + if(walkable) + { + dy-=1-z3diagskip; + dx+=1-z3diagskip; + z3step=2; + } + else + { + dx+=1-z3diagskip; + z3step=2; + } + } + else + { + if(walkable) + { + dy-=z3step-z3skip; + z3step=(z3step%2)+1; + } + } + + break; + + case down: + if(shiftdir==left) + { + if(walkable) + { + dy+=1-z3diagskip; + dx-=1-z3diagskip; + z3step=2; + } + else + { + dx-=1-z3diagskip; + z3step=2; + } + } + else if(shiftdir==right) + { + if(walkable) + { + dy+=1-z3diagskip; + dx+=1-z3diagskip; + z3step=2; + } + else + { + dx+=1-z3diagskip; + z3step=2; + } + } + else + { + if(walkable) + { + dy+=z3step-z3skip; + z3step=(z3step%2)+1; + } + } + + break; + + case right: + if(shiftdir==up) + { + if(walkable) + { + dy-=1-z3diagskip; + dx+=1-z3diagskip; + z3step=2; + } + else + { + dy-=1-z3diagskip; + z3step=2; + } + } + else if(shiftdir==down) + { + if(walkable) + { + dy+=1-z3diagskip; + dx+=1-z3diagskip; + z3step=2; + } + else + { + dy+=1-z3diagskip; + z3step=2; + } + } + else + { + if(walkable) + { + dx+=z3step-z3skip; + z3step=(z3step%2)+1; + } + } + + break; + + case left: + if(shiftdir==up) + { + if(walkable) + { + dy-=1-z3diagskip; + dx-=1-z3diagskip; + z3step=2; + } + else + { + dy-=1-z3diagskip; + z3step=2; + } + } + else if(shiftdir==down) + { + if(walkable) + { + dy+=1-z3diagskip; + dx-=1-z3diagskip; + z3step=2; + } + else + { + dy+=1-z3diagskip; + z3step=2; + } + } + else + { + if(walkable) + { + dx-=z3step-z3skip; + z3step=(z3step%2)+1; + } + } + + break; + } + } + else + { + switch(d2) + { + case up: + if(!(tmpscr->flags7&fSIDEVIEW) || (ladderx && laddery && ladderdir==up)) dy-=ystep; + + break; + + case down: + if(!(tmpscr->flags7&fSIDEVIEW) || (ladderx && laddery && ladderdir==up)) dy+=ystep; + + break; + + case left: + dx-=xstep; + break; + + case right: + dx+=xstep; + break; + } + } + } + + if((charging==0 || attack==wHammer) && spins==0 && attackclk!=HAMMERCHARGEFRAME) + { + dir=d2; + } + + if(action != swimming) + { + linkstep(); + + //ack... don't walk if in midair! -DD + if(charging==0 && spins==0 && z==0 && !(tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM)) + action = walking; + + if(++link_count > (16*link_animation_speed)) + link_count=0; + } + else if(!(frame & 1)) + { + linkstep(); + } + + if(charging==0 || attack!=wHammer) + { + sprite::move((fix)dx,(fix)dy); + } +} + +LinkClass::WalkflagInfo LinkClass::walkflag(int wx,int wy,int cnt,byte d2) +{ + WalkflagInfo ret; + + if(toogam) + { + ret.setUnwalkable(false); + return ret; + } + + if(blockpath && wy<(bigHitbox?80:88)) + { + ret.setUnwalkable(true); + return ret; + } + + if(blockmoving && mblock2.hit(wx,wy,0,1,1,1)) + { + ret.setUnwalkable(true); + return ret; + } + + if(isdungeon() && currscr<128 && wy<(bigHitbox?32:40) && ((diagonalMovement?(x<=112||x>=128):x!=120) || _walkflag(120,24,2)) + && !get_bit(quest_rules,qr_FREEFORM)) + { + ret.setUnwalkable(true); + return ret; + } + + bool wf = _walkflag(wx,wy,cnt); + + if(isdungeon() && currscr<128 && !get_bit(quest_rules,qr_FREEFORM)) + { + if(diagonalMovement) + { + if(wx>=112&&wx<120&&wy<40&&wy>=32) wf=true; + + if(wx>=136&&wx<144&&wy<40&&wy>=32) wf=true; + } + } + + if(action==swimming) + { + if(!wf) + { + if(landswim>= (get_bit(quest_rules,qr_DROWN) && isSwimming() ? 1 + : (!diagonalMovement) ? 1 : 22)) + { + //Check for out of bounds for swimming + bool changehop = true; + + if(diagonalMovement) + { + if(wx<0||wy<0) + changehop = false; + else if(wx>248) + changehop = false; + else if(wx>240&&cnt==2) + changehop = false; + else if(wy>168) + changehop = false; + } + + // hop out of the water + if(changehop) + ret.setHopClk(1); + } + else + { + if(dir==d2 || shiftdir==d2) + { + //int vx=((int)x+4)&0xFFF8; + //int vy=((int)y+4)&0xFFF8; + if(d2==left) + { + if(!iswater(MAPCOMBO(x-1,y+(bigHitbox?7:11)))&&!iswater(MAPCOMBO(x-1,y+(bigHitbox?8:12))) + && !_walkflag(x-1,y+(bigHitbox?7:11),1) && !_walkflag(x-1,y+(bigHitbox?8:12),1)) + { + ret.setHopDir(d2); + ret.setIlswim(true); + } + else ret.setIlswim(false); + } + else if(d2==right) + { + if(!iswater(MAPCOMBO(x+16,y+(bigHitbox?7:11)))&&!iswater(MAPCOMBO(x+16,y+(bigHitbox?8:12))) + && !_walkflag(x+16,y+(bigHitbox?7:11),1) && !_walkflag(x+16,y+(bigHitbox?8:12),1)) + { + ret.setHopDir(d2); + ret.setIlswim(true); + } + else ret.setIlswim(false); + } + else if(d2==up) + { + if(!iswater(MAPCOMBO(x+7,y+(bigHitbox?0:8)-1))&&!iswater(MAPCOMBO(x+8,y+(bigHitbox?0:8)-1)) + && !_walkflag(x+7,y+(bigHitbox?0:8)-1,1) && !_walkflag(x+8,y+(bigHitbox?0:8)-1,1)) + { + ret.setHopDir(d2); + ret.setIlswim(true); + } + else ret.setIlswim(false); + } + else if(d2==down) + { + if(!iswater(MAPCOMBO(x+7,y+16))&&!iswater(MAPCOMBO(x+8,y+16)) + && !_walkflag(x+7,y+16,1) && !_walkflag(x+8,y+16,1)) + { + ret.setHopDir(d2); + ret.setIlswim(true); + } + else ret.setIlswim(false); + } + } + + if(wx<0||wy<0); + else if(wx>248); + else if(wx>240&&cnt==2); + else if(wy>168); + else if(get_bit(quest_rules, qr_DROWN) && !ilswim); + else if(iswater(MAPCOMBO(wx,wy)) && iswater(MAPCOMBO(wx,wy))) + { + ret.setUnwalkable(false); + return ret; + } + else + { + ret.setUnwalkable(true); + return ret; + } + } + } + else + { + bool wtrx = iswater(MAPCOMBO(wx,wy)); + bool wtrx8 = iswater(MAPCOMBO(x+8,wy)); + + if((d2>=left && wtrx) || (d2<=down && wtrx && wtrx8)) + { + ret.setUnwalkable(false); + return ret; + } + } + } + else if(ladderx+laddery) // ladder is being used + { + int lx = !(get_bit(quest_rules, qr_DROWN)&&iswater(MAPCOMBO(x+4,y+11))&&!_walkflag(x+4,y+11,1)) ? wx : x; + int ly = !(get_bit(quest_rules, qr_DROWN)&&iswater(MAPCOMBO(x+4,y+11))&&!_walkflag(x+4,y+11,1)) ? wy : y; + + if(diagonalMovement) + { + if(ladderdir==up) + { + if(abs(ly-(laddery+8))<=8) // ly is between laddery (laddery+8-8) and laddery+16 (laddery+8+8) + { + bool temp = false; + + if(!(abs(lx-(ladderx+8))<=8)) + temp = true; + + if(cnt==2) + if(!(abs((lx+8)-(ladderx+8))<=8)) + temp=true; + + if(!temp) + { + ret.setUnwalkable(false); + return ret; + } + + if(current_item_power(itype_ladder)<2 && (d2==left || d2==right) && !(tmpscr->flags7&fSIDEVIEW)) + { + ret.setUnwalkable(true); + return ret; + } + } + } + else + { + if(abs(lx-(ladderx+8))<=8) + { + if(abs(ly-(laddery+(bigHitbox?8:12)))<=(bigHitbox?8:4)) + { + ret.setUnwalkable(false); + return ret; + } + + if(current_item_power(itype_ladder)<2 && (d2==up || d2==down)) + { + ret.setUnwalkable(true); + return ret; + } + + if((abs(ly-laddery+8)<=8) && d2<=down) + { + ret.setUnwalkable(false); + return ret; + } + } + } + } // diagonalMovement + else + { + if((d2&2)==ladderdir) // same direction + { + switch(d2) + { + case up: + if(int(y)<=laddery) + { + ret.setUnwalkable(_walkflag(ladderx,laddery-8,1) || + _walkflag(ladderx+8,laddery-8,1)); + return ret; + + } + + // no break + case down: + if((wy&0xF0)==laddery) + { + ret.setUnwalkable(false); + return ret; + } + + break; + + default: + if((wx&0xF0)==ladderx) + { + ret.setUnwalkable(false); + return ret; + } + } + + if(d2<=down) + { + ret.setUnwalkable(_walkflag(ladderx,wy,1) || _walkflag(ladderx+8,wy,1)); + return ret; + } + + ret.setUnwalkable(_walkflag((wx&0xF0),wy,1) || _walkflag((wx&0xF0)+8,wy,1)); + return ret; + } + + // different dir + if(current_item_power(itype_ladder)<2 && !(tmpscr->flags7&fSIDEVIEW && (d2==left || d2==right))) + { + ret.setUnwalkable(true); + return ret; + } + + if(wy>=laddery && wy<=laddery+16 && d2<=down) + { + ret.setUnwalkable(false); + return ret; + } + } + } + else if(wf || (tmpscr->flags7&fSIDEVIEW) || get_bit(quest_rules, qr_DROWN)) + { + // see if it's a good spot for the ladder or for swimming + bool unwalkablex = _walkflag(wx,wy,1); //will be used later for the ladder -DD + bool unwalkablex8 = _walkflag(x+8,wy,1); + + if(get_bit(quest_rules, qr_DROWN)) + { + // Drowning changes the following attributes: + // * Dangerous water is also walkable, so ignore the previous + // definitions of unwalkablex and unwalkablex8. + // * Instead, prevent the ladder from being used in the + // one frame where Link has landed on water before drowning. + unwalkablex = unwalkablex8 = !iswater(MAPCOMBO(x+4,y+11)); + } + + // check if he can swim + if(current_item(itype_flippers) && z==0) + { + bool wtrx = iswater(MAPCOMBO(wx,wy)); + bool wtrx8 = iswater(MAPCOMBO(x+8,wy)); + //ladder ignores water combos that are now walkable thanks to flippers -DD + unwalkablex = unwalkablex && !wtrx; + unwalkablex8 = unwalkablex8 && !wtrx8; + + if(landswim >= 22) + { + ret.setHopClk(2); + ret.setUnwalkable(false); + return ret; + } + else if((d2>=left && wtrx) || (d2<=down && wtrx && wtrx8)) + { + if(!diagonalMovement) + { + ret.setHopClk(2); + + if(charging || spins>5) + { + //if Link is charging, he might be facing the wrong direction (we want him to + //hop into the water, not in the facing direction) + ret.setDir(d2); + //moreover Link can't charge in the water -DD + ret.setChargeAttack(); + } + + ret.setUnwalkable(false); + return ret; + } + else if(dir==d2) + { + ret.setIlswim(true); + ladderx = 0; + laddery = 0; + } + } + } + + // check if he can use the ladder + // "Allow Ladder Anywhere" is toggled by fLADDER + if(can_deploy_ladder()) + // laddersetup + { + // Check if there's water to use the ladder over + bool wtrx = iswater(MAPCOMBO(wx,wy)); + bool wtrx8 = iswater(MAPCOMBO(x+8,wy)); + + if(wtrx || wtrx8) + { + if(tmpscr->flags7&fSIDEVIEW) + { + wtrx = !_walkflag(wx, wy+8, 1) && !_walkflag(wx, wy, 1) && dir!=down; + wtrx8 = !_walkflag(wx+8, wy+8, 1) && !_walkflag(wx+8, wy, 1) && dir!=down; + } + // * walk on half-water using the ladder instead of using flippers. + // * otherwise, walk on ladder(+hookshot) combos. + else if(wtrx==wtrx8 && (isstepable(MAPCOMBO(wx, wy)) || isstepable(MAPCOMBO(wx+8,wy)) || wtrx==true)) + { + //if Link could swim on a tile instead of using the ladder, + //refuse to use the ladder to step over that tile. -DD + wtrx = isstepable(MAPCOMBO(wx, wy)) && unwalkablex; + wtrx8 = isstepable(MAPCOMBO(wx+8,wy)) && unwalkablex8; + } + } + // No water; how about ladder combos? + else + { + int combo=combobuf[MAPCOMBO(wx, wy)].type; + wtrx=(combo==cLADDERONLY || combo==cLADDERHOOKSHOT); + combo=combobuf[MAPCOMBO(wx+8, wy)].type; + wtrx8=(combo==cLADDERONLY || combo==cLADDERHOOKSHOT); + } + + bool walkwater = get_bit(quest_rules, qr_DROWN) && !iswater(MAPCOMBO(wx,wy)); + + if(diagonalMovement) + { + if(d2==dir) + { + int c = walkwater ? 0:8; + int b = walkwater ? 8:0; + + if(d2>=left) + { + // If the difference between wy and y is small enough + if(abs((wy)-(int(y+c)))<=(b) && wtrx) + { + ladderx = wx&0xF0; + laddery = y; + ladderdir = left; + ladderstart = d2; + ret.setUnwalkable(laddery!=int(y)); + return ret; + } + } + else if(d2<=down) + { + // If the difference between wx and x is small enough + if(abs((wx)-(int(x+c)))<=(b) && wtrx) + { + ladderx = x; + laddery = wy&0xF0; + ladderdir = up; + ladderstart = d2; + ret.setUnwalkable(ladderx!=int(x)); + return ret; + } + + if(cnt==2) + { + if(abs((wx+8)-(int(x+c)))<=(b) && wtrx8) + { + ladderx = x; + laddery = wy&0xF0; + ladderdir = up; + ladderstart = d2; + ret.setUnwalkable(ladderx!=int(x)); + return ret; + } + } + } + } + } + else + { + bool flgx = _walkflag(wx,wy,1) && !wtrx; // Solid, and not steppable + bool flgx8 = _walkflag(x+8,wy,1) && !wtrx8; // Solid, and not steppable + + if((d2>=left && wtrx) + // Deploy the ladder vertically even if Link is only half on water. + || (d2<=down && ((wtrx && !flgx8) || (wtrx8 && !flgx)))) + { + if(((int(y)+15) < wy) || ((int(y)+8) > wy)) + ladderdir = up; + else + ladderdir = left; + + if(ladderdir==up) + { + ladderx = int(x)&0xF8; + laddery = wy&0xF0; + } + else + { + ladderx = wx&0xF0; + laddery = int(y)&0xF8; + } + + ret.setUnwalkable(false); + return ret; + } + } + } + } + + ret.setUnwalkable(wf); + return ret; +} + +// Only checks for moving blocks. Apparently this is a thing we need. +LinkClass::WalkflagInfo LinkClass::walkflagMBlock(int wx,int wy) +{ + WalkflagInfo ret; + ret.setUnwalkable(blockmoving && mblock2.hit(wx,wy,0,1,1,1)); + return ret; +} + +void LinkClass::checkpushblock() +{ + if(toogam) return; + + if(z!=0) return; + + // Return early in some cases.. + bool earlyReturn=false; + + if(!diagonalMovement || dir==left) + if(int(x)&15) earlyReturn=true; + + // if(y<16) return; + if(tmpscr->flags7&fSIDEVIEW && !ON_SIDEPLATFORM) return; + + int bx = int(x)&0xF0; + int by = (int(y)&0xF0); + + switch(dir) + { + case up: + if(y<16) + { + earlyReturn=true; + break; + } + + if(!((int)y&15)&&y!=0) by-=bigHitbox ? 16 : 0; + + if((int)x&8) bx+=16; + + break; + + case down: + if(y>128) + { + earlyReturn=true; + break; + } + else + { + by+=16; + + if((int)x&8) bx+=16; + } + + break; + + case left: + if(x<32) + { + earlyReturn=true; + break; + } + else + { + bx-=16; + + if(int(y)&8) + { + by+=16; + } + } + + break; + + case right: + if(x>208) + { + earlyReturn=true; + break; + } + else + { + bx+=16; + + if(int(y)&8) + { + by+=16; + } + } + + break; + } + + // In sideview, we still have to check for damage combos. + if(earlyReturn && (tmpscr->flags7&fSIDEVIEW)==0) + return; + + int f = MAPFLAG(bx,by); + int f2 = MAPCOMBOFLAG(bx,by); + int t = combobuf[MAPCOMBO(bx,by)].type; + + // Unlike push blocks, damage combos should be tested on layers 2 and under + for(int i=(get_bit(quest_rules,qr_DMGCOMBOLAYERFIX) ? 2 : 0); i>=0; i--) + { + t = combobuf[i==0 ? MAPCOMBO(bx,by) : MAPCOMBO2(i-1,bx,by)].type; + + // Solid damage combos use pushing>0, hence the code is here. + if(combo_class_buf[t].modify_hp_amount && _walkflag(bx,by,1) && pushing>0 && hclk<1 && action!=casting && !get_bit(quest_rules, qr_NOSOLIDDAMAGECOMBOS)) + { + // Bite Link + checkdamagecombos(bx+8-(tmpscr->csensitive), + bx+8+(zc_max(tmpscr->csensitive-1,0)), + by+(bigHitbox?8:12)-(bigHitbox?tmpscr->csensitive:(tmpscr->csensitive+1)/2), + by+zc_max((bigHitbox?tmpscr->csensitive:(tmpscr->csensitive+1)/2)-1,0), i-1, true); + return; + } + if((tmpscr->flags7&fSIDEVIEW) && // Check for sideview damage combos + hclk<1 && action!=casting) // ... but only if Link could be hurt + { + if(checkdamagecombos(x+4, x+12, y+16, y+24)) + return; + } + } + + if(earlyReturn) + return; + + int itemid=current_item_id(itype_bracelet); + + if((t==cPUSH_WAIT || t==cPUSH_HW || t==cPUSH_HW2) && (pushing<16 || hasMainGuy())) return; + + if((t==cPUSH_HW || t==cPUSH_HEAVY || t==cPUSH_HEAVY2 || t==cPUSH_HW2) + && (itemid<0 || itemsbuf[itemid].power<((t==cPUSH_HEAVY2 || t==cPUSH_HW2)?2:1) || + ((itemid>=0 && itemsbuf[itemid].flags & ITEM_FLAG1) && (didstuff&did_glove)))) return; + + if(get_bit(quest_rules,qr_HESITANTPUSHBLOCKS)&&(pushing<4)) return; + + bool doit=false; + bool changeflag=false; + bool changecombo=false; + + if(((f==mfPUSHUD || f==mfPUSHUDNS|| f==mfPUSHUDINS) && dir<=down) || + ((f==mfPUSHLR || f==mfPUSHLRNS|| f==mfPUSHLRINS) && dir>=left) || + ((f==mfPUSHU || f==mfPUSHUNS || f==mfPUSHUINS) && dir==up) || + ((f==mfPUSHD || f==mfPUSHDNS || f==mfPUSHDINS) && dir==down) || + ((f==mfPUSHL || f==mfPUSHLNS || f==mfPUSHLINS) && dir==left) || + ((f==mfPUSHR || f==mfPUSHRNS || f==mfPUSHRINS) && dir==right) || + f==mfPUSH4 || f==mfPUSH4NS || f==mfPUSH4INS) + { + changeflag=true; + doit=true; + } + + if((((f2==mfPUSHUD || f2==mfPUSHUDNS|| f2==mfPUSHUDINS) && dir<=down) || + ((f2==mfPUSHLR || f2==mfPUSHLRNS|| f2==mfPUSHLRINS) && dir>=left) || + ((f2==mfPUSHU || f2==mfPUSHUNS || f2==mfPUSHUINS) && dir==up) || + ((f2==mfPUSHD || f2==mfPUSHDNS || f2==mfPUSHDINS) && dir==down) || + ((f2==mfPUSHL || f2==mfPUSHLNS || f2==mfPUSHLINS) && dir==left) || + ((f2==mfPUSHR || f2==mfPUSHRNS || f2==mfPUSHRINS) && dir==right) || + f2==mfPUSH4 || f2==mfPUSH4NS || f2==mfPUSH4INS)&&(f!=mfPUSHED)) + { + changecombo=true; + doit=true; + } + + if(get_bit(quest_rules,qr_SOLIDBLK)) + { + switch(dir) + { + case up: + if(_walkflag(bx,by-8,2)&&!(MAPFLAG(bx,by-8)==mfBLOCKHOLE||MAPCOMBOFLAG(bx,by-8)==mfBLOCKHOLE)) doit=false; + + break; + + case down: + if(_walkflag(bx,by+24,2)&&!(MAPFLAG(bx,by+24)==mfBLOCKHOLE||MAPCOMBOFLAG(bx,by+24)==mfBLOCKHOLE)) doit=false; + + break; + + case left: + if(_walkflag(bx-16,by+8,2)&&!(MAPFLAG(bx-16,by+8)==mfBLOCKHOLE||MAPCOMBOFLAG(bx-16,by+8)==mfBLOCKHOLE)) doit=false; + + break; + + case right: + if(_walkflag(bx+16,by+8,2)&&!(MAPFLAG(bx+16,by+8)==mfBLOCKHOLE||MAPCOMBOFLAG(bx+16,by+8)==mfBLOCKHOLE)) doit=false; + + break; + } + } + + switch(dir) + { + case up: + if((MAPFLAG(bx,by-8)==mfNOBLOCKS||MAPCOMBOFLAG(bx,by-8)==mfNOBLOCKS)) doit=false; + + break; + + case down: + if((MAPFLAG(bx,by+24)==mfNOBLOCKS||MAPCOMBOFLAG(bx,by+24)==mfNOBLOCKS)) doit=false; + + break; + + case left: + if((MAPFLAG(bx-16,by+8)==mfNOBLOCKS||MAPCOMBOFLAG(bx-16,by+8)==mfNOBLOCKS)) doit=false; + + break; + + case right: + if((MAPFLAG(bx+16,by+8)==mfNOBLOCKS||MAPCOMBOFLAG(bx+16,by+8)==mfNOBLOCKS)) doit=false; + + break; + } + + if(doit) + { + if(itemid>=0 && itemsbuf[itemid].flags & ITEM_FLAG1) didstuff|=did_glove; + + // for(int i=0; i<1; i++) + if(!blockmoving) + { + if(changeflag) + { + tmpscr->sflag[(by&0xF0)+(bx>>4)]=0; + } + + //if (changecombo) + //{ + //++tmpscr->data[(by&0xF0)+(bx>>4)]; + //} + if(mblock2.clk<=0) + { + mblock2.push((fix)bx,(fix)by,dir,f); + + if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1PUSHBLOCK,(int)x); + + // break; + } + } + } +} + +bool usekey() +{ + int itemid = current_item_id(itype_magickey); + + if(itemid<0 || + (itemsbuf[itemid].flags & ITEM_FLAG1 ? itemsbuf[itemid].powerlvlkeys[dlevel]!=0) + { + game->lvlkeys[dlevel]--; + return true; + } + + if(game->get_keys()==0) + return false; + + game->change_keys(-1); + } + + return true; +} + +bool islockeddoor(int x, int y, int lock) +{ + int mc = (y&0xF0)+(x>>4); + bool ret = (((mc==7||mc==8||mc==23||mc==24) && tmpscr->door[up]==lock) + || ((mc==151||mc==152||mc==167||mc==168) && tmpscr->door[down]==lock) + || ((mc==64||mc==65||mc==80||mc==81) && tmpscr->door[left]==lock) + || ((mc==78||mc==79||mc==94||mc==95) && tmpscr->door[right]==lock)); + return ret; +} + +void LinkClass::checklockblock() +{ + if(toogam) return; + + int bx = int(x)&0xF0; + int bx2 = int(x+8)&0xF0; + int by = int(y)&0xF0; + + switch(dir) + { + case up: + if(!((int)y&15)&&y!=0) by-=bigHitbox ? 16 : 0; + + break; + + case down: + by+=16; + break; + + case left: + bx-=16; + + if(int(y)&8) + { + by+=16; + } + + bx2=bx; + break; + + case right: + bx+=16; + + if(int(y)&8) + { + by+=16; + } + + bx2=bx; + break; + } + + bool found=false; + + // Layer 0 is overridden by Locked Doors + if((combobuf[MAPCOMBO(bx,by)].type==cLOCKBLOCK && !islockeddoor(bx,by,dLOCKED))|| + (combobuf[MAPCOMBO(bx2,by)].type==cLOCKBLOCK && !islockeddoor(bx2,by,dLOCKED))) + { + found=true; + } + + // Layers + if(!found) + { + for(int i=0; i<2; i++) + { + if((combobuf[MAPCOMBO2(i,bx,by)].type==cLOCKBLOCK)|| + (combobuf[MAPCOMBO2(i,bx2,by)].type==cLOCKBLOCK)) + { + found=true; + break; + } + } + } + + if(!found || pushing<8) + { + return; + } + + if(!usekey()) return; + + setmapflag(mLOCKBLOCK); + remove_lockblocks((currscr>=128)?1:0); + sfx(WAV_DOOR); +} + +void LinkClass::checkbosslockblock() +{ + if(toogam) return; + + int bx = int(x)&0xF0; + int bx2 = int(x+8)&0xF0; + int by = int(y)&0xF0; + + switch(dir) + { + case up: + if(!((int)y&15)&&y!=0) by-=bigHitbox ? 16 : 0; + + break; + + case down: + by+=16; + break; + + case left: + bx-=16; + + if(int(y)&8) + { + by+=16; + } + + bx2=bx; + break; + + case right: + bx+=16; + + if(int(y)&8) + { + by+=16; + } + + bx2=bx; + break; + } + + bool found=false; + + if((combobuf[MAPCOMBO(bx,by)].type==cBOSSLOCKBLOCK && !islockeddoor(bx,by,dBOSS))|| + (combobuf[MAPCOMBO(bx2,by)].type==cBOSSLOCKBLOCK && !islockeddoor(bx,by,dBOSS))) + { + found=true; + } + + if(!found) + { + for(int i=0; i<2; i++) + { + if((combobuf[MAPCOMBO2(i,bx,by)].type==cBOSSLOCKBLOCK)|| + (combobuf[MAPCOMBO2(i,bx2,by)].type==cBOSSLOCKBLOCK)) + { + found=true; + break; + } + } + } + + if(!found || pushing<8) + { + return; + } + + if(!(game->lvlitems[dlevel]&liBOSSKEY)) return; + + setmapflag(mBOSSLOCKBLOCK); + remove_bosslockblocks((currscr>=128)?1:0); + sfx(WAV_DOOR); +} + +void LinkClass::checkchest(int type) +{ + // chests aren't affected by tmpscr->flags2&fAIRCOMBOS + if(toogam || z>0) return; + + int bx = int(x)&0xF0; + int bx2 = int(x+8)&0xF0; + int by = int(y)&0xF0; + + switch(dir) + { + case up: + if(tmpscr->flags7&fSIDEVIEW) return; + + if(!((int)y&15)&&y!=0) by-=bigHitbox ? 16 : 0; + + break; + + case left: + case right: + if(tmpscr->flags7&fSIDEVIEW) break; + + case down: + return; + } + + bool found=false; + bool itemflag=false; + + if((combobuf[MAPCOMBO(bx,by)].type==type)|| + (combobuf[MAPCOMBO(bx2,by)].type==type)) + { + found=true; + } + + if(!found) + { + for(int i=0; i<2; i++) + { + if((combobuf[MAPCOMBO2(i,bx,by)].type==type)|| + (combobuf[MAPCOMBO2(i,bx2,by)].type==type)) + { + found=true; + break; + } + } + } + + if(!found || pushing<8) + { + return; + } + + switch(type) + { + case cLOCKEDCHEST: + if(!usekey()) return; + + setmapflag(mLOCKEDCHEST); + break; + + case cCHEST: + setmapflag(mCHEST); + break; + + case cBOSSCHEST: + if(!(game->lvlitems[dlevel]&liBOSSKEY)) return; + + setmapflag(mBOSSCHEST); + break; + } + + itemflag |= MAPCOMBOFLAG(bx,by)==mfARMOS_ITEM; + itemflag |= MAPCOMBOFLAG(bx2,by)==mfARMOS_ITEM; + itemflag |= MAPFLAG(bx,by)==mfARMOS_ITEM; + itemflag |= MAPFLAG(bx2,by)==mfARMOS_ITEM; + itemflag |= MAPCOMBOFLAG(bx,by)==mfARMOS_ITEM; + itemflag |= MAPCOMBOFLAG(bx2,by)==mfARMOS_ITEM; + + if(!itemflag) + { + for(int i=0; i<2; i++) + { + itemflag |= MAPFLAG2(i,bx,by)==mfARMOS_ITEM; + itemflag |= MAPFLAG2(i,bx2,by)==mfARMOS_ITEM; + itemflag |= MAPCOMBOFLAG2(i,bx,by)==mfARMOS_ITEM; + itemflag |= MAPCOMBOFLAG2(i,bx2,by)==mfARMOS_ITEM; + } + } + + if(itemflag && !getmapflag()) + { + items.add(new item(x, y,(fix)0, tmpscr->catchall, ipONETIME2 + ipBIGRANGE + ipHOLDUP, 0)); + } +} + +void LinkClass::checklocked() +{ + if(toogam) return; + + if(!isdungeon()) return; + + if(pushing!=8) return; + + if((tmpscr->door[dir]!=dLOCKED) && (tmpscr->door[dir]!=dBOSS)) return; + + int si = (currmap<<7) + currscr; + int di = nextscr(dir); + + switch(dir) + { + case up: + if(y>32 || (diagonalMovement?(x<=112||x>=128):x!=120)) return; + + if(tmpscr->door[dir]==dLOCKED) + { + if(usekey()) + { + putdoor(scrollbuf,0,up,dUNLOCKED); + tmpscr->door[0]=dUNLOCKED; + setmapflag(si, mDOOR_UP); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_DOWN); + } + else return; + } + else if(tmpscr->door[dir]==dBOSS) + { + if(game->lvlitems[dlevel]&liBOSSKEY) + { + putdoor(scrollbuf,0,up,dOPENBOSS); + tmpscr->door[0]=dOPENBOSS; + setmapflag(si, mDOOR_UP); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_DOWN); + } + else return; + } + + break; + + case down: + if(y<128 || (diagonalMovement?(x<=112||x>=128):x!=120)) return; + + if(tmpscr->door[dir]==dLOCKED) + { + if(usekey()) + { + putdoor(scrollbuf,0,down,dUNLOCKED); + tmpscr->door[1]=dUNLOCKED; + setmapflag(si, mDOOR_DOWN); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_UP); + } + else return; + } + else if(tmpscr->door[dir]==dBOSS) + { + if(game->lvlitems[dlevel]&liBOSSKEY) + { + putdoor(scrollbuf,0,down,dOPENBOSS); + tmpscr->door[1]=dOPENBOSS; + setmapflag(si, mDOOR_DOWN); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_UP); + } + else return; + } + + break; + + case left: + if((diagonalMovement?(y<=72||y>=88):y!=80) || x>32) return; + + if(tmpscr->door[dir]==dLOCKED) + { + if(usekey()) + { + putdoor(scrollbuf,0,left,dUNLOCKED); + tmpscr->door[2]=dUNLOCKED; + setmapflag(si, mDOOR_LEFT); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_RIGHT); + } + else return; + } + else if(tmpscr->door[dir]==dBOSS) + { + if(game->lvlitems[dlevel]&liBOSSKEY) + { + putdoor(scrollbuf,0,left,dOPENBOSS); + tmpscr->door[2]=dOPENBOSS; + setmapflag(si, mDOOR_LEFT); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_RIGHT); + } + else return; + } + + break; + + case right: + if((diagonalMovement?(y<=72||y>=88):y!=80) || x<208) return; + + if(tmpscr->door[dir]==dLOCKED) + { + if(usekey()) + { + putdoor(scrollbuf,0,right,dUNLOCKED); + tmpscr->door[3]=dUNLOCKED; + setmapflag(si, mDOOR_RIGHT); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_LEFT); + } + else return; + } + else if(tmpscr->door[dir]==dBOSS) + { + if(game->lvlitems[dlevel]&liBOSSKEY) + { + putdoor(scrollbuf,0,right,dOPENBOSS); + tmpscr->door[3]=dOPENBOSS; + setmapflag(si, mDOOR_RIGHT); + + if(di != 0xFFFF) + setmapflag(di, mDOOR_LEFT); + } + else return; + } + } + + sfx(WAV_DOOR); + markBmap(-1); +} + +void LinkClass::checkswordtap() +{ + if(attack!=wSword || charging<=0 || pushing<8) return; + + int bx=x; + int by=y+8; + + switch(dir) + { + case up: + if(!Up()) return; + + by-=16; + break; + + case down: + if(!Down()) return; + + by+=16; + bx+=8; + break; + + case left: + if(!Left()) return; + + bx-=16; + by+=8; + break; + + case right: + if(!Right()) return; + + bx+=16; + by+=8; + break; + } + + if(!_walkflag(bx,by,0)) return; + + attackclk=SWORDTAPFRAME; + pushing=-8; //16 frames between taps + tapping=true; + + int type = COMBOTYPE(bx,by); + + if(!isCuttableType(type)) + { + bool hollow = (MAPFLAG(bx,by) == mfBOMB || MAPCOMBOFLAG(bx,by) == mfBOMB || + MAPFLAG(bx,by) == mfSBOMB || MAPCOMBOFLAG(bx,by) == mfSBOMB); + + // Layers + for(int i=0; i < 6; i++) + hollow = (hollow || MAPFLAG2(i,bx,by) == mfBOMB || MAPCOMBOFLAG2(i,bx,by) == mfBOMB || + MAPFLAG2(i,bx,by) == mfSBOMB || MAPCOMBOFLAG2(i,bx,by) == mfSBOMB); + + for(int i=0; i<4; i++) + if(tmpscr->door[i]==dBOMB && i==dir) + switch(i) + { + case up: + case down: + if(bx>=112 && bx<144 && (by>=144 || by<=32)) hollow=true; + + break; + + case left: + case right: + if(by>=72 && by<104 && (bx>=224 || bx<=32)) hollow=true; + + break; + } + + sfx(hollow ? WAV_ZN1TAP2 : WAV_ZN1TAP,pan(int(x))); + } + +} + +void LinkClass::fairycircle(int type) +{ + if(fairyclk==0) + { + switch(type) + { + case REFILL_LIFE: + if(didstuff&did_fairy) return; + + didstuff|=did_fairy; + break; + + case REFILL_MAGIC: + if(didstuff&did_magic) return; + + didstuff|=did_magic; + break; + + case REFILL_ALL: + if(didstuff&did_all) return; + + didstuff|=did_all; + } + + refill_what=type; + refill_why=REFILL_FAIRY; + StartRefill(type); + action=freeze; + holdclk=0; + hopclk=0; + } + + ++fairyclk; + + if(refilling!=REFILL_FAIRYDONE) + { + if(!refill()) + refilling=REFILL_FAIRYDONE; + } + + else if(++holdclk>80) + { + reset_swordcharge(); + attackclk=0; + action=none; + fairyclk=0; + holdclk=0; + refill_why = 0; + refilling=REFILL_NONE; + map_bkgsfx(true); + } +} + +int touchcombo(int x,int y) +{ + switch(combobuf[MAPCOMBO(x,y)].type) + { + case cBSGRAVE: + case cGRAVE: + if(MAPFLAG(x,y)||MAPCOMBOFLAG(x,y)) + { + break; + } + + // fall through + case cARMOS: + { + return combobuf[MAPCOMBO(x,y)].type; + } + } + + return 0; +} + +void LinkClass::checktouchblk() +{ + if(toogam) return; + + if(!pushing) + return; + + int tdir = dir; //Bad hack #2. _L_, your welcome to fix this properly. ;) + + if(charging > 0 || spins > 0) //if not I probably will at some point... + { + if(Up()&&Left())tdir = (charging%2)*2; + else if(Up()&&Right())tdir = (charging%2)*3; + else if(Down()&&Left())tdir = 1+(charging%2)*1; + else if(Down()&&Right())tdir = 1+(charging%2)*2; + else + { + if(Up())tdir=0; + else if(Down())tdir=1; + else if(Left())tdir=2; + else if(Right())tdir=3; + } + } + + int tx=0,ty=-1; + + switch(tdir) + { + case up: + if(touchcombo(x,y+(bigHitbox?0:7))) + { + tx=x; + ty=y+(bigHitbox?0:7); + } + else if(touchcombo(x+8,y+(bigHitbox?0:7))) + { + tx=x+8; + ty=y+(bigHitbox?0:7); + } + + break; + + case down: + if(touchcombo(x,y+16)) + { + tx=x; + ty=y+16; + } + else if(touchcombo(x+8,y+16)) + { + tx=x+8; + ty=y+16; + } + + break; + + case left: + if(touchcombo(x-1,y+15)) + { + tx=x-1; + ty=y+15; + } + + break; + + case right: + if(touchcombo(x+16,y+15)) + { + tx=x+16; + ty=y+15; + } + + break; + } + + if(ty>=0) + { + ty&=0xF0; + tx&=0xF0; + int di = ty+(tx>>4); + int gc=0; + int eclk=-14; + + for(int i=0; imainguy) + { + ++gc; + } + } + + if(di<176 && !guygrid[di] && gc<11) + { + if((getAction() != hopping || (tmpscr->flags7&fSIDEVIEW))) + { + guygrid[di]=61; //Note: not 60. + int id2=0; + + switch(combobuf[MAPCOMBO(tx,ty)].type) + { + case cARMOS: //id2=eARMOS; break; + for(int i=0; idata[di]++; + + //fall through + case cGRAVE: + for(int i=0; idid_armos=false; + } + } + } +} + +int LinkClass::nextcombo(int cx, int cy, int cdir) +{ + switch(cdir) + { + case up: + cy-=16; + break; + + case down: + cy+=16; + break; + + case left: + cx-=16; + break; + + case right: + cx+=16; + break; + } + + // off the screen + if(cx<0 || cy<0 || cx>255 || cy>175) + { + int ns = nextscr(cdir); + + if(ns==0xFFFF) return 0; + + // want actual screen index, not game->maps[] index + ns = (ns&127) + (ns>>7)*MAPSCRS; + + switch(cdir) + { + case up: + cy=160; + break; + + case down: + cy=0; + break; + + case left: + cx=240; + break; + + case right: + cx=0; + break; + } + + // from MAPCOMBO() + int cmb = (cy&0xF0)+(cx>>4); + + if(cmb>175) + return 0; + + return TheMaps[ns].data[cmb]; // entire combo code + } + + return MAPCOMBO(cx,cy); +} + +int LinkClass::nextflag(int cx, int cy, int cdir, bool comboflag) +{ + switch(cdir) + { + case up: + cy-=16; + break; + + case down: + cy+=16; + break; + + case left: + cx-=16; + break; + + case right: + cx+=16; + break; + } + + // off the screen + if(cx<0 || cy<0 || cx>255 || cy>175) + { + int ns = nextscr(cdir); + + if(ns==0xFFFF) return 0; + + // want actual screen index, not game->maps[] index + ns = (ns&127) + (ns>>7)*MAPSCRS; + + switch(cdir) + { + case up: + cy=160; + break; + + case down: + cy=0; + break; + + case left: + cx=240; + break; + + case right: + cx=0; + break; + } + + // from MAPCOMBO() + int cmb = (cy&0xF0)+(cx>>4); + + if(cmb>175) + return 0; + + if(!comboflag) + { + return TheMaps[ns].sflag[cmb]; // flag + } + else + { + return combobuf[TheMaps[ns].data[cmb]].flag; // flag + } + } + + if(comboflag) + { + return MAPCOMBOFLAG(cx,cy); + } + + return MAPFLAG(cx,cy); +} + +bool did_secret; + +void LinkClass::checkspecial() +{ + checktouchblk(); + + bool hasmainguy = hasMainGuy(); // calculate it once + + if(!(loaded_enemies && !hasmainguy)) + did_secret=false; + else + { + // after beating enemies + + // if room has traps, guys don't come back + for(int i=0; iitem; + + //if(getmapflag()) + // Item=0; + if(!getmapflag(mITEM) && (tmpscr->hasitem != 0)) + { + if(hasitem==1) + sfx(WAV_CLEARED); + + items.add(new item((fix)tmpscr->itemx, + (tmpscr->flags7&fITEMFALLS && tmpscr->flags7&fSIDEVIEW) ? (fix)-170 : (fix)tmpscr->itemy+1, + (tmpscr->flags7&fITEMFALLS && !(tmpscr->flags7&fSIDEVIEW)) ? (fix)170 : (fix)0, + Item,ipONETIME+ipBIGRANGE+((itemsbuf[Item].family==itype_triforcepiece || + (tmpscr->flags3&fHOLDITEM)) ? ipHOLDUP : 0),0)); + } + + hasitem=0; + } + + // clear enemies and open secret + if(!did_secret && (tmpscr->flags2&fCLEARSECRET)) + { + hidden_entrance(0,true,true,-2); + + if(tmpscr->flags4&fENEMYSCRTPERM && !isdungeon()) + { + if(!(tmpscr->flags5&fTEMPSECRETS)) setmapflag(mSECRET); + } + + sfx(tmpscr->secretsfx); + did_secret=true; + } + } + + // doors + for(int i=0; i<4; i++) + if(tmpscr->door[i]==dSHUTTER) + { + if(opendoors==0 && loaded_enemies) + { + if(!(tmpscr->flags&fSHUTTERS) && !hasmainguy) + opendoors=12; + } + else if(opendoors<0) + ++opendoors; + else if((--opendoors)==0) + openshutters(); + + break; + } + + // set boss flag when boss is gone + if(loaded_enemies && tmpscr->enemyflags&efBOSS && !hasmainguy) + { + game->lvlitems[dlevel]|=liBOSS; + stop_sfx(tmpscr->bosssfx); + } + + if(getmapflag(mCHEST)) // if special stuff done before + { + remove_chests((currscr>=128)?1:0); + } + + if(getmapflag(mLOCKEDCHEST)) // if special stuff done before + { + remove_lockedchests((currscr>=128)?1:0); + } + + if(getmapflag(mBOSSCHEST)) // if special stuff done before + { + remove_bosschests((currscr>=128)?1:0); + } +} + +void LinkClass::checkspecial2(int *ls) +{ + if(get_bit(quest_rules,qr_OLDSTYLEWARP) && !diagonalMovement) + { + if(int(y)&7) + return; + + if(int(x)&7) + return; + } + + if(toogam) return; + + bool didstrig = false; + + for(int i=bigHitbox?0:8; i<16; i+=bigHitbox?15:7) + { + for(int j=0; j<16; j+=15) for(int k=0; k<2; k++) + { + int stype = combobuf[k>0 ? MAPFFCOMBO(x+j,y+i) : MAPCOMBO(x+j,y+i)].type; + + if(stype==cSWARPA) + { + if(tmpscr->flags5&fDIRECTSWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir=dir; + dowarp(0,0); + return; + } + + if(stype==cSWARPB) + { + if(tmpscr->flags5&fDIRECTSWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir=dir; + dowarp(0,1); + return; + } + + if(stype==cSWARPC) + { + if(tmpscr->flags5&fDIRECTSWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir=dir; + dowarp(0,2); + return; + } + + if(stype==cSWARPD) + { + if(tmpscr->flags5&fDIRECTSWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir=dir; + dowarp(0,3); + return; + } + + if(stype==cSWARPR) + { + if(tmpscr->flags5&fDIRECTSWARP) + { + didpit=true; + pitx=x; + pity=y; + } + + sdir=dir; + dowarp(0,rand()%4); + return; + } + + if((stype==cSTRIGNOFLAG || stype==cSTRIGFLAG) && stepsecret!=MAPCOMBO(x+j,y+i)) + { + if(stype==cSTRIGFLAG && !isdungeon()) + { + if(!didstrig) + { + stepsecret = ((int)(y+i)&0xF0)+((int)(x+j)>>4); + + if(!(tmpscr->flags5&fTEMPSECRETS)) + { + setmapflag(mSECRET); + } + + hidden_entrance(0,true,false); + didstrig = true; + } + } + else + { + if(!didstrig) + { + stepsecret = ((int)(y+i)&0xF0)+((int)(x+j)>>4); + hidden_entrance(0,true,true); + didstrig = true; + } + } + } + } + } + + // check if he's standing on a warp he just came out of + if(((int)y>=warpy-8&&(int)y<=warpy+7)&&warpy!=-1) + { + if(((int)x>=warpx-8&&(int)x<=warpx+7)&&warpx!=-1) + { + return; + } + } + + warpy=255; + int tx=x; + int ty=y; + + int flag=0; + int flag2=0; + int flag3=0; + int type=0; + bool water=false; + int index = 0; + + //bool gotpit=false; + + int x1,x2,y1,y2; + x1 = tx; + x2 = tx+15; + y1 = ty; + y2 = ty+15; + + if(diagonalMovement) + { + x1 = tx+4; + x2 = tx+11; + y1 = ty+4; + y2 = ty+11; + } + + int types[4]; + types[0]=types[1]=types[2]=types[3]=-1; + + // + // First, let's find flag1 (combo flag), flag2 (inherent flag) and flag3 (FFC flag)... + // + types[0] = MAPFLAG(x1,y1); + types[1] = MAPFLAG(x1,y2); + types[2] = MAPFLAG(x2,y1); + types[3] = MAPFLAG(x2,y2); + + if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2]) + flag = types[0]; + + // 2.10 compatibility... + else if(int(y)%16==8 && types[0]==types[2] && (types[0]==mfFAIRY || types[0]==mfMAGICFAIRY || types[0]==mfALLFAIRY)) + flag = types[0]; + + + types[0] = MAPCOMBOFLAG(x1,y1); + types[1] = MAPCOMBOFLAG(x1,y2); + types[2] = MAPCOMBOFLAG(x2,y1); + types[3] = MAPCOMBOFLAG(x2,y2); + + if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2]) + flag2 = types[0]; + + types[0] = MAPFFCOMBOFLAG(x1,y1); + types[1] = MAPFFCOMBOFLAG(x1,y2); + types[2] = MAPFFCOMBOFLAG(x2,y1); + types[3] = MAPFFCOMBOFLAG(x2,y2); + + if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2]) + flag3 = types[0]; + + // + // Now, let's check for warp combos... + // + types[0] = COMBOTYPE(x1,y1); + + if(MAPFFCOMBO(x1,y1)) + types[0] = FFCOMBOTYPE(x1,y1); + + types[1] = COMBOTYPE(x1,y2); + + if(MAPFFCOMBO(x1,y2)) + types[1] = FFCOMBOTYPE(x1,y2); + + types[2] = COMBOTYPE(x2,y1); + + if(MAPFFCOMBO(x2,y1)) + types[2] = FFCOMBOTYPE(x2,y1); + + types[3] = COMBOTYPE(x2,y2); + + if(MAPFFCOMBO(x2,y2)) + types[3] = FFCOMBOTYPE(x2,y2); + + // Change B, C and D warps into A, for the comparison below... + for(int i=0; i<4; i++) + { + if(types[i]==cCAVE) + { + index=0; + } + else if(types[i]==cCAVEB) + { + types[i]=cCAVE; + index=1; + } + else if(types[i]==cCAVEC) + { + types[i]=cCAVE; + index=2; + } + else if(types[i]==cCAVED) + { + types[i]=cCAVE; + index=3; + } + + if(types[i]==cPIT) index=0; + else if(types[i]==cPITB) + { + types[i]=cPIT; + index=1; + } + else if(types[i]==cPITC) + { + types[i]=cPIT; + index=2; + } + else if(types[i]==cPITD) + { + types[i]=cPIT; + index=3; + } + else if(types[i]==cPITR) + { + types[i]=cPIT; + index=rand()%4; + } + + if(types[i]==cSTAIR) + { + index=0; + } + else if(types[i]==cSTAIRB) + { + types[i]=cSTAIR; + index=1; + } + else if(types[i]==cSTAIRC) + { + types[i]=cSTAIR; + index=2; + } + else if(types[i]==cSTAIRD) + { + types[i]=cSTAIR; + index=3; + } + else if(types[i]==cSTAIRR) + { + types[i]=cSTAIR; + index=rand()%4; + } + + if(types[i]==cCAVE2) + { + index=0; + } + else if(types[i]==cCAVE2B) + { + types[i]=cCAVE2; + index=1; + } + else if(types[i]==cCAVE2C) + { + types[i]=cCAVE2; + index=2; + } + else if(types[i]==cCAVE2D) + { + types[i]=cCAVE2; + index=3; + } + + if(types[i]==cSWIMWARP) index=0; + else if(types[i]==cSWIMWARPB) + { + types[i]=cSWIMWARP; + index=1; + } + else if(types[i]==cSWIMWARPC) + { + types[i]=cSWIMWARP; + index=2; + } + else if(types[i]==cSWIMWARPD) + { + types[i]=cSWIMWARP; + index=3; + } + + if(types[i]==cDIVEWARP) index=0; + else if(types[i]==cDIVEWARPB) + { + types[i]=cDIVEWARP; + index=1; + } + else if(types[i]==cDIVEWARPC) + { + types[i]=cDIVEWARP; + index=2; + } + else if(types[i]==cDIVEWARPD) + { + types[i]=cDIVEWARP; + index=3; + } + + if(types[i]==cSTEP) ; + else if(types[i]==cSTEPSAME) types[i]=cSTEP; + else if(types[i]==cSTEPALL) types[i]=cSTEP; + } + + // Special case for step combos; otherwise, they act oddly in some cases + if((types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2])||(types[1]==cSTEP&&types[3]==cSTEP)) + { + if(action!=freeze&&(!messageMgr.messageIsActive() || !get_bit(quest_rules,qr_MSGFREEZE))) + type = types[1]; + } + + // + // Now, let's check for Save combos... + // + x1 = tx+4; + x2 = tx+11; + y1 = ty+4; + y2 = ty+11; + + types[0] = COMBOTYPE(x1,y1); + + if(MAPFFCOMBO(x1,y1)) + types[0] = FFCOMBOTYPE(x1,y1); + + types[1] = COMBOTYPE(x1,y2); + + if(MAPFFCOMBO(x1,y2)) + types[1] = FFCOMBOTYPE(x1,y2); + + types[2] = COMBOTYPE(x2,y1); + + if(MAPFFCOMBO(x2,y1)) + types[2] = FFCOMBOTYPE(x2,y1); + + types[3] = COMBOTYPE(x2,y2); + + if(MAPFFCOMBO(x2,y2)) + types[3] = FFCOMBOTYPE(x2,y2); + + bool setsave=false; + + for(int i=0; i<4; i++) + { + if(types[i]==cSAVE) setsave=true; + + if(types[i]==cSAVE2) setsave=true; + } + + if(types[0]==types[1]&&types[2]==types[3]&&types[1]==types[2]) + if(setsave) + { + type = types[0]; + } + + + // + // Now, let's check for Drowning combos... + // + if(get_bit(quest_rules,qr_DROWN)) + { + y1 = ty+9; + y2 = ty+15; + types[0] = COMBOTYPE(x1,y1); + + if(MAPFFCOMBO(x1,y1)) + types[0] = FFCOMBOTYPE(x1,y1); + + types[1] = COMBOTYPE(x1,y2); + + if(MAPFFCOMBO(x1,y2)) + types[1] = FFCOMBOTYPE(x1,y2); + + types[2] = COMBOTYPE(x2,y1); + + if(MAPFFCOMBO(x2,y1)) + types[2] = FFCOMBOTYPE(x2,y1); + + types[3] = COMBOTYPE(x2,y2); + + if(MAPFFCOMBO(x2,y2)) + types[3] = FFCOMBOTYPE(x2,y2); + + if(combo_class_buf[types[0]].water && combo_class_buf[types[1]].water && + combo_class_buf[types[2]].water && combo_class_buf[types[3]].water) + water = true; + } + + // Pits have a bigger 'hitbox' than stairs... + x1 = tx+7; + x2 = tx+8; + y1 = ty+7+(bigHitbox?0:4); + y2 = ty+8+(bigHitbox?0:4); + + types[0] = COMBOTYPE(x1,y1); + + if(MAPFFCOMBO(x1,y1)) + types[0] = FFCOMBOTYPE(x1,y1); + + types[1] = COMBOTYPE(x1,y2); + + if(MAPFFCOMBO(x1,y2)) + types[1] = FFCOMBOTYPE(x1,y2); + + types[2] = COMBOTYPE(x2,y1); + + if(MAPFFCOMBO(x2,y1)) + types[2] = FFCOMBOTYPE(x2,y1); + + types[3] = COMBOTYPE(x2,y2); + + if(MAPFFCOMBO(x2,y2)) + types[3] = FFCOMBOTYPE(x2,y2); + + for(int i=0; i<4; i++) + { + if(types[i]==cPIT) index=0; + else if(types[i]==cPITB) + { + types[i]=cPIT; + index=1; + } + else if(types[i]==cPITC) + { + types[i]=cPIT; + index=2; + } + else if(types[i]==cPITD) + { + types[i]=cPIT; + index=3; + } + } + + if(types[0]==cPIT||types[1]==cPIT||types[2]==cPIT||types[3]==cPIT) + if(action!=freeze&& (!messageMgr.messageIsActive() || !get_bit(quest_rules,qr_MSGFREEZE))) + type=cPIT; + + // + // Time to act on our results for type, flag, flag2 and flag3... + // + if(type==cSAVE&&currscr<128) + *ls=1; + + if(type==cSAVE2&&currscr<128) + *ls=2; + + if(refilling==REFILL_LIFE || flag==mfFAIRY||flag2==mfFAIRY||flag3==mfFAIRY) + { + fairycircle(REFILL_LIFE); + + if(fairyclk!=0) return; + } + + if(refilling==REFILL_MAGIC || flag==mfMAGICFAIRY||flag2==mfMAGICFAIRY||flag3==mfMAGICFAIRY) + { + fairycircle(REFILL_MAGIC); + + if(fairyclk!=0) return; + } + + if(refilling==REFILL_ALL || flag==mfALLFAIRY||flag2==mfALLFAIRY||flag3==mfALLFAIRY) + { + fairycircle(REFILL_ALL); + + if(fairyclk!=0) return; + } + + // Just in case Link was moved off of the fairy flag + if(refilling==REFILL_FAIRYDONE) + { + fairycircle(REFILL_NONE); + + if(fairyclk!=0) return; + } + + if(flag==mfZELDA||flag2==mfZELDA||flag3==mfZELDA || combo_class_buf[type].win_game) + { + saved_Zelda(); + return; + } + + if(z>0 && !(tmpscr->flags2&fAIRCOMBOS)) + return; + + if((type==cTRIGNOFLAG || type==cTRIGFLAG)) + { + if((((ty+8)&0xF0)+((tx+8)>>4))!=stepsecret || get_bit(quest_rules,qr_TRIGGERSREPEAT)) + { + stepsecret = (((ty+8)&0xF0)+((tx+8)>>4)); + + if(type==cTRIGFLAG && !isdungeon()) + { + if(!(tmpscr->flags5&fTEMPSECRETS)) setmapflag(mSECRET); + + hidden_entrance(0,true,false); + } + else + hidden_entrance(0,true,true); + } + } + else if(!didstrig) + { + stepsecret = -1; + } + + // Drown if: + // * Water (obviously walkable), + // * Quest Rule allows it, + // * Not on stepladder, + // * Not jumping, + // * Not hovering, + // * Not rafting, + // * Not swimming, + // * Not swallowed, + // * Not a dried lake. + if(water && get_bit(quest_rules,qr_DROWN) && z==0 && fall>=0 && !ladderx && !hoverclk && action!=rafting && !isSwimming() && !inlikelike && !DRIEDLAKE) + { + if(!current_item(itype_flippers)) + { + Drown(); + } + else + { + attackclk = charging = spins = 0; + action=swimming; + landswim=0; + } + + return; + } + + if(type==cSTEP) + { + if((((ty+8)&0xF0)+((tx+8)>>4))!=stepnext) + { + stepnext=((ty+8)&0xF0)+((tx+8)>>4); + + if(COMBOTYPE(tx+8,ty+8)==cSTEP) + { + tmpscr->data[stepnext]++; + } + + if(COMBOTYPE(tx+8,ty+8)==cSTEPSAME) + { + int stepc = tmpscr->data[stepnext]; + + for(int k=0; k<176; k++) + { + if(tmpscr->data[k]==stepc) + { + tmpscr->data[k]++; + } + } + } + + if(COMBOTYPE(tx+8,ty+8)==cSTEPALL) + { + for(int k=0; k<176; k++) + { + if( + (combobuf[tmpscr->data[k]].type==cSTEP)|| + (combobuf[tmpscr->data[k]].type==cSTEPSAME)|| + (combobuf[tmpscr->data[k]].type==cSTEPALL)|| + (combobuf[tmpscr->data[k]].type==cSTEPCOPY) + ) + { + tmpscr->data[k]++; + } + } + } + } + } + else stepnext = -1; + + detail_int[0]=tx; + detail_int[1]=ty; + + if(!((type==cCAVE || type==cCAVE2) && z==0) && type!=cSTAIR && + type!=cPIT && type!=cSWIMWARP && type!=cRESET && + !(type==cDIVEWARP && diveclk>30)) + { + switch(flag) + { + case mfDIVE_ITEM: + if(diveclk>30 && !getmapflag()) + { + additem(x, y, tmpscr->catchall, + ipONETIME2 + ipBIGRANGE + ipHOLDUP + ipNODRAW); + sfx(tmpscr->secretsfx); + } + + return; + + case mfRAFT: + case mfRAFT_BRANCH: + + // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK) + if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && z==0 && combo_class_buf[type].dock) + { + if(isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true))) + { + reset_swordcharge(); + action=rafting; + sfx(tmpscr->secretsfx); + } + } + + return; + + default: + break; + //return; + } + + switch(flag2) + { + case mfDIVE_ITEM: + if(diveclk>30 && !getmapflag()) + { + additem(x, y, tmpscr->catchall, + ipONETIME2 + ipBIGRANGE + ipHOLDUP + ipNODRAW); + sfx(tmpscr->secretsfx); + } + + return; + + case mfRAFT: + case mfRAFT_BRANCH: + + // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK) + if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && z==0 && combo_class_buf[type].dock) + { + if((isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true)))) + { + reset_swordcharge(); + action=rafting; + sfx(tmpscr->secretsfx); + } + } + + return; + + default: + break; + //return; + } + + switch(flag3) + { + case mfDIVE_ITEM: + if(diveclk>30 && !getmapflag()) + { + additem(x, y, tmpscr->catchall, + ipONETIME2 + ipBIGRANGE + ipHOLDUP + ipNODRAW); + sfx(tmpscr->secretsfx); + } + + return; + + case mfRAFT: + case mfRAFT_BRANCH: + + // if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && type==cOLD_DOCK) + if(current_item(itype_raft) && action!=rafting && action!=swimhit && action!=gothit && z==0 && combo_class_buf[type].dock) + { + if((isRaftFlag(nextflag(tx,ty,dir,false))||isRaftFlag(nextflag(tx,ty,dir,true)))) + { + reset_swordcharge(); + action=rafting; + sfx(tmpscr->secretsfx); + } + } + + return; + + default: + return; + } + } + + int t=(currscr<128)?0:1; + + if((type==cCAVE || type==cCAVE2) && (tmpscr[t].tilewarptype[index]==wtNOWARP)) return; + + //don't do this for canceled warps -DD + //I have no idea why we do this skip, but I'll dutifully propagate it to all cases below... + /*if(tmpscr[t].tilewarptype[index] != wtNOWARP) + { + draw_screen(tmpscr); + advanceframe(true); + }*/ + + bool skippedaframe=false; + + if(type==cCAVE || type==cCAVE2 || type==cSTAIR) + { + // Stop music only if: + // * entering a Guy Cave + // * warping to a DMap whose music is different. + + int tdm = tmpscr[t].tilewarpdmap[index]; + + if(tmpscr[t].tilewarptype[index]<=wtPASS) + { + if((DMaps[currdmap].flags&dmfCAVES) && tmpscr[t].tilewarptype[index] == wtCAVE) + music_stop(); + } + else + { + if(zcmusic!=NULL) + { + if(strcmp(zcmusic->filename, DMaps[tdm].tmusic) != 0 || + zcmusic->track!=DMaps[tdm].tmusictrack) + music_stop(); + } + else if(DMaps[tmpscr->tilewarpdmap[index]].midi != (currmidi-ZC_MIDI_COUNT+4) && + TheMaps[(DMaps[tdm].map*MAPSCRS + (tmpscr[t].tilewarpscr[index] + DMaps[tdm].xoff))].screen_midi != (currmidi-ZC_MIDI_COUNT+4)) + music_stop(); + } + + //stop_sfx(WAV_ER); + bool opening = (tmpscr[t].tilewarptype[index]<=wtPASS && !(DMaps[currdmap].flags&dmfCAVES && tmpscr[t].tilewarptype[index]==wtCAVE) + ? false : COOLSCROLL); + + draw_screen(tmpscr); + advanceframe(true); + + skippedaframe=true; + + if(type==cCAVE2) walkup(opening, true); + else if(type==cCAVE) walkdown(opening, false); + } + + if(type==cPIT) + { + didpit=true; + pitx=x; + pity=y; + } + + if(DMaps[currdmap].flags&dmf3STAIR && (currscr==129 || !(DMaps[currdmap].flags&dmfGUYCAVES)) + && tmpscr[specialcave > 0 && DMaps[currdmap].flags&dmfGUYCAVES ? 1:0].room==rWARP && type==cSTAIR) + { + if(!skippedaframe) + { + draw_screen(tmpscr); + advanceframe(true); + } + + // "take any road you want" + int dw = x<112 ? 1 : (x>136 ? 3 : 2); + int code = WARPCODE(currdmap,homescr,dw); + + if(code>-1) + { + currdmap = code>>8; + dlevel = DMaps[currdmap].level; + currmap = DMaps[currdmap].map; + homescr = (code&0xFF) + DMaps[currdmap].xoff; + init_dmap(); + + if(!isdungeon()) + setmapflag(mSECRET); + } + + if(specialcave==STAIRCAVE) exitcave(); + + return; + } + + if(type==cRESET) + { + if(!skippedaframe) + { + draw_screen(tmpscr); + advanceframe(true); + } + + if(!(tmpscr->noreset&mSECRET)) unsetmapflag(mSECRET); + + if(!(tmpscr->noreset&mITEM)) unsetmapflag(mITEM); + + if(!(tmpscr->noreset&mBELOW)) unsetmapflag(mBELOW); + + if(!(tmpscr->noreset&mNEVERRET)) unsetmapflag(mNEVERRET); + + if(!(tmpscr->noreset&mCHEST)) unsetmapflag(mCHEST); + + if(!(tmpscr->noreset&mLOCKEDCHEST)) unsetmapflag(mLOCKEDCHEST); + + if(!(tmpscr->noreset&mBOSSCHEST)) unsetmapflag(mBOSSCHEST); + + if(!(tmpscr->noreset&mLOCKBLOCK)) unsetmapflag(mLOCKBLOCK); + + if(!(tmpscr->noreset&mBOSSLOCKBLOCK)) unsetmapflag(mBOSSLOCKBLOCK); + + if(isdungeon()) + { + if(!(tmpscr->noreset&mDOOR_LEFT)) unsetmapflag(mDOOR_LEFT); + + if(!(tmpscr->noreset&mDOOR_RIGHT)) unsetmapflag(mDOOR_RIGHT); + + if(!(tmpscr->noreset&mDOOR_DOWN)) unsetmapflag(mDOOR_DOWN); + + if(!(tmpscr->noreset&mDOOR_UP)) unsetmapflag(mDOOR_UP); + } + + didpit=true; + pitx=x; + pity=y; + sdir=dir; + dowarp(4,0); + } + else + { + if(!skippedaframe && (tmpscr[t].tilewarptype[index]!=wtNOWARP)) + { + draw_screen(tmpscr); + advanceframe(true); + } + + sdir = dir; + dowarp(0,index); + } +} + +int selectWlevel(int d) +{ + if(TriforceCount()==0) + return 0; + + word l = game->get_wlevel(); + + do + { + if(d==0 && (game->lvlitems[l+1] & liTRIFORCE)) + break; + else if(d<0) + l = (l==0) ? 7 : l-1; + else + l = (l==7) ? 0 : l+1; + } + while(!(game->lvlitems[l+1] & liTRIFORCE)); + + game->set_wlevel(l); + return l; +} + +void LinkClass::setEntryPoints(int x2, int y2) +{ + entry_x=warpx=x2; + entry_y=warpy=y2; +} + +const char *roomtype_string[rMAX] = +{ + "(None)","Special Item","Pay for Info","Secret Money","Gamble", + "Door Repair","Red Potion or Heart Container","Feed the Goriya","Level 9 Entrance", + "Potion Shop","Shop","More Bombs","Leave Money or Life","10 Rupees", + "3-Stair Warp","Ganon","Zelda", "-", "1/2 Magic Upgrade", "Learn Slash", "More Arrows","Take One Item" +}; + +bool LinkClass::dowarp(int type, int index) +{ + if(index<0) + return false; + + word wdmap=0; + byte wscr=0,wtype=0,t=0; + bool overlay=false; + t=(currscr<128)?0:1; + int wrindex = 0; + //int lastent_org = lastentrance; + //int lastdmap_org = lastentrance_dmap; + bool wasSideview = (tmpscr[t].flags7 & fSIDEVIEW) > 0 ? true :false; + + // Drawing commands probably shouldn't carry over... + script_drawing_commands.Clear(); + + switch(type) + { + case 0: // tile warp + wtype = tmpscr[t].tilewarptype[index]; + wdmap = tmpscr[t].tilewarpdmap[index]; + wscr = tmpscr[t].tilewarpscr[index]; + overlay = get_bit(&tmpscr[t].tilewarpoverlayflags,index)?1:0; + wrindex=(tmpscr->warpreturnc>>(index*2))&3; + break; + + case 1: // side warp + wtype = tmpscr[t].sidewarptype[index]; + wdmap = tmpscr[t].sidewarpdmap[index]; + wscr = tmpscr[t].sidewarpscr[index]; + overlay = get_bit(&tmpscr[t].sidewarpoverlayflags,index)?1:0; + wrindex=(tmpscr->warpreturnc>>(8+(index*2)))&3; + break; + + case 2: // whistle warp + { + wtype = wtWHISTLE; + int wind = whistleitem>-1 ? itemsbuf[whistleitem].misc2 : 8; + int level=0; + + if(blowcnt==0) + level = selectWlevel(0); + else + { + for(int i=0; i QMisc.warp[wind].size) + { + level %= QMisc.warp[wind].size; + game->set_wlevel(level); + } + + wdmap = QMisc.warp[wind].dmap[level]; + wscr = QMisc.warp[wind].scr[level]; + } + break; + + case 3: + wtype = wtIWARP; + wdmap = cheat_goto_dmap; + wscr = cheat_goto_screen; + break; + + case 4: + wtype = wtIWARP; + wdmap = currdmap; + wscr = homescr-DMaps[currdmap].xoff; + break; + } + + bool intradmap = (wdmap == currdmap); + rehydratelake(type!=wtSCROLL); + + switch(wtype) + { + case wtCAVE: + { + // cave/item room + ALLOFF(); + homescr=currscr; + currscr=0x80; + + if(DMaps[currdmap].flags&dmfCAVES) // cave + { + music_stop(); + kill_sfx(); + + if(tmpscr->room==rWARP) + { + currscr=0x81; + specialcave = STAIRCAVE; + } + else specialcave = GUYCAVE; + + //lighting(2,dir); + lighting(false, true); + loadlvlpal(10); + bool b2 = COOLSCROLL&& + ((combobuf[MAPCOMBO(x,y-16)].type==cCAVE)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2)|| + (combobuf[MAPCOMBO(x,y-16)].type==cCAVEB)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2B)|| + (combobuf[MAPCOMBO(x,y-16)].type==cCAVEC)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2C)|| + (combobuf[MAPCOMBO(x,y-16)].type==cCAVED)||(combobuf[MAPCOMBO(x,y-16)].type==cCAVE2D)); + blackscr(30,b2?false:true); + loadscr(0,wdmap,currscr,up,false); + loadscr(1,wdmap,homescr,up,false); + //preloaded freeform combos + ffscript_engine(true); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + dir=up; + x=112; + y=160; + + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + reset_hookshot(); + stepforward(diagonalMovement?5:6, false); + } + else // item room + { + specialcave = ITEMCELLAR; + map_bkgsfx(false); + draw_screen(tmpscr,false); + + //unless the room is already dark, fade to black + if(!darkroom) + { + darkroom = true; + fade(DMaps[currdmap].color,true,false); + } + + blackscr(30,true); + loadscr(0,wdmap,currscr,down,false); + loadscr(1,wdmap,homescr,-1,false); + dontdraw=true; + draw_screen(tmpscr); + fade(11,true,true); + darkroom = false; + dir=down; + x=48; + y=0; + + // is this didpit check necessary? + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + reset_hookshot(); + lighting(false, true); + dontdraw=false; + stepforward(diagonalMovement?16:18, false); + } + + break; + } + + case wtPASS: // passageway + { + map_bkgsfx(false); + ALLOFF(); + homescr=currscr; + currscr=0x81; + specialcave = PASSAGEWAY; + byte warpscr2 = wscr + DMaps[wdmap].xoff; + draw_screen(tmpscr,false); + + if(!darkroom) + fade(DMaps[currdmap].color,true,false); + + darkroom=true; + blackscr(30,true); + loadscr(0,wdmap,currscr,down,false); + loadscr(1,wdmap,homescr,-1,false); + //preloaded freeform combos + ffscript_engine(true); + dontdraw=true; + draw_screen(tmpscr); + lighting(false, true); + dir=down; + x=48; + + if((homescr&15) > (warpscr2&15)) + { + x=192; + } + + if((homescr&15) == (warpscr2&15)) + { + if((currscr>>4) > (warpscr2>>4)) + { + x=192; + } + } + + // is this didpit check necessary? + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + setEntryPoints(x,y=0); + reset_hookshot(); + dontdraw=false; + stepforward(diagonalMovement?16:18, false); + newscr_clk=frame; + activated_timed_warp=false; + stepoutindex=index; + stepoutscr = warpscr2; + stepoutdmap = wdmap; + stepoutwr=wrindex; + } + break; + + case wtEXIT: // entrance/exit + { + ALLOFF(); + music_stop(); + kill_sfx(); + blackscr(30,false); + currdmap = wdmap; + dlevel=DMaps[currdmap].level; + currmap=DMaps[currdmap].map; + init_dmap(); + update_subscreens(wdmap); + loadfullpal(); + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + //lastentrance_dmap = currdmap; + homescr = currscr = wscr + DMaps[currdmap].xoff; + loadscr(0,currdmap,currscr,-1,overlay); + + if(tmpscr->flags&fDARK) + { + if(get_bit(quest_rules,qr_FADE)) + { + interpolatedfade(); + } + else + { + loadfadepal((DMaps[currdmap].color)*pdLEVEL+poFADE3); + } + + darkroom=naturaldark=true; + } + else + { + darkroom=naturaldark=false; + } + + int wrx,wry; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + wrx=tmpscr->warpreturnx[0]; + wry=tmpscr->warpreturny[0]; + } + else + { + wrx=tmpscr->warparrivalx; + wry=tmpscr->warparrivaly; + } + + if(((wrx>0||wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT)))&&(!(tmpscr->flags6&fNOCONTINUEHERE))) + { + if(dlevel) + { + lastentrance = currscr; + } + else + { + lastentrance = DMaps[currdmap].cont + DMaps[currdmap].xoff; + } + + lastentrance_dmap = wdmap; + } + + if(dlevel) + { + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + x=tmpscr->warpreturnx[wrindex]; + y=tmpscr->warpreturny[wrindex]; + } + else + { + x=tmpscr->warparrivalx; + y=tmpscr->warparrivaly; + } + } + else + { + x=tmpscr->warpreturnx[wrindex]; + y=tmpscr->warpreturny[wrindex]; + } + + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + dir=down; + + if(x==0) dir=right; + + if(x==240) dir=left; + + if(y==0) dir=down; + + if(y==160) dir=up; + + if(dlevel) + { + // reset enemy kill counts + for(int i=0; i<128; i++) + { + game->guys[(currmap*MAPSCRSNORMAL)+i] = 0; + game->maps[(currmap*MAPSCRSNORMAL)+i] &= ~mTMPNORET; + } + } + + markBmap(dir^1); + //preloaded freeform combos + ffscript_engine(true); + reset_hookshot(); + + if(isdungeon()) + { + openscreen(); + stepforward(diagonalMovement?11:12, false); + } + else + { + if(!COOLSCROLL) + openscreen(); + + int type1 = combobuf[MAPCOMBO(x,y-16)].type; // Old-style blue square placement + int type2 = combobuf[MAPCOMBO(x,y)].type; + int type3 = combobuf[MAPCOMBO(x,y+16)].type; // More old-style blue square placement + + if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED)) + { + reset_pal_cycling(); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + walkup(COOLSCROLL, false); + } + else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D)) + { + reset_pal_cycling(); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + walkdown(COOLSCROLL, true); + } + else if(COOLSCROLL) + { + openscreen(); + } + } + + show_subscreen_life=true; + show_subscreen_numbers=true; + playLevelMusic(); + currcset=DMaps[currdmap].color; + showCurrentDMapIntro(); + setEntryPoints(x,y); + + for(int i=0; i<6; i++) + visited[i]=-1; + + break; + } + + case wtSCROLL: // scrolling warp + { + int c = DMaps[currdmap].color; + currmap = DMaps[wdmap].map; + + // fix the scrolling direction, if it was a tile or instant warp + if(type==0 || type>=3) + { + sdir = dir; + } + + scrollscr(sdir, wscr+DMaps[wdmap].xoff, wdmap); + reset_hookshot(); + + if(!intradmap) + { + currdmap = wdmap; + dlevel = DMaps[currdmap].level; + homescr = currscr = wscr + DMaps[wdmap].xoff; + init_dmap(); + + int wrx,wry; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + wrx=tmpscr->warpreturnx[0]; + wry=tmpscr->warpreturny[0]; + } + else + { + wrx=tmpscr->warparrivalx; + wry=tmpscr->warparrivaly; + } + + if(((wrx>0||wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT)))&&(!get_bit(quest_rules,qr_NOSCROLLCONTINUE))&&(!(tmpscr->flags6&fNOCONTINUEHERE))) + { + if(dlevel) + { + lastentrance = currscr; + } + else + { + lastentrance = DMaps[currdmap].cont + DMaps[currdmap].xoff; + } + + lastentrance_dmap = wdmap; + } + } + + if(DMaps[currdmap].color != c) + { + lighting(false, true); + } + + playLevelMusic(); + currcset=DMaps[currdmap].color; + showCurrentDMapIntro(); + } + break; + + case wtWHISTLE: // whistle warp + { + currmap = DMaps[wdmap].map; + scrollscr(index, wscr+DMaps[wdmap].xoff, wdmap); + reset_hookshot(); + currdmap=wdmap; + dlevel=DMaps[currdmap].level; + lighting(false, true); + init_dmap(); + + playLevelMusic(); + currcset=DMaps[currdmap].color; + showCurrentDMapIntro(); + action=inwind; + int wry; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + wry=tmpscr->warpreturny[0]; + else wry=tmpscr->warparrivaly; + + int wrx; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + wrx=tmpscr->warpreturnx[0]; + else wrx=tmpscr->warparrivalx; + + Lwpns.add(new weapon((fix)(index==left?240:index==right?0:wrx),(fix)(index==down?0:index==up?160:wry), + (fix)0,wWind,1,0,index,whistleitem,getUID())); + whirlwind=255; + whistleitem=-1; + } + break; + + case wtIWARP: + case wtIWARPBLK: + case wtIWARPOPEN: + case wtIWARPZAP: + case wtIWARPWAVE: // insta-warps + { + //for determining whether to exit cave + int type1 = combobuf[MAPCOMBO(x,y-16)].type; + int type2 = combobuf[MAPCOMBO(x,y)].type; + int type3 = combobuf[MAPCOMBO(x,y+16)].type; + + bool cavewarp = ((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED) + ||(type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D)); + + if(!(tmpscr->flags3&fIWARPFULLSCREEN)) + { + //ALLOFF kills the action, but we want to preserve Link's action if he's swimming or diving -DD + bool wasswimming = (action == swimming); + byte olddiveclk = diveclk; + ALLOFF(); + + if(wasswimming) + { + action = swimming; + diveclk = olddiveclk; + } + + kill_sfx(); + } + + if(wtype==wtIWARPZAP) + { + zapout(); + } + else if(wtype==wtIWARPWAVE) + { + //only draw Link if he's not in a cave -DD + wavyout(!cavewarp); + } + else if(wtype!=wtIWARP) + { + bool b2 = COOLSCROLL&&cavewarp; + blackscr(30,b2?false:true); + } + + int c = DMaps[currdmap].color; + currdmap = wdmap; + dlevel = DMaps[currdmap].level; + currmap = DMaps[currdmap].map; + init_dmap(); + update_subscreens(wdmap); + + ringcolor(false); + + if(DMaps[currdmap].color != c) + loadlvlpal(DMaps[currdmap].color); + + homescr = currscr = wscr + DMaps[currdmap].xoff; + + lightingInstant(); // Also sets naturaldark + + loadscr(0,currdmap,currscr,-1,overlay); + + x = tmpscr->warpreturnx[wrindex]; + y = tmpscr->warpreturny[wrindex]; + + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + type1 = combobuf[MAPCOMBO(x,y-16)].type; + type2 = combobuf[MAPCOMBO(x,y)].type; + type3 = combobuf[MAPCOMBO(x,y+16)].type; + + if(x==0) dir=right; + + if(x==240) dir=left; + + if(y==0) dir=down; + + if(y==160) dir=up; + + markBmap(dir^1); + + if(iswater(MAPCOMBO(x,y+8)) && _walkflag(x,y+8,0) && current_item(itype_flippers)) + { + hopclk=0xFF; + attackclk = charging = spins = 0; + action=swimming; + } + else + action = none; + + //preloaded freeform combos + ffscript_engine(true); + + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + + if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED)) + { + reset_pal_cycling(); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + walkup(COOLSCROLL, false); + } + else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D)) + { + reset_pal_cycling(); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + walkdown(COOLSCROLL, true); + } + else if(wtype==wtIWARPZAP) + { + zapin(); + } + else if(wtype==wtIWARPWAVE) + { + wavyin(); + } + else if(wtype==wtIWARPOPEN) + { + openscreen(); + } + + show_subscreen_life=true; + show_subscreen_numbers=true; + playLevelMusic(); + currcset=DMaps[currdmap].color; + showCurrentDMapIntro(); + setEntryPoints(x,y); + } + break; + + + case wtNOWARP: + default: + didpit=false; + update_subscreens(); + return false; + } + + // Stop Link from drowning! + if(action==drowning) + { + drownclk=0; + action=none; + } + + // But keep him swimming if he ought to be! + if(action!=rafting && iswater(MAPCOMBO(x,y+8)) && (_walkflag(x,y+8,0) || get_bit(quest_rules,qr_DROWN)) + && (current_item(itype_flippers)) && (action!=inwind)) + { + hopclk=0xFF; + action=swimming; + } + + newscr_clk=frame; + activated_timed_warp=false; + eat_buttons(); + + if(wtype!=wtIWARP) + attackclk=0; + + didstuff=0; + map_bkgsfx(true); + loadside=dir^1; + whistleclk=-1; + + if(z>0 && (tmpscr->flags7)&fSIDEVIEW) + { + y-=z; + z=0; + } + else if(!((tmpscr->flags7)&fSIDEVIEW)) + { + fall=0; + } + + // If warping between top-down and sideview screens, + // fix enemies that are carried over by Full Screen Warp + const bool tmpscr_is_sideview = (tmpscr->flags7 & fSIDEVIEW) > 0 ? true : false; + + if(!wasSideview && tmpscr_is_sideview) + { + for(int i=0; iz > 0) + { + guys.spr(i)->y -= guys.spr(i)->z; + guys.spr(i)->z = 0; + } + + if(((enemy*)guys.spr(i))->family!=eeTRAP && ((enemy*)guys.spr(i))->family!=eeSPINTILE) + guys.spr(i)->yofs += 2; + } + } + else if(wasSideview && !tmpscr_is_sideview) + { + for(int i=0; ifamily!=eeTRAP && ((enemy*)guys.spr(i))->family!=eeSPINTILE) + guys.spr(i)->yofs -= 2; + } + } + + if((DMaps[currdmap].type&dmfCONTINUE) || (currdmap==0)) + { + if(dlevel) + { + int wrx,wry; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + wrx=tmpscr->warpreturnx[0]; + wry=tmpscr->warpreturny[0]; + } + else + { + wrx=tmpscr->warparrivalx; + wry=tmpscr->warparrivaly; + } + + if((wtype == wtEXIT) + || (((wtype == wtSCROLL) && !intradmap) && ((wrx>0 || wry>0)||(get_bit(quest_rules,qr_WARPSIGNOREARRIVALPOINT))))) + { + if(!(wtype==wtSCROLL)||!(get_bit(quest_rules,qr_NOSCROLLCONTINUE))) + { + game->set_continue_scrn(homescr); + //Z_message("continue_scrn = %02X e/e\n",game->get_continue_scrn()); + } + else if(currdmap != game->get_continue_dmap()) + { + game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff); + } + } + else + { + if(currdmap != game->get_continue_dmap()) + { + game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff); + //Z_message("continue_scrn = %02X dlevel\n",game->get_continue_scrn()); + } + } + } + else + { + game->set_continue_scrn(DMaps[currdmap].cont + DMaps[currdmap].xoff); + //Z_message("continue_scrn = %02X\n !dlevel\n",game->get_continue_scrn()); + } + + game->set_continue_dmap(currdmap); + lastentrance_dmap = currdmap; + lastentrance = game->get_continue_scrn(); + //Z_message("continue_map = %d\n",game->get_continue_dmap()); + } + + if(tmpscr->flags4&fAUTOSAVE) + { + save_game(true,0); + } + + if(tmpscr->flags6&fCONTINUEHERE) + { + lastentrance_dmap = currdmap; + lastentrance = homescr; + } + + update_subscreens(); + verifyBothWeapons(); + + if(wtype==wtCAVE) + { + if(DMaps[currdmap].flags&dmfGUYCAVES) + Z_eventlog("Entered %s containing %s.\n",DMaps[currdmap].flags&dmfCAVES ? "Cave" : "Item Cellar", + roomtype_string[tmpscr[1].room]); + else + Z_eventlog("Entered %s.",DMaps[currdmap].flags&dmfCAVES ? "Cave" : "Item Cellar"); + } + else Z_eventlog("Warped to DMap %d: %s, screen %d, via %s.\n", currdmap, DMaps[currdmap].name,currscr, + wtype==wtPASS ? "Passageway" : + wtype==wtEXIT ? "Entrance/Exit" : + wtype==wtSCROLL ? "Scrolling Warp" : + wtype==wtWHISTLE ? "Whistle Warp" : + "Insta-Warp"); + + eventlog_mapflags(); + return true; +} + +void LinkClass::exitcave() +{ + //stop_sfx(WAV_ER); + currscr=homescr; + loadscr(0,currdmap,currscr,255,false); // bogus direction + x = tmpscr->warpreturnx[0]; + y = tmpscr->warpreturny[0]; + + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + if(x+y == 0) + x = y = 80; + + int type1 = combobuf[MAPCOMBO(x,y-16)].type; + int type2 = combobuf[MAPCOMBO(x,y)].type; + int type3 = combobuf[MAPCOMBO(x,y+16)].type; + bool b = COOLSCROLL && + ((type1==cCAVE) || (type1>=cCAVEB && type1<=cCAVED) || + (type2==cCAVE) || (type2>=cCAVEB && type2<=cCAVED) || + (type3==cCAVE2) || (type3>=cCAVE2B && type3<=cCAVE2D) || + (type2==cCAVE2) || (type2>=cCAVE2B && type2<=cCAVE2D)); + ALLOFF(); + blackscr(30,b?false:true); + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + lighting(false, true); + music_stop(); + kill_sfx(); + putscr(scrollbuf,0,0,tmpscr); + putscrdoors(scrollbuf,0,0,tmpscr); + + if((type1==cCAVE)||(type1>=cCAVEB && type1<=cCAVED) || (type2==cCAVE)||(type2>=cCAVEB && type2<=cCAVED)) + { + walkup(COOLSCROLL, false); + } + else if((type3==cCAVE2)||(type3>=cCAVE2B && type3<=cCAVE2D) || (type2==cCAVE2)||(type2>=cCAVE2B && type2<=cCAVE2D)) + { + walkdown(COOLSCROLL, true); + } + + show_subscreen_life=true; + show_subscreen_numbers=true; + playLevelMusic(); + currcset=DMaps[currdmap].color; + showCurrentDMapIntro(); + newscr_clk=frame; + activated_timed_warp=false; + dir=down; + setEntryPoints(x,y); + eat_buttons(); + didstuff=0; + map_bkgsfx(true); + loadside=dir^1; +} + + +void LinkClass::stepforward(int steps, bool adjust) +{ + int tx=x; //temp x + int ty=y; //temp y + int tstep=0; //temp single step distance + int s=0; //calculated step distance for all steps + z3step=2; + int sh=shiftdir; + shiftdir=-1; + + for(int i=steps; i>0; --i) + { + if(diagonalMovement) + { + tstep=z3step; + z3step=(z3step%2)+1; + } + else + { + tstep=lsteps[int((dir=0) + { + if(diagonalMovement) + { + if((dir152) + y-=s; + else + y+=s; + + break; + + case left: + if(x<8) + x+=s; + else + x-=s; + + break; + + case right: + if(x>=232) + x-=s; + else + x+=s; + + break; + } + } + + draw_screen(tmpscr); + advanceframe(true); + + if(Quit) + return; + } + + setEntryPoints(x,y); + draw_screen(tmpscr); + eat_buttons(); + shiftdir=sh; +} + +void LinkClass::walkdown(bool opening, bool cave2) //exiting cave +{ + // Fix Link's position to the grid + y=int(y)&0xF0; + z=fall=0; + + if(cave2) + { + dir=down; + int type = combobuf[MAPCOMBO(x,y)].type; + + // Wait, isn't this why cave2 is true in the first place? + if((type==cCAVE2)||(type>=cCAVE2B && type<=cCAVE2D)) + y-=16; + + if(opening) + beginScreenWipeIn(x+8, y+8+playing_field_offset+16); + } + else + { + if(opening) + beginScreenWipeOut(x+8, y+8+playing_field_offset); + } + + hclk=0; + stop_item_sfx(itype_brang); + sfx(WAV_STAIRS,pan(int(x))); + clk=0; + action=cave2 ? climbcovertop : climbcoverbottom; + attack=wNone; + attackid=-1; + reset_swordcharge(); + climb_cover_x=int(x)&0xF0; + climb_cover_y=(int(y)&0xF0)+(cave2 ? 0 : 16); + + guys.clear(); + chainlinks.clear(); + Lwpns.clear(); + Ewpns.clear(); + items.clear(); + + for(int i=0; i<64; i++) + { + linkstep(); + + if(zinit.linkanimationstyle==las_zelda3 || zinit.linkanimationstyle==las_zelda3slow) + link_count=(link_count+1)%16; + + if((i&3)==3) + ++y; + + draw_screen(tmpscr); + advanceframe(true); + + if(Quit) + break; + } + + action=none; +} + +void LinkClass::walkup(bool opening, bool cave2) //exiting cave +{ + // Fix Link's position to the grid + y=int(y)&0xF0; + z=fall=0; + + if(cave2) + { + dir=up; + if(opening) + beginScreenWipeOut(x+8, y+8+playing_field_offset); + } + else + { + int type = combobuf[MAPCOMBO(x,y)].type; + + // ... + if((type==cCAVE)||(type>=cCAVEB && type<=cCAVED)) + y+=16; + + if(opening) + beginScreenWipeIn(x+8, y+8+playing_field_offset-16); + } + + hclk=0; + stop_item_sfx(itype_brang); + sfx(WAV_STAIRS,pan(int(x))); + clk=0; + // int cmby=int(y)&0xF0; + action=cave2 ? climbcovertop : climbcoverbottom; + attack=wNone; + attackid=-1; + reset_swordcharge(); + climb_cover_x=int(x)&0xF0; + climb_cover_y=(int(y)&0xF0)-(cave2 ? 16 : 0); + + guys.clear(); + chainlinks.clear(); + Lwpns.clear(); + Ewpns.clear(); + items.clear(); + + for(int i=0; i<64; i++) + { + linkstep(); + + if(zinit.linkanimationstyle==las_zelda3 || zinit.linkanimationstyle==las_zelda3slow) + link_count=(link_count+1)%16; + + if((i&3)==0) + --y; + + draw_screen(tmpscr); + advanceframe(true); + + if(Quit) + break; + } + + map_bkgsfx(true); + loadside=dir^1; + action=none; +} + +void LinkClass::stepout() // Step out of item cellars and passageways +{ + int sc = specialcave; // This gets erased by ALLOFF() + ALLOFF(); + //stop_sfx(WAV_ER); + map_bkgsfx(false); + draw_screen(tmpscr,false); + fade(sc>=GUYCAVE?10:11,true,false); + blackscr(30,true); + ringcolor(false); + + if(sc==PASSAGEWAY && abs(x-warpx)>16) // How did Link leave the passageway? + { + currdmap=stepoutdmap; + currmap=DMaps[currdmap].map; + dlevel=DMaps[currdmap].level; + + //we might have just left a passage, so be sure to update the CSet record -DD + currcset=DMaps[currdmap].color; + + init_dmap(); + homescr=stepoutscr; + } + + currscr=homescr; + loadscr(0,currdmap,currscr,255,false); // bogus direction + draw_screen(tmpscr,false); + + if((tmpscr->flags&fDARK) == 0) + { + darkroom = naturaldark = false; + fade(DMaps[currdmap].color,true,true); + } + else + { + darkroom = naturaldark = true; + + if(get_bit(quest_rules,qr_FADE)) + { + interpolatedfade(); + } + else + { + loadfadepal((DMaps[currdmap].color)*pdLEVEL+poFADE3); + } + } + + x = tmpscr->warpreturnx[stepoutwr]; + y = tmpscr->warpreturny[stepoutwr]; + + if(didpit) + { + didpit=false; + x=pitx; + y=pity; + } + + if(x+y == 0) + x = y = 80; + + dir=down; + + setEntryPoints(x,y); + + // Let's use the 'exit cave' animation if we entered this cellar via a cave combo. + int type = combobuf[MAPCOMBO(tmpscr->warpreturnx[stepoutwr],tmpscr->warpreturny[stepoutwr])].type; + + if((type==cCAVE)||(type>=cCAVEB && type<=cCAVED)) + { + walkup(false, false); + } + else if((type==cCAVE2)||(type>=cCAVE2B && type<=cCAVE2D)) + { + walkdown(false, true); + } + + newscr_clk=frame; + activated_timed_warp=false; + didstuff=0; + eat_buttons(); + markBmap(-1); + map_bkgsfx(true); + + if(get_bit(quest_rules, qr_CAVEEXITNOSTOPMUSIC) == 0) + { + music_stop(); + playLevelMusic(); + } + + loadside=dir^1; +} + +bool LinkClass::nextcombo_wf(int d2) +{ + if(toogam || action!=swimming || hopclk==0) + return false; + + // assumes Link is about to scroll screens + + int ns = nextscr(d2); + + if(ns==0xFFFF) + return false; + + // want actual screen index, not game->maps[] index + ns = (ns&127) + (ns>>7)*MAPSCRS; + + int cx = x; + int cy = y; + + switch(d2) + { + case up: + cy=160; + break; + + case down: + cy=0; + break; + + case left: + cx=240; + break; + + case right: + cx=0; + break; + } + + // check lower half of combo + cy += 8; + + // from MAPCOMBO() + int cmb = (cy&0xF0)+(cx>>4); + + if(cmb>175) + return true; + + newcombo c = combobuf[TheMaps[ns].data[cmb]]; + bool dried = iswater_type(c.type) && DRIEDLAKE; + bool swim = iswater_type(c.type) && (current_item(itype_flippers)) && !dried; + int b=1; + + if(cx&8) b<<=2; + + if(cy&8) b<<=1; + + if((c.walk&b) && !dried && !swim) + return true; + + // next block (i.e. cnt==2) + if(!(cx&8)) + { + b<<=2; + } + else + { + c = combobuf[TheMaps[ns].data[++cmb]]; + dried = iswater_type(c.type) && DRIEDLAKE; + swim = iswater_type(c.type) && (current_item(itype_flippers)) && !dried; + b=1; + + if(cy&8) + { + b<<=1; + } + } + + return (c.walk&b) ? !dried && !swim : false; +} + +bool LinkClass::nextcombo_solid(int d2) +{ + if(toogam || currscr>=128) + return false; + + // assumes Link is about to scroll screens + + int ns = nextscr(d2); + + if(ns==0xFFFF) + return false; + + // want actual screen index, not game->maps[] index + ns = (ns&127) + (ns>>7)*MAPSCRS; + + int cx = x; + int cy = y; + + switch(d2) + { + case up: + cy=160; + break; + + case down: + cy=0; + break; + + case left: + cx=240; + break; + + case right: + cx=0; + break; + } + + if(d2==up) cy += 8; + + if(d2==left||d2==right) cy+=bigHitbox?0:8; + + // from MAPCOMBO() + + for(int i=0; i<=((bigHitbox&&!(d2==up||d2==down))?((cy&7)?2:1):((cy&7)?1:0)); cy+=8,i++) + { + int cmb = (cy&0xF0)+(cx>>4); + + if(cmb>175) + { + return true; + } + + newcombo c = combobuf[TheMaps[ns].data[cmb]]; + bool dried = iswater_type(c.type) && DRIEDLAKE; + bool swim = iswater_type(c.type) && (current_item(itype_flippers) || action==rafting) && !dried; + int b=1; + + if(cx&8) b<<=2; + + if(cy&8) b<<=1; + + if((c.walk&b) && !dried && !swim) + { + return true; + } + +#if 0 + + // next block (i.e. cnt==2) + if(!(cx&8)) + { + b<<=2; + } + else + { + c = combobuf[TheMaps[ns].data[++cmb]]; + dried = iswater_type(c.type) && DRIEDLAKE; + swim = iswater_type(c.type) && (current_item(itype_flippers)); + b=1; + + if(cy&8) + { + b<<=1; + } + } + + if((c.walk&b) && !dried && !swim) + { + return true; + } + + cx+=8; + + if(cx&7) + { + if(!(cx&8)) + { + b<<=2; + } + else + { + c = combobuf[TheMaps[ns].data[++cmb]]; + dried = iswater_type(c.type) && DRIEDLAKE; + swim = iswater_type(c.type) && (current_item(itype_flippers) || action==rafting); + b=1; + + if(cy&8) + { + b<<=1; + } + } + + if((c.walk&b) && !dried && !swim) + return true; + } + +#endif + } + + return false; +} + +void LinkClass::checkscroll() +{ + //DO NOT scroll if Link is vibrating due to Farore's Wind effect -DD + if(action == casting) + return; + + if(toogam) + { + if(x<0 && (currscr&15)==0) x=0; + + if(y<0 && currscr<16) y=0; + + if(x>240 && (currscr&15)==15) x=240; + + if(y>160 && currscr>=112) y=160; + } + + if(y<0) + { + bool doit=true; + y=0; + + if(nextcombo_wf(up)) + doit=false; + + if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling && !(tmpscr->flags2&wfUP)) + { + if(nextcombo_solid(up)) + doit=false; + } + + if(doit || action==inwind) + { + if(currscr>=128) + { + if(specialcave >= GUYCAVE) + exitcave(); + else stepout(); + } + else if(action==inwind) + { + if(DMaps[currdmap].flags&dmfWHIRLWINDRET) + { + action=none; + restart_level(); + } + else + { + dowarp(2,up); + } + } + else if(tmpscr->flags2&wfUP && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false))) + { + sdir=up; + dowarp(1,(tmpscr->sidewarpindex)&3); + } + else if(!edge_of_dmap(up)) + { + scrollscr(up); + + if(tmpscr->flags4&fAUTOSAVE) + { + save_game(true,0); + } + + if(tmpscr->flags6&fCONTINUEHERE) + { + lastentrance_dmap = currdmap; + lastentrance = homescr; + } + } + } + } + + if(y>160) + { + bool doit=true; + y=160; + + if(nextcombo_wf(down)) + doit=false; + + if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfDOWN)) + { + if(nextcombo_solid(down)) + doit=false; + } + + if(doit || action==inwind) + { + if(currscr>=128) + { + if(specialcave >= GUYCAVE) + exitcave(); + else stepout(); + } + else if(action==inwind) + { + if(DMaps[currdmap].flags&dmfWHIRLWINDRET) + { + action=none; + restart_level(); + } + else + { + dowarp(2,down); + } + } + else if(tmpscr->flags2&wfDOWN && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false))) + { + sdir=down; + dowarp(1,(tmpscr->sidewarpindex>>2)&3); + } + else if(!edge_of_dmap(down)) + { + scrollscr(down); + + if(tmpscr->flags4&fAUTOSAVE) + { + save_game(true,0); + } + + if(tmpscr->flags6&fCONTINUEHERE) + { + lastentrance_dmap = currdmap; + lastentrance = homescr; + } + } + } + } + + if(x<0) + { + bool doit=true; + x=0; + + if(nextcombo_wf(left)) + doit=false; + + if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfLEFT)) + { + if(nextcombo_solid(left)) + doit=false; + } + + if(doit || action==inwind) + { + if(currscr>=128) + { + if(specialcave >= GUYCAVE) + exitcave(); + else stepout(); + } + + if(action==inwind) + { + if(DMaps[currdmap].flags&dmfWHIRLWINDRET) + { + action=none; + restart_level(); + } + else + { + dowarp(2,left); + } + } + else if(tmpscr->flags2&wfLEFT && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false))) + { + sdir=left; + dowarp(1,(tmpscr->sidewarpindex>>4)&3); + } + else if(!edge_of_dmap(left)) + { + scrollscr(left); + + if(tmpscr->flags4&fAUTOSAVE) + { + save_game(true,0); + } + + if(tmpscr->flags6&fCONTINUEHERE) + { + lastentrance_dmap = currdmap; + lastentrance = homescr; + } + } + } + } + + if(x>240) + { + bool doit=true; + x=240; + + if(nextcombo_wf(right)) + doit=false; + + if(get_bit(quest_rules, qr_SMARTSCREENSCROLL)&&(!(tmpscr->flags&fMAZE))&&action!=inwind &&action!=scrolling &&!(tmpscr->flags2&wfRIGHT)) + { + if(nextcombo_solid(right)) + doit=false; + } + + if(doit || action==inwind) + { + if(currscr>=128) + { + if(specialcave >= GUYCAVE) + exitcave(); + else stepout(); + } + + if(action==inwind) + { + if(DMaps[currdmap].flags&dmfWHIRLWINDRET) + { + action=none; + restart_level(); + } + else + { + dowarp(2,right); + } + } + else if(tmpscr->flags2&wfRIGHT && (!(tmpscr->flags8&fMAZEvSIDEWARP) || checkmaze(tmpscr,false))) + { + sdir=right; + dowarp(1,(tmpscr->sidewarpindex>>6)&3); + } + else if(!edge_of_dmap(right)) + { + scrollscr(right); + + if(tmpscr->flags4&fAUTOSAVE) + { + save_game(true,0); + } + + if(tmpscr->flags6&fCONTINUEHERE) + { + lastentrance_dmap = currdmap; + lastentrance = homescr; + } + } + } + } +} + +// assumes current direction is in lastdir[3] +// compares directions with scr->path and scr->exitdir +bool LinkClass::checkmaze(mapscr *scr, bool sound) +{ + if(!(scr->flags&fMAZE)) + return true; + + if(lastdir[3]==scr->exitdir) + return true; + + for(int i=0; i<4; i++) + if(lastdir[i]!=scr->path[i]) + return false; + + if(sound) + sfx(scr->secretsfx); + + return true; +} + +bool LinkClass::edge_of_dmap(int side) +{ + if(checkmaze(tmpscr,false)==false) + return false; + + // needs fixin' + // should check dmap style + switch(side) + { + case up: + return currscr<16; + + case down: + return currscr>=112; + + case left: + if((currscr&15)==0) + return true; + + if((DMaps[currdmap].type&dmfTYPE)!=dmOVERW) + // if(dlevel) + return (((currscr&15)-DMaps[currdmap].xoff)<=0); + + break; + + case right: + if((currscr&15)==15) + return true; + + if((DMaps[currdmap].type&dmfTYPE)!=dmOVERW) + // if(dlevel) + return (((currscr&15)-DMaps[currdmap].xoff)>=7); + + break; + } + + return false; +} + +int LinkClass::lookahead(int destscr, int d2) // Helper for scrollscr that gets next combo on next screen. +{ + // Can use destscr for scrolling warps, + // but assumes currmap is correct. + + int s = currscr; + int cx = x; + int cy = y + 8; + + switch(d2) + { + case up: + s-=16; + cy=160; + break; + + case down: + s+=16; + cy=0; + break; + + case left: + --s; + cx=240; + break; + + case right: + ++s; + cx=0; + break; + } + + if(s < 0 || s >= 0x80) + return 0; + + if(destscr != -1) + s = destscr; + + int combo = (cy&0xF0)+(cx>>4); + + if(combo>175) + return 0; + + return TheMaps[currmap*MAPSCRS+s].data[combo]; // entire combo code +} + +int LinkClass::lookaheadflag(int destscr, int d2) +{ + // Helper for scrollscr that gets next combo on next screen. + // Can use destscr for scrolling warps, + // but assumes currmap is correct. + + int s = currscr; + int cx = x; + int cy = y + 8; + + switch(d2) + { + case up: + s-=16; + cy=160; + break; + + case down: + s+=16; + cy=0; + break; + + case left: + --s; + cx=240; + break; + + case right: + ++s; + cx=0; + break; + } + + if(s < 0 || s >= 0x80) + return 0; + + if(destscr != -1) + s = destscr; + + int combo = (cy&0xF0)+(cx>>4); + + if(combo>175) + return 0; + + if(!TheMaps[currmap*MAPSCRS+s].sflag[combo]) + { + return combobuf[TheMaps[currmap*MAPSCRS+s].data[combo]].flag; // flag + } + + return TheMaps[currmap*MAPSCRS+s].sflag[combo]; // flag +} + +//Bit of a messy kludge to give the correct Link->X/Link->Y in the script +void LinkClass::run_scrolling_script(int scrolldir, int cx, int sx, int sy, bool end_frames) +{ + fix storex = x, storey = y; + + switch(scrolldir) + { + case up: + if(y < 160) y = 176; + else if(cx > 0 && !end_frames) y = sy + 156; + else y = 160; + + break; + + case down: + if(y > 0) y = -16; + else if(cx > 0 && !end_frames) y = sy - 172; + else y = 0; + + break; + + case left: + if(x < 240) x = 256; + else if(cx > 0) x = sx + 236; + else x = 240; + + break; + + case right: + if(x > 0) x = -16; + else if(cx > 0) x = sx - 252; + else x = 0; + + break; + } + + if(g_doscript) + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME); + + x = storex, y = storey; +} + +//Has solving the maze enabled a side warp? +//Only used just before scrolling screens +// Note: since scrollscr() calls this, and dowarp() calls scrollscr(), +// return true to abort the topmost scrollscr() call. -L +bool LinkClass::maze_enabled_sizewarp(int scrolldir) +{ + for(int i = 0; i < 3; i++) lastdir[i] = lastdir[i+1]; + + lastdir[3] = tmpscr->flags&fMAZE ? scrolldir : 0xFF; + + if(tmpscr->flags8&fMAZEvSIDEWARP && tmpscr->flags&fMAZE && scrolldir != tmpscr->exitdir) + { + switch(scrolldir) + { + case up: + if(tmpscr->flags2&wfUP && checkmaze(tmpscr,true)) + { + lastdir[3] = 0xFF; + sdir=up; + dowarp(1,(tmpscr->sidewarpindex)&3); + return true; + } + + break; + + case down: + if(tmpscr->flags2&wfDOWN && checkmaze(tmpscr,true)) + { + lastdir[3] = 0xFF; + sdir=down; + dowarp(1,(tmpscr->sidewarpindex>>2)&3); + return true; + } + + break; + + case left: + if(tmpscr->flags2&wfLEFT && checkmaze(tmpscr,true)) + { + lastdir[3] = 0xFF; + sdir=left; + dowarp(1,(tmpscr->sidewarpindex>>4)&3); + return true; + } + + break; + + case right: + if(tmpscr->flags2&wfRIGHT && checkmaze(tmpscr,true)) + { + lastdir[3] = 0xFF; + sdir=right; + dowarp(1,(tmpscr->sidewarpindex)&3); + return true; + } + + break; + } + } + + return false; +} + +int LinkClass::get_scroll_step(int scrolldir) +{ + // For side-scrollers, where the reletive speed of 'fast' scrolling is a bit slow. + if(get_bit(quest_rules, qr_VERYFASTSCROLLING)) + return 16; + + if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) != 0) + { + return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 2 : 4; + } + else + { + if(scrolldir == up || scrolldir == down) + { + return 8; + } + else + { + return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 2 : 4; + } + } +} + +int LinkClass::get_scroll_delay(int scrolldir) +{ + if(get_bit(quest_rules, qr_NOSCROLL)) + return 0; + + if( (get_bit(quest_rules, qr_VERYFASTSCROLLING) != 0) || + (get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) != 0) ) + { + return 1; + } + else + { + if(scrolldir == up || scrolldir == down) + { + return (isdungeon() && !get_bit(quest_rules,qr_FASTDNGN)) ? 4 : 2; + } + else + { + return 1; + } + } +} + +void LinkClass::scrollscr(int scrolldir, int destscr, int destdmap) +{ + if(action==freeze) + { + return; + } + + bool overlay = false; + + if(scrolldir >= 0 && scrolldir <= 3) + { + overlay = get_bit(&tmpscr[(currscr < 128) ? 0 : 1].sidewarpoverlayflags, scrolldir) ? true : false; + } + + if(destdmap == -1) + { + if(ZCMaps[currmap].tileWidth != ZCMaps[DMaps[currdmap].map].tileWidth + || ZCMaps[currmap].tileHeight != ZCMaps[DMaps[currdmap].map].tileHeight) + return; + } + else + { + if(ZCMaps[currmap].tileWidth != ZCMaps[DMaps[destdmap].map].tileWidth + || ZCMaps[currmap].tileHeight != ZCMaps[DMaps[destdmap].map].tileHeight) + return; + } + + if(maze_enabled_sizewarp(scrolldir)) // dowarp() was called + return; + + //stop_sfx(WAV_ER); + screenscrolling = true; + + tmpscr[1] = tmpscr[0]; + + const int _mapsSize = ZCMaps[currmap].tileWidth * ZCMaps[currmap].tileHeight; + tmpscr[1].data.resize(_mapsSize, 0); + tmpscr[1].sflag.resize(_mapsSize, 0); + tmpscr[1].cset.resize(_mapsSize, 0); + + for(int i = 0; i < 6; i++) + { + tmpscr3[i] = tmpscr2[i]; + tmpscr3[1].data.resize(_mapsSize, 0); + tmpscr3[1].sflag.resize(_mapsSize, 0); + tmpscr3[1].cset.resize(_mapsSize, 0); + } + + mapscr *newscr = &tmpscr[0]; + mapscr *oldscr = &tmpscr[1]; + + //scroll x, scroll y, old screen x, old screen y, new screen x, new screen y + int sx = 0, sy = 0, tx = 0, ty = 0, tx2 = 0, ty2 = 0; + int cx = 0; + int step = get_scroll_step(scrolldir); + int delay = get_scroll_delay(scrolldir); + + int scx = get_bit(quest_rules, qr_FASTDNGN) ? 30 : 0; + if(get_bit(quest_rules, qr_VERYFASTSCROLLING)) + scx = 32; + + actiontype lastaction = action; + ALLOFF(false, false); + + int ahead = lookahead(destscr, scrolldir); + int aheadflag = lookaheadflag(destscr, scrolldir); + + bool nowinwater = false; + + if(lastaction != inwind) + { + if(lastaction == rafting && isRaftFlag(aheadflag)) + { + action = rafting; + } + else if(iswater(ahead) && (current_item(itype_flippers))) + { + if(lastaction==swimming) + { + action = swimming; + hopclk = 0xFF; + nowinwater = true; + } + else + { + action = hopping; + hopclk = 2; + nowinwater = true; + } + } + } + + lstep = (lstep + 6) % 12; + cx = scx; + + do + { + draw_screen(tmpscr); + + if(cx == scx) + rehydratelake(false); + + advanceframe(true); + + if(Quit) + { + screenscrolling = false; + return; + } + + ++cx; + } + while(cx < 32); + + if((DMaps[currdmap].type&dmfTYPE)==dmCAVE) + markBmap(scrolldir); + + + if(fixed_door) + { + unsetmapflag(mSECRET); + fixed_door = false; + } + + switch(scrolldir) + { + case up: + { + if(destscr != -1) + currscr = destscr; + else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir)) + currscr -= 16; + + loadscr(0,destdmap,currscr,scrolldir,overlay); + blit(scrollbuf,scrollbuf,0,0,0,176,256,176); + putscr(scrollbuf,0,0,newscr); + putscrdoors(scrollbuf,0,0,newscr); + sy=176; + + if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) == 0) + sy+=3; + + cx=176/step; + } + break; + + case down: + { + if(destscr != -1) + currscr = destscr; + else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir)) + currscr += 16; + + loadscr(0,destdmap,currscr,scrolldir,overlay); + putscr(scrollbuf,0,176,newscr); + putscrdoors(scrollbuf,0,176,newscr); + sy = 0; + + if(get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING) == 0) + sy+=3; + + cx = 176 / step; + } + break; + + case left: + { + if(destscr!=-1) + currscr = destscr; + else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir)) + --currscr; + + loadscr(0,destdmap,currscr,scrolldir,overlay); + blit(scrollbuf,scrollbuf,0,0,256,0,256,176); + putscr(scrollbuf,0,0,newscr); + putscrdoors(scrollbuf,0,0,newscr); + sx = 256; + cx = 256 / step; + } + break; + + case right: + { + if(destscr != -1) + currscr = destscr; + else if(checkmaze(oldscr,true) && !edge_of_dmap(scrolldir)) + ++currscr; + + loadscr(0,destdmap,currscr,scrolldir,overlay); + putscr(scrollbuf,256,0,newscr); + putscrdoors(scrollbuf,256,0,tmpscr); + sx = 0; + cx = 256 / step; + } + break; + } + + // The naturaldark state can be read/set by an FFC script before + // fade() or lighting() is called. + naturaldark = ((TheMaps[currmap*MAPSCRS+currscr].flags & fDARK) != 0); + + if(newscr->oceansfx != oldscr->oceansfx) adjust_sfx(oldscr->oceansfx, 128, false); + + if(newscr->bosssfx != oldscr->bosssfx) adjust_sfx(oldscr->bosssfx, 128, false); + + //Preloaded ffc scripts + if(destdmap >= 0) + { + long dmap = currdmap; // Kludge + currdmap = destdmap; + ffscript_engine(true); + currdmap = dmap; + } + else + ffscript_engine(true); + + // There are two occasions when scrolling must be darkened: + // 1) When scrolling into a dark room. + // 2) When scrolling between DMaps of different colours. + if(destdmap != -1 && DMaps[destdmap].color != currcset) + { +fade((specialcave > 0) ? (specialcave >= GUYCAVE) ? 10 : 11 : currcset, true, false); + darkroom = true; + } + else if(!darkroom) + lighting(false, false); // NES behaviour: fade to dark before scrolling + + if(action != rafting) // Is this supposed to be here?! + + cx++; //This was the easiest way to re-arrange the loop so drawing is in the middle + + cx *= delay; //so we can have drawing re-done every frame, + //previously it was for(0 to delay) advanceframes at end of loop + int no_move = 0; + bool end_frames = false; + + for(word i = 0; cx >= 0 && delay != 0; i++, cx--) //Go! + { + if(Quit) + { + screenscrolling = false; + return; + } + + script_drawing_commands.Clear(); + + // For rafting (and possibly other esoteric things) + // Link's action should remain unchanged while scrolling, + // but for the sake of scripts, here's an eye-watering kludge. + action = scrolling; + ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames); + action = lastaction; + + if(no_move > 0) + no_move--; + + //Don't want to move things on the first or last iteration, or between delays + if(i == 0 || cx == 0 || cx % delay != 0) + no_move++; + + if(scrolldir == up || scrolldir == down) + { + if(!get_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING)) + { + //Add a few extra frames if on the second loop and cool scrolling is not set + if(i == 1) + { + cx += (scrolldir == down) ? 3 : 2; + no_move += (scrolldir == down) ? 3 : 2; + } + } + else + { + //4 frames after we've finished scrolling of being still + if(cx == 0 && !end_frames) + { + cx += 4; + no_move += 4; + end_frames = true; + } + } + } + + //Move Link and the scroll position + if(!no_move) + { + switch(scrolldir) + { + case up: + sy -= step; + y += step; + break; + + case down: + sy += step; + y -= step; + break; + + case left: + sx -= step; + x += step; + break; + + case right: + sx += step; + x -= step; + break; + } + + //bound Link when me move him off the screen in the last couple of frames of scrolling + if(y > 160) y = 160; + + if(y < 0) y = 0; + + if(x > 240) x = 240; + + if(x < 0) x = 0; + + if(ladderx > 0 || laddery > 0) + { + // If the ladder moves on both axes, the player can + // gradually shift it by going back and forth + if(scrolldir==up || scrolldir==down) + laddery = int(y); + else + ladderx = int(x); + } + } + + if(global_wait) + { + // And now to injure your other eye + action = scrolling; + ZScriptVersion::RunScrollingScript(scrolldir, cx, sx, sy, end_frames); + action = lastaction; + } + + //Drawing + tx = sx; + ty = sy; + tx2 = sx; + ty2 = sy; + + switch(scrolldir) + { + case right: + tx -= 256; + break; + + case down: + ty -= 176; + break; + + case left: + tx2 -= 256; + break; + + case up: + ty2 -= 176; + break; + } + + clear_bitmap(scrollbuf); + clear_bitmap(framebuf); + + switch(scrolldir) + { + case up: + if(newscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, newscr, 0, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, oldscr, 0, -176+playing_field_offset, 3); + + if(newscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, newscr, 0, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, oldscr, 0, -176+playing_field_offset, 3); + + // Draw both screens' background layer primitives together, after both layers' combos. + // Not ideal, but probably good enough for all realistic purposes. + if(newscr->flags7&fLAYER2BG || oldscr->flags7&fLAYER2BG) do_primitives(scrollbuf, 2, newscr, sx, sy); + + if(newscr->flags7&fLAYER3BG || oldscr->flags7&fLAYER3BG) do_primitives(scrollbuf, 3, newscr, sx, sy); + + putscr(scrollbuf, 0, 0, newscr); + putscr(scrollbuf, 0, 176, oldscr); + break; + + case down: + if(newscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, newscr, 0, -176+playing_field_offset, 2); + + if(oldscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, oldscr, 0, playing_field_offset, 3); + + if(newscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, newscr, 0, -176+playing_field_offset, 2); + + if(oldscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, oldscr, 0, playing_field_offset, 3); + + if(newscr->flags7&fLAYER2BG || oldscr->flags7&fLAYER2BG) do_primitives(scrollbuf, 2, newscr, sx, sy); + + if(newscr->flags7&fLAYER3BG || oldscr->flags7&fLAYER3BG) do_primitives(scrollbuf, 3, newscr, sx, sy); + + putscr(scrollbuf, 0, 0, oldscr); + putscr(scrollbuf, 0, 176, newscr); + break; + + case left: + if(newscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, newscr, 0, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, oldscr, -256, playing_field_offset, 3); + + if(newscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, newscr, 0, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, oldscr, -256, playing_field_offset, 3); + + if(newscr->flags7&fLAYER2BG || oldscr->flags7&fLAYER2BG) do_primitives(scrollbuf, 2, newscr, sx, sy); + + if(newscr->flags7&fLAYER3BG || oldscr->flags7&fLAYER3BG) do_primitives(scrollbuf, 3, newscr, sx, sy); + + putscr(scrollbuf, 0, 0, newscr); + putscr(scrollbuf, 256, 0, oldscr); + break; + + case right: + if(newscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, newscr, -256, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER2BG) do_layer(scrollbuf,1, oldscr, 0, playing_field_offset, 3); + + if(newscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, newscr, -256, playing_field_offset, 2); + + if(oldscr->flags7&fLAYER3BG) do_layer(scrollbuf,2, oldscr, 0, playing_field_offset, 3); + + if(newscr->flags7&fLAYER2BG || oldscr->flags7&fLAYER2BG) do_primitives(scrollbuf, 2, newscr, sx, sy); + + if(newscr->flags7&fLAYER3BG || oldscr->flags7&fLAYER3BG) do_primitives(scrollbuf, 3, newscr, sx, sy); + + putscr(scrollbuf, 0, 0, oldscr); + putscr(scrollbuf, 256, 0, newscr); + break; + } + + blit(scrollbuf, framebuf, sx, sy, 0, playing_field_offset, 256, 168); + do_primitives(framebuf, 0, newscr, 0, playing_field_offset); + + do_layer(framebuf, 0, oldscr, tx2, ty2, 3); + + if(!(oldscr->flags7&fLAYER2BG)) do_layer(framebuf,1, oldscr, tx2, ty2, 3); + + do_layer(framebuf, 0, newscr, tx, ty, 2, false, true); + + if(!(newscr->flags7&fLAYER2BG)) do_layer(framebuf,1, newscr, tx, ty, 2, false, !(oldscr->flags7&fLAYER2BG)); + + do_layer(framebuf, -2, oldscr, tx2, ty2, 3); //push blocks + do_layer(framebuf, -2, newscr, tx, ty, 2); + + do_walkflags(framebuf, oldscr, tx2, ty2,3); //show walkflags if the cheat is on + do_walkflags(framebuf, newscr, tx, ty,2); + + if(get_bit(quest_rules, qr_FFCSCROLL)) + { + do_layer(framebuf, -3, oldscr, tx2, ty2, 3, true); //ffcs + do_layer(framebuf, -3, newscr, tx, ty, 2, true); + } + + putscrdoors(framebuf, 0-tx2, 0-ty2+playing_field_offset, oldscr); + putscrdoors(framebuf, 0-tx, 0-ty+playing_field_offset, newscr); + linkstep(); + + if(z > 0 && (!get_bit(quest_rules,qr_SHADOWSFLICKER) || frame&1)) + { + drawshadow(framebuf, get_bit(quest_rules, qr_TRANSSHADOWS) != 0); + } + + if(!isdungeon() || get_bit(quest_rules,qr_FREEFORM)) + { + draw_under(framebuf); //draw the ladder or raft + decorations.draw2(framebuf, true); + draw(framebuf); //Link + decorations.draw(framebuf, true); + } + + if(!(oldscr->flags7&fLAYER3BG)) do_layer(framebuf,2, oldscr, tx2, ty2, 3); + + do_layer(framebuf, 3, oldscr, tx2, ty2, 3); //layer 3 + do_layer(framebuf,-1, oldscr, tx2, ty2, 3); //overhead combos + do_layer(framebuf, 4, oldscr, tx2, ty2, 3); //layer 4 + do_layer(framebuf,-4, oldscr, tx2, ty2, 3, true); //overhead FFCs + do_layer(framebuf, 5, oldscr, tx2, ty2, 3); //layer 5 + + if(!(newscr->flags7&fLAYER3BG)) do_layer(framebuf,2, newscr, tx, ty, 2, false, !(oldscr->flags7&fLAYER3BG)); + + do_layer(framebuf, 3, newscr, tx, ty, 2, false, true); //layer 3 + do_layer(framebuf,-1, newscr, tx, ty, 2); //overhead combos + do_layer(framebuf, 4, newscr, tx, ty, 2, false, true); //layer 4 + do_layer(framebuf,-4, newscr, tx, ty, 2, true); //overhead FFCs + do_layer(framebuf, 5, newscr, tx, ty, 2, false, true); //layer 5 + + // Pretty sure this isn't even possible... + //if(msgdisplaybuf->clip == 0) + //masked_blit(msgdisplaybuf, framebuf, tx2, ty2, 0, playing_field_offset, 256, 168); + + put_passive_subscr(framebuf, &QMisc, 0, passive_subscreen_offset, false, sspUP); + + if(get_bit(quest_rules,qr_SUBSCREENOVERSPRITES)) + do_primitives(framebuf, 7, newscr, 0, playing_field_offset); + + //end drawing + + advanceframe(true); + }//end main scrolling loop + + + messageMgr.clear(true); + + //Move link to the other side of the screen if scrolling's not turned on + if(get_bit(quest_rules, qr_NOSCROLL)) + { + switch(scrolldir) + { + case up: + y = 160; + break; + + case down: + y = 0; + break; + + case left: + x = 240; + break; + + case right: + x = 0; + break; + } + } + + if(z > 0 && tmpscr->flags7&fSIDEVIEW) + { + y -= z; + z = 0; + } + + entry_x = x; + entry_y = y; + warpx = -1; + warpy = -1; + + screenscrolling = false; + + if(destdmap != -1) + currdmap = destdmap; + + //if Link is going from non-water to water, and we set his animation to "hopping" above, we must now + //change it to swimming - since we have manually moved Link onto the first tile, the hopping code + //will get confused and try to hop Link onto the next (possibly nonexistant) water tile in his current + //direction. -DD + + if(nowinwater) + { + action = swimming; + hopclk = 0xFF; + } + + // NES behaviour: Fade to light after scrolling + lighting(false, false); // No, we don't need to set naturaldark... + + homescr=currscr; + init_dmap(); + putscr(scrollbuf,0,0,newscr); + putscrdoors(scrollbuf,0,0,newscr); + + // Check for raft flags + if(action!=rafting && hopclk==0 && !toogam) + { + if(MAPFLAG(x,y)==mfRAFT||MAPCOMBOFLAG(x,y)==mfRAFT) + { + sfx(tmpscr->secretsfx); + action=rafting; + } + + // Half a tile off? + else if((dir==left || dir==right) && (MAPFLAG(x,y+8)==mfRAFT||MAPCOMBOFLAG(x,y+8)==mfRAFT)) + { + sfx(tmpscr->secretsfx); + action=rafting; + } + } + + opendoors=0; + markBmap(-1); + + if(isdungeon()) + { + switch(tmpscr->door[scrolldir^1]) + { + case dOPEN: + case dUNLOCKED: + case dOPENBOSS: + dir = scrolldir; + + if(action!=rafting) + stepforward(diagonalMovement?11:12, false); + + break; + + case dSHUTTER: + case d1WAYSHUTTER: + dir = scrolldir; + + if(action!=rafting) + stepforward(diagonalMovement?21:24, false); + + putdoor(scrollbuf,0,scrolldir^1,tmpscr->door[scrolldir^1]); + opendoors=-4; + sfx(WAV_DOOR); + break; + + default: + dir = scrolldir; + + if(action!=rafting) + stepforward(diagonalMovement?21:24, false); + } + } + + if(action == scrolling) + action = none; + + if(action != attacking) + { + charging = 0; + tapping = false; + } + + map_bkgsfx(true); + + if(newscr->flags2&fSECRET) + { + sfx(newscr->secretsfx); + } + + playLevelMusic(); + + newscr_clk = frame; + activated_timed_warp=false; + loadside = scrolldir^1; + eventlog_mapflags(); +} + +// How much to reduce Link's damage, taking into account various rings. +int LinkClass::ringpower(int dmg) +{ + int result = 1; + int itemid = current_item_id(itype_ring); + bool usering = false; + + if(itemid>-1) // current_item_id checks magic cost for rings + { + usering = true; + paymagiccost(itemid); + result *= itemsbuf[itemid].power; + } + + /* Now for the Peril Ring */ + itemid = current_item_id(itype_perilring); + + if(itemid>-1 && game->get_life()<=itemsbuf[itemid].misc1*HP_PER_HEART && checkmagiccost(itemid)) + { + usering = true; + paymagiccost(itemid); + result *= itemsbuf[itemid].power; + } + + // Ring divisor of 0 = no damage. -L + if(usering && result<=0) + return 0; + + return dmg/zc_max(result, 1); // well, better safe... +} + +bool LinkClass::sideviewhammerpound() +{ + asIScriptFunction* func=scriptData->getFunction("bool sideviewhammerpound()"); + scriptData->runFunction(func); + return scriptData->getLastResult(); +} + +/************************************/ +/******** More Items Code *********/ +/************************************/ + +// The following are only used for Link damage. Damage is in quarter hearts. +int enemy_dp(int index) +{ + return (((enemy*)guys.spr(index))->dp)*(HP_PER_HEART/4); +} + +int ewpn_dp(int index) +{ + return (((weapon*)Ewpns.spr(index))->power)*(HP_PER_HEART/4); +} + +int lwpn_dp(int index) +{ + return (((weapon*)Lwpns.spr(index))->power)*(HP_PER_HEART/4); +} + +bool checkmagiccost(int itemid) +{ + if(itemid < 0) + { + return false; + } + else if(itemsbuf[itemid].flags & ITEM_RUPEE_MAGIC) + { + return (game->get_rupies()+game->get_drupy()>=itemsbuf[itemid].magic); + } + else if(get_bit(quest_rules,qr_ENABLEMAGIC)) + { + return (((current_item_power(itype_magicring) > 0) + ? game->get_maxmagic() + : game->get_magic()+game->get_dmagic())>=itemsbuf[itemid].magic*game->get_magicdrainrate()); + } + + return 1; +} + +void paymagiccost(int itemid) +{ + if(itemid < 0) + return; + + if(itemsbuf[itemid].magic <= 0) + return; + + if(itemsbuf[itemid].flags & ITEM_RUPEE_MAGIC) + { + game->change_drupy(-itemsbuf[itemid].magic); + return; + } + + if(current_item_power(itype_magicring) > 0) + return; + + game->change_magic(-(itemsbuf[itemid].magic*game->get_magicdrainrate())); +} + +int Bweapon(int pos) +{ + if(pos < 0 || current_subscreen_active == NULL) + { + return 0; + } + + int p=-1; + + for(int i=0; current_subscreen_active->objects[i].type!=ssoNULL; ++i) + { + if(current_subscreen_active->objects[i].type==ssoCURRENTITEM && current_subscreen_active->objects[i].d3==pos) + { + p=i; + break; + } + } + + if(p==-1) + { + return 0; + } + + int actualItem = current_subscreen_active->objects[p].d8; + //int familyCheck = actualItem ? itemsbuf[actualItem].family : current_subscreen_active->objects[p].d1 + int family = -1; + bool bow = false; + + if(actualItem) + { + bool select = false; + + switch(itemsbuf[actualItem-1].family) + { + case itype_bomb: + if((game->get_bombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (actualItem-1>-1 && itemsbuf[actualItem-1].misc1==0 && Lwpns.idCount(wLitBomb)>0)) || + current_item_power(itype_bombbag)) + { + select=true; + } + + break; + + case itype_bowandarrow: + case itype_arrow: + if(actualItem-1>-1 && current_item_id(itype_bow)>-1) + { + //bow=(current_subscreen_active->objects[p].d1==itype_bowandarrow); + select=true; + } + + break; + + case itype_letterpotion: + /*if(current_item_id(itype_potion)>-1) + { + select=true; + } + else if(current_item_id(itype_letter)>-1) + { + select=true; + }*/ + break; + + case itype_sbomb: + { + int bombbagid = current_item_id(itype_bombbag); + + if((game->get_sbombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (actualItem-1>-1 && itemsbuf[actualItem-1].misc1==0 && Lwpns.idCount(wLitSBomb)>0)) || + (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1))) + { + select=true; + } + + break; + } + + case itype_sword: + { + if(!get_bit(quest_rules,qr_SELECTAWPN)) + break; + + select=true; + } + break; + + default: + select=true; + } + + if(!item_disabled(actualItem-1) && game->get_item(actualItem-1) && select) + { + directItem = actualItem-1; + + if(directItem>-1 && itemsbuf[directItem].family == itype_arrow) bow=true; + + return actualItem-1+(bow?0xF000:0); + } + else return 0; + } + + directItem = -1; + + switch(current_subscreen_active->objects[p].d1) + { + case itype_bomb: + { + int bombid = current_item_id(itype_bomb); + + if((game->get_bombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (bombid>-1 && itemsbuf[bombid].misc1==0 && Lwpns.idCount(wLitBomb)>0)) || + current_item_power(itype_bombbag)) + { + family=itype_bomb; + } + + break; + } + + case itype_bowandarrow: + case itype_arrow: + if(current_item_id(itype_bow)>-1 && current_item_id(itype_arrow)>-1) + { + bow=(current_subscreen_active->objects[p].d1==itype_bowandarrow); + family=itype_arrow; + } + + break; + + case itype_letterpotion: + if(current_item_id(itype_potion)>-1) + { + family=itype_potion; + } + else if(current_item_id(itype_letter)>-1) + { + family=itype_letter; + } + + break; + + case itype_sbomb: + { + int bombbagid = current_item_id(itype_bombbag); + int sbombid = current_item_id(itype_sbomb); + + if((game->get_sbombs() || + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + (sbombid>-1 && itemsbuf[sbombid].misc1==0 && Lwpns.idCount(wLitSBomb)>0)) || + (current_item_power(itype_bombbag) && bombbagid>-1 && (itemsbuf[bombbagid].flags & ITEM_FLAG1))) + { + family=itype_sbomb; + } + + break; + } + + case itype_sword: + { + if(!get_bit(quest_rules,qr_SELECTAWPN)) + break; + + family=itype_sword; + } + break; + + default: + family=current_subscreen_active->objects[p].d1; + } + + if(family==-1) + return 0; + + for(int j=0; jid==wCByrna) + w->dead=1; + } +} + +// Used to find out if an item family is attached to one of the buttons currently pressed. +bool isWpnPressed(int wpn) +{ + if((wpn==getItemFamily(itemsbuf,Bwpn&0xFFF)) && DrunkcBbtn()) return true; + + if((wpn==getItemFamily(itemsbuf,Awpn&0xFFF)) && DrunkcAbtn()) return true; + + return false; +} + +void selectNextAWpn(int type) +{ + if(!get_bit(quest_rules,qr_SELECTAWPN)) + return; + + int ret = selectWpn_new(type, game->awpn, game->bwpn); + Awpn = Bweapon(ret); + directItemA = directItem; + game->awpn = ret; +} + +void selectNextBWpn(int type) +{ + int ret = selectWpn_new(type, game->bwpn, game->awpn); + Bwpn = Bweapon(ret); + directItemB = directItem; + game->bwpn = ret; +} + +void verifyAWpn() +{ + if(!get_bit(quest_rules,qr_SELECTAWPN)) + { + Awpn = selectSword(); + game->awpn = 0xFF; + } + else + { + game->awpn = selectWpn_new(SEL_VERIFY_RIGHT, game->awpn, game->bwpn); + Awpn = Bweapon(game->awpn); + directItemA = directItem; + } +} + +void verifyBWpn() +{ + game->bwpn = selectWpn_new(SEL_VERIFY_RIGHT, game->bwpn, game->awpn); + Bwpn = Bweapon(game->bwpn); + directItemB = directItem; +} + +void verifyBothWeapons() +{ + verifyAWpn(); + verifyBWpn(); +} + +int selectWpn_new(int type, int startpos, int forbiddenpos) +{ + //what will be returned when all else fails. + //don't return the forbiddenpos... no matter what -DD + + int failpos(0); + + if(startpos == forbiddenpos) + failpos = 0xFF; + else failpos = startpos; + + // verify startpos + if(startpos < 0 || startpos >= 0xFF) + startpos = 0; + + if(current_subscreen_active == NULL) + return failpos; + + if(type==SEL_VERIFY_RIGHT || type==SEL_VERIFY_LEFT) + { + int wpn = Bweapon(startpos); + + if(wpn != 0 && startpos != forbiddenpos) + { + return startpos; + } + } + + int p=-1; + int curpos = startpos; + int firstValidPos=-1; + + for(int i=0; current_subscreen_active->objects[i].type!=ssoNULL; ++i) + { + if(current_subscreen_active->objects[i].type==ssoCURRENTITEM) + { + if(firstValidPos==-1 && current_subscreen_active->objects[i].d3>=0) + { + firstValidPos=i; + } + + if(current_subscreen_active->objects[i].d3==curpos) + { + p=i; + break; + } + } + } + + if(p == -1) + { + //can't find the current position + // Switch to a valid weapon if there is one; otherwise, + // the selector can simply disappear + if(firstValidPos>=0) + { + return current_subscreen_active->objects[firstValidPos].d3; + } + //FAILURE + else + { + return failpos; + } + } + + //remember we've been here + set oldPositions; + oldPositions.insert(curpos); + + //1. Perform any shifts required by the above + //2. If that's not possible, go to position 1 and reset the b weapon. + //2a. -if we arrive at a position we've already visited, give up and stay there + //3. Get the weapon at the new slot + //4. If it's not possible, go to step 1. + + for(;;) + { + //shift + switch(type) + { + case SEL_LEFT: + case SEL_VERIFY_LEFT: + curpos = current_subscreen_active->objects[p].d6; + break; + + case SEL_RIGHT: + case SEL_VERIFY_RIGHT: + curpos = current_subscreen_active->objects[p].d7; + break; + + case SEL_DOWN: + curpos = current_subscreen_active->objects[p].d5; + break; + + case SEL_UP: + curpos = current_subscreen_active->objects[p].d4; + break; + } + + //find our new position + p = -1; + + for(int i=0; current_subscreen_active->objects[i].type!=ssoNULL; ++i) + { + if(current_subscreen_active->objects[i].type==ssoCURRENTITEM) + { + if(current_subscreen_active->objects[i].d3==curpos) + { + p=i; + break; + } + } + } + + if(p == -1) + { + //can't find the current position + //FAILURE + return failpos; + } + + //if we've already been here, give up + if(oldPositions.find(curpos) != oldPositions.end()) + { + return failpos; + } + + //else, remember we've been here + oldPositions.insert(curpos); + + //see if this weapon is acceptable + if(Bweapon(curpos) != 0 && curpos != forbiddenpos) + return curpos; + + //keep going otherwise + } +} + +// Select the sword for the A button if the 'select A button weapon' quest rule isn't set. +int selectSword() +{ + int ret = current_item_id(itype_sword); + + if(ret == -1) + ret = 0; + + return ret; +} + +// Used for the 'Pickup Hearts' item pickup condition. +bool canget(int id) +{ + return id>=0 && (game->get_maxlife()>=(itemsbuf[id].pickup_hearts*HP_PER_HEART)); +} + +void getitem(int id, bool nosound) +{ + if(id<0) + { + return; + } + + if(itemsbuf[id].family!=0xFF) + { + if(itemsbuf[id].flags & ITEM_GAMEDATA && itemsbuf[id].family != itype_triforcepiece) + { + // Fix boomerang sounds. + int itemid = current_item_id(itemsbuf[id].family); + + if(itemid>=0 && (itemsbuf[id].family == itype_brang || itemsbuf[id].family == itype_nayruslove + || itemsbuf[id].family == itype_hookshot || itemsbuf[id].family == itype_cbyrna) + && sfx_allocated(itemsbuf[itemid].usesound) + && itemsbuf[id].usesound != itemsbuf[itemid].usesound) + { + stop_sfx(itemsbuf[itemid].usesound); + cont_sfx(itemsbuf[id].usesound); + } + + game->set_item(id,true); + + if(!(itemsbuf[id].flags & ITEM_KEEPOLD)) + { + if(current_item(itemsbuf[id].family)id==wBrang) + { + w->LOADGFX(itemsbuf[id].wpn); + } + } + } + + if(itemsbuf[id].count!=-1) + { + if(itemsbuf[id].setmax) + { + // Bomb bags are a special case; they may be set not to increase super bombs + if(itemsbuf[id].family==itype_bombbag && itemsbuf[id].count==2 && (itemsbuf[id].flags&16)==0) + { + int max = game->get_maxbombs(); + + if(maxset_maxbombs(zc_min(game->get_maxbombs()+itemsbuf[id].setmax,max), false); + } + else + { + int max = game->get_maxcounter(itemsbuf[id].count); + + if(maxset_maxcounter(zc_min(game->get_maxcounter(itemsbuf[id].count)+itemsbuf[id].setmax,max), itemsbuf[id].count); + } + } + + // Amount is an unsigned short, but the range is -9999 to 16383 + // -1 is actually 16385 ... -9999 is 26383, and 0x8000 means use the drain counter + if(itemsbuf[id].amount&0x3FFF) + { + if(itemsbuf[id].amount&0x8000) + game->set_dcounter( + game->get_dcounter(itemsbuf[id].count)+((itemsbuf[id].amount&0x4000)?-(itemsbuf[id].amount&0x3FFF):itemsbuf[id].amount&0x3FFF), itemsbuf[id].count); + else + { + if(itemsbuf[id].amount>=16385 && game->get_counter(0)<=itemsbuf[id].amount-16384) + game->set_counter(0, itemsbuf[id].count); + else + // This is too confusing to try and change... + game->set_counter(zc_min(game->get_counter(itemsbuf[id].count)+((itemsbuf[id].amount&0x4000)?-(itemsbuf[id].amount&0x3FFF):itemsbuf[id].amount&0x3FFF),game->get_maxcounter(itemsbuf[id].count)), itemsbuf[id].count); + } + } + } + } + + if(itemsbuf[id].playsound&&!nosound) + { + sfx(itemsbuf[id].playsound); + } + + //add lower-level items + if(itemsbuf[id].flags&ITEM_GAINOLD) + { + for(int i=itemsbuf[id].fam_type-1; i>0; i--) + { + int potid = getItemID(itemsbuf, itemsbuf[id].family, i); + + if(potid != -1) + { + game->set_item(potid, true); + } + } + } + + switch(itemsbuf[id&0xFF].family) + { + case itype_clock: + Link.addItemEffect(getItemEffect(id&0xFF)); + break; + + case itype_lkey: + if(game->lvlkeys[dlevel]<255) game->lvlkeys[dlevel]++; + + break; + + case itype_ring: + case itype_magicring: + if((get_bit(quest_rules,qr_OVERWORLDTUNIC) != 0) || (currscr<128 || dlevel)) + { + ringcolor(false); + } + + break; + + case itype_whispring: + { + if(itemsbuf[id].flags & ITEM_FLAG1) + { + if(LinkSwordClk()==-1) setSwordClk(150); // Let's not bother applying the divisor. + + if(LinkItemClk()==-1) setItemClk(150); // Let's not bother applying the divisor. + } + + if(itemsbuf[id].power==0) + { + setSwordClk(0); + setItemClk(0); + } + + break; + } + + + case itype_map: + game->lvlitems[dlevel]|=liMAP; + break; + + case itype_compass: + game->lvlitems[dlevel]|=liCOMPASS; + break; + + case itype_bosskey: + game->lvlitems[dlevel]|=liBOSSKEY; + break; + + case itype_fairy: + + game->set_life(zc_min(game->get_life()+(itemsbuf[id].flags&ITEM_FLAG1 ?(int)(game->get_maxlife()*(itemsbuf[id].misc1/100.0)):((itemsbuf[id].misc1*HP_PER_HEART))),game->get_maxlife())); + game->set_magic(zc_min(game->get_magic()+(itemsbuf[id].flags&ITEM_FLAG2 ?(int)(game->get_maxmagic()*(itemsbuf[id].misc2/100.0)):((itemsbuf[id].misc2*MAGICPERBLOCK))),game->get_maxmagic())); + break; + + case itype_heartpiece: + game->change_HCpieces(1); + + if(game->get_HCpieces()get_hcp_per_hc()) + break; + + game->set_HCpieces(0); + + for(int i=0; iset_item(id, false); + + /* Lower the counters! */ + if(itemsbuf[id].count!=-1) + { + if(itemsbuf[id].setmax) + { + game->set_maxcounter(game->get_maxcounter(itemsbuf[id].count)-itemsbuf[id].setmax, itemsbuf[id].count); + } + + if(itemsbuf[id].amount&0x3FFF) + { + if(itemsbuf[id].amount&0x8000) + game->set_dcounter(game->get_dcounter(itemsbuf[id].count)-((itemsbuf[id].amount&0x4000)?-(itemsbuf[id].amount&0x3FFF):itemsbuf[id].amount&0x3FFF), itemsbuf[id].count); + else game->set_counter(game->get_counter(itemsbuf[id].count)-((itemsbuf[id].amount&0x4000)?-(itemsbuf[id].amount&0x3FFF):itemsbuf[id].amount&0x3FFF), itemsbuf[id].count); + } + } + + switch(itemsbuf[id&0xFF].family) + { + // NES consistency: replace all flying boomerangs with the current boomerang. + case itype_brang: + if(current_item(itype_brang)) for(int i=0; iid==wBrang) + { + w->LOADGFX(itemsbuf[current_item_id(itype_brang)].wpn); + } + } + + break; + + case itype_heartpiece: + if(game->get_maxlife()>HP_PER_HEART) + { + if(game->get_HCpieces()==0) + { + game->set_HCpieces(game->get_hcp_per_hc()); + takeitem(iHeartC); + } + + game->change_HCpieces(-1); + } + + break; + + case itype_map: + game->lvlitems[dlevel]&=~liMAP; + break; + + case itype_compass: + game->lvlitems[dlevel]&=~liCOMPASS; + break; + + case itype_bosskey: + game->lvlitems[dlevel]&=~liBOSSKEY; + break; + + case itype_lkey: + if(game->lvlkeys[dlevel]) game->lvlkeys[dlevel]--; + + break; + } +} + +// Attempt to pick up an item. (-1 = check items touching Link.) +void LinkClass::checkitems(int index) +{ + int tmp=currscr>=128?1:0; + + if(index==-1) + { + if(diagonalMovement) + { + index=items.hit(x,y+(bigHitbox?0:8),z,6,6,1); + } + else index=items.hit(x,y+(bigHitbox?0:8),z,1,1,1); + } + + if(index==-1) + return; + + // if (tmpscr[tmp].room==rSHOP && boughtsomething==true) + // return; + + item* theItem=(item*)items.spr(index); + + if(!theItem->canPickUp(this)) + return; + + int pickup=theItem->pickup; + int PriceIndex=theItem->PriceIndex; + int itemID=theItem->id; + + int id2=theItem->getUpgradeResult(); + if(id2>=0) + { + // Not quite sure how this is going to work. When picking up + // an upgrade item, Link has to have enough hearts for both + // the item itself and the upgrade result. + if(get_bit(quest_rules,qr_HEARTSREQUIREDFIX) || + (theItem->pickup&ipSPECIAL)) + { + if(game->get_maxlife()onPickUp) + ;//__debugbreak();//theItem->onPickUp(); + + getitem(id2); + + if(pickup&ipHOLDUP) + { + attackclk=0; + reset_swordcharge(); + + if(action!=swimming) + reset_hookshot(); + + messageMgr.clear(true); + + // Not sure yet what should be done with this... + if(get_bit(quest_rules, qr_OLDPICKUP) || ((tmpscr[tmp].room==rSP_ITEM || tmpscr[tmp].room==rRP_HC || tmpscr[tmp].room==rTAKEONE) && (pickup&ipONETIME2))) + { + fadeclk=66; + } + + if(id2!=iBombs || action==swimming || get_bit(quest_rules,qr_BOMBHOLDFIX)) + { + // don't hold up bombs unless swimming or the bomb hold fix quest rule is on + if(action==swimming) + { + action=waterhold1; + } + else + { + action=landhold1; + } + + if(((item*)items.spr(index))->twohand) + { + if(action==waterhold1) + { + action=waterhold2; + } + else + { + action=landhold2; + } + } + + holdclk=130; + + //restart music + if(get_bit(quest_rules, qr_HOLDNOSTOPMUSIC) == 0) + music_stop(); + + holditem=((item*)items.spr(index))->id; // NES consistency: when combining blue potions, hold up the blue potion. + freeze_guys=true; + } + + if(itemsbuf[id2].family!=itype_triforcepiece || !(itemsbuf[id2].flags & ITEM_GAMEDATA)) + { + sfx(tmpscr[0].holdupsfx); + } + + items.del(index); + + for(int i=0; iadjustDraggedItem(index); + } + + // clear up shop stuff + if(!isdungeon()&&index!=0) + { + if(boughtsomething) + { + fadeclk=66; + + if(((item*)items.spr(0))->id == iRupy && ((item*)items.spr(0))->pickup & ipDUMMY) + items.del(0); + + for(int i=0; iadjustDraggedItem(0); + } + } + + messageMgr.clear(true); + } + + // items.del(index); + } + else + { + items.del(index); + + for(int i=0; iadjustDraggedItem(index); + } + + messageMgr.clear(true); + } + + if(itemsbuf[id2].family==itype_triforcepiece) + { + if(itemsbuf[id2].misc2==1) + beginSpecialSequence(seq_getTriforce, id2); + else + //getBigTri(id2); + beginSpecialSequence(seq_getBigTriforce, id2); + } +} + +void LinkClass::StartRefill(int refillWhat) +{ + if(!refilling) + { + refillclk=21; + //stop_sfx(WAV_ER); + sfx(WAV_REFILL,128,true); + refilling=refillWhat; + + if(refill_why>=0) // Item index + { + if((itemsbuf[refill_why].family==itype_potion)&&(!get_bit(quest_rules,qr_NONBUBBLEMEDICINE))) + { + swordclk=0; + + if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0; + } + + if((itemsbuf[refill_why].family==itype_triforcepiece)&&(!get_bit(quest_rules,qr_NONBUBBLETRIFORCE))) + { + swordclk=0; + + if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0; + } + } + else if((refill_why==REFILL_FAIRY)&&(!get_bit(quest_rules,qr_NONBUBBLEFAIRIES))) + { + swordclk=0; + + if(get_bit(quest_rules,qr_ITEMBUBBLE)) itemclk=0; + } + } +} + +bool LinkClass::refill() +{ + if(refilling==REFILL_NONE || refilling==REFILL_FAIRYDONE) + return false; + + ++refillclk; + int speed = get_bit(quest_rules,qr_FASTFILL) ? 6 : 22; + int refill_heart_stop=game->get_maxlife(); + int refill_magic_stop=game->get_maxmagic(); + + if(refill_why>=0 && itemsbuf[refill_why].family==itype_potion) + { + refill_heart_stop=zc_min(potion_life+(itemsbuf[refill_why].flags & ITEM_FLAG1 ?int(game->get_maxlife()*(itemsbuf[refill_why].misc1 /100.0)):((itemsbuf[refill_why].misc1 *HP_PER_HEART))),game->get_maxlife()); + refill_magic_stop=zc_min(potion_magic+(itemsbuf[refill_why].flags & ITEM_FLAG2 ?int(game->get_maxmagic()*(itemsbuf[refill_why].misc2 /100.0)):((itemsbuf[refill_why].misc2 *MAGICPERBLOCK))),game->get_maxmagic()); + } + + if(refillclk%speed == 0) + { + // game->life&=0xFFC; + switch(refill_what) + { + case REFILL_LIFE: + game->set_life(zc_min(refill_heart_stop, (game->get_life()+HP_PER_HEART/2))); + + if(game->get_life()>=refill_heart_stop) + { + game->set_life(refill_heart_stop); + kill_sfx(); + sfx(WAV_MSG); + refilling=REFILL_NONE; + return false; + } + + break; + + case REFILL_MAGIC: + game->set_magic(zc_min(refill_magic_stop, (game->get_magic()+MAGICPERBLOCK/4))); + + if(game->get_magic()>=refill_magic_stop) + { + game->set_magic(refill_magic_stop); + kill_sfx(); + sfx(WAV_MSG); + refilling=REFILL_NONE; + return false; + } + + break; + + case REFILL_ALL: + game->set_life(zc_min(refill_heart_stop, (game->get_life()+HP_PER_HEART/2))); + game->set_magic(zc_min(refill_magic_stop, (game->get_magic()+MAGICPERBLOCK/4))); + + if((game->get_life()>=refill_heart_stop)&&(game->get_magic()>=refill_magic_stop)) + { + game->set_life(refill_heart_stop); + game->set_magic(refill_magic_stop); + kill_sfx(); + sfx(WAV_MSG); + refilling=REFILL_NONE; + return false; + } + + break; + } + } + + return true; +} + +void LinkClass::saved_Zelda() +{ + Playing=Paused=false; + action=won; + Quit=qWON; + hclk=0; + x = 136; + y = (isdungeon() && currscr<128) ? 75 : 73; + z = fall = spins = 0; + dir=left; +} + +void LinkClass::reset_swordcharge() +{ + charging=spins=tapping=0; +} + +void LinkClass::reset_hookshot() +{ + if(action!=rafting && action!=landhold1 && action!=landhold2) + { + action=none; + } + + hookshot_frozen=false; + hookshot_used=false; + pull_link=false; + hs_fix=false; + Lwpns.del(Lwpns.idFirst(wHSHandle)); + Lwpns.del(Lwpns.idFirst(wHookshot)); + chainlinks.clear(); + int index=directItem>-1 ? directItem : current_item_id(itype_hookshot); + + if(index>=0) + { + stop_sfx(itemsbuf[index].usesound); + } + + hs_xdist=0; + hs_ydist=0; +} + + +bool LinkClass::can_deploy_ladder() +{ + bool ladderallowed = ((!get_bit(quest_rules,qr_LADDERANYWHERE) && tmpscr->flags&fLADDER) || isdungeon() + || (get_bit(quest_rules,qr_LADDERANYWHERE) && !(tmpscr->flags&fLADDER))); + return (current_item_id(itype_ladder)>-1 && ladderallowed && !ilswim && z==0 && + (!(tmpscr->flags7&fSIDEVIEW) || ON_SIDEPLATFORM)); +} + +void LinkClass::reset_ladder() +{ + ladderx=laddery=0; +} + +void LinkClass::check_conveyor() +{ + if(action==casting||action==drowning||inlikelike||pull_link||(z>0 && !(tmpscr->flags2&fAIRCOMBOS))) + { + return; + } + + WalkflagInfo info; + int xoff,yoff; + int deltax=0, deltay=0; + + if(conveyclk<=0) + { + is_on_conveyor=false; + int ctype; + ctype=(combobuf[MAPCOMBO(x+7,y+(bigHitbox?8:12))].type); + deltax=combo_class_buf[ctype].conveyor_x_speed; + deltay=combo_class_buf[ctype].conveyor_y_speed; + + if((deltax==0&&deltay==0)&&(tmpscr->flags7&fSIDEVIEW && ON_SIDEPLATFORM)) + { + ctype=(combobuf[MAPCOMBO(x+8,y+16)].type); + deltax=combo_class_buf[ctype].conveyor_x_speed; + deltay=combo_class_buf[ctype].conveyor_y_speed; + } + + if(deltax!=0||deltay!=0) + { + is_on_conveyor=true; + } + + if(deltay<0) + { + info = walkflag(x,y+8-(bigHitbox*8)-2,2,up); + execute(info); + + if(!info.isUnwalkable()) + { + int step=0; + + if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!diagonalMovement) + { + while(step<(abs(deltay)*((tmpscr->flags7&fSIDEVIEW)?2:1))) + { + yoff=((int)y-step)&7; + + if(!yoff) break; + + step++; + } + } + else + { + step=abs(deltay); + } + + y=y-step; + hs_starty-=step; + + for(int j=0; jy-=step; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->y-=step; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->y-=step; + } + } + else checkdamagecombos(x,y+8-(bigHitbox ? 8 : 0)-2); + } + else if(deltay>0) + { + info = walkflag(x,y+15+2,2,down); + execute(info); + + if(!info.isUnwalkable()) + { + int step=0; + + if((DrunkRight()||DrunkLeft())&&dir!=left&&dir!=right&&!diagonalMovement) + { + while(stepy+=step; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=step; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=step; + } + } + else checkdamagecombos(x,y+15); + } + + if(deltax<0) + { + info = walkflag(x-int(lsteps[int(x)&7]),y+8-(bigHitbox ? 8 : 0),1,left); + execute(info); + + if(!info.isUnwalkable()) + { + int step=0; + + if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!diagonalMovement) + { + while(stepx-=step; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->x-=step; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->x-=step; + } + } + else checkdamagecombos(x-int(lsteps[int(x)&7]),y+8-(bigHitbox ? 8 : 0)); + } + else if(deltax>0) + { + info = walkflag(x+15+2,y+8-(bigHitbox ? 8 : 0),1,right); + execute(info); + + if(!info.isUnwalkable()) + { + int step=0; + + if((DrunkUp()||DrunkDown())&&dir!=up&&dir!=down&&!diagonalMovement) + { + while(stepx+=step; + } + + if(Lwpns.idFirst(wHookshot)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=step; + } + + if(Lwpns.idFirst(wHSHandle)>-1) + { + Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=step; + } + } + else checkdamagecombos(x+15+2,y+8-(bigHitbox ? 8 : 0)); + } + } +} + +void LinkClass::setScrollDir(int sd) +{ + sdir=sd; +} + +void LinkClass::setInvincible(bool inv) +{ + superman=inv; +} + +void LinkClass::execute(LinkClass::WalkflagInfo info) +{ + int flags = info.getFlags(); + + if(flags & WalkflagInfo::CLEARILSWIM) + ilswim =false; + else if(flags & WalkflagInfo::SETILSWIM) + ilswim = true; + + if(flags & WalkflagInfo::CLEARCHARGEATTACK) + { + charging = 0; + attackclk = 0; + } + + if(flags & WalkflagInfo::SETDIR) + { + dir = info.getDir(); + } + + if(flags & WalkflagInfo::SETHOPCLK) + { + hopclk = info.getHopClk(); + } + + if(flags & WalkflagInfo::SETHOPDIR) + { + hopdir = info.getHopDir(); + } + +} + +LinkClass::WalkflagInfo LinkClass::WalkflagInfo::operator ||(LinkClass::WalkflagInfo other) +{ + LinkClass::WalkflagInfo ret; + ret.newhopclk = newhopclk; + ret.newdir = newdir; + ret.newhopdir = (other.newhopdir >-1 ? other.newhopdir : newhopdir); + + int flags1 = (flags & ~UNWALKABLE) & (other.flags & ~UNWALKABLE); + int flags2 = (flags & UNWALKABLE) | (other.flags & UNWALKABLE); + ret.flags = flags1 | flags2; + return ret; +} + +LinkClass::WalkflagInfo LinkClass::WalkflagInfo::operator &&(LinkClass::WalkflagInfo other) +{ + LinkClass::WalkflagInfo ret; + ret.newhopclk = newhopclk; + ret.newdir = newdir; + ret.newhopdir = (other.newhopdir >-1 ? other.newhopdir : newhopdir); + + ret.flags = flags & other.flags; + return ret; +} + +LinkClass::WalkflagInfo LinkClass::WalkflagInfo::operator !() +{ + LinkClass::WalkflagInfo ret; + ret.newhopclk = newhopclk; + ret.newdir = newdir; + ret.newhopdir = newhopdir; + + ret.flags = flags ^ UNWALKABLE; + return ret; +} + +/*** end of link.cpp ***/ diff --git a/src/link.h b/src/link.h new file mode 100644 index 0000000000..6dadfcbaf9 --- /dev/null +++ b/src/link.h @@ -0,0 +1,407 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// link.cc +// +// Link's class: LinkClass +// Handles a lot of game play stuff as well as Link's +// movement, attacking, etc. +// +//-------------------------------------------------------- + +#ifndef _LINK_H_ +#define _LINK_H_ + +#include "zc_alleg.h" +#include "zcmusic.h" +#include "zdefs.h" +#include "maps.h" +#include "tiles.h" +#include "colors.h" +#include "pal.h" +#include "aglogo.h" +#include "zsys.h" +#include "qst.h" +#include "matrix.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "weapons.h" +//#include "save_gif.h" +#include "sprite.h" +#include "zc_custom.h" +#include "subscr.h" +#include "item/itemEffect.h" +class asIScriptFunction; +class ItemAction; + +extern movingblock mblock2; //mblock[4]? +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations; + +extern const byte lsteps[8]; + +enum { did_fairy=1, did_candle=2, did_whistle=4, did_magic=8, did_glove=16, did_all=32 }; + +enum actiontype +{ + none, walking, attacking, freeze, landhold1, landhold2, + rafting, gothit, inwind, scrolling, won, swimming, hopping, + swimhit, waterhold1, waterhold2, casting, climbcovertop, + climbcoverbottom, dying, drowning, climbing, + // Fake actiontypes: used by ZScripts + ischarging, isspinning, isdiving +}; + +typedef struct tilesequence +{ + word tile; + byte frames; // animation frame count + byte speed; // animation speed + byte exp; // not used +} tilesequence; + +#define SWORDCHARGEFRAME 20 +#define SWORDTAPFRAME SWORDCHARGEFRAME-8 +#define HAMMERCHARGEFRAME 11 +#define WANDCHARGEFRAME 12 + +// Values for specialcave +#define ITEMCELLAR 1 +#define PASSAGEWAY 2 +#define GUYCAVE 3 +#define STAIRCAVE 4 + +class LinkClass : public sprite +{ + class WalkflagInfo + { + public: + WalkflagInfo() : flags(0), newhopclk(0), newhopdir(0), newdir(0), newladderdir(0), + newladderx(0), newladdery(0), newladderstart(0) {} + static const int UNWALKABLE = 1; + static const int SETILSWIM = 2; + static const int CLEARILSWIM = 4; + static const int SETHOPCLK = 8; + static const int SETDIR = 16; + static const int CLEARCHARGEATTACK = 32; + static const int SETHOPDIR = 64; + + inline int getHopClk() const { return newhopclk; } + inline int getHopDir() const { return newhopdir; } + inline int getDir() const { return newdir; } + inline int getLadderdir() const { return newladderdir; } + inline int getLadderx() const { return newladderx; } + inline int getLaddery() const { return newladdery; } + inline int getLadderstart() const { return newladderstart; } + + void setUnwalkable(bool val) + { + if(val) flags |= UNWALKABLE; + else flags &= ~UNWALKABLE; + } + + void setIlswim(bool val) + { + if(val) flags |= SETILSWIM; + else flags |= CLEARILSWIM; + } + + void setHopClk(int val) + { + flags |= SETHOPCLK; + newhopclk = val; + } + + void setHopDir(int val) + { + flags |= SETHOPDIR; + newhopdir = val; + } + + void setDir(int val) + { + flags |= SETDIR; + newdir = val; + } + + void setChargeAttack() + { + flags |= CLEARCHARGEATTACK; + } + + int getFlags() + { + return flags; + } + + bool isUnwalkable() + { + return (flags & UNWALKABLE) != 0; + } + + WalkflagInfo operator||(WalkflagInfo other); + WalkflagInfo operator&&(WalkflagInfo other); + WalkflagInfo operator!(); + + private: + int flags; + int newhopclk; + int newhopdir; + int newdir; + int newladderdir; + int newladderx; + int newladdery; + int newladderstart; + }; + + void execute(WalkflagInfo info); + + bool autostep,superman,inwallm,tapping,stomping,last_hurrah; + int refilling, + ladderx, + laddery, + stepnext, //location of step->next just triggered (don't recursively trigger it) + stepsecret, //location of step->secrets just triggered (don't recursively trigger it) + warpx,warpy, //location of warp just arrived at (don't recursively enter it) + pushing, //incremental time spent pushing. + jumping, //incremental time spent airborne. + charging, //incremental time spent charging weapon. + spins, //1 + number of sword spins left to do. 0 = not spinning. + fairyclk, //fairy circle timeout. + refillclk,//life refill timeout. + drunkclk, //intoxication timeout. + hoverclk, //hover boots timeout. + hclk, //damage blinking timeout. + holdclk, //"hold up item" timeout. + holditem, //item being held. + attackclk,//attack timeout. + attack, //current attack wpnid. + attackid, //current attack itemid. + swordclk, //sword jinx timeout. + itemclk, //item jinx timeout. + didstuff, //played the whistle? used the blue candle? + blowcnt, //number of times whistle blown on this screen. + drownclk, //drowning timeout. + stepoutindex, // where to step out when in a passageway + stepoutwr, // which warp return to use for a passageway + stepoutdmap, // which dmap the passageway exits to + stepoutscr, // which screen the passageway exits to + slashxofs, slashyofs; // used by positionSword() and draw() + byte skipstep,lstep, + hopclk, // hopping into water timeout. + diveclk, // diving timeout. + whirlwind, // is Link inside an arriving whirlwind? (yes = 255) + specialcave, // is Link inside a special cave? + hitdir, // direction from which damage was taken. + ladderdir, // direction of ladder + lastdir[4], // used in Maze Path screens + ladderstart, // starting direction of ladder...? + inlikelike; // 1 = Like Like. 2 = Taking damage while trapped + bool nayrusLoveActive; + int shiftdir; // shift direction when walking into corners of solid combos + int sdir; // scrolling direction + int hopdir; // direction to hop out of water (diagonal movement only) + int holddir; + int landswim; // incremental time spent swimming against land + bool ilswim; // is land swimming? + bool walkable; + actiontype action; // current action + int hshandle_id, hshead_id; + byte conveyor_flags; + fix climb_cover_x, climb_cover_y; + fix entry_x, entry_y; // When drowning, re-create Link here + fix falling_oldy; // Used by the Stomp Boots in sideview + bool dontdraw; + bool diagonalMovement; + bool bigHitbox; + + // Methods below here. + void movelink(); + void move(int d); + void hitlink(int hit); + int nextcombo(int cx,int cy,int cdir); + int nextflag(int cx,int cy,int cdir, bool comboflag); + bool nextcombo_wf(int d); + bool nextcombo_solid(int d); + int lookahead(int destscr = -1, int d=up); + int lookaheadflag(int destscr = -1, int d=up); + void checkhit(); + bool checkdamagecombos(int dx, int dy); + bool checkdamagecombos(int dx1, int dx2, int dy1, int dy2, int layer = -1, bool solid = false); + void checkscroll(); + void checkspecial(); + void checkspecial2(int *ls); + void checkspecial3(); + void checkpushblock(); + void checkbosslockblock(); + void checklockblock(); + void checkswordtap(); + void checkchest(int type); + void checktouchblk(); + void checklocked(); + void deselectbombs(int super); // switch Link's weapon if his current weapon (bombs) was depleted. + bool startwpn(int itemid); + bool doattack(); + bool can_attack(); + void do_rafting(); + void do_hopping(); + WalkflagInfo walkflag(int wx,int wy,int cnt,byte d); + WalkflagInfo walkflagMBlock(int wx,int wy); + bool edge_of_dmap(int side); + bool checkmaze(mapscr *scr, bool sound); + bool maze_enabled_sizewarp(int scrolldir); + + int get_scroll_step(int scrolldir); + int get_scroll_delay(int scrolldir); +public: + void run_scrolling_script(int scrolldir, int cx, int sx, int sy, bool end_frames); +private: + void scrollscr(int dir,int destscr = -1, int destdmap = -1); + void walkdown(bool opening, bool cave2); + void walkup(bool opening, bool cave2); + + void exitcave(); + void stepout(); + void masked_draw(BITMAP *dest); + int weaponattackpower(); + void positionSword(weapon* w,int itemid); + void checkstab(); + void fairycircle(int type); + int EwpnHit(); + int LwpnHit(); + void saved_Zelda(); + void check_conveyor(); + bool sideviewhammerpound(); + bool agonyflag(int flag); + int ringpower(int dmg); + +public: + void StartRefill(int refillWhat); + void checkitems(int index = -1); + int DrunkClock(); + void setDrunkClock(int newdrunkclk); + void setEntryPoints(int x, int y); + LinkClass(); + void init(); + virtual void drawshadow(BITMAP* dest, bool translucent); + virtual void draw(BITMAP* dest); + virtual bool animate(int index); + bool dowarp(int type, int index); + + void linkstep(); + void stepforward(int steps, bool adjust); + void draw_under(BITMAP* dest); + + // called by ALLOFF() + void resetflags(bool all); + void Freeze(); + void unfreeze(); + void finishedmsg(); + void Drown(); + fix getFall(); + fix getXOfs(); + fix getYOfs(); + void setXOfs(int newxofs); + void setYOfs(int newyofs); + fix getClimbCoverX(); + fix getClimbCoverY(); + int getLStep(); + int getCharging(); + bool isCharged(); + void cancelAttack(); + int getSwordClk(); + int getItemClk(); + void setSwordClk(int newclk); + void setItemClk(int newclk); + int getHitDir(); + void setHitDir(int new_dir); + int getClk(); + int getPushing(); + void reset_swordcharge(); + void reset_hookshot(); + bool can_deploy_ladder(); + void reset_ladder(); + bool refill(); + void Catch(); + bool getClock(); + void setClock(bool state); + int getAction(); + void setAction(actiontype new_action); + int getHeldItem(); + void setHeldItem(int newitem); + bool isDiving(); + bool isSwimming(); + void setDontDraw(bool new_dontdraw); + bool getDontDraw(); + void setHitTimer(int newhclk); + int getHClk(); + void setScrollDir(int sd); + void setInvincible(bool inv); + int getSpecialCave(); // used only by maps.cpp + + inline bool isHoldingItem() const { return holdclk>0; } + inline void addItemEffect(ItemEffect* newEffect) { itemEffects.add(newEffect); } + inline void setNayrusLoveActive(bool nl) { nayrusLoveActive=nl; } // Eh. + + // This'll be moved... + inline void modWhistleCounter(int amt) { blowcnt+=amt; } + +//private: // sigh + ItemAction* currentItemAction; + ItemEffectList itemEffects; + + // Cancels charging when the wand or sword hits an enemy. + void onMeleeWeaponHit(); + + // Load up script functions + void scriptInit(); + +private: + asIScriptFunction* asUpdate; + + void updateGravity(); + void checkLadderRemoval(); + + friend class LinkHandler; + friend class LinkZScriptInterface; + friend void registerLink(); +}; + +bool isRaftFlag(int flag); +void do_lens(); +int touchcombo(int x,int y); +extern bool did_secret; +int selectWlevel(int d); + +/************************************/ +/******** More Items Code *********/ +/************************************/ + +int enemy_dp(int index); +int ewpn_dp(int index); +int lwpn_dp(int index); +bool checkmagiccost(int itemid); +void paymagiccost(int itemid); +int Bweapon(int pos); +void stopCaneOfByrna(); +//void selectWpn(int xstep, int ystep, bool b); +const int SEL_UP = 0; +const int SEL_LEFT = 1; +const int SEL_DOWN = 2; +const int SEL_RIGHT = 3; +const int SEL_VERIFY_LEFT = 4; +const int SEL_VERIFY_RIGHT = 5; +int selectWpn_new(int type, int startpos, int forbiddenpos = -1); +bool isWpnPressed(int wpn); +int selectSword(); +void selectNextAWpn(int type); +void selectNextBWpn(int type); +void verifyBothWeapons(); +void verifyAWpn(); +void verifyBWpn(); +bool canget(int id); +void getitem(int id, bool nosound=false); +void takeitem(int id); + +#endif +/*** end of link.cc ***/ diff --git a/src/linkHandler.cpp b/src/linkHandler.cpp new file mode 100644 index 0000000000..1ebefb9a65 --- /dev/null +++ b/src/linkHandler.cpp @@ -0,0 +1,131 @@ +#include "linkHandler.h" +#include "decorations.h" +#include "guys.h" +#include "link.h" +#include "linkZScriptInterface.h" +#include "sequence.h" +#include "sfxManager.h" +#include "sound.h" +#include "zc_sys.h" +#include "zelda.h" + +extern LinkClass Link; +extern SFXManager sfxMgr; +extern LinkZScriptInterface linkIF; + +LinkHandler::LinkHandler(): + link(Link), + lowHealthSFX(sfxMgr.getSFX(WAV_ER)) +{ +} + +void LinkHandler::addDecorations() +{ + fix x=Link.getX(); + fix y=Link.getY(); + fix z=Link.getZ(); + if(isGrassType(COMBOTYPE(x,y+15)) && isGrassType(COMBOTYPE(x+15,y+15))&& z<=8) + { + if(!tallGrassDeco) + { + tallGrassDeco.reset(new dTallGrass(x, y, dTALLGRASS, 0)); + decorations.add(tallGrassDeco.get()); + } + } + else if(tallGrassDeco) + tallGrassDeco.del(); + + if((COMBOTYPE(x,y+15)==cSHALLOWWATER)&&(COMBOTYPE(x+15,y+15)==cSHALLOWWATER) && z==0) + { + if(!ripplesDeco) + { + ripplesDeco.reset(new dRipples(x, y, dRIPPLES, 0)); + decorations.add(ripplesDeco.get()); + } + } + else if(ripplesDeco) + ripplesDeco.del(); + + if(Link.hoverclk>0) + { + if(!hoverDeco) + { + hoverDeco.reset(new dHover(x, y, dHOVER, 0)); + decorations.add(hoverDeco.get()); + sfx(itemsbuf[current_item_id(itype_hoverboots)].usesound,pan(int(x))); + } + } + else if(hoverDeco) + hoverDeco.del(); +} + +void LinkHandler::updateLowHealthWarning() +{ + // This is pretty incomplete. There are a lot of times when the sound + // should be suspended. + if(game->get_life()<=(HP_PER_HEART) && !(game->get_maxlife()<=(HP_PER_HEART))) + { + if(heart_beep) + { + if(!lowHealthSFX.isLooping()) + lowHealthSFX.startLooping(); + } + else + { + if(heart_beep_timer==-1) + heart_beep_timer=70; + + if(heart_beep_timer>0) + --heart_beep_timer; + else + lowHealthSFX.stopLooping(); + } + } + else + { + heart_beep_timer=-1; + lowHealthSFX.stopLooping(); + } +} + +bool LinkHandler::update() +{ + if(linkIF.warpPending()) + { + linkIF.activateWarp(); + return false; + } + + if(DrunkrLbtn() && !get_bit(quest_rules,qr_SELECTAWPN)) + selectNextBWpn(SEL_LEFT); + else if(DrunkrRbtn() && !get_bit(quest_rules,qr_SELECTAWPN)) + selectNextBWpn(SEL_RIGHT); + + if(rPbtn()) + onViewMap(); // return? + + updateLowHealthWarning(); + + if(link.animate(0)) + return true; + addDecorations(); + + if((!loaded_guys) && (frame - newscr_clk >= 1)) + { + if(tmpscr->room==rGANON) + { + beginSpecialSequence(seq_ganonIntro); + return false; // May be unnecessary + } + else + loadguys(); + } + + if((!loaded_enemies) && (frame - newscr_clk >= 2)) + loadenemies(); + + // check lots of other things + link.checkscroll(); + + return false; +} diff --git a/src/linkHandler.h b/src/linkHandler.h new file mode 100644 index 0000000000..54a7e06c3d --- /dev/null +++ b/src/linkHandler.h @@ -0,0 +1,32 @@ +#ifndef _ZC_LINKHANDLER_H_ +#define _ZC_LINKHANDLER_H_ + +#include "entityPtr.h" +#include "sfxClass.h" +class dHover; +class dRipples; +class dTallGrass; +class LinkClass; + +/// This class will handle some things that Link does but shouldn't be LinkClass's responsibility. +class LinkHandler +{ +public: + LinkHandler(); + bool update(); + +private: + LinkClass& link; + SFX lowHealthSFX; + EntityPtr tallGrassDeco; + EntityPtr ripplesDeco; + EntityPtr hoverDeco; + + /// Add tall grass, shallow water, and hover decorations. + void addDecorations(); + + /// Play or stop the low health beep. + void updateLowHealthWarning(); +}; + +#endif diff --git a/src/linkZScriptInterface.cpp b/src/linkZScriptInterface.cpp new file mode 100644 index 0000000000..0ea7ee993a --- /dev/null +++ b/src/linkZScriptInterface.cpp @@ -0,0 +1,150 @@ +#include "linkZScriptInterface.h" +#include "link.h" +#include "zdefs.h" +#include "zelda.h" +extern LinkClass Link; +extern mapscr tmpscr[2]; + +LinkZScriptInterface::LinkZScriptInterface(): + link(Link), + warpDMap(-1) +{ +} + +int LinkZScriptInterface::getX() const +{ + return link.getX(); +} + +int LinkZScriptInterface::getY() const +{ + return link.getY(); +} + +int LinkZScriptInterface::getZ() const +{ + return link.getZ(); +} + +void LinkZScriptInterface::setX(int newX) +{ + if(Lwpns.idFirst(wHookshot)>-1) + Lwpns.spr(Lwpns.idFirst(wHookshot))->x+=(newX-link.x); + + if(Lwpns.idFirst(wHSHandle)>-1) + Lwpns.spr(Lwpns.idFirst(wHSHandle))->x+=(newX-link.x); + + link.setX(fix(newX)); + + // A kludge. Why? Who knows. + if(!link.diagonalMovement && link.dir<=down) + is_on_conveyor=true; +} + +void LinkZScriptInterface::setY(int newY) +{ + if(Lwpns.idFirst(wHookshot)>-1) + Lwpns.spr(Lwpns.idFirst(wHookshot))->y+=(newY-link.y); + + if(Lwpns.idFirst(wHSHandle)>-1) + Lwpns.spr(Lwpns.idFirst(wHSHandle))->y+=(newY-link.y); + + link.setY(fix(newY)); + + if(!link.diagonalMovement && link.dir>=left) + is_on_conveyor=true; +} + +void LinkZScriptInterface::setZ(int newZ) +{ + if((tmpscr->flags7&fSIDEVIEW)!=0) + return; + + if(link.z==0 && newZ>0) + { + switch(link.action) + { + case swimming: + link.diveclk=0; + link.action=walking; + break; + + case waterhold1: + link.action=landhold1; + break; + + case waterhold2: + link.action=landhold2; + break; + + default: + if(link.charging) + { + link.reset_swordcharge(); + link.attackclk=0; + } + + break; + } + } + + link.setZ(fix(newZ>0 ? newZ : 0)); +} + +int LinkZScriptInterface::getDir() const +{ + return Link.dir; +} + +void LinkZScriptInterface::setDir(int newDir) +{ + link.dir=newDir; + link.reset_hookshot(); +} + +void LinkZScriptInterface::setJump(fix newJump) +{ + link.fall=-newJump; + link.jumping=-1; +} + +void LinkZScriptInterface::setAction(int newAction) +{ + if(newAction==dying || newAction==won || newAction==scrolling || + newAction==inwind || newAction==rafting || newAction==ischarging) + return; // Can't use these actions. + link.setAction(static_cast(newAction)); +} + +int LinkZScriptInterface::getLadderX() const +{ + return link.ladderx; +} + +int LinkZScriptInterface::getLadderY() const +{ + return link.laddery; +} + +void LinkZScriptInterface::warp(int dmap, int screen, bool pit) +{ + warpDMap=dmap; + warpScreen=screen; + warpIsPit=pit; +} + +void LinkZScriptInterface::activateWarp() +{ + if(warpIsPit) + { + didpit=true; + pitx=link.getX(); + pity=link.getY(); + } + + tmpscr->sidewarpdmap[0]=warpDMap; + tmpscr->sidewarpscr[0]=warpScreen; + tmpscr->sidewarptype[0]=wtIWARP; + warpDMap=-1; // So warpPending() returns false + link.dowarp(1,0); +} diff --git a/src/linkZScriptInterface.h b/src/linkZScriptInterface.h new file mode 100644 index 0000000000..e31d94912e --- /dev/null +++ b/src/linkZScriptInterface.h @@ -0,0 +1,36 @@ +#ifndef _ZC_LINKZSCRIPTINTERFACE_H_ +#define _ZC_LINKZSCRIPTINTERFACE_H_ + +#include "types.h" +class LinkClass; + +/** All ZScript access to Link should go through this class. It'll perform + * validation and any extra steps needed to keep things working correctly. + */ +class LinkZScriptInterface +{ +public: + LinkZScriptInterface(); + int getX() const; + int getY() const; + int getZ() const; + void setX(int x); + void setY(int y); + void setZ(int z); + int getDir() const; + void setDir(int newDir); + void setJump(fix newJump); + void setAction(int action); + int getLadderX() const; + int getLadderY() const; + void warp(int dmap, int screen, bool pit); + inline bool warpPending() const { return warpDMap!=-1; } + void activateWarp(); + +private: + LinkClass& link; + int warpDMap, warpScreen; + bool warpIsPit; +}; + +#endif diff --git a/src/load_gif.cpp b/src/load_gif.cpp new file mode 100644 index 0000000000..0e8d486549 --- /dev/null +++ b/src/load_gif.cpp @@ -0,0 +1,420 @@ +/* GIF Loader + * by Paul Bartrum + */ + +#include "precompiled.h" //always first + +#ifdef MSS +#include /* For all those memory debugging fans ;-) */ +#endif +#include +#include +#include +#include +#include "zc_alleg.h" +#include +#include "load_gif.h" + +/* The following prototype comes from Allegro's internal. To avoid doing + * such ugly things, the best would be to #include , but + * since that's just a wip, it's left like this for Allegro 3.0 compatibility + */ +//int _color_load_depth(int depth); + +struct LZW_STRING +{ + short base; + char new_char; + short length; +}; + +PACKFILE *f; +int gif_empty_string, curr_bit_size, bit_overflow; +int bit_pos, data_pos, data_len, entire, code; +int cc, string_length, i, bit_size; +unsigned char string[4096]; +struct LZW_STRING str[4096]; +BITMAP *bmp; +int image_x, image_y, image_w, image_h, x, y; +int interlace; + +void clear_table(void) +{ + gif_empty_string = cc + 2; + curr_bit_size = bit_size + 1; + bit_overflow = 0; +} + +void get_code(void) +{ + if(bit_pos + curr_bit_size > 8) + { + if(data_pos >= data_len) + { + data_len = pack_getc(f); + data_pos = 0; + } + + entire = (pack_getc(f) << 8) + entire; + data_pos ++; + } + + if(bit_pos + curr_bit_size > 16) + { + if(data_pos >= data_len) + { + data_len = pack_getc(f); + data_pos = 0; + } + + entire = (pack_getc(f) << 16) + entire; + data_pos ++; + } + + code = (entire >> bit_pos) & ((1 << curr_bit_size) - 1); + + if(bit_pos + curr_bit_size > 8) + entire >>= 8; + + if(bit_pos + curr_bit_size > 16) + entire >>= 8; + + bit_pos = (bit_pos + curr_bit_size) % 8; + + if(bit_pos == 0) + { + if(data_pos >= data_len) + { + data_len = pack_getc(f); + data_pos = 0; + } + + entire = pack_getc(f); + data_pos ++; + } +} + +void get_string(int num) +{ + if(num < cc) + { + string_length = 1; + string[0] = str[num].new_char; + } + else + { + i = str[num].length; + string_length = i; + + while(i > 0) + { + i --; + string[i] = str[num].new_char; + num = str[num].base; + } + + /* if(num != -1) **-{[ERROR]}-** */ + } +} + +void output_string(void) +{ + for(i = 0; i < string_length; i ++) + { + putpixel(bmp, x, y, string[i]); + x ++; + + if(x >= image_x + image_w) + { + x = image_x; + y += interlace; + + if(interlace) + { + if(y >= image_y + image_h) + { + if(interlace == 8 && (y - image_y) % 8 == 0) + { + interlace = 8; + y = image_y + 4; + } + else if(interlace == 8 && (y - image_y) % 8 == 4) + { + interlace = 4; + y = image_y + 2; + } + else if(interlace == 4) + { + interlace = 2; + y = image_y + 1; + } + } + } + } + } +} + +/* load_gif: + * Loads a 2-256 colour GIF file onto a bitmap, returning the bitmap + * structure and storing the pallete data in the specified pallete (this + * should be an array of at least 256 RGB structures). + */ +BITMAP *load_gif(const char *filename, RGB *pal) +{ + int width, height, depth; + int old; + BITMAP *bmp2; + int dest_depth; + + f = pack_fopen_password(filename, F_READ,""); + + if(!f) /* can't open file */ + return NULL; + + i = pack_mgetw(f) << 8; + i += pack_getc(f); + + if(i != 0x474946) /* is it really a GIF? */ + { + pack_fclose(f); + return NULL; + } + + pack_fseek(f, 3); /* skip version */ + + width = pack_igetw(f); + height = pack_igetw(f); + + bmp = create_bitmap_ex(8, width, height); + + if(bmp == NULL) + { + pack_fclose(f); + return NULL; + } + + clear_bitmap(bmp); + + i = pack_getc(f); + + if(i & 128) /* no global colour table? */ + depth = (i & 7) + 1; + else + depth = 0; + + pack_fseek(f, 2); /* skip background colour and aspect ratio */ + + if(pal && depth) /* only read palette if pal and depth are not 0 */ + { + for(i = 0; i < (1 << depth); i ++) + { + pal[i].r = pack_getc(f) / 4; + pal[i].g = pack_getc(f) / 4; + pal[i].b = pack_getc(f) / 4; + } + } + else if(depth) + pack_fseek(f, (1 << depth) * 3); + + for(;;) + { + i = pack_getc(f); + + if(i == EOF) + i=0x3B; + + switch(i) + { + case 0x2C: /* Image Descriptor */ + image_x = pack_igetw(f); + image_y = pack_igetw(f); /* individual image dimensions */ + image_w = pack_igetw(f); + image_h = pack_igetw(f); + + i = pack_getc(f); + + if(i & 64) + interlace = 8; + else + interlace = 1; + + if(i & 128) + { + depth = (i & 7) + 1; + + if(pal) + { + for(i = 0; i < (1 << depth); i ++) + { + pal[i].r = pack_getc(f) / 4; + pal[i].g = pack_getc(f) / 4; + pal[i].b = pack_getc(f) / 4; + } + } + else + pack_fseek(f, (1 << depth) * 3); + } + + /* lzw stream starts now */ + bit_size = pack_getc(f); + cc = 1 << bit_size; + + /* initialise string table */ + for(i = 0; i < cc; i ++) + { + str[i].base = -1; + str[i].new_char = i; + str[i].length = 1; + } + + /* initialise the variables */ + bit_pos = 0; + data_len = pack_getc(f); + data_pos = 0; + entire = pack_getc(f); + data_pos ++; + string_length = 0; + x = image_x; + y = image_y; + + /* starting code */ + clear_table(); + get_code(); + + if(code == cc) + get_code(); + + get_string(code); + output_string(); + old = code; + + for(;;) + { + get_code(); + + if(code == cc) + { + /* starting code */ + clear_table(); + get_code(); + get_string(code); + output_string(); + old = code; + } + else if(code == cc + 1) + { + break; + } + else if(code < gif_empty_string) + { + get_string(code); + output_string(); + + if(bit_overflow == 0) + { + str[gif_empty_string].base = old; + str[gif_empty_string].new_char = string[0]; + str[gif_empty_string].length = str[old].length + 1; + gif_empty_string ++; + + if(gif_empty_string == (1 << curr_bit_size)) + curr_bit_size ++; + + if(curr_bit_size == 13) + { + curr_bit_size = 12; + bit_overflow = 1; + } + } + + old = code; + } + else + { + get_string(old); + string[str[old].length] = string[0]; + string_length ++; + + if(bit_overflow == 0) + { + str[gif_empty_string].base = old; + str[gif_empty_string].new_char = string[0]; + str[gif_empty_string].length = str[old].length + 1; + gif_empty_string ++; + + if(gif_empty_string == (1 << curr_bit_size)) + curr_bit_size ++; + + if(curr_bit_size == 13) + { + curr_bit_size = 12; + bit_overflow = 1; + } + } + + output_string(); + old = code; + } + } + + break; + + case 0x21: /* Extension Introducer */ + i = pack_getc(f); + + if(i == 0xF9) /* Graphic Control Extension */ + { + pack_fseek(f, 1); /* skip size (it's 4) */ + i = pack_getc(f); + + if(i & 1) /* is transparency enabled? */ + { + pack_fseek(f, 2); + pack_getc(f); /* transparent colour */ + } + else + pack_fseek(f, 3); + } + + i = pack_getc(f); + + while(i) /* skip Data Sub-blocks */ + { + pack_fseek(f, i); + i = pack_getc(f); + } + + break; + + case 0x3B: /* Trailer - end of data */ + pack_fclose(f); + + /* convert to correct colour depth */ + dest_depth = _color_load_depth(8,0); + + if(dest_depth != 8) + { + bmp2 = create_bitmap_ex(dest_depth, bmp->w, bmp->h); + + if(!bmp2) + { + destroy_bitmap(bmp); + return NULL; + } + + select_palette(pal); + blit(bmp, bmp2, 0, 0, 0, 0, bmp->w, bmp->h); + unselect_palette(); + + destroy_bitmap(bmp); + bmp = bmp2; + } + + return bmp; + } + } + + /* this is never executed but DJGPP complains if you leave it out */ + //return NULL;//UNREACHABLE +} + diff --git a/src/load_gif.h b/src/load_gif.h new file mode 100644 index 0000000000..1e913f4821 --- /dev/null +++ b/src/load_gif.h @@ -0,0 +1,15 @@ +#ifndef LOAD_GIF_H +#define LOAD_GIF_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +BITMAP *load_gif(const char *filename, RGB *pal); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/maps.cpp b/src/maps.cpp new file mode 100644 index 0000000000..886caf79ee --- /dev/null +++ b/src/maps.cpp @@ -0,0 +1,4703 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// maps.cc +// +// Map and screen scrolling stuff for zelda.cc +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include +#include +#include + +//#include "zc_math.h" +#include "ffc.h" +#include "maps.h" +#include "zelda.h" +#include "zc_sys.h" +#include "tiles.h" +#include "sprite.h" +#include "jwin.h" +#include "zsys.h" +#include "subscr.h" +#include "zc_subscr.h" +#include "link.h" +#include "guys.h" +#include "ffscript.h" +#include "particles.h" +#include "mem_debug.h" +#include "messageManager.h" +#include "room.h" +#include "sound.h" + +#define EPSILON 0.01 // Define your own tolerance +#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON))) + + +//MSVC does not provide a log2 funcion in +#ifdef _MSC_VER +double log2(double n) +{ + return log(n) / log(2.0); +} +float log2(float n) +{ + return log(n) / log(2.f); +} +#endif + + +FONT *get_zc_font(int index); + +extern MessageManager messageMgr; +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations, particles; +extern movingblock mblock2; //mblock[4]? +extern zinitdata zinit; +extern LinkClass Link; +int current_ffcombo=-1; + +int draw_screen_clip_rect_x1=0; +int draw_screen_clip_rect_x2=255; +int draw_screen_clip_rect_y1=0; +int draw_screen_clip_rect_y2=223; + + + +void Z_message_d(const char *format,...) +{ +#ifdef _DEBUG + char buf[512]; + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + + al_trace("%s",buf); +#else + format=format; +#endif +} + + + +//bool draw_screen_clip_rect_show_link=true; +//bool draw_screen_clip_rect_show_guys=false; +bool checktrigger=false; + +void debugging_box(int x1, int y1, int x2, int y2) +{ + //reference/optimization: the start of the unused drawing command index can now be queried. -Gleeok + int index = script_drawing_commands.GetNext(); + + if(index < 0) + return; + + int *sdci = &script_drawing_commands[index][0]; + + sdci[0] = RECTR; + sdci[1] = 30000; + sdci[2] = x1*10000; + sdci[3] = y1*10000; + sdci[4] = x2*10000; + sdci[5] = y2*10000; + sdci[6] = 10000; + sdci[7] = 10000; + sdci[8] = 0; + sdci[9] = 0; + sdci[10] = 0; + sdci[11] = 10000; + sdci[12] = 1280000; +} + +void clear_dmap(word i) +{ + memset(&DMaps[i],0,sizeof(dmap)); +} + +void clear_dmaps() +{ + for(int i=0; i175 || combo < 0) + return 0; + + return tmpscr->data[combo]; // entire combo code +} + +int MAPFFCOMBO(int x,int y) +{ + for(int i=0; iffcs[i].isUnderPoint(x, y)) + return tmpscr->ffcs[i].getCombo(); + } + + return 0; +} + +int MAPCSET(int x,int y) +{ + if(x<0 || x>255 || y<0 || y>175) + return 0; + + int combo = COMBOPOS(x,y); + return tmpscr->cset[combo]; // entire combo code +} + +int MAPFLAG(int x,int y) +{ + if(x<0 || x>255 || y<0 || y>175) + return 0; + + int combo = COMBOPOS(x,y); + return tmpscr->sflag[combo]; // flag +} + +int COMBOTYPE(int x,int y) +{ + return combobuf[MAPCOMBO(x,y)].type; +} + +int FFCOMBOTYPE(int x,int y) +{ + return combobuf[MAPFFCOMBO(x,y)].type; +} + +int MAPCOMBOFLAG(int x,int y) +{ + if(x<0 || x>255 || y<0 || y>175) + return 0; + + int combo = COMBOPOS(x,y); + return combobuf[tmpscr->data[combo]].flag; // entire combo code +} + +int MAPFFCOMBOFLAG(int x,int y) +{ + for(int i=0; iffcs[i].isUnderPoint(x, y)) + { + current_ffcombo = i; + return combobuf[tmpscr->ffcs[i].getCombo()].flag; + } + } + + current_ffcombo=-1; + return 0; +} + +int getFFCAt(int x, int y) +{ + for(int i=0; iffcs[i].isUnderPoint(x, y)) + return i; + } + + return -1; +} + +int MAPCOMBO2(int layer,int x,int y) +{ + if(layer<=-1) return MAPCOMBO(x,y); + + if(tmpscr2[layer].data.empty()) return 0; + + if(tmpscr2[layer].valid==0) return 0; + + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return tmpscr2[layer].data[combo]; // entire combo code +} + +int MAPCSET2(int layer,int x,int y) +{ + if(layer==-1) return MAPCSET(x,y); + + if(tmpscr2[layer].cset.empty()) return 0; + + if(tmpscr2[layer].valid==0) return 0; + + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return tmpscr2[layer].cset[combo]; // entire combo code +} + +int MAPFLAG2(int layer,int x,int y) +{ + if(layer==-1) return MAPFLAG(x,y); + + if(tmpscr2[layer].sflag.empty()) return 0; + + if(tmpscr2[layer].valid==0) return 0; + + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return tmpscr2[layer].sflag[combo]; // flag +} + +int COMBOTYPE2(int layer,int x,int y) +{ + if(layer==-1) return COMBOTYPE(x,y); + + if(tmpscr2[layer].valid==0) + { + return 0; + } + + return combobuf[MAPCOMBO2(layer,x,y)].type; +} + +int MAPCOMBOFLAG2(int layer,int x,int y) +{ + if(layer==-1) return MAPCOMBOFLAG(x,y); + + if(tmpscr2[layer].data.empty()) return 0; + + if(tmpscr2[layer].valid==0) return 0; + + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return combobuf[tmpscr2[layer].data[combo]].flag; // entire combo code +} + +void setmapflag(int flag) +{ + setmapflag((currmap*MAPSCRSNORMAL)+homescr,flag); +} + +const char *screenstate_string[15] = +{ + "Door Up", "Door Down", "Door Left", "Door Right", "Item", "Special Item", "No Return", + "Temporary No Return", "Lock Blocks", "Boss Lock Blocks", "Treasure Chests", "Locked Chests", + "Boss Locked Chests", "Secrets", "Visited" +}; + +void eventlog_mapflag_line(word* g, word flag, int ss_s_index) +{ + if((*g)&flag) + { + (*g)&=~flag; + Z_eventlog("%s%s", screenstate_string[ss_s_index], (*g)!=0 ? ", " : ""); + } +} + +void eventlog_mapflags() +{ + word g = game->maps[(currmap*MAPSCRSNORMAL)+homescr] &0x3FFF; + word g2 = g; + Z_eventlog("Screen (%d, %02x) %s", currmap+1, homescr, (g2) != 0 ? "[":""); + // Print them in order of importance. + eventlog_mapflag_line(&g, mSECRET,13); + eventlog_mapflag_line(&g, mITEM,4); + eventlog_mapflag_line(&g, mBELOW,5); + eventlog_mapflag_line(&g, mLOCKBLOCK,8); + eventlog_mapflag_line(&g, mBOSSLOCKBLOCK,9); + eventlog_mapflag_line(&g, mCHEST,10); + eventlog_mapflag_line(&g, mLOCKEDCHEST,11); + eventlog_mapflag_line(&g, mBOSSCHEST,12); + eventlog_mapflag_line(&g, mDOOR_UP,0); + eventlog_mapflag_line(&g, mDOOR_DOWN,1); + eventlog_mapflag_line(&g, mDOOR_LEFT,2); + eventlog_mapflag_line(&g, mDOOR_RIGHT,3); + eventlog_mapflag_line(&g, mNEVERRET,6); + eventlog_mapflag_line(&g, mTMPNORET,7); + Z_eventlog("%s\n",g2 != 0 ? "]":""); +} + +// set specific flag +void setmapflag(int mi2, int flag) +{ + byte cscr = mi2&((1<<7)-1); + byte cmap = (mi2>>7); + char buf[20]; + sprintf(buf,"Screen (%d, %02X)",cmap+1,cscr); + + game->maps[mi2] |= flag; + Z_eventlog("%s's State was set: %s\n", + mi2 != (currmap*MAPSCRSNORMAL)+homescr ? buf : "Current screen", + flag>0 ? screenstate_string[(int)log2((float)flag)] : ""); + + if(flag==mSECRET||flag==mITEM||flag==mBELOW||flag==mLOCKBLOCK|| + flag==mBOSSLOCKBLOCK||flag==mCHEST||flag==mBOSSCHEST||flag==mLOCKEDCHEST) + { + byte nmap=TheMaps[((cmap)*MAPSCRS)+cscr].nextmap; + byte nscr=TheMaps[((cmap)*MAPSCRS)+cscr].nextscr; + + std::vector done; + bool looped = (nmap==cmap+1 && nscr==cscr); + + while((nmap!=0) && !looped && !(nscr>=128)) + { + if((tmpscr->nocarry&flag)!=flag) + { + Z_eventlog("State change carried over to (%d, %02X)\n",nmap,nscr); + game->maps[((nmap-1)<<7)+nscr] |= flag; + } + + cmap=nmap; + cscr=nscr; + nmap=TheMaps[((cmap-1)*MAPSCRS)+cscr].nextmap; + nscr=TheMaps[((cmap-1)*MAPSCRS)+cscr].nextscr; + + for(std::vector::iterator it = done.begin(); it != done.end(); it++) + { + if(*it == ((nmap-1)<<7)+nscr) + looped = true; + } + + done.push_back(((nmap-1)<<7)+nscr); + } + } +} + +void unsetmapflag(int flag) +{ + unsetmapflag((currmap*MAPSCRSNORMAL)+homescr,flag); +} + +void unsetmapflag(int mi2, int flag, bool anyflag) +{ + if(anyflag) + game->maps[mi2] &= ~flag; + else if(flag==mITEM || flag==mBELOW) + { + if(!(tmpscr->flags4&fNOITEMRESET)) + game->maps[mi2] &= ~flag; + } + else game->maps[(currmap*MAPSCRSNORMAL)+homescr] &= ~flag; + + byte cscr = mi2&((1<<7)-1); + byte cmap = (mi2>>7); + char buf[20]; + sprintf(buf,"Screen (%d, %02X)",cmap+1,cscr); + + Z_eventlog("%s's State was unset: %s\n", + mi2 != (currmap*MAPSCRSNORMAL)+homescr ? buf : "Current screen", + flag>0 ? screenstate_string[(int)log2((float)flag)] : ""); + + if(flag==mSECRET||flag==mITEM||flag==mBELOW||flag==mLOCKBLOCK|| + flag==mBOSSLOCKBLOCK||flag==mCHEST||flag==mBOSSCHEST||flag==mLOCKEDCHEST) + { + byte nmap=TheMaps[((cmap)*MAPSCRS)+cscr].nextmap; + byte nscr=TheMaps[((cmap)*MAPSCRS)+cscr].nextscr; + + std::vector done; + bool looped = (nmap==cmap+1 && nscr==cscr); + + while((nmap!=0) && !looped && !(nscr>=128)) + { + if((tmpscr->nocarry&flag)!=flag) + { + Z_eventlog("State change carried over to (%d, %02X)\n",nmap,nscr); + game->maps[((nmap-1)<<7)+nscr] &= ~flag; + } + + cmap=nmap; + cscr=nscr; + nmap=TheMaps[((cmap-1)*MAPSCRS)+cscr].nextmap; + nscr=TheMaps[((cmap-1)*MAPSCRS)+cscr].nextscr; + + for(std::vector::iterator it = done.begin(); it != done.end(); it++) + { + if(*it == ((nmap-1)<<7)+nscr) + looped = true; + } + + done.push_back(((nmap-1)<<7)+nscr); + } + } +} + +bool getmapflag(int flag) +{ + return (game->maps[(currmap*MAPSCRSNORMAL)+homescr] & flag) != 0; +} + +int WARPCODE(int dmap,int scr,int dw) +// returns: -1 = not a warp screen +// 0+ = warp screen code ( high byte=dmap, low byte=scr ) +{ + mapscr *s = &TheMaps[DMaps[dmap].map*MAPSCRS+scr]; + + if(s->room!=rWARP) + return -1; + + int ring=s->catchall; + int size=QMisc.warp[ring].size; + + if(size==0) + return -2; + + int index=-1; + + for(int i=0; idata[i]; + y=animated_combo_table[x][0]; + + if(combobuf[x].animflags & AF_FRESH) continue; + + //time to restart + if((animated_combo_table4[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c=newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + x=tmpscr->data[i]; + y=animated_combo_table2[x][0]; + + if(!(combobuf[x].animflags & AF_FRESH)) continue; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c=newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + if(newdata[i]==-1) + continue; + + screen_combo_modify_preroutine(tmpscr,i); + tmpscr->data[i]=newdata[i]; + tmpscr->cset[i]=newcset[i]; + screen_combo_modify_postroutine(tmpscr,i); + + newdata[i]=-1; + newcset[i]=-1; + } + + for(int i=0; iffcs[i].getCombo(); + y=animated_combo_table[x][0]; + + if(combobuf[x].animflags & AF_FRESH) continue; + + //time to restart + if((animated_combo_table4[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c=newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; iffcs[i].getCombo(); + y=animated_combo_table2[x][0]; + + if(!(combobuf[x].animflags & AF_FRESH)) continue; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c=newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + } + } + + for(int i=0; iffcs[i].setCombo(newdata[i]); + tmpscr->ffcs[i].setCSet(newcset[i]); + + newdata[i]=-1; + newcset[i]=-1; + } + + if(get_bit(quest_rules,qr_CMBCYCLELAYERS)) + { + for(int j=0; j<6; j++) + { + if(tmpscr2[j].data.empty()) continue; + + for(int i=0; i<176; i++) + { + x=(tmpscr2+j)->data[i]; + y=animated_combo_table[x][0]; + + if(combobuf[x].animflags & AF_FRESH) continue; + + //time to restart + if((animated_combo_table4[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c=newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + x=(tmpscr2+j)->data[i]; + y=animated_combo_table2[x][0]; + + if(!(combobuf[x].animflags & AF_FRESH)) continue; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata2[i]=combobuf[x].nextcombo; + newcset2[i]=combobuf[x].nextcset; + int c=newdata2[i]; + int cs=newcset2[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + + if(combobuf[c].type==cSPINTILE1) + { + // Uses animated_combo_table2 + addenemy((i&15)<<4,i&0xF0,(cs<<12)+eSPINTILE1,animated_combo_table2[c][1]+zc_max(1,combobuf[c].frames)); + } + } + } + + for(int i=0; i<176; i++) + { + if(newdata[i]!=-1) + { + screen_combo_modify_preroutine(tmpscr2+j,i); + (tmpscr2+j)->data[i]=newdata[i]; + (tmpscr2+j)->cset[i]=newcset[i]; + screen_combo_modify_postroutine(tmpscr2+j,i); + + newdata[i]=-1; + newcset[i]=-1; + } + + if(newdata2[i]!=-1) + { + (tmpscr2+j)->data[i]=newdata2[i]; + (tmpscr2+j)->cset[i]=newcset2[i]; + newdata2[i]=-1; + newcset2[i]=-1; + } + } + } + } + + for(int i=0; i=0; i--) + { + int c = MAPCOMBO2(i-1,bx,by); + int t = combobuf[c].type; + + if(i == 0 && (t == cHOOKSHOTONLY || t == cLADDERHOOKSHOT)) return true; + + bool dried = (iswater_type(t) && DRIEDLAKE); + + int b=1; + + if(bx&8) b<<=2; + + if(by&8) b<<=1; + + if(combobuf[c].walk&b && !dried && !(combo_class_buf[t].ladder_pass && t!=cLADDERONLY) && t!=cHOOKSHOTONLY) + ret = false; + } + + return ret; +} + +bool hiddenstair(int tmp,bool redraw) // tmp = index of tmpscr[] +{ + mapscr *s = tmpscr + tmp; + + if((s->stairx || s->stairy) && s->secretcombo[sSTAIRS]) + { + int di = COMBOPOS(s->stairx,s->stairy); + s->data[di] = s->secretcombo[sSTAIRS]; + s->cset[di] = s->secretcset[sSTAIRS]; + s->sflag[di] = s->secretflag[sSTAIRS]; + + if(redraw) + putcombo(scrollbuf,s->stairx,s->stairy,s->data[di],s->cset[di]); + + return true; + } + + return false; +} + +bool remove_screenstatecombos(int tmp, int what1, int what2) +{ + mapscr *s = tmpscr + tmp; + mapscr *t = tmpscr2; + bool didit=false; + + for(int i=0; i<176; i++) + { + if((combobuf[s->data[i]].type== what1) || + (combobuf[s->data[i]].type== what2)) + { + s->data[i]++; + didit=true; + } + } + + for(int j=0; j<6; j++) + { + if(t[j].data.empty()) continue; + + for(int i=0; i<176; i++) + { + if((combobuf[t[j].data[i]].type== what1) || + (combobuf[t[j].data[i]].type== what2)) + { + t[j].data[i]++; + didit=true; + } + } + } + + return didit; +} + +bool remove_lockblocks(int tmp) +{ + return remove_screenstatecombos(tmp, cLOCKBLOCK, cLOCKBLOCK2); +} + +bool remove_bosslockblocks(int tmp) +{ + return remove_screenstatecombos(tmp, cBOSSLOCKBLOCK, cBOSSLOCKBLOCK2); +} + +bool remove_chests(int tmp) // tmp = index of tmpscr[] +{ + return remove_screenstatecombos(tmp, cCHEST, cCHEST2); +} + +bool remove_lockedchests(int tmp) // tmp = index of tmpscr[] +{ + return remove_screenstatecombos(tmp, cLOCKEDCHEST, cLOCKEDCHEST2); +} + +bool remove_bosschests(int tmp) // tmp = index of tmpscr[] +{ + return remove_screenstatecombos(tmp, cBOSSCHEST, cBOSSCHEST2); +} + + +bool overheadcombos(mapscr *s) +{ + for(int i=0; i<176; i++) + { +// if (combobuf[s->data[i]].type==cOLD_OVERHEAD) + if(combo_class_buf[combobuf[s->data[i]].type].overhead) + { + return true; + } + } + + return false; +} + +void delete_fireball_shooter(mapscr *s, int i) +{ + int cx=0, cy=0; + int ct=combobuf[s->data[i]].type; + + if(ct!=cL_STATUE && ct!=cR_STATUE && ct!=cC_STATUE) + return; + + switch(ct) + { + case cL_STATUE: + cx=((i&15)<<4)+4; + cy=(i&0xF0)+7; + break; + + case cR_STATUE: + cx=((i&15)<<4)-8; + cy=(i&0xF0)-1; + break; + + case cC_STATUE: + cx=((i&15)<<4); + cy=(i&0xF0); + break; + } + + for(int j=0; jx)==cx)&&(int(guys.spr(j)->y)==cy)&&(guysbuf[(guys.spr(j)->id)&0xFFF].flags2 & eneflag_fire)) + { + guys.del(j); + } + } +} + +int findtrigger(int scombo, bool ff) +{ + int checkflag=0; + int iter; + int ret = 0; + + for(int j=0; j<(ff?MAXFFCS:176); j++) + { + if(ff) + { + checkflag=combobuf[tmpscr->ffcs[j].getCombo()].flag; + iter=1; + } + else iter=2; + + for(int layer=-1; !ff && layer<6; layer++) + { + if(layer>-1 && tmpscr2[layer].valid==0) continue; + + for(int i=0; i-1 ? combobuf[tmpscr2[layer].data[j]].flag : combobuf[tmpscr->data[j]].flag); + else if(i==1&&!ff) + checkflag = (layer>-1 ? tmpscr2[layer].sflag[j] : tmpscr->sflag[j]); + + switch(checkflag) + { + case mfBCANDLE: + case mfRCANDLE: + case mfWANDFIRE: + case mfDINSFIRE: + case mfARROW: + case mfSARROW: + case mfGARROW: + case mfSBOMB: + case mfBOMB: + case mfBRANG: + case mfMBRANG: + case mfFBRANG: + case mfWANDMAGIC: + case mfREFMAGIC: + case mfREFFIREBALL: + case mfSWORD: + case mfWSWORD: + case mfMSWORD: + case mfXSWORD: + case mfSWORDBEAM: + case mfWSWORDBEAM: + case mfMSWORDBEAM: + case mfXSWORDBEAM: + case mfHOOKSHOT: + case mfWAND: + case mfHAMMER: + case mfSTRIKE: + if(scombo!=j) + ret += 1; + + default: + break; + } + } + } + } + + return ret; +} + +// single: +// >-1 : the singular triggering combo +// -1: triggered by some other cause +// -2: triggered by Enemies->Secret +// -3: triggered by Secrets screen state +// -4: Screen->TriggerSecrets() +void hidden_entrance(int tmp,bool , bool high16only,int single) //Perhaps better known as 'Trigger Secrets' +{ + //There are no calls to 'hidden_entrance' in the code where tmp != 0 + Z_eventlog("%sScreen Secrets triggered%s.\n", + single>-1? "Restricted ":"", + single==-2? " by the 'Enemies->Secret' screen flag": + single==-3? " by the 'Secrets' screen state" : + single==-4? " by a script":""); + mapscr *s = tmpscr + tmp; + mapscr *t = tmpscr2; + int ft=0; //Flag trigger? + int msflag=0; // Misc. secret flag + + for(int i=0; i<176; i++) //Do the 'trigger flags' (non 16-31) + { + if(single>=0 && i!=single) continue; //If it's got a singular flag and i isn't where the flag is + + bool putit; + + // Remember the misc. secret flag; if triggered, use this instead + if(s->sflag[i]>=mfSECRETS01 && s->sflag[i]<=mfSECRETS16) + msflag=sSECRET01+(s->sflag[i]-mfSECRETS01); + else if(combobuf[s->data[i]].flag>=mfSECRETS01 && combobuf[s->data[i]].flag<=mfSECRETS16) + msflag=sSECRET01+(combobuf[s->data[i]].flag-mfSECRETS01); + else + msflag=0; + + if(!high16only || single>=0) + { + int newflag = -1; + + + for(int iter=0; iter<2; ++iter) + { + putit=true; + int checkflag=combobuf[s->data[i]].flag; //Inherent + + if(iter==1) checkflag=s->sflag[i]; //Placed + + switch(checkflag) + { + case mfBCANDLE: + ft=sBCANDLE; + break; + + case mfRCANDLE: + ft=sRCANDLE; + break; + + case mfWANDFIRE: + ft=sWANDFIRE; + break; + + case mfDINSFIRE: + ft=sDINSFIRE; + break; + + case mfARROW: + ft=sARROW; + break; + + case mfSARROW: + ft=sSARROW; + break; + + case mfGARROW: + ft=sGARROW; + break; + + case mfSBOMB: + ft=sSBOMB; + break; + + case mfBOMB: + ft=sBOMB; + break; + + case mfBRANG: + ft=sBRANG; + break; + + case mfMBRANG: + ft=sMBRANG; + break; + + case mfFBRANG: + ft=sFBRANG; + break; + + case mfWANDMAGIC: + ft=sWANDMAGIC; + break; + + case mfREFMAGIC: + ft=sREFMAGIC; + break; + + case mfREFFIREBALL: + ft=sREFFIREBALL; + break; + + case mfSWORD: + ft=sSWORD; + break; + + case mfWSWORD: + ft=sWSWORD; + break; + + case mfMSWORD: + ft=sMSWORD; + break; + + case mfXSWORD: + ft=sXSWORD; + break; + + case mfSWORDBEAM: + ft=sSWORDBEAM; + break; + + case mfWSWORDBEAM: + ft=sWSWORDBEAM; + break; + + case mfMSWORDBEAM: + ft=sMSWORDBEAM; + break; + + case mfXSWORDBEAM: + ft=sXSWORDBEAM; + break; + + case mfHOOKSHOT: + ft=sHOOKSHOT; + break; + + case mfWAND: + ft=sWAND; + break; + + case mfHAMMER: + ft=sHAMMER; + break; + + case mfSTRIKE: + ft=sSTRIKE; + break; + + default: + putit = false; + break; + } + + if(putit) //Change the combos for the secret + { + // Use misc. secret flag instead if one is present + if(msflag!=0) + ft=msflag; + + screen_combo_modify_preroutine(s,i); + s->data[i] = s->secretcombo[ft]; + s->cset[i] = s->secretcset[ft]; + newflag = s->secretflag[ft]; + screen_combo_modify_postroutine(s,i); + } + } + + if(newflag >-1) s->sflag[i] = newflag; //Tiered secret + + for(int j=0; j<6; j++) //Layers + { + if(t[j].data.empty()||t[j].cset.empty()) continue; //If layer isn't used + + if(single>=0 && i!=single) continue; //If it's got a singular flag and i isn't where the flag is + + int newflag2 = -1; + + // Remember the misc. secret flag; if triggered, use this instead + if(t[j].sflag[i]>=mfSECRETS01 && t[j].sflag[i]<=mfSECRETS16) + msflag=sSECRET01+(t[j].sflag[i]-mfSECRETS01); + else if(combobuf[t[j].data[i]].flag>=mfSECRETS01 && combobuf[t[j].data[i]].flag<=mfSECRETS16) + msflag=sSECRET01+(combobuf[t[j].data[i]].flag-mfSECRETS01); + else + msflag=0; + + for(int iter=0; iter<2; ++iter) + { + putit=true; + int checkflag=combobuf[t[j].data[i]].flag; //Inherent + + if(iter==1) checkflag=t[j].sflag[i]; //Placed + + switch(checkflag) + { + case mfBCANDLE: + ft=sBCANDLE; + break; + + case mfRCANDLE: + ft=sRCANDLE; + break; + + case mfWANDFIRE: + ft=sWANDFIRE; + break; + + case mfDINSFIRE: + ft=sDINSFIRE; + break; + + case mfARROW: + ft=sARROW; + break; + + case mfSARROW: + ft=sSARROW; + break; + + case mfGARROW: + ft=sGARROW; + break; + + case mfSBOMB: + ft=sSBOMB; + break; + + case mfBOMB: + ft=sBOMB; + break; + + case mfBRANG: + ft=sBRANG; + break; + + case mfMBRANG: + ft=sMBRANG; + break; + + case mfFBRANG: + ft=sFBRANG; + break; + + case mfWANDMAGIC: + ft=sWANDMAGIC; + break; + + case mfREFMAGIC: + ft=sREFMAGIC; + break; + + case mfREFFIREBALL: + ft=sREFFIREBALL; + break; + + case mfSWORD: + ft=sSWORD; + break; + + case mfWSWORD: + ft=sWSWORD; + break; + + case mfMSWORD: + ft=sMSWORD; + break; + + case mfXSWORD: + ft=sXSWORD; + break; + + case mfSWORDBEAM: + ft=sSWORDBEAM; + break; + + case mfWSWORDBEAM: + ft=sWSWORDBEAM; + break; + + case mfMSWORDBEAM: + ft=sMSWORDBEAM; + break; + + case mfXSWORDBEAM: + ft=sXSWORDBEAM; + break; + + case mfHOOKSHOT: + ft=sHOOKSHOT; + break; + + case mfWAND: + ft=sWAND; + break; + + case mfHAMMER: + ft=sHAMMER; + break; + + case mfSTRIKE: + ft=sSTRIKE; + break; + + default: + putit = false; + break; + } + + if(putit) //Change the combos for the secret + { + // Use misc. secret flag instead if one is present + if(msflag!=0) + ft=msflag; + + t[j].data[i] = t[j].secretcombo[ft]; + t[j].cset[i] = t[j].secretcset[ft]; + newflag2 = t[j].secretflag[ft]; + int c=t[j].data[i]; + int cs=t[j].cset[i]; + + if(combobuf[c].type==cSPINTILE1) //Surely this means we can have spin tiles on layers 3+? Isn't that bad? ~Joe123 + addenemy((i&15)<<4,i&0xF0,(cs<<12)+eSPINTILE1,animated_combo_table[c][1]+zc_max(1,combobuf[c].frames)); + } + } + + if(newflag2 >-1) t[j].sflag[i] = newflag2; //Tiered secret + } + } + } + + for(int i=0; i=0) if(i+176!=single) continue; + + bool putit; + + if((!high16only)||(single>=0)) + { + //for (int iter=0; iter<1; ++iter) // Only one kind of FFC flag now. + { + putit=true; + int checkflag=combobuf[s->ffcs[i].getCombo()].flag; //Inherent + + //No placed flags yet + switch(checkflag) + { + case mfBCANDLE: + ft=sBCANDLE; + break; + + case mfRCANDLE: + ft=sRCANDLE; + break; + + case mfWANDFIRE: + ft=sWANDFIRE; + break; + + case mfDINSFIRE: + ft=sDINSFIRE; + break; + + case mfARROW: + ft=sARROW; + break; + + case mfSARROW: + ft=sSARROW; + break; + + case mfGARROW: + ft=sGARROW; + break; + + case mfSBOMB: + ft=sSBOMB; + break; + + case mfBOMB: + ft=sBOMB; + break; + + case mfBRANG: + ft=sBRANG; + break; + + case mfMBRANG: + ft=sMBRANG; + break; + + case mfFBRANG: + ft=sFBRANG; + break; + + case mfWANDMAGIC: + ft=sWANDMAGIC; + break; + + case mfREFMAGIC: + ft=sREFMAGIC; + break; + + case mfREFFIREBALL: + ft=sREFFIREBALL; + break; + + case mfSWORD: + ft=sSWORD; + break; + + case mfWSWORD: + ft=sWSWORD; + break; + + case mfMSWORD: + ft=sMSWORD; + break; + + case mfXSWORD: + ft=sXSWORD; + break; + + case mfSWORDBEAM: + ft=sSWORDBEAM; + break; + + case mfWSWORDBEAM: + ft=sWSWORDBEAM; + break; + + case mfMSWORDBEAM: + ft=sMSWORDBEAM; + break; + + case mfXSWORDBEAM: + ft=sXSWORDBEAM; + break; + + case mfHOOKSHOT: + ft=sHOOKSHOT; + break; + + case mfWAND: + ft=sWAND; + break; + + case mfHAMMER: + ft=sHAMMER; + break; + + case mfSTRIKE: + ft=sSTRIKE; + break; + + default: + putit = false; + break; + } + + if(putit) //Change the ffc's combo + { + s->ffcs[i].setCombo(s->secretcombo[ft]); + s->ffcs[i].setCSet(s->secretcset[ft]); + } + } + } + } + + if(checktrigger) //Hit all triggers->16-31 + { + checktrigger=false; + + if(tmpscr->flags6&fTRIGGERF1631) + { + int tr = findtrigger(-1,false); //Normal flags + + if(tr) + { + Z_eventlog("Hit All Triggers->16-31 not fulfilled (%d trigger flag%s remain).\n", tr, tr>1?"s":""); + goto endhe; + } + + int ftr = findtrigger(-1,true); //FFCs + + if(ftr) + { + Z_eventlog("Hit All Triggers->16-31 not fulfilled (%d trigger FFC%s remain).\n", ftr, ftr>1?"s":""); + goto endhe; + } + } + } + + for(int i=0; i<176; i++) // Do the 16-31 secrets + { + //If it's an enemies->secret screen, only do the high 16 if told to + //That way you can have secret and burn/bomb entrance separately + if((!(s->flags2&fCLEARSECRET) /*Enemies->Secret*/ && single < 0) || high16only || s->flags4&fENEMYSCRTPERM) + { + int newflag = -1; + + for(int iter=0; iter<2; ++iter) + { + int checkflag=combobuf[s->data[i]].flag; //Inherent + + if(iter==1) checkflag=s->sflag[i]; //Placed + + if((checkflag > 15)&&(checkflag < 32)) //If we've got a 16->32 flag change the combo + { + screen_combo_modify_preroutine(s,i); + s->data[i] = s->secretcombo[checkflag-16+4]; + s->cset[i] = s->secretcset[checkflag-16+4]; + newflag = s->secretflag[checkflag-16+4]; + screen_combo_modify_postroutine(s,i); + } + } + + if(newflag >-1) s->sflag[i] = newflag; //Tiered flag + + for(int j=0; j<6; j++) //Layers + { + if(t[j].data.empty()||t[j].cset.empty()) continue; //If layer is not valid (surely checking for 'valid' would be better?) + + int newflag2 = -1; + + for(int iter=0; iter<2; ++iter) + { + int checkflag=combobuf[t[j].data[i]].flag; //Inherent + + if(iter==1) checkflag=t[j].sflag[i]; //Placed + + if((checkflag > 15)&&(checkflag < 32)) //If we've got a 16->32 flag change the combo + { + t[j].data[i] = t[j].secretcombo[checkflag-16+4]; + t[j].cset[i] = t[j].secretcset[checkflag-16+4]; + newflag2 = t[j].secretflag[checkflag-16+4]; + } + } + + if(newflag2 >-1) t[j].sflag[i] = newflag2; //Tiered flag + } + } + + /* + if(putit && refresh) + putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]); + */ + } + + for(int i=0; iflags2&fCLEARSECRET) /*Enemies->Secret*/ && single < 0) || high16only || s->flags4&fENEMYSCRTPERM) + { + for(int iter=0; iter<1; ++iter) // Only one kind of FFC flag now. + { + int checkflag=combobuf[s->ffcs[i].getCombo()].flag; //Inherent + + //No placed flags yet + if((checkflag > 15)&&(checkflag < 32)) //If we find a flag, change the combo + { + s->ffcs[i].setCombo(s->secretcombo[checkflag-16+4]); + s->ffcs[i].setCSet(s->secretcset[checkflag-16+4]); + } + } + } + } + +endhe: + + if(tmpscr->flags4&fDISABLETIME) //Finish timed warp if 'Secrets Disable Timed Warp' + { + activated_timed_warp=true; + tmpscr->timedwarptics = 0; + } +} + + +bool findentrance(int x, int y, int flag, bool setflag) +{ + bool foundflag=false; + bool foundcflag=false; + bool foundnflag=false; + bool foundfflag=false; + //bool ffcombosingle = false; + int ffcombos[4] = {-1, -1, -1, -1}; + bool single16=false; + int scombo=-1; + + for(int i=-1; i<6; i++) // Layers. -1 = screen. + { + if(MAPFLAG2(i,x,y)==flag || MAPFLAG2(i,x+15,y)==flag || + MAPFLAG2(i,x,y+15)==flag || MAPFLAG2(i,x+15,y+15)==flag) + { + foundflag=true; + foundnflag=true; + } + } + + for(int i=-1; i<6; i++) // Layers. -1 = screen. + { + if(MAPCOMBOFLAG2(i,x,y)==flag || MAPCOMBOFLAG2(i,x+15,y)==flag || + MAPCOMBOFLAG2(i,x,y+15)==flag || MAPCOMBOFLAG2(i,x+15,y+15)==flag) + { + foundflag=true; + foundcflag=true; + } + } + + if(MAPFFCOMBOFLAG(x,y)==flag) + { + foundflag=true; + foundfflag=true; + } + + ffcombos[0] = current_ffcombo; + + if(MAPFFCOMBOFLAG(x+15,y)==flag) + { + foundflag=true; + foundfflag=true; + } + + ffcombos[1] = current_ffcombo; + + if(MAPFFCOMBOFLAG(x,y+15)==flag) + { + foundflag=true; + foundfflag=true; + } + + ffcombos[2] = current_ffcombo; + + if(MAPFFCOMBOFLAG(x+15,y+15)==flag) + { + foundflag=true; + foundfflag=true; + } + + ffcombos[3] = current_ffcombo; + + if(!foundflag) + { + return false; + } + + for(int i=-1; i<6; i++) // Look for Trigger->Self on all layers + { + if(foundnflag) // Trigger->Self (a.k.a Singular) is inherent + { + if((MAPCOMBOFLAG2(i,x,y)==mfSINGLE)&&(MAPFLAG2(i,x,y)==flag)) + { + scombo=COMBOPOS(x,y); + } + else if((MAPCOMBOFLAG2(i,x,y)==mfSINGLE16)&&(MAPFLAG2(i,x,y)==flag)) + { + scombo=COMBOPOS(x,y); + single16=true; + } + else if((MAPCOMBOFLAG2(i,x+15,y)==mfSINGLE)&&(MAPFLAG2(i,x+15,y)==flag)) + { + scombo=COMBOPOS(x+15,y); + } + else if((MAPCOMBOFLAG2(i,x+15,y)==mfSINGLE16)&&(MAPFLAG2(i,x+15,y)==flag)) + { + scombo=COMBOPOS(x+15,y); + single16=true; + } + else if((MAPCOMBOFLAG2(i,x,y+15)==mfSINGLE)&&(MAPFLAG2(i,x,y+15)==flag)) + { + scombo=COMBOPOS(x,y+15); + } + else if((MAPCOMBOFLAG2(i,x,y+15)==mfSINGLE16)&&(MAPFLAG2(i,x,y+15)==flag)) + { + scombo=COMBOPOS(x,y+15); + single16=true; + } + else if((MAPCOMBOFLAG2(i,x+15,y+15)==mfSINGLE)&&(MAPFLAG2(i,x+15,y+15)==flag)) + { + scombo=COMBOPOS(x+15,y+15); + } + else if((MAPCOMBOFLAG2(i,x+15,y+15)==mfSINGLE16)&&(MAPFLAG2(i,x+15,y+15)==flag)) + { + scombo=COMBOPOS(x+15,y+15); + single16=true; + } + } + + if(foundcflag) // Trigger->Self (a.k.a Singular) is non-inherent + { + if((MAPFLAG2(i,x,y)==mfSINGLE)&&(MAPCOMBOFLAG2(i,x,y)==flag)) + { + scombo=COMBOPOS(x,y); + } + else if((MAPFLAG2(i,x,y)==mfSINGLE16)&&(MAPCOMBOFLAG2(i,x,y)==flag)) + { + scombo=COMBOPOS(x,y); + single16=true; + } + else if((MAPFLAG2(i,x+15,y)==mfSINGLE)&&(MAPCOMBOFLAG2(i,x+15,y)==flag)) + { + scombo=COMBOPOS(x+15,y); + } + else if((MAPFLAG2(i,x+15,y)==mfSINGLE16)&&(MAPCOMBOFLAG2(i,x+15,y)==flag)) + { + scombo=COMBOPOS(x+15,y); + single16=true; + } + else if((MAPFLAG2(i,x,y+15)==mfSINGLE)&&(MAPCOMBOFLAG2(i,x,y+15)==flag)) + { + scombo=COMBOPOS(x,y+15); + } + else if((MAPFLAG2(i,x,y+15)==mfSINGLE16)&&(MAPCOMBOFLAG2(i,x,y+15)==flag)) + { + scombo=COMBOPOS(x,y+15); + single16=true; + } + else if((MAPFLAG2(i,x+15,y+15)==mfSINGLE)&&(MAPCOMBOFLAG2(i,x+15,y+15)==flag)) + { + scombo=COMBOPOS(x+15,y+15); + } + else if((MAPFLAG2(i,x+15,y+15)==mfSINGLE16)&&(MAPCOMBOFLAG2(i,x+15,y+15)==flag)) + { + scombo=COMBOPOS(x+15,y+15); + single16=true; + } + } + } + + if(scombo<0) + { + checktrigger=true; + hidden_entrance(0,true); + } + else + { + checktrigger=true; + hidden_entrance(0,true,single16,scombo); + } + + sfx(tmpscr->secretsfx); + + if(tmpscr->flags6&fTRIGGERFPERM) + { + int tr = findtrigger(-1,false); //Normal flags + + if(tr) + { + Z_eventlog("Hit All Triggers->Perm Secret not fulfilled (%d trigger flag%s remain).\n", tr, tr>1?"s":""); + setflag=false; + } + + int ftr = findtrigger(-1,true); //FFCs + + if(ftr) + { + Z_eventlog("Hit All Triggers->Perm Secret not fulfilled (%d trigger FFC%s remain).\n", ftr, ftr>1?"s":""); + setflag=false; + } + } + + if(setflag && !isdungeon()) + if(!(tmpscr->flags5&fTEMPSECRETS)) + setmapflag(mSECRET); + + return true; +} + +void update_freeform_combos() +{ + ffscript_engine(false); + tmpscr->ffcs.updateMovement(tmpscr, Link.isHoldingItem()); +} + +bool hitcombo(int x, int y, int combotype) +{ + return (COMBOTYPE(x,y)==combotype); +} + +bool hitflag(int x, int y, int flagtype) +{ + return (MAPFLAG(x,y)==flagtype||MAPCOMBOFLAG(x,y)==flagtype); +} + +int nextscr(int dir) +{ + int m = currmap; + int s = currscr; + + switch(dir) + { + case up: + s-=16; + break; + + case down: + s+=16; + break; + + case left: + s-=1; + break; + + case right: + s+=1; + break; + } + + // need to check for screens on other maps, 's' not valid, etc. + + int index = (tmpscr->sidewarpindex >> (dir*2))&3; + + // Fun fact: when a scrolling warp is triggered, this function + // is never even called! - Saf + if(tmpscr->sidewarptype[index] == 3) // scrolling warp + { + switch(dir) + { + case up: + if(!(tmpscr->flags2&wfUP)) goto nowarp; + + break; + + case down: + if(!(tmpscr->flags2&wfDOWN)) goto nowarp; + + break; + + case left: + if(!(tmpscr->flags2&wfLEFT)) goto nowarp; + + break; + + case right: + if(!(tmpscr->flags2&wfRIGHT)) goto nowarp; + + break; + } + + m = DMaps[tmpscr->sidewarpdmap[index]].map; + s = tmpscr->sidewarpscr[index] + DMaps[tmpscr->sidewarpdmap[index]].xoff; + } + +nowarp: + if(s<0||s>=128) + return 0xFFFF; + + return (m<<7) + s; +} + +void bombdoor(int x,int y) +{ + if(tmpscr->door[0]==dBOMB && isinRect(x,y,100,0,139,48)) + { + tmpscr->door[0]=dBOMBED; + putdoor(scrollbuf,0,0,dBOMBED); + setmapflag(mDOOR_UP); + markBmap(-1); + + if(nextscr(up)!=0xFFFF) + { + setmapflag(nextscr(up), mDOOR_DOWN); + markBmap(-1,nextscr(up)-(get_currdmap()<<7)); + } + } + + if(tmpscr->door[1]==dBOMB && isinRect(x,y,100,112,139,176)) + { + tmpscr->door[1]=dBOMBED; + putdoor(scrollbuf,0,1,dBOMBED); + setmapflag(mDOOR_DOWN); + markBmap(-1); + + if(nextscr(down)!=0xFFFF) + { + setmapflag(nextscr(down), mDOOR_UP); + markBmap(-1,nextscr(down)-(get_currdmap()<<7)); + } + } + + if(tmpscr->door[2]==dBOMB && isinRect(x,y,0,60,48,98)) + { + tmpscr->door[2]=dBOMBED; + putdoor(scrollbuf,0,2,dBOMBED); + setmapflag(mDOOR_LEFT); + markBmap(-1); + + if(nextscr(left)!=0xFFFF) + { + setmapflag(nextscr(left), mDOOR_RIGHT); + markBmap(-1,nextscr(left)-(get_currdmap()<<7)); + } + } + + if(tmpscr->door[3]==dBOMB && isinRect(x,y,192,60,240,98)) + { + tmpscr->door[3]=dBOMBED; + putdoor(scrollbuf,0,3,dBOMBED); + setmapflag(mDOOR_RIGHT); + markBmap(-1); + + if(nextscr(right)!=0xFFFF) + { + setmapflag(nextscr(right), mDOOR_LEFT); + markBmap(-1,nextscr(right)-(get_currdmap()<<7)); + } + } +} + +void do_scrolling_layer(BITMAP *bmp, int type, mapscr* layer, int x, int y, bool scrolling, int tempscreen) +{ + static int mf; + + switch(type) + { + case -4: //overhead FFCs + case -3: //freeform combos + for(int i=MAXFFCS-1; i>=0; i--) + { + const FFC& ffc=layer->ffcs[i]; + if(ffc.isVisible(lensclk!=0)) + { + // If scrolling, only draw carryover ffcs from newscr, + // not oldscr; otherwise, we'll draw the same one twice + if(scrolling && ffc.carriesOver() && tempscreen == 3) + continue; + + if(ffc.overlay()==(type==-4)) + { + int tx=ffc.getXInt(); + int ty=ffc.getYInt()+playing_field_offset; + + if((ffc.getFlags()&ffTRANS)!=0) + { + overcomboblocktranslucent(bmp, tx-x, ty-y, + ffc.getCombo(), ffc.getCSet(), + ffc.getTileWidth(), ffc.getTileHeight(), 128); + } + else + { + overcomboblock(bmp, tx-x, ty-y, + ffc.getCombo(), ffc.getCSet(), + ffc.getTileWidth(), ffc.getTileHeight()); + } + } + } + } + + break; + + case -2: //push blocks + for(int i=0; i<176; i++) + { + mf=layer->sflag[i]; + + if(mf==mfPUSHUD || mf==mfPUSH4 || mf==mfPUSHED || ((mf>=mfPUSHLR)&&(mf<=mfPUSHRINS))) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,layer->data[i],layer->cset[i]); + } + else + { + mf=combobuf[layer->data[i]].flag; + + if(mf==mfPUSHUD || mf==mfPUSH4 || mf==mfPUSHED || ((mf>=mfPUSHLR)&&(mf<=mfPUSHRINS))) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,layer->data[i],layer->cset[i]); + } + } + } + + break; + + case -1: //over combo + for(int i=0; i<176; i++) + { +// if (combobuf[layer->data[i]].type==cOLD_OVERHEAD) + if(combo_class_buf[combobuf[layer->data[i]].type].overhead) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,layer->data[i],layer->cset[i]); + } + } + + break; + + case 0: + + //case 1: + //case 2: + case 3: + case 4: + case 5: + if(TransLayers || layer->layeropacity[type]==255) + { + if(layer->layermap[type]>0) + { + if(scrolling) + { + if(layer->layeropacity[type]==255) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + else + { + if(layer->layeropacity[type]==255) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + } + } + + break; + + case 1: + if(TransLayers || layer->layeropacity[type]==255) + { + if(layer->layermap[type]>0) + { + if(scrolling) + { + if(layer->layeropacity[type]==255) + { + if(layer->flags7&fLAYER2BG) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + } + else + { + if(layer->flags7&fLAYER2BG) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + } + else + { + if(layer->layeropacity[type]==255) + { + if(layer->flags7&fLAYER2BG) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + } + else + { + if(layer->flags7&fLAYER2BG) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + } + } + } + + break; + + case 2: + if(TransLayers || layer->layeropacity[type]==255) + { + if(layer->layermap[type]>0) + { + if(scrolling) + { + if(layer->layeropacity[type]==255) + { + if(layer->flags7&fLAYER3BG&&!(layer->flags7&fLAYER2BG)) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + } + else + { + if(layer->flags7&fLAYER3BG&&!(layer->flags7&fLAYER2BG)) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + } + else + { + if(layer->layeropacity[type]==255) + { + if(layer->flags7&fLAYER3BG&&!(layer->flags7&fLAYER2BG)) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + } + else + { + if(layer->flags7&fLAYER3BG&&!(layer->flags7&fLAYER2BG)) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + putcombo(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i]); + } + } + } + else + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr2[type].data[i],tmpscr2[type].cset[i],layer->layeropacity[type]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(bmp,((i&15)<<4)-x,(i&0xF0)+playing_field_offset-y,tmpscr3[type].data[i],tmpscr3[type].cset[i],layer->layeropacity[type]); + } + } + } + } + } + } + } + + break; + } +} + + +void do_layer(BITMAP *bmp, int type, mapscr* layer, int x, int y, int tempscreen, bool scrolling, bool drawprimitives) +{ + bool showlayer = true; + + switch(type) + { + case -4: + case -3: + if(!show_ffcs) + { + showlayer = false; + } + + break; + + case -2: + if(!show_layer_push) + { + showlayer = false; + } + + break; + + case -1: + if(!show_layer_over) + { + showlayer = false; + } + + break; + + case 0: + if(!show_layer_1) + { + showlayer = false; + } + + break; + + case 1: + if(!show_layer_2) + { + showlayer = false; + } + + break; + + case 2: + if(!show_layer_3) + { + showlayer = false; + } + + break; + + case 3: + if(!show_layer_4) + { + showlayer = false; + } + + break; + + case 4: + if(!show_layer_5) + { + showlayer = false; + } + + break; + + case 5: + if(!show_layer_6) + { + showlayer = false; + } + + break; + } + + if(type==(int)(layer->lens_layer&7) && ((layer->lens_layer&llLENSSHOWS && !lensclk) || (layer->lens_layer&llLENSHIDES && lensclk))) + { + showlayer = false; + } + + if(showlayer) + { + do_scrolling_layer(bmp, type, layer, x, y, scrolling, tempscreen); + + if(drawprimitives && type >= 0 && type <= 5) + { + do_primitives(bmp, type+1, layer, 0, playing_field_offset); + } + } +} + + +// Called by do_walkflags +void put_walkflags(BITMAP *dest,int x,int y,int xofs,int yofs, word cmbdat,int lyr) +{ + newcombo c = combobuf[cmbdat]; + + int xx = x-xofs; + int yy = y+playing_field_offset-yofs; + + for(int i=0; i<4; i++) + { + int tx=((i&2)<<2)+xx; + int ty=((i&1)<<3)+yy; + + if(lyr==0 && iswater(cmbdat)!=0 && get_bit(quest_rules, qr_DROWN)) + rectfill(dest,tx,ty,tx+7,ty+7,makecol(85,85,255)); + + if(c.walk&(1<data[i], 0); + } + + int layermap; + + for(int k=0; k<2; k++) + { + layermap=layer->layermap[k%2]; + + if(layermap>0) + { + if(tempscreen==2) + { + for(int i=0; i<176; i++) + { + put_walkflags(temp_buf,((i&15)<<4),(i&0xF0),x,y,tmpscr2[k].data[i], k%2+1); + put_walkflags(scrollbuf,((i&15)<<4),(i&0xF0),x,y,tmpscr2[k].data[i], k%2+1); + } + } + else + { + for(int i=0; i<176; i++) + { + put_walkflags(temp_buf,((i&15)<<4),(i&0xF0),x,y,tmpscr3[k].data[i], k%2+1); + put_walkflags(scrollbuf,((i&15)<<4),(i&0xF0),x,y,tmpscr3[k].data[i], k%2+1); + } + } + } + } + } +} + +void draw_screen(mapscr* this_screen, bool showlink) +{ + + //The Plan: + //1. Draw some layers onto scrollbuf with clipping + //2. Blit scrollbuf onto framebuf + //3. Draw some sprites onto framebuf + //4. Blit framebuf onto temp_buf + //5. Draw some layers onto temp_buf and scrollbuf + //6. Blit temp_buf onto framebuf with clipping + //6b. Draw the subscreen onto temp_buf, without clipping + //7. Draw some flying sprites onto framebuf + //8. Blit frame_buf onto temp_buf + //9. Draw some layers onto temp_buf + //10. Blit temp_buf onto framebuf with clipping + //11. Draw some text on framebuf and scrollbuf + //12. Draw the subscreen onto framebuf, without clipping + clear_bitmap(framebuf); + set_clip_rect(framebuf,0,0,256,224); + + clear_bitmap(temp_buf); + set_clip_state(temp_buf,1); + set_clip_rect(temp_buf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + + int cmby2=0; + int pcounter; + + //1. Draw some layers onto temp_buf + clear_bitmap(scrollbuf); + + if(this_screen->flags7&fLAYER2BG) + { + do_layer(scrollbuf,1, this_screen, 0, 0, 2, false, true); + + for(pcounter=0; pcounterlayer==1) + { + particles.spr(pcounter)->draw(scrollbuf); + } + } + } + + if(this_screen->flags7&fLAYER3BG) + { + do_layer(scrollbuf,2, this_screen, 0, 0, 2, false, true); + + for(pcounter=0; pcounterlayer==2) + { + particles.spr(pcounter)->draw(scrollbuf); + } + } + } + + putscr(scrollbuf,0,playing_field_offset,this_screen); + + // Lens hints, then primitives, then particles. + if((lensclk || (get_debug() && key[KEY_L])) && !get_bit(quest_rules, qr_OLDLENSORDER)) + { + draw_lens_under(scrollbuf, false); + } + + if(show_layer_0) + do_primitives(scrollbuf, 0, this_screen, 0, playing_field_offset); + + for(pcounter=0; pcounterlayer==-3) + { + particles.spr(pcounter)->draw(scrollbuf); + } + } + + set_clip_rect(scrollbuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + + if(!(get_bit(quest_rules,qr_LAYER12UNDERCAVE))) + { + if(showlink && + ((Link.getAction()==climbcovertop)||(Link.getAction()==climbcoverbottom))) + { + if(Link.getAction()==climbcovertop) + { + cmby2=16; + } + else if(Link.getAction()==climbcoverbottom) + { + cmby2=-16; + } + + decorations.draw2(scrollbuf,true); + Link.draw(scrollbuf); + decorations.draw(scrollbuf,true); + int ccx = (int)(Link.getClimbCoverX()); + int ccy = (int)(Link.getClimbCoverY()); + + overcombo(scrollbuf,ccx,ccy+cmby2+playing_field_offset,MAPCOMBO(ccx,ccy+cmby2),MAPCSET(ccx,ccy+cmby2)); + putcombo(scrollbuf,ccx,ccy+playing_field_offset,MAPCOMBO(ccx,ccy),MAPCSET(ccx,ccy)); + + if(int(Link.getX())&15) + { + overcombo(scrollbuf,ccx+16,ccy+cmby2+playing_field_offset,MAPCOMBO(ccx+16,ccy+cmby2),MAPCSET(ccx+16,ccy+cmby2)); + putcombo(scrollbuf,ccx+16,ccy+playing_field_offset,MAPCOMBO(ccx+16,ccy),MAPCSET(ccx+16,ccy)); + } + } + } + + do_layer(scrollbuf,0, this_screen, 0, 0, 2, false, true); // LAYER 1 + + for(pcounter=0; pcounterlayer==0) + { + particles.spr(pcounter)->draw(scrollbuf); + } + } + + do_layer(scrollbuf,-3, this_screen, 0, 0, 2); // freeform combos! + + if(!(this_screen->flags7&fLAYER2BG)) + { + do_layer(scrollbuf,1, this_screen, 0, 0, 2, false, true); // LAYER 2 + + for(pcounter=0; pcounterlayer==1) + { + particles.spr(pcounter)->draw(scrollbuf); + } + } + } + + if(get_bit(quest_rules,qr_LAYER12UNDERCAVE)) + { + if(showlink && + ((Link.getAction()==climbcovertop)||(Link.getAction()==climbcoverbottom))) + { + if(Link.getAction()==climbcovertop) + { + cmby2=16; + } + else if(Link.getAction()==climbcoverbottom) + { + cmby2=-16; + } + + decorations.draw2(scrollbuf,true); + Link.draw(scrollbuf); + decorations.draw(scrollbuf,true); + int ccx = (int)(Link.getClimbCoverX()); + int ccy = (int)(Link.getClimbCoverY()); + + overcombo(scrollbuf,ccx,ccy+cmby2+playing_field_offset,MAPCOMBO(ccx,ccy+cmby2),MAPCSET(ccx,ccy+cmby2)); + putcombo(scrollbuf,ccx,ccy+playing_field_offset,MAPCOMBO(ccx,ccy),MAPCSET(ccx,ccy)); + + if(int(Link.getX())&15) + { + overcombo(scrollbuf,ccx+16,ccy+cmby2+playing_field_offset,MAPCOMBO(ccx+16,ccy+cmby2),MAPCSET(ccx+16,ccy+cmby2)); + putcombo(scrollbuf,ccx+16,ccy+playing_field_offset,MAPCOMBO(ccx+16,ccy),MAPCSET(ccx+16,ccy)); + } + } + } + + do_layer(scrollbuf,-2, this_screen, 0, 0, 2); // push blocks! + + //Show walkflags cheat + do_walkflags(temp_buf,this_screen,0,0,2); + do_walkflags(scrollbuf,this_screen,0,0,2); + + putscrdoors(scrollbuf,0,playing_field_offset,this_screen); + + // Lens hints, doors etc. + if(lensclk || (get_debug() && key[KEY_L])) + { + if(get_bit(quest_rules, qr_OLDLENSORDER)) + { + draw_lens_under(scrollbuf, false); + } + + draw_lens_under(scrollbuf, true); + } + + //2. Blit those layers onto framebuf + + + set_clip_rect(framebuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + masked_blit(scrollbuf, framebuf, 0, 0, 0, 0, 256, 224); + + + //3. Draw some sprites onto framebuf + set_clip_rect(framebuf,0,0,256,224); + roomItems.drawPrices(framebuf, playing_field_offset); + + if(showlink && ((Link.getAction()!=climbcovertop)&&(Link.getAction()!=climbcoverbottom))) + { + Link.draw_under(framebuf); + + if(Link.isSwimming()) + { + decorations.draw2(framebuf,true); + Link.draw(framebuf); + decorations.draw(framebuf,true); + } + } + + if(drawguys) + { + if(get_bit(quest_rules,qr_NOFLICKER) || (frame&1)) + { + for(int i=0; ibehind) + Ewpns.spr(i)->draw(framebuf); + } + + if(get_bit(quest_rules,qr_SHADOWS)&&(!get_bit(quest_rules,qr_SHADOWSFLICKER)||frame&1)) + { + guys.drawshadow(framebuf,get_bit(quest_rules,qr_TRANSSHADOWS)!=0,true); + } + + guys.draw(framebuf,true); + chainlinks.draw(framebuf,true); + Lwpns.draw(framebuf,true); + + for(int i=0; ibehind) + Ewpns.spr(i)->draw(framebuf); + } + + items.draw(framebuf,true); + } + else + { + for(int i=0; ibehind) + Ewpns.spr(i)->draw(framebuf); + } + + if(get_bit(quest_rules,qr_SHADOWS)&&(!get_bit(quest_rules,qr_SHADOWSFLICKER)||frame&1)) + { + guys.drawshadow(framebuf,get_bit(quest_rules,qr_TRANSSHADOWS)!=0,true); + } + + items.draw(framebuf,false); + chainlinks.draw(framebuf,false); + Lwpns.draw(framebuf,false); + guys.draw(framebuf,false); + + for(int i=0; ibehind) + { + Ewpns.spr(i)->draw(framebuf); + } + } + } + + guys.draw2(framebuf,true); + } + + if(showlink && ((Link.getAction()!=climbcovertop)&& (Link.getAction()!=climbcoverbottom))) + { + mblock2.draw(framebuf); + + if(!Link.isSwimming()) + { + if(Link.getZ()>0 &&(!get_bit(quest_rules,qr_SHADOWSFLICKER)||frame&1)) + { + Link.drawshadow(framebuf,get_bit(quest_rules,qr_TRANSSHADOWS)!=0); + } + + decorations.draw2(framebuf,true); + Link.draw(framebuf); + decorations.draw(framebuf,true); + } + } + + for(int i=0; ifamily == eeWALLM + || ((enemy*)guys.spr(i))->family == eeWALK) + { + if(((ASEnemy*)guys.spr(i))->haslink) + { + guys.spr(i)->draw(framebuf); + } + } + + if(guys.spr(i)->z > Link.getZ()) + { + //Jumping enemies in front of Link. + guys.spr(i)->draw(framebuf); + } + } + + //4. Blit framebuf onto temp_buf + + //you have to do this, because do_layer calls overcombo, which doesn't respect the clipping rectangle, which messes up the triforce curtain. -DD + blit(framebuf, temp_buf, 0, 0, 0, 0, 256, 224); + + //5. Draw some layers onto temp_buf and scrollbuf + + if(!(this_screen->flags7&fLAYER3BG)) + { + do_layer(temp_buf,2, this_screen, 0, 0, 2, false, true); + do_layer(scrollbuf, 2, this_screen, 0, 0, 2); + + for(pcounter=0; pcounterlayer==2) + { + particles.spr(pcounter)->draw(temp_buf); + } + } + } + + do_layer(temp_buf,3, this_screen, 0, 0, 2, false, true); + do_layer(scrollbuf, 3, this_screen, 0, 0, 2); + //do_primitives(temp_buf, 3, this_screen, 0,playing_field_offset);//don't uncomment me + + for(pcounter=0; pcounterlayer==3) + { + particles.spr(pcounter)->draw(temp_buf); + } + } + + do_layer(temp_buf,-1, this_screen, 0, 0, 2); + do_layer(scrollbuf,-1, this_screen, 0, 0, 2); + + for(pcounter=0; pcounterlayer==-1) + { + particles.spr(pcounter)->draw(temp_buf); + } + } + + //6. Blit temp_buf onto framebuf with clipping + + set_clip_rect(framebuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + blit(temp_buf, framebuf, 0, 0, 0, 0, 256, 224); + + //6b. Draw the subscreen, without clipping + if(!get_bit(quest_rules,qr_SUBSCREENOVERSPRITES)) + { + set_clip_rect(framebuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + put_passive_subscr(framebuf, &QMisc, 0, passive_subscreen_offset, false, sspUP); + } + + + //7. Draw some flying sprites onto framebuf + set_clip_rect(framebuf,0,0,256,224); + + //Jumping Link and jumping enemies are drawn on this layer. + if(Link.getZ() > (fix)zinit.jump_link_layer_threshold) + { + decorations.draw2(framebuf,false); + Link.draw(framebuf); + chainlinks.draw(framebuf,true); + + for(int i=0; iz > (fix)zinit.jump_link_layer_threshold) + { + Lwpns.spr(i)->draw(framebuf); + } + } + + decorations.draw(framebuf,false); + } + + if(!get_bit(quest_rules,qr_ENEMIESZAXIS)) for(int i=0; iid)) || guys.spr(i)->z > (fix)zinit.jump_link_layer_threshold) + { + guys.spr(i)->draw(framebuf); + } + } + else + { + for(int i=0; iid)) || guys.spr(i)->z > 0) + { + guys.spr(i)->draw(framebuf); + } + } + } + + // Draw the Moving Fairy above layer 3 + for(int i=0; iid].family == itype_fairy && itemsbuf[items.spr(i)->id].misc3) + items.spr(i)->draw(framebuf); + + //8. Blit framebuf onto temp_buf + + masked_blit(framebuf, temp_buf, 0, 0, 0, 0, 256, 224); + + //9. Draw some layers onto temp_buf and scrollbuf + + set_clip_rect(framebuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + + do_layer(temp_buf,4, this_screen, 0, 0, 2, false, true); + do_layer(scrollbuf, 4, this_screen, 0, 0, 2); + + for(pcounter=0; pcounterlayer==4) + { + particles.spr(pcounter)->draw(temp_buf); + } + } + + do_layer(temp_buf,-4, this_screen, 0, 0, 2); // overhead freeform combos! + do_layer(scrollbuf, -4, this_screen, 0, 0, 2); + + do_layer(temp_buf,5, this_screen, 0, 0, 2, false, true); + do_layer(scrollbuf, 5, this_screen, 0, 0, 2); + + for(pcounter=0; pcounterlayer==5) + { + particles.spr(pcounter)->draw(temp_buf); + } + } + + //10. Blit temp_buf onto framebuf with clipping + + set_clip_rect(framebuf,draw_screen_clip_rect_x1,draw_screen_clip_rect_y1,draw_screen_clip_rect_x2,draw_screen_clip_rect_y2); + blit(temp_buf, framebuf, 0, 0, 0, 0, 256, 224); + + + //11. Draw some text on framebuf + + set_clip_rect(framebuf,0,0,256,224); + set_clip_rect(scrollbuf,0,0,256,224); + + messageMgr.drawToScreen(framebuf, playing_field_offset); + messageMgr.drawToScreen(scrollbuf, playing_field_offset); + + //12. Draw the subscreen, without clipping + + if(get_bit(quest_rules,qr_SUBSCREENOVERSPRITES)) + { + put_passive_subscr(framebuf, &QMisc, 0, passive_subscreen_offset, false, sspUP); + + // Draw primitives over subscren + do_primitives(framebuf, 7, this_screen, 0, playing_field_offset); //Layer '7' appears above subscreen if quest rule is set + } + + set_clip_rect(scrollbuf, 0, 0, scrollbuf->w, scrollbuf->h); +} + +void put_door(BITMAP *dest,int t,int pos,int side,int type,bool redraw,bool even_walls) +{ + int d=tmpscr[t].door_combo_set; + + switch(type) + { + case dt_wall: + case dt_walk: + if(!even_walls) + break; + + case dt_pass: + if(!get_bit(quest_rules, qr_REPLACEOPENDOORS) && !even_walls) + break; + + case dt_lock: + case dt_shut: + case dt_boss: + case dt_olck: + case dt_osht: + case dt_obos: + case dt_bomb: + switch(side) + { + case up: + tmpscr[t].data[pos] = DoorComboSets[d].doorcombo_u[type][0]; + tmpscr[t].cset[pos] = DoorComboSets[d].doorcset_u[type][0]; + tmpscr[t].sflag[pos] = 0; + tmpscr[t].data[pos+1] = DoorComboSets[d].doorcombo_u[type][1]; + tmpscr[t].cset[pos+1] = DoorComboSets[d].doorcset_u[type][1]; + tmpscr[t].sflag[pos+1] = 0; + tmpscr[t].data[pos+16] = DoorComboSets[d].doorcombo_u[type][2]; + tmpscr[t].cset[pos+16] = DoorComboSets[d].doorcset_u[type][2]; + tmpscr[t].sflag[pos+16] = 0; + tmpscr[t].data[pos+16+1] = DoorComboSets[d].doorcombo_u[type][3]; + tmpscr[t].cset[pos+16+1] = DoorComboSets[d].doorcset_u[type][3]; + tmpscr[t].sflag[pos+16+1] = 0; + + if(redraw) + { + putcombo(dest,(pos&15)<<4,pos&0xF0, + DoorComboSets[d].doorcombo_u[type][0], + DoorComboSets[d].doorcset_u[type][0]); + putcombo(dest,((pos&15)<<4)+16,pos&0xF0, + DoorComboSets[d].doorcombo_u[type][1], + DoorComboSets[d].doorcset_u[type][1]); + } + + break; + + case down: + tmpscr[t].data[pos] = DoorComboSets[d].doorcombo_d[type][0]; + tmpscr[t].cset[pos] = DoorComboSets[d].doorcset_d[type][0]; + tmpscr[t].sflag[pos] = 0; + tmpscr[t].data[pos+1] = DoorComboSets[d].doorcombo_d[type][1]; + tmpscr[t].cset[pos+1] = DoorComboSets[d].doorcset_d[type][1]; + tmpscr[t].sflag[pos+1] = 0; + tmpscr[t].data[pos+16] = DoorComboSets[d].doorcombo_d[type][2]; + tmpscr[t].cset[pos+16] = DoorComboSets[d].doorcset_d[type][2]; + tmpscr[t].sflag[pos+16] = 0; + tmpscr[t].data[pos+16+1] = DoorComboSets[d].doorcombo_d[type][3]; + tmpscr[t].cset[pos+16+1] = DoorComboSets[d].doorcset_d[type][3]; + tmpscr[t].sflag[pos+16+1] = 0; + + if(redraw) + { + putcombo(dest,(pos&15)<<4,(pos&0xF0)+16, + DoorComboSets[d].doorcombo_d[type][2], + DoorComboSets[d].doorcset_d[type][2]); + putcombo(dest,((pos&15)<<4)+16,(pos&0xF0)+16, + DoorComboSets[d].doorcombo_d[type][3], + DoorComboSets[d].doorcset_d[type][3]); + } + + break; + + case left: + tmpscr[t].data[pos] = DoorComboSets[d].doorcombo_l[type][0]; + tmpscr[t].cset[pos] = DoorComboSets[d].doorcset_l[type][0]; + tmpscr[t].sflag[pos] = 0; + tmpscr[t].data[pos+1] = DoorComboSets[d].doorcombo_l[type][1]; + tmpscr[t].cset[pos+1] = DoorComboSets[d].doorcset_l[type][1]; + tmpscr[t].sflag[pos+1] = 0; + tmpscr[t].data[pos+16] = DoorComboSets[d].doorcombo_l[type][2]; + tmpscr[t].cset[pos+16] = DoorComboSets[d].doorcset_l[type][2]; + tmpscr[t].sflag[pos+16] = 0; + tmpscr[t].data[pos+16+1] = DoorComboSets[d].doorcombo_l[type][3]; + tmpscr[t].cset[pos+16+1] = DoorComboSets[d].doorcset_l[type][3]; + tmpscr[t].sflag[pos+16+1] = 0; + tmpscr[t].data[pos+32] = DoorComboSets[d].doorcombo_l[type][4]; + tmpscr[t].cset[pos+32] = DoorComboSets[d].doorcset_l[type][4]; + tmpscr[t].sflag[pos+32] = 0; + tmpscr[t].data[pos+32+1] = DoorComboSets[d].doorcombo_l[type][5]; + tmpscr[t].cset[pos+32+1] = DoorComboSets[d].doorcset_l[type][5]; + tmpscr[t].sflag[pos+32+1] = 0; + + if(redraw) + { + putcombo(dest,(pos&15)<<4,pos&0xF0, + DoorComboSets[d].doorcombo_l[type][0], + DoorComboSets[d].doorcset_l[type][0]); + putcombo(dest,(pos&15)<<4,(pos&0xF0)+16, + DoorComboSets[d].doorcombo_l[type][2], + DoorComboSets[d].doorcset_l[type][2]); + putcombo(dest,(pos&15)<<4,(pos&0xF0)+32, + DoorComboSets[d].doorcombo_l[type][4], + DoorComboSets[d].doorcset_l[type][4]); + } + + break; + + case right: + tmpscr[t].data[pos] = DoorComboSets[d].doorcombo_r[type][0]; + tmpscr[t].cset[pos] = DoorComboSets[d].doorcset_r[type][0]; + tmpscr[t].sflag[pos] = 0; + tmpscr[t].data[pos+1] = DoorComboSets[d].doorcombo_r[type][1]; + tmpscr[t].cset[pos+1] = DoorComboSets[d].doorcset_r[type][1]; + tmpscr[t].sflag[pos+1] = 0; + tmpscr[t].data[pos+16] = DoorComboSets[d].doorcombo_r[type][2]; + tmpscr[t].cset[pos+16] = DoorComboSets[d].doorcset_r[type][2]; + tmpscr[t].sflag[pos+16] = 0; + tmpscr[t].data[pos+16+1] = DoorComboSets[d].doorcombo_r[type][3]; + tmpscr[t].cset[pos+16+1] = DoorComboSets[d].doorcset_r[type][3]; + tmpscr[t].sflag[pos+16+1] = 0; + tmpscr[t].data[pos+32] = DoorComboSets[d].doorcombo_r[type][4]; + tmpscr[t].cset[pos+32] = DoorComboSets[d].doorcset_r[type][4]; + tmpscr[t].sflag[pos+32] = 0; + tmpscr[t].data[pos+32+1] = DoorComboSets[d].doorcombo_r[type][5]; + tmpscr[t].cset[pos+32+1] = DoorComboSets[d].doorcset_r[type][5]; + tmpscr[t].sflag[pos+32+1] = 0; + + if(redraw) + { + putcombo(dest,(pos&15)<<4,pos&0xF0, + DoorComboSets[d].doorcombo_r[type][0], + DoorComboSets[d].doorcset_r[type][0]); + putcombo(dest,(pos&15)<<4,(pos&0xF0)+16, + DoorComboSets[d].doorcombo_r[type][2], + DoorComboSets[d].doorcset_r[type][2]); + putcombo(dest,(pos&15)<<4,(pos&0xF0)+32, + DoorComboSets[d].doorcombo_r[type][4], + DoorComboSets[d].doorcset_r[type][4]); + } + + break; + } + + break; + + default: + break; + } +} + +void over_door(BITMAP *dest,int t, int pos,int side, int xoff, int yoff) +{ + int d=tmpscr[t].door_combo_set; + int x=(pos&15)<<4; + int y=(pos&0xF0); + + switch(side) + { + case up: + overcombo2(dest,x+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_u[0], + DoorComboSets[d].bombdoorcset_u[0]); + overcombo2(dest,x+16+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_u[1], + DoorComboSets[d].bombdoorcset_u[1]); + break; + + case down: + overcombo2(dest,x+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_d[0], + DoorComboSets[d].bombdoorcset_d[0]); + overcombo2(dest,x+16+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_d[1], + DoorComboSets[d].bombdoorcset_d[1]); + break; + + case left: + overcombo2(dest,x+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_l[0], + DoorComboSets[d].bombdoorcset_l[0]); + overcombo2(dest,x+xoff,y+yoff+16, + DoorComboSets[d].bombdoorcombo_l[1], + DoorComboSets[d].bombdoorcset_l[1]); + overcombo2(dest,x+xoff,y+yoff+16, + DoorComboSets[d].bombdoorcombo_l[2], + DoorComboSets[d].bombdoorcset_l[2]); + break; + + case right: + overcombo2(dest,x+xoff,y+yoff, + DoorComboSets[d].bombdoorcombo_r[0], + DoorComboSets[d].bombdoorcset_r[0]); + overcombo2(dest,x+xoff,y+yoff+16, + DoorComboSets[d].bombdoorcombo_r[1], + DoorComboSets[d].bombdoorcset_r[1]); + overcombo2(dest,x+xoff,y+yoff+16, + DoorComboSets[d].bombdoorcombo_r[2], + DoorComboSets[d].bombdoorcset_r[2]); + break; + } +} + +void putdoor(BITMAP *dest,int t,int side,int door,bool redraw,bool even_walls) +{ + /* + #define dWALL 0 // 000 0 + #define dBOMB 6 // 011 0 + #define 8 // 100 0 + enum {dt_pass=0, dt_lock, dt_shut, dt_boss, dt_olck, dt_osht, dt_obos, dt_wall, dt_bomb, dt_walk, dt_max}; + */ + + if(!even_walls&&(door==dWALL||door==dWALK)) + { + return; + } + + int doortype; + + switch(door) + { + case dWALL: + doortype=dt_wall; + break; + + case dWALK: + doortype=dt_walk; + break; + + case dOPEN: + doortype=dt_pass; + break; + + case dLOCKED: + doortype=dt_lock; + break; + + case dUNLOCKED: + doortype=dt_olck; + break; + + case dSHUTTER: + if(screenscrolling && ((LinkDir()^1)==side)) + { + doortype=dt_osht; + opendoors=-4; + break; + } + + //fallthrough + case d1WAYSHUTTER: + doortype=dt_shut; + break; + + case dOPENSHUTTER: + doortype=dt_osht; + break; + + case dBOSS: + doortype=dt_boss; + break; + + case dOPENBOSS: + doortype=dt_obos; + break; + + case dBOMBED: + doortype=dt_bomb; + break; + + default: + return; + } + + switch(side) + { + case up: + switch(door) + { + case dBOMBED: + if(redraw) + { + over_door(dest,t,39,side,0,0); + } + + default: + put_door(dest,t,7,side,doortype,redraw, even_walls); + break; + } + + break; + + case down: + switch(door) + { + case dBOMBED: + if(redraw) + { + over_door(dest,t,135,side,0,0); + } + + default: + put_door(dest,t,151,side,doortype,redraw, even_walls); + break; + } + + break; + + case left: + switch(door) + { + case dBOMBED: + if(redraw) + { + over_door(dest,t,66,side,0,0); + } + + default: + put_door(dest,t,64,side,doortype,redraw, even_walls); + break; + } + + break; + + case right: + switch(door) + { + case dBOMBED: + if(redraw) + { + over_door(dest,t,77,side,0,0); + } + + default: + put_door(dest,t,78,side,doortype,redraw, even_walls); + break; + } + + break; + } +} + +void putcombo_not_zero(BITMAP *dest, int x, int y, int combo, int cset) +{ + if(combo!=0) + { + putcombo(dest,x, y, combo, cset); + } +} + +void overcombo_not_zero(BITMAP *dest, int x, int y, int combo, int cset) +{ + if(combo!=0) + { + overcombo(dest,x, y, combo, cset); + } +} + +void showbombeddoor(BITMAP *dest, int side) +{ + int d=tmpscr->door_combo_set; + + switch(side) + { + case up: + putcombo_not_zero(dest,(7&15)<<4,(7&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_u[dt_bomb][0], + DoorComboSets[d].doorcset_u[dt_bomb][0]); + putcombo_not_zero(dest,(8&15)<<4,(8&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_u[dt_bomb][1], + DoorComboSets[d].doorcset_u[dt_bomb][1]); + putcombo_not_zero(dest,(23&15)<<4,(23&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_u[dt_bomb][2], + DoorComboSets[d].doorcset_u[dt_bomb][2]); + putcombo_not_zero(dest,(24&15)<<4,(24&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_u[dt_bomb][3], + DoorComboSets[d].doorcset_u[dt_bomb][3]); + overcombo_not_zero(dest,(39&15)<<4,(39&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_u[0], + DoorComboSets[d].bombdoorcset_u[0]); + overcombo_not_zero(dest,(40&15)<<4,(40&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_u[1], + DoorComboSets[d].bombdoorcset_u[1]); + break; + + case down: + putcombo_not_zero(dest,(151&15)<<4,(151&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_d[dt_bomb][0], + DoorComboSets[d].doorcset_d[dt_bomb][0]); + putcombo_not_zero(dest,(152&15)<<4,(152&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_d[dt_bomb][1], + DoorComboSets[d].doorcset_d[dt_bomb][1]); + putcombo_not_zero(dest,(167&15)<<4,(167&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_d[dt_bomb][2], + DoorComboSets[d].doorcset_d[dt_bomb][2]); + putcombo_not_zero(dest,(168&15)<<4,(168&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_d[dt_bomb][3], + DoorComboSets[d].doorcset_d[dt_bomb][3]); + overcombo_not_zero(dest,(135&15)<<4,(135&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_d[0], + DoorComboSets[d].bombdoorcset_d[0]); + overcombo_not_zero(dest,(136&15)<<4,(136&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_d[1], + DoorComboSets[d].bombdoorcset_d[1]); + break; + + case left: + putcombo_not_zero(dest,(64&15)<<4,(64&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][0], + DoorComboSets[d].doorcset_l[dt_bomb][0]); + putcombo_not_zero(dest,(65&15)<<4,(65&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][1], + DoorComboSets[d].doorcset_l[dt_bomb][1]); + putcombo_not_zero(dest,(80&15)<<4,(80&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][2], + DoorComboSets[d].doorcset_l[dt_bomb][2]); + putcombo_not_zero(dest,(81&15)<<4,(81&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][3], + DoorComboSets[d].doorcset_l[dt_bomb][3]); + putcombo_not_zero(dest,(96&15)<<4,(96&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][4], + DoorComboSets[d].doorcset_l[dt_bomb][4]); + putcombo_not_zero(dest,(97&15)<<4,(97&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_l[dt_bomb][5], + DoorComboSets[d].doorcset_l[dt_bomb][5]); + overcombo_not_zero(dest,(66&15)<<4,(66&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_l[0], + DoorComboSets[d].bombdoorcset_l[0]); + overcombo_not_zero(dest,(82&15)<<4,(82&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_l[1], + DoorComboSets[d].bombdoorcset_l[1]); + overcombo_not_zero(dest,(98&15)<<4,(98&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_l[2], + DoorComboSets[d].bombdoorcset_l[2]); + break; + + case right: + putcombo_not_zero(dest,(78&15)<<4,(78&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][0], + DoorComboSets[d].doorcset_r[dt_bomb][0]); + putcombo_not_zero(dest,(79&15)<<4,(79&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][1], + DoorComboSets[d].doorcset_r[dt_bomb][1]); + putcombo_not_zero(dest,(94&15)<<4,(94&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][2], + DoorComboSets[d].doorcset_r[dt_bomb][2]); + putcombo_not_zero(dest,(95&15)<<4,(95&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][3], + DoorComboSets[d].doorcset_r[dt_bomb][3]); + putcombo_not_zero(dest,(110&15)<<4,(110&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][4], + DoorComboSets[d].doorcset_r[dt_bomb][4]); + putcombo_not_zero(dest,(111&15)<<4,(111&0xF0)+playing_field_offset, + DoorComboSets[d].doorcombo_r[dt_bomb][5], + DoorComboSets[d].doorcset_r[dt_bomb][5]); + overcombo_not_zero(dest,(77&15)<<4,(77&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_r[0], + DoorComboSets[d].bombdoorcset_r[0]); + overcombo_not_zero(dest,(93&15)<<4,(93&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_r[1], + DoorComboSets[d].bombdoorcset_r[1]); + overcombo_not_zero(dest,(109&15)<<4,(109&0xF0)+playing_field_offset, + DoorComboSets[d].bombdoorcombo_r[2], + DoorComboSets[d].bombdoorcset_r[2]); + break; + } +} + +void openshutters() +{ + for(int i=0; i<4; i++) + if(tmpscr->door[i]==dSHUTTER) + { + putdoor(scrollbuf,0,i,dOPENSHUTTER); + tmpscr->door[i]=dOPENSHUTTER; + } + + sfx(WAV_DOOR,128); +} + +void loadscr(int tmp,int destdmap, int scr,int ldir,bool overlay=false) +{ + for(word x=0; x0 && tmpscr[tmp].layermap[i]>0) + { + int lm = tmpscr[tmp].layermap[i]*MAPSCRS+tmpscr[tmp].layerscreen[i]; + int fm = ffscr.layermap[i]*MAPSCRS+ffscr.layerscreen[i]; + + if(!TheMaps[lm].data.empty() && !TheMaps[fm].data.empty()) + { + for(int c=0; c< ZCMaps[currmap].tileHeight*ZCMaps[currmap].tileWidth; ++c) + { + if(TheMaps[lm].data[c]==0) + { + TheMaps[lm].data[c] = TheMaps[fm].data[c]; + TheMaps[lm].sflag[c] = TheMaps[fm].sflag[c]; + TheMaps[lm].cset[c] = TheMaps[fm].cset[c]; + } + } + } + } + } + } + + if(tmp==0) + { + // Before loading new FFCs, deallocate the arrays the current ones own + // except those that carry over without resetting. + // TODO: It would be nice if the FFCs handled this themselves... + for(long i=1; i0 && (ZCMaps[tmpscr[tmp].layermap[i]-1].tileWidth==ZCMaps[currmap].tileWidth) + && (ZCMaps[tmpscr[tmp].layermap[i]-1].tileHeight==ZCMaps[currmap].tileHeight)) + { + // const int _mapsSize = (ZCMaps[currmap].tileWidth)*(ZCMaps[currmap].tileHeight); + + tmpscr2[i]=TheMaps[(tmpscr[tmp].layermap[i]-1)*MAPSCRS+tmpscr[tmp].layerscreen[i]]; + + tmpscr2[i].data.resize(_mapsSize, 0); + tmpscr2[i].sflag.resize(_mapsSize, 0); + tmpscr2[i].cset.resize(_mapsSize, 0); + + if(overlay) + { + for(int y=0; yzero_memory(); + } + } + } + + if(!isdungeon(destdmap,scr)/*||TheMaps[(currmap*MAPSCRS)+currscr].flags6&fTRIGGERFPERM*/) + { + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mSECRET) // if special stuff done before + { + hiddenstair(tmp,false); + hidden_entrance(tmp,false,false,-3); + } + } + + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mLOCKBLOCK) // if special stuff done before + { + remove_lockblocks(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mBOSSLOCKBLOCK) // if special stuff done before + { + remove_bosslockblocks(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mCHEST) // if special stuff done before + { + remove_chests(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mLOCKEDCHEST) // if special stuff done before + { + remove_lockedchests(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mBOSSCHEST) // if special stuff done before + { + remove_bosschests(tmp); + } + + // check doors + if(isdungeon(destdmap,scr)) + { + for(int i=0; i<4; i++) + { + int door=tmpscr[tmp].door[i]; + bool putit=true; + + switch(door) + { + case d1WAYSHUTTER: + case dSHUTTER: + if((ldir^1)==i) + { + tmpscr[tmp].door[i]=dOPENSHUTTER; + // putit=false; + } + + opendoors = -4; + break; + + case dLOCKED: + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&(1<maps[(currmap*MAPSCRSNORMAL)+scr]&(1<maps[(currmap*MAPSCRSNORMAL)+scr]&(1<0)&&(ZCMaps[tmpscr[tmp].layermap[j]-1].tileWidth==ZCMaps[currmap].tileWidth) && (ZCMaps[tmpscr[tmp].layermap[j]-1].tileHeight==ZCMaps[currmap].tileHeight))) + { + mapscr *layerscreen= (j<0 ? &tmpscr[tmp] : !tmpscr2[j].data.empty() ? &tmpscr2[j] : + &TheMaps[(tmpscr[tmp].layermap[j]-1)*MAPSCRS]+tmpscr[tmp].layerscreen[j]); + + for(int i=0; i<(ZCMaps[currmap].tileWidth)*(ZCMaps[currmap].tileHeight); ++i) + { + int c=layerscreen->data[i]; + int cs=layerscreen->cset[i]; + + // New screen flag: Cycle Combos At Screen Init + if(combobuf[c].nextcombo != 0 && (tmpscr[tmp].flags3 & fCYCLEONINIT) && (j<0 || get_bit(quest_rules,qr_CMBCYCLELAYERS))) + { + int r = 0; + + while(combobuf[c].nextcombo != 0 && r++ < 10) + { + layerscreen->data[i] = combobuf[c].nextcombo; + layerscreen->cset[i] = combobuf[c].nextcset; + c=layerscreen->data[i]; + cs=layerscreen->cset[i]; + } + } + } + } + } +} + +// Screen is being viewed by the Overworld Map viewer. +void loadscr2(int tmp,int scr,int) +{ + for(word x=0; x0) + { + + if((ZCMaps[tmpscr[tmp].layermap[i]-1].tileWidth==ZCMaps[currmap].tileWidth) && (ZCMaps[tmpscr[tmp].layermap[i]-1].tileHeight==ZCMaps[currmap].tileHeight)) + { + tmpscr2[i]=TheMaps[(tmpscr[tmp].layermap[i]-1)*MAPSCRS+tmpscr[tmp].layerscreen[i]]; + + tmpscr2[i].data.resize(_mapsSize, 0); + tmpscr2[i].sflag.resize(_mapsSize, 0); + tmpscr2[i].cset.resize(_mapsSize, 0); + } + else + { + (tmpscr2+i)->zero_memory(); + } + } + else + { + (tmpscr2+i)->zero_memory(); + } + } + } + + if(!isdungeon(scr)) + { + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mSECRET) // if special stuff done before + { + hiddenstair(tmp,false); + hidden_entrance(tmp,false,false,-3); + } + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mLOCKBLOCK) // if special stuff done before + { + remove_lockblocks(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mBOSSLOCKBLOCK) // if special stuff done before + { + remove_bosslockblocks(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mCHEST) // if special stuff done before + { + remove_chests(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mLOCKEDCHEST) // if special stuff done before + { + remove_lockedchests(tmp); + } + + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&mBOSSCHEST) // if special stuff done before + { + remove_bosschests(tmp); + } + + // check doors + if(isdungeon(scr)) + { + for(int i=0; i<4; i++) + { + int door=tmpscr[tmp].door[i]; + bool putit=true; + + switch(door) + { + case d1WAYSHUTTER: + case dSHUTTER: + /* + if((ldir^1)==i) + { + tmpscr[tmp].door[i]=dOPENSHUTTER; + // putit=false; + } + */ + break; + + case dLOCKED: + if(game->maps[(currmap*MAPSCRSNORMAL)+scr]&(1<maps[(currmap*MAPSCRSNORMAL)+scr]&(1<maps[(currmap*MAPSCRSNORMAL)+scr]&(1<0)&&(ZCMaps[tmpscr[tmp].layermap[j]-1].tileWidth==ZCMaps[currmap].tileWidth) && (ZCMaps[tmpscr[tmp].layermap[j]-1].tileHeight==ZCMaps[currmap].tileHeight))) + { + mapscr *layerscreen= (j<0 ? &tmpscr[tmp] + : &(TheMaps[(tmpscr[tmp].layermap[j]-1)*MAPSCRS+tmpscr[tmp].layerscreen[j]])); + + for(int i=0; i<(ZCMaps[currmap].tileWidth)*(ZCMaps[currmap].tileHeight); ++i) + { + int c=layerscreen->data[i]; + int cs=layerscreen->cset[i]; + + // New screen flag: Cycle Combos At Screen Init + if((tmpscr[tmp].flags3 & fCYCLEONINIT) && (j<0 || get_bit(quest_rules,qr_CMBCYCLELAYERS))) + { + int r = 0; + + while(combobuf[c].nextcombo != 0 && r++ < 10) + { + layerscreen->data[i] = combobuf[c].nextcombo; + layerscreen->cset[i] = combobuf[c].nextcset; + c=layerscreen->data[i]; + cs=layerscreen->cset[i]; + } + } + } + } + } + +} + +void putscr(BITMAP* dest,int x,int y, mapscr* scrn) +{ + if(scrn->valid==0||!show_layer_0) + { + rectfill(dest,x,y,x+255,y+175,0); + return; + } + + for(int i=0; i<176; i++) + { + if(scrn->flags7&fLAYER2BG||scrn->flags7&fLAYER3BG) + { + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,scrn->data[i],scrn->cset[i]); + } + else + { + putcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,scrn->data[i],scrn->cset[i]); + } + } +} + +void putscrdoors(BITMAP *dest,int x,int y, mapscr* scrn) +{ + if(scrn->valid==0||!show_layer_0) + { + return; + } + + if(scrn->door[0]==dBOMBED) + { + over_door(dest,0,39,up,x,y); + } + + if(scrn->door[1]==dBOMBED) + { + over_door(dest,0,135,down,x,y); + } + + if(scrn->door[2]==dBOMBED) + { + over_door(dest,0,66,left,x,y); + } + + if(scrn->door[3]==dBOMBED) + { + over_door(dest,0,77,right,x,y); + } +} + +bool _walkflag(int x,int y,int cnt) +{ + // walkflagx=x; walkflagy=y; + if(get_bit(quest_rules,qr_LTTPWALK)) + { + if(x<0||y<0) return false; + + if(x>255) return false; + + if(x>247&&cnt==2) return false; + + if(y>175) return false; + } + else + { + if(x<0||y<0) return false; + + if(x>248) return false; + + if(x>240&&cnt==2) return false; + + if(y>168) return false; + } + + mapscr *s1, *s2; + s1=(((*tmpscr).layermap[0]-1)>=0)?tmpscr2:tmpscr; + s2=(((*tmpscr).layermap[1]-1)>=0)?tmpscr2+1:tmpscr; + // s2=TheMaps+((*tmpscr).layermap[1]-1)MAPSCRS+((*tmpscr).layerscreen[1]); + + int bx=(x>>4)+(y&0xF0); + newcombo c = combobuf[tmpscr->data[bx]]; + newcombo c1 = combobuf[s1->data[bx]]; + newcombo c2 = combobuf[s2->data[bx]]; + bool dried = (((iswater_type(c.type)) || (iswater_type(c1.type)) || + (iswater_type(c2.type))) && DRIEDLAKE); + int b=1; + + if(x&8) b<<=2; + + if(y&8) b<<=1; + + if(((c.walk&b) || (c1.walk&b) || (c2.walk&b)) && !dried) + return true; + + if(cnt==1) return false; + + ++bx; + + if(!(x&8)) + b<<=2; + else + { + c = combobuf[tmpscr->data[bx]]; + c1 = combobuf[s1->data[bx]]; + c2 = combobuf[s2->data[bx]]; + dried = (((iswater_type(c.type)) || (iswater_type(c1.type)) || + (iswater_type(c2.type))) && DRIEDLAKE); + b=1; + + if(y&8) b<<=1; + } + + return ((c.walk&b)||(c1.walk&b)||(c2.walk&b)) ? !dried : false; +} + +bool water_walkflag(int x,int y,int cnt) +{ + if(get_bit(quest_rules,qr_LTTPWALK)) + { + if(x<0||y<0) return false; + + if(x>255) return false; + + if(x>247&&cnt==2) return false; + + if(y>175) return false; + } + else + { + if(x<0||y<0) return false; + + if(x>248) return false; + + if(x>240&&cnt==2) return false; + + if(y>168) return false; + } + + mapscr *s1, *s2; + /* + s1=(((*tmpscr).layermap[0]-1)>=0)? + (TheMaps+((*tmpscr).layermap[0]-1)*MAPSCRS+((*tmpscr).layerscreen[0])): + tmpscr; + s2=(((*tmpscr).layermap[1]-1)>=0)? + (TheMaps+((*tmpscr).layermap[1]-1)*MAPSCRS+((*tmpscr).layerscreen[1])): + tmpscr; + */ + s1=(((*tmpscr).layermap[0]-1)>=0)?tmpscr2:tmpscr; + s2=(((*tmpscr).layermap[1]-1)>=0)?tmpscr2+1:tmpscr; + + int bx=(x>>4)+(y&0xF0); + newcombo c = combobuf[tmpscr->data[bx]]; + newcombo c1 = combobuf[s1->data[bx]]; + newcombo c2 = combobuf[s2->data[bx]]; + int b=1; + + if(x&8) b<<=2; + + if(y&8) b<<=1; + + if((c.walk&b) && !iswater_type(c.type)) + return true; + + if((c1.walk&b) && !iswater_type(c1.type)) + return true; + + if((c2.walk&b) && !iswater_type(c2.type)) + return true; + + if(cnt==1) return false; + + if(x&8) + b<<=2; + else + { + c = combobuf[tmpscr->data[++bx]]; + c1 = combobuf[s1->data[bx]]; + c2 = combobuf[s2->data[bx]]; + b=1; + + if(y&8) b<<=1; + } + + return (c.walk&b) ? !iswater_type(c.type) : + (c1.walk&b) ? !iswater_type(c1.type) : + (c2.walk&b) ? !iswater_type(c2.type) :false; +} + +bool hit_walkflag(int x,int y,int cnt) +{ + if(dlevel) + if(x<32 || y<40 || (x+(cnt-1)*8)>=224 || y>=144) + return true; + + if(blockpath && y<((get_bit(quest_rules,qr_LTTPCOLLISION))?80:88)) + return true; + + if(x<16 || y<16 || (x+(cnt-1)*8)>=240 || y>=160) + return true; + + // for(int i=0; i<4; i++) + if(mblock2.clk && mblock2.hit(x,y,0,cnt*8,1,16)) + return true; + + return _walkflag(x,y,cnt); +} + +void map_bkgsfx(bool on) +{ + if(on) + { + cont_sfx(tmpscr->oceansfx); + + if(tmpscr->bosssfx && !(game->lvlitems[dlevel]&liBOSS)) + cont_sfx(tmpscr->bosssfx); + } + else + { + adjust_sfx(tmpscr->oceansfx,128,false); + adjust_sfx(tmpscr->bosssfx,128,false); + + for(int i=0; ibgsfx) + stop_sfx(((enemy*)guys.spr(i))->bgsfx); + } + } +} + +/**** Script Functions ****/ + +bool asScreenFlagIsSet(int flag) +{ + int flagSet=flag>>8; + flag&=0xFF; + switch(flagSet) + { + case 0: + return tmpscr->flags&flag; + case 1: + return tmpscr->flags2&flag; + case 2: + return tmpscr->flags3&flag; + case 3: + return tmpscr->flags4&flag; + case 4: + return tmpscr->flags5&flag; + case 5: + return tmpscr->flags6&flag; + case 6: + return tmpscr->flags7&flag; + case 7: + return tmpscr->flags8&flag; + case 8: + return tmpscr->flags9&flag; + case 9: + return tmpscr->flags10&flag; + + default: + return false; + } +} + +int asGetComboType(int pos) +{ + return combobuf[tmpscr->data[pos]].type; +} + +/**** View Map ****/ + +//BITMAP *mappic = NULL; +int mapres = 0; + +bool displayOnMap(int x, int y) +{ + int s = (y<<4) + x; + if(!(game->maps[(currmap*MAPSCRSNORMAL)+s]&mVISITED)) + return false; + + // Don't display if not part of DMap + if(((DMaps[currdmap].flags&dmfDMAPMAP) && + (DMaps[currdmap].type != dmOVERW) && + !(x >= DMaps[currdmap].xoff && + x < DMaps[currdmap].xoff+8 && + DMaps[currdmap].grid[y]&(128>>(x-DMaps[currdmap].xoff))))) + return false; + else + return true; +} + +void ViewMap() +{ + mapscr tmpscr_b[2]; + mapscr tmpscr_c[6]; + + for(int i=0; i<6; ++i) + { + tmpscr_c[i] = tmpscr2[i]; + tmpscr2[i].zero_memory(); + + if(i>=2) + { + continue; + } + + tmpscr_b[i] = tmpscr[i]; + tmpscr[i].zero_memory(); + } + + BITMAP* mappic = NULL; + static double scales[17] = + { + 0.03125, 0.04419, 0.0625, 0.08839, 0.125, 0.177, 0.25, 0.3535, + 0.50, 0.707, 1.0, 1.414, 2.0, 2.828, 4.0, 5.657, 8.0 + }; + + int px = ((8-(currscr&15)) << 9) - 256; + int py = ((4-(currscr>>4)) * 352) - 176; + int lx = ((currscr&15)<<8) + LinkX()+8; + int ly = ((currscr>>4)*176) + LinkY()+8; + int sc = 6; + + bool done=false, redraw=true; + + mappic = create_bitmap_ex(8,(256*16)>>mapres,(176*8)>>mapres); + + if(!mappic) + { + system_pal(); + jwin_alert("View Map","Not enough memory.",NULL,NULL,"OK",NULL,13,27,lfont); + game_pal(); + return; + } + + // draw the map + set_clip_rect(scrollbuf, 0, 0, scrollbuf->w, scrollbuf->h); + + for(int y=0; y<8; y++) + { + for(int x=0; x<16; x++) + { + if(!displayOnMap(x, y)) + { + rectfill(scrollbuf, 256, 0, 511, 223, WHITE); + } + else + { + int s = (y<<4) + x; + loadscr2(1,s,-1); + + for(int i=0; i<6; i++) + { + if(tmpscr[1].layermap[i]<=0) + continue; + + if((ZCMaps[tmpscr[1].layermap[i]-1].tileWidth==ZCMaps[currmap].tileWidth) && + (ZCMaps[tmpscr[1].layermap[i]-1].tileHeight==ZCMaps[currmap].tileHeight)) + { + const int _mapsSize = (ZCMaps[currmap].tileWidth)*(ZCMaps[currmap].tileHeight); + + tmpscr2[i]=TheMaps[(tmpscr[1].layermap[i]-1)*MAPSCRS+tmpscr[1].layerscreen[i]]; + + tmpscr2[i].data.resize(_mapsSize, 0); + tmpscr2[i].sflag.resize(_mapsSize, 0); + tmpscr2[i].cset.resize(_mapsSize, 0); + } + } + + if((tmpscr+1)->flags7&fLAYER2BG) do_layer(scrollbuf, 1, tmpscr+1, -256, playing_field_offset, 2); + + if((tmpscr+1)->flags7&fLAYER3BG) do_layer(scrollbuf, 2, tmpscr+1, -256, playing_field_offset, 2); + + putscr(scrollbuf,256,0,tmpscr+1); + do_layer(scrollbuf, 0, tmpscr+1, -256, playing_field_offset, 2); + + if(!((tmpscr+1)->flags7&fLAYER2BG)) do_layer(scrollbuf, 1, tmpscr+1, -256, playing_field_offset, 2); + + putscrdoors(scrollbuf,256,0,tmpscr+1); + do_layer(scrollbuf,-2, tmpscr+1, -256, playing_field_offset, 2); + do_layer(scrollbuf,-3, tmpscr+1, -256, playing_field_offset, 2); // Freeform combos! + + if(!((tmpscr+1)->flags7&fLAYER3BG)) do_layer(scrollbuf, 2, tmpscr+1, -256, playing_field_offset, 2); + + do_layer(scrollbuf, 3, tmpscr+1, -256, playing_field_offset, 2); + do_layer(scrollbuf,-1, tmpscr+1, -256, playing_field_offset, 2); + do_layer(scrollbuf, 4, tmpscr+1, -256, playing_field_offset, 2); + do_layer(scrollbuf, 5, tmpscr+1, -256, playing_field_offset, 2); + + } + + stretch_blit(scrollbuf, mappic, 256, 0, 256, 176, x<<(8-mapres), (y*176)>>mapres, 256>>mapres, 176>>mapres); + } + } + + for(int i=0; i<6; ++i) + { + tmpscr2[i]=tmpscr_c[i]; + + if(i>=2) + { + continue; + } + + tmpscr[i]=tmpscr_b[i]; + } + + + clear_keybuf(); + pause_all_sfx(); + + // view it + int delay = 0; + static int show = 3; + + do + { + load_control_state(); + int step = int(16.0/scales[sc]); + step = (step>>1) + (step&1); + bool r = cRbtn(); + + if(cLbtn()) + { + step <<= 2; + delay = 0; + } + + if(r) + { + if(rUp()) + { + py+=step; + redraw=true; + } + + if(rDown()) + { + py-=step; + redraw=true; + } + + if(rLeft()) + { + px+=step; + redraw=true; + } + + if(rRight()) + { + px-=step; + redraw=true; + } + } + else + { + if(Up()) + { + py+=step; + redraw=true; + } + + if(Down()) + { + py-=step; + redraw=true; + } + + if(Left()) + { + px+=step; + redraw=true; + } + + if(Right()) + { + px-=step; + redraw=true; + } + } + + if(delay) + --delay; + else + { + bool a = cAbtn(); + bool b = cBbtn(); + + if(a && !b) + { + sc=zc_min(sc+1,16); + delay=8; + redraw=true; + } + + if(b && !a) + { + sc=zc_max(sc-1,0); + delay=8; + redraw=true; + } + } + + if(rPbtn()) + --show; + + px = vbound(px,-4096,4096); + py = vbound(py,-1408,1408); + + double scale = scales[sc]; + + if(!redraw) + { + blit(scrollbuf,framebuf,256,0,0,0,256,224); + } + else + { + clear_to_color(framebuf,BLACK); + stretch_blit(mappic,framebuf,0,0,mappic->w,mappic->h, + int(256+(px-mappic->w)*scale)/2,int(224+(py-mappic->h)*scale)/2, + int(mappic->w*scale),int(mappic->h*scale)); + + blit(framebuf,scrollbuf,0,0,256,0,256,224); + redraw=false; + } + + int x = int(256+(px-((2048-lx)*2))*scale)/2; + int y = int(224+(py-((704-ly)*2))*scale)/2; + + if(show&1) + { + line(framebuf,x-7,y-7,x+7,y+7,(frame&3)+252); + line(framebuf,x+7,y-7,x-7,y+7,(frame&3)+252); + } + + // text_mode(BLACK); + + if(show&2 || r) + textprintf_ex(framebuf,font,224,216,WHITE,BLACK,"%1.2f",scale); + + if(r) + { + textprintf_ex(framebuf,font,0,208,WHITE,BLACK,"m: %d %d",px,py); + textprintf_ex(framebuf,font,0,216,WHITE,BLACK,"x: %d %d",x,y); + } + + //since stuff in here accesses tmpscr and tmpscr2... -DD + advanceframe(false, false); + + + if(rSbtn()) + done = true; + + } + while(!done && !Quit); + + destroy_bitmap(mappic); + + resume_all_sfx(); +} + +int onViewMap() +{ + if(Playing && currscr<128 && DMaps[currdmap].flags&dmfVIEWMAP) + { + clear_to_color(framebuf,BLACK); + // text_mode(BLACK); + textout_centre_ex(framebuf,font,"Drawing map...",128,108,WHITE,BLACK); + advanceframe(true); + ViewMap(); + } + + return D_O_K; +} + +bool isGrassType(int type) +{ + switch(type) + { + case cTALLGRASS: + case cTALLGRASSNEXT: + case cTALLGRASSTOUCHY: + return true; + } + + return false; +} + +bool isFlowersType(int type) +{ + switch(type) + { + case cFLOWERS: + case cFLOWERSTOUCHY: + return true; + } + + return false; +} + +bool isBushType(int type) +{ + switch(type) + { + case cBUSH: + case cBUSHNEXT: + case cBUSHTOUCHY: + case cBUSHNEXTTOUCHY: + return true; + } + + return false; +} + +bool isSlashType(int type) +{ + switch(type) + { + case cSLASH: + case cSLASHITEM: + case cSLASHTOUCHY: + case cSLASHITEMTOUCHY: + case cSLASHNEXT: + case cSLASHNEXTITEM: + case cSLASHNEXTTOUCHY: + case cSLASHNEXTITEMTOUCHY: + return true; + } + + return false; +} + +bool isCuttableNextType(int type) +{ + switch(type) + { + case cSLASHNEXT: + case cSLASHNEXTITEM: + case cTALLGRASSNEXT: + case cBUSHNEXT: + case cSLASHNEXTTOUCHY: + case cSLASHNEXTITEMTOUCHY: + case cBUSHNEXTTOUCHY: + return true; + } + + return false; +} + +bool isTouchyType(int type) +{ + switch(type) + { + case cSLASHTOUCHY: + case cSLASHITEMTOUCHY: + case cBUSHTOUCHY: + case cFLOWERSTOUCHY: + case cTALLGRASSTOUCHY: + case cSLASHNEXTTOUCHY: + case cSLASHNEXTITEMTOUCHY: + case cBUSHNEXTTOUCHY: + return true; + } + + return false; +} + +bool isCuttableType(int type) +{ + switch(type) + { + case cSLASH: + case cSLASHITEM: + case cBUSH: + case cFLOWERS: + case cTALLGRASS: + case cTALLGRASSNEXT: + case cSLASHNEXT: + case cSLASHNEXTITEM: + case cBUSHNEXT: + + case cSLASHTOUCHY: + case cSLASHITEMTOUCHY: + case cBUSHTOUCHY: + case cFLOWERSTOUCHY: + case cTALLGRASSTOUCHY: + case cSLASHNEXTTOUCHY: + case cSLASHNEXTITEMTOUCHY: + case cBUSHNEXTTOUCHY: + return true; + } + + return false; +} + +bool isCuttableItemType(int type) +{ + switch(type) + { + case cSLASHITEM: + case cBUSH: + case cFLOWERS: + case cTALLGRASS: + case cTALLGRASSNEXT: + case cSLASHNEXTITEM: + case cBUSHNEXT: + + case cSLASHITEMTOUCHY: + case cBUSHTOUCHY: + case cFLOWERSTOUCHY: + case cTALLGRASSTOUCHY: + case cSLASHNEXTITEMTOUCHY: + case cBUSHNEXTTOUCHY: + return true; + } + + return false; +} + + +/*** end of maps.cc ***/ + diff --git a/src/maps.h b/src/maps.h new file mode 100644 index 0000000000..f31c7a003f --- /dev/null +++ b/src/maps.h @@ -0,0 +1,119 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// maps.cc +// +// Map and screen scrolling stuff for zelda.cc +// +//-------------------------------------------------------- + +#ifndef _MAPS_H_ +#define _MAPS_H_ +#include "zdefs.h" + +#define DRIEDLAKE ((tmpscr->flags7 & fWHISTLEWATER) && (whistleclk>=88)) +#define COMBOPOS(x,y) (((y)&0xF0)+((x)>>4)) +void debugging_box(int x1, int y1, int x2, int y2); +void clear_dmap(word i); +void clear_dmaps(); +int count_dmaps(); +bool isdungeon(int dmap = -1, int scr = -1); +int MAPCOMBO(int x,int y); +int MAPFFCOMBO(int x,int y); +int MAPCSET(int x,int y); +int MAPFLAG(int x,int y); +int MAPCOMBOFLAG(int x,int y); +int MAPFFCOMBOFLAG(int x,int y); +int COMBOTYPE(int x,int y); +int FFCOMBOTYPE(int x, int y); +int MAPCOMBO2(int layer,int x,int y); +int MAPCSET2(int layer,int x,int y); +int MAPFLAG2(int layer,int x,int y); +int MAPCOMBOFLAG2(int layer,int x,int y); +int COMBOTYPE2(int layer,int x,int y); +int getFFCAt(int x, int y); +void eventlog_mapflags(); +void setmapflag(int mi2, int flag); +void setmapflag(int flag = 32); // 32 = mBELOW +void unsetmapflag(int mi2, int flag, bool anyflag=false); +void unsetmapflag(int flag = 32); +bool getmapflag(int flag = 32); // 32 = mBELOW +int WARPCODE(int dmap,int scr,int dw); +void update_combo_cycling(); +bool iswater(int combo); +bool iswater_type(int type); +bool isGrassType(int type); +bool isFlowersType(int type); +bool isBushType(int type); +bool isSlashType(int type); +bool isCuttableNextType(int type); +bool isTouchyType(int type); +bool isCuttableType(int type); +bool isCuttableItemType(int type); +bool isstepable(int combo); //can use ladder on it +bool ishookshottable(int bx, int by); +bool hiddenstair(int tmp, bool redraw); // tmp = index of tmpscr[] +bool remove_lockblocks(int tmp); // tmp = index of tmpscr[] +bool remove_bosslockblocks(int tmp); // tmp = index of tmpscr[] +bool remove_chests(int tmp); // tmp = index of tmpscr[] +bool remove_lockedchests(int tmp); // tmp = index of tmpscr[] +bool remove_bosschests(int tmp); // tmp = index of tmpscr[] +bool overheadcombos(mapscr *s); +void delete_fireball_shooter(mapscr *s, int i); +void hidden_entrance(int tmp,bool refresh, bool high16only=false,int single=-1); +void update_freeform_combos(); +bool findentrance(int x, int y, int flag, bool setflag); +bool hitcombo(int x, int y, int combotype); +bool hitflag(int x, int y, int flagtype); +int nextscr(int dir); +void bombdoor(int x,int y); +void do_scrolling_layer(BITMAP *bmp, int type, mapscr* layer, int x, int y, bool scrolling, int tempscreen); +void do_layer(BITMAP *bmp, int type, mapscr* layer, int x, int y, int tempscreen, bool scrolling = false, bool drawprimitives=false); +void put_walkflags(BITMAP *dest,int x,int y,int xofs,int yofs, word cmbdat,int lyr); +void do_walkflags(BITMAP *dest,mapscr* layer,int x, int y, int tempscreen); +void do_primitives(BITMAP *bmp, int type, mapscr *layer, int x, int y); +void draw_screen(mapscr* this_screen, bool showlink=true); +/* + INLINE void do_scrolling_layer(int type, mapscr* layer, int x, int y, bool scrolling, int tempscreen) + { + do_scrolling_layer(framebuf, type, layer, x, y, scrolling, tempscreen); + } + + INLINE void do_layer(int type, mapscr* layer, int x, int y, int tempscreen) + { + do_layer(framebuf, type, layer, x, y, tempscreen); + } + */ +void put_door(BITMAP *dest,int t,int pos,int side,int type,bool redraw,bool even_walls=false); +void over_door(BITMAP *dest,int t, int pos,int side); +void putdoor(BITMAP *dest,int t,int side,int door,bool redraw=true,bool even_walls=false); +void showbombeddoor(BITMAP *dest, int side); +void openshutters(); +void loadscr(int tmp,int destdmap,int scr,int ldir,bool overlay); +void putscr(BITMAP* dest,int x,int y,mapscr* screen); +void putscrdoors(BITMAP *dest,int x,int y,mapscr* screen); +bool _walkflag(int x,int y,int cnt); +bool water_walkflag(int x,int y,int cnt); +bool hit_walkflag(int x,int y,int cnt); +void map_bkgsfx(bool on); + +// Used by scripts +bool asScreenFlagIsSet(int flag); +int asGetComboType(int pos); + +//extern FONT *lfont; +/**** View Map ****/ +extern int mapres; +bool displayOnMap(int x, int y); +void ViewMap(); +int onViewMap(); + + +#define DegtoFix(d) ((d)*0.7111111111111) +#define RadtoFix(d) ((d)*40.743665431525) + +#endif + +/*** end of maps.cc ***/ + diff --git a/src/matrix.cpp b/src/matrix.cpp new file mode 100644 index 0000000000..929c5d50b4 --- /dev/null +++ b/src/matrix.cpp @@ -0,0 +1,317 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// matrix.c +// +// Code for the "Matrix" screen saver. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "matrix.h" +#include "zc_alleg.h" +#include "zc_sys.h" + +// external FONTs +extern FONT *deffont, *mfont; + + +#define MAX_COLS 256 +#define MAX_MATRIX_TRACERS MAX_COLS * 2 + +#define BLACK 253 +#define LIGHT_GREEN 250 +#define MED_GREEN 245 +#define DARK_GREEN 244 + +//#ifndef _MSC_VER +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) +//#endif + +typedef unsigned char byte; + +typedef struct MATRIX_TRACER +{ + byte x, y; + byte speed; + byte cnt; +} MATRIX_TRACER; + +typedef struct MATRIX_COLUMN +{ + short speed, cnt; +} MATRIX_COLUMN; + +static BITMAP *linebmp = NULL; +static MATRIX_TRACER tracer[MAX_MATRIX_TRACERS]; +static MATRIX_TRACER eraser[MAX_MATRIX_TRACERS]; +static MATRIX_COLUMN column[MAX_COLS]; +static byte activecol[MAX_COLS]; +static int cols, rows, maxtracers, _speed, _density; + +static void InitMatrix(); +static void AddTracer(); +static void AddEraser(int col); +static void UpdateTracers(); +static void UpdateErasers(); +static void UpdateColumns(); +static void DrawLetter(int x, int y, int color); +static void DrawEraser(int x, int y, int type); + +extern void throttleFPS(); + + +void Matrix(int speed, int density, int mousedelay) +{ + // speed 0-6, density 0-6 + _density = zc_max(zc_min(density, 6), 0); + _speed = zc_max(zc_min(speed, 6), 0); + + InitMatrix(); + + for(;;) + { + //vsync(); + throttleFPS(); + + AddTracer(); + AddEraser(-1); + UpdateTracers(); + UpdateErasers(); + UpdateColumns(); + + poll_joystick(); + + int idle; + + if(mousedelay > 0) + { + mousedelay--; + idle = input_idle(false); + } + else + { + idle = input_idle(true); + } + + if(!idle) + break; + } + + if(linebmp != NULL) + destroy_bitmap(linebmp); + + clear_keybuf(); + + clear_to_color(screen, BLACK); +} + +static void InitMatrix() +{ + RGB c_blck = {0,0,0,0}; + RGB c_lgrn = {0,255,0,0}; + RGB c_mgrn = {0,170,0,0}; + RGB c_dgrn = {0,85,0,0}; + + set_color(BLACK, &c_blck); + set_color(LIGHT_GREEN, &c_lgrn); + set_color(MED_GREEN, &c_mgrn); + set_color(DARK_GREEN, &c_dgrn); + + cols = zc_max(zc_min(SCREEN_W / 8, MAX_COLS), 1); + rows = zc_max(zc_min(SCREEN_H / 8, MAX_COLS), 1); + + linebmp = create_bitmap_ex(8,8, rows*8); + + maxtracers = ((_density + 2) * cols) / 4; + + for(int i=0; i=0 || (tracer[i].speed + && tracer[i].y > 5 + (_density - _speed)/2 + && (rand() % ((7 + _density - _speed)*5 + 10)) == 0))) + { + eraser[i].x = col>=0 ? col : tracer[i].x; + eraser[i].y = 0; + eraser[i].speed = col>=0 ? (rand()&7) * (4-_speed/2) + 8 - _speed : tracer[i].speed + (rand()&3); + eraser[i].cnt = 0; + activecol[eraser[i].x] = 0; + DrawEraser(eraser[i].x, eraser[i].y, 1); + break; + } + } +} + +static void UpdateTracers() +{ + for(int i=0; i= tracer[i].speed) + { + DrawLetter(tracer[i].x, tracer[i].y, MED_GREEN); + + if(tracer[i].y >= rows-1) + tracer[i].speed = 0; + else + { + tracer[i].cnt = 0; + DrawLetter(tracer[i].x, ++tracer[i].y, LIGHT_GREEN); + } + } + } + } +} + +static void UpdateErasers() +{ + for(int i=0; i= eraser[i].speed) + { + DrawEraser(eraser[i].x, eraser[i].y, 0); + + if(eraser[i].y >= rows-1) + eraser[i].speed = 0; + else + { + eraser[i].cnt = 0; + DrawEraser(eraser[i].x, ++eraser[i].y, 1); + } + } + } + } +} + +static void DrawLetter(int x, int y, int color) +{ + int r = rand(); + int letter = r & 255; + + if(letter < 32) + letter += (r>>10) % 224; + + FONT *fnt = (r&512) || ((letter&0xE0)==0x80) ? mfont : deffont; + + textprintf_ex(screen, fnt, x<<3, y<<3, color, BLACK, "%c", letter); +} + +static void DrawEraser(int x, int y, int type) +{ + x <<= 3; + y <<= 3; + + if(type == 0) + { + rectfill(screen, x, y, x+7, y+7, BLACK); + } + else + { + for(int i=0; i<8; i++) + for(int j=0; j<8; j++) + { + int pix = getpixel(screen, x+i, y+j); + + if(pix == LIGHT_GREEN || pix == MED_GREEN) + putpixel(screen, x+i, y+j, DARK_GREEN); + } + } +} + +static void UpdateColumns() +{ + for(int i=0; i= column[i].speed) + { + column[i].cnt = 0; + + for(int j=0; j= rows) + tracer[j].speed = 0; + } + + if(eraser[j].x == i) + { + eraser[j].y++; + if(eraser[j].y >= rows) + eraser[j].speed = 0; + } + } + + blit(screen, linebmp, i*8, 0, 0, 0, 8, rows*8 - 8); + blit(linebmp, screen, 0, 0, i*8, 8, 8, rows*8 - 8); + + if(activecol[i]) + { + DrawLetter(i, 0, MED_GREEN); + + if(++activecol[i] >= rows/3) + { + if(rand()&15) + AddEraser(i); + } + } + else + { + DrawEraser(i, 0, 0); + } + } + } +} + diff --git a/src/matrix.h b/src/matrix.h new file mode 100644 index 0000000000..db029baae9 --- /dev/null +++ b/src/matrix.h @@ -0,0 +1,18 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// matrix.h +// +// Code for the "Matrix" screen saver. +// +//-------------------------------------------------------- + +#ifndef _MATRIX_H_ +#define _MATRIX_H_ + +extern int input_idle(bool checkmouse); + +void Matrix(int speed, int density, int mousedelay); +#endif + diff --git a/src/md5.cpp b/src/md5.cpp new file mode 100644 index 0000000000..afc840dca9 --- /dev/null +++ b/src/md5.cpp @@ -0,0 +1,342 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to + not require an integer type which is exactly 32 bits. This work + draws on the changes for the same purpose by Tatu Ylonen + as part of SSH, but since I didn't actually use + that code, there is no copyright issue. I hereby disclaim + copyright in any changes I have made; this code remains in the + public domain. */ + +/* Note regarding cvs_* namespace: this avoids potential conflicts + with libraries such as some versions of Kerberos. No particular + need to worry about whether the system supplies an MD5 library, as + this file is only about 3k of object code. */ + +#include "precompiled.h" //always first + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* for memcpy() and memset() */ + +/* Add prototype support. */ +#ifndef PROTO +#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__) +#define PROTO(ARGS) ARGS +#else +#define PROTO(ARGS) () +#endif +#endif + +#include "md5.h" + +/* Little-endian byte-swapping routines. Note that these do not + depend on the size of datatypes such as cvs_uint32, nor do they require + us to detect the endianness of the machine we are running on. It + is possible they should be macros for speed, but I would be + surprised if they were a performance bottleneck for MD5. */ + +static cvs_uint32 +getu32(const unsigned char *addr) +{ + return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) + | addr[1]) << 8 | addr[0]; +} + +static void +putu32(cvs_uint32 data, + unsigned char *addr) +{ + addr[0] = (unsigned char)data; + addr[1] = (unsigned char)(data >> 8); + addr[2] = (unsigned char)(data >> 16); + addr[3] = (unsigned char)(data >> 24); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +cvs_MD5Init(cvs_MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +cvs_MD5Update(cvs_MD5Context *ctx, + unsigned char const *buf, + unsigned len) +{ + cvs_uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + + if((ctx->bits[0] = (t + ((cvs_uint32)len << 3)) & 0xffffffff) < t) + ctx->bits[1]++; /* Carry from low to high */ + + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if(t) + { + unsigned char *p = ctx->in + t; + + t = 64-t; + + if(len < t) + { + memcpy(p, buf, len); + return; + } + + memcpy(p, buf, t); + cvs_MD5Transform(ctx->buf, ctx->in); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + while(len >= 64) + { + memcpy(ctx->in, buf, 64); + cvs_MD5Transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +cvs_MD5Final(unsigned char digest[16], + cvs_MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if(count < 8) + { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + cvs_MD5Transform(ctx->buf, ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } + else + { + /* Pad block to 56 bytes */ + memset(p, 0, count-8); + } + + /* Append length in bits and transform */ + putu32(ctx->bits[0], ctx->in + 56); + putu32(ctx->bits[1], ctx->in + 60); + + cvs_MD5Transform(ctx->buf, ctx->in); + putu32(ctx->buf[0], digest); + putu32(ctx->buf[1], digest + 4); + putu32(ctx->buf[2], digest + 8); + putu32(ctx->buf[3], digest + 12); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +cvs_MD5Transform(cvs_uint32 buf[4], + const unsigned char inraw[64]) +{ + register cvs_uint32 a, b, c, d; + cvs_uint32 in[16]; + int i; + + for(i = 0; i < 16; ++i) + in[i] = getu32(inraw + 4 * i); + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} +#endif + +#ifdef TEST +/* Simple test program. Can use it to manually run the tests from + RFC1321 for example. */ +#include + +int +main(int argc, char **argv) +{ + cvs_MD5Context context; + unsigned char checksum[16]; + int i; + int j; + + if(argc < 2) + { + fprintf(stderr, "usage: %s string-to-hash\n", argv[0]); + exit(1); + } + + for(j = 1; j < argc; ++j) + { + printf("MD5 (\"%s\") = ", argv[j]); + cvs_MD5Init(&context); + cvs_MD5Update(&context, argv[j], strlen(argv[j])); + cvs_MD5Final(checksum, &context); + + for(i = 0; i < 16; i++) + { + printf("%02x", (unsigned int) checksum[i]); + } + + printf("\n"); + } + + return 0; +} +#endif /* TEST */ diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 0000000000..5e47064583 --- /dev/null +++ b/src/md5.h @@ -0,0 +1,38 @@ +/* See md5.c for explanation and copyright information. */ + +/* + * $FreeBSD: src/contrib/cvs/lib/md5.h,v 1.2 1999/12/11 15:10:02 peter Exp $ + */ + +#ifndef MD5_H +#define MD5_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Unlike previous versions of this code, uint32 need not be exactly + 32 bits, merely 32 bits or more. Choosing a data type which is 32 + bits instead of 64 is not important; speed is considerably more + important. ANSI guarantees that "unsigned long" will be big enough, + and always using it seems to have few disadvantages. */ +typedef unsigned long cvs_uint32; + +typedef struct +{ + cvs_uint32 buf[4]; + cvs_uint32 bits[2]; + unsigned char in[64]; +} cvs_MD5Context; + +void cvs_MD5Init(cvs_MD5Context *context); +void cvs_MD5Update(cvs_MD5Context *context, unsigned char const *buf, unsigned len); +void cvs_MD5Final(unsigned char digest[16], cvs_MD5Context *context); +void cvs_MD5Transform(cvs_uint32 buf[4], const unsigned char in[64]); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* !MD5_H */ diff --git a/src/mem_debug.h b/src/mem_debug.h new file mode 100644 index 0000000000..39a471cad0 --- /dev/null +++ b/src/mem_debug.h @@ -0,0 +1,61 @@ + +/* For stupid memory management bullshit */ +#ifndef __trapperkeeper_h_ +#define __trapperkeeper_h_ + +#include "zc_malloc.h" + + +#ifndef TK_NO_CRTDBG +#ifdef _MSC_VER + + +#pragma once + +#define _CRTDBG_MAP_ALLOC +#include +#include + + +#ifndef TK_NO_NEW_REMAP +//taken from msdn +#ifdef _DEBUG +#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) +#define new DEBUG_NEW +#endif +#endif + + +#ifdef _DEBUG +inline static void InitCrtDebug(int flags = 0) +{ + if(flags == 0) + flags = + _CRTDBG_ALLOC_MEM_DF + | + _CRTDBG_LEAK_CHECK_DF + //| + //_CRTDBG_REPORT_FLAG + ; + + _CrtSetDbgFlag(flags); + +} +#else // NOT _DEBUG +/*inline static void InitCrtDebug( int flags = 0 ) + { + flags = flags; //do nothing + }*/ +#endif + +#else // NOT _MSC_VER +/*static void InitCrtDebug( int flags = 0 ) + { + flags = flags; //do nothing + }*/ +#endif //_MSC_VER +#endif //TK_HEADER_NO_DEBUG_REMAP + + + +#endif diff --git a/src/message.cpp b/src/message.cpp new file mode 100644 index 0000000000..850adc417d --- /dev/null +++ b/src/message.cpp @@ -0,0 +1,299 @@ +#include "message.h" + +#include "link.h" +#include "messageManager.h" +#include "pal.h" +#include "sound.h" +#include "zc_sys.h" +#include "zdefs.h" +#include "zelda.h" +#include + + +Message::Message(const MsgStr* msgstr, MessageManager& mm): + manager(mm), + stream(msgstr->s), + msgX(msgstr->x), + msgY(msgstr->y), + textSFX(msgstr->sfx), + textSpeed(zinit.msg_speed), + wordWrappingEnabled((msgstr->stringflags&STRINGFLAG_WRAP)!=0), + timer(textSpeed) +{ + renderer.initialize(msgstr); +} + +Message::Message(int dmap, MessageManager& mm): + manager(mm), + stream(DMaps[dmap].intro), + msgX(24), + msgY(32), + textSFX(18), + textSpeed(zinit.msg_speed), // Is that right? Maybe it's fixed... + wordWrappingEnabled(false), + timer(textSpeed) +{ + renderer.initialize(0); +} + +void Message::update(updateSpeed speed) +{ + if(stream.atEnd()) // Might happen if given an empty message + return; + + if(speed==spd_normal && timer>0) + { + timer--; + if(timer>0) + return; + } + + processNext(speed); + timer=textSpeed; +} + +void Message::processNext(updateSpeed speed) +{ + do + { + if(stream.nextIsWhitespace()) + { + do + { + if(stream.getCharacter()==' ') + renderer.putChar(' '); + else // Line break; stream already advanced + renderer.startNewLine(); + } while(stream.nextIsWhitespace()); + + if(wordWrappingEnabled && !renderer.atLineStart()) + checkWordWrapping(); + } + + char c=stream.getCharacter(); + if(c>' ') + { + renderer.putChar(c); + if(speed!=spd_instant) + sfx(textSFX); + } + else + executeControlCode(c-1); + } while(speed==spd_instant && !stream.atEnd()); +} + +void Message::checkWordWrapping() +{ + unsigned int streamPos=stream.tell(); + int wordWidth=0; + int wordLength=0; + + Font font=renderer.getFont(); + + // Find the width of the word, not counting spacing + while(!(stream.nextIsWhitespace() || stream.atEnd())) + { + char c=stream.getCharacter(); + + if(c>' ') + { + wordWidth+=font.getWidth(c); + wordLength++; + } + else + { + // Control code; skip past it + for(int i=getNumControlCodeArgs(c-1); i>0; i--) + stream.getControlCodeArgument(); + } + } + + if(!renderer.wordFits(wordWidth, wordLength)) + renderer.startNewLine(); + + stream.seek(streamPos); +} + +void Message::executeControlCode(char code) +{ + int arg1, arg2, arg3; + int numArgs=getNumControlCodeArgs(code); + + if(numArgs>=1) + arg1=stream.getControlCodeArgument(); + if(numArgs>=2) + arg2=stream.getControlCodeArgument(); + if(numArgs==3) + arg3=stream.getControlCodeArgument(); + + switch(code) + { + // Message property change codes + case MSGC_SPEED: + textSpeed=arg1; + break; + + case MSGC_COLOUR: + renderer.setColor(CSET(arg1)+arg2); + break; + + // Message switch codes + case MSGC_GOTOIFRAND: + if(arg1<=1 || rand()%arg1==0) + manager.switchTo(arg2); + break; + + case MSGC_GOTOIFGLOBAL: // Screen->D[], not global. Should be renamed. + { + arg1=vbound(arg1, 0, 7); + int scr=(get_currdmap()<<7)+get_currscr(); + if(DMaps[get_currdmap()].type!=dmOVERW) + scr-=DMaps[get_currdmap()].xoff; + + if(game->screen_d[scr][arg1]>=arg2) + manager.switchTo(arg3); + break; + } + + case MSGC_GOTOIF: // If item. Rename this one, too. + if(arg1>=0 && arg1item[arg1]) + manager.switchTo(arg2); + break; + + case MSGC_GOTOIFCTR: + if(game->get_counter(arg1)>=arg2) + manager.switchTo(arg3); + break; + + case MSGC_GOTOIFCTRPC: + { + int amount=(arg2*game->get_maxcounter(arg1))/100; + if(game->get_counter(arg1)>=amount) + manager.switchTo(arg3); + break; + } + + case MSGC_GOTOIFTRICOUNT: + if(TriforceCount()>=arg1) + manager.switchTo(arg2); + break; + + case MSGC_GOTOIFTRI: + if(arg1>=0 && arg1lvlitems[arg1]&liTRIFORCE)!=0) + manager.switchTo(arg2); + break; + + // Item and counter codes + case MSGC_CTRUP: + game->change_counter(arg2, arg1); + break; + + case MSGC_CTRDN: + game->change_counter(-arg2, arg1); + break; + + case MSGC_CTRSET: + game->set_counter(vbound(arg2, 0, game->get_maxcounter(arg1)), arg1); + break; + + case MSGC_CTRUPPC: + { + int amount=(arg2*game->get_maxcounter(arg1))/100; + game->change_counter(arg2, amount); + break; + } + + case MSGC_CTRDNPC: + { + int amount=(arg2*game->get_maxcounter(arg1))/100; + game->change_counter(-arg2, amount); + break; + } + + case MSGC_CTRSETPC: + { + int amount=vbound((arg2*game->get_maxcounter(arg1))/100, + 0, game->get_maxcounter(arg1)); + game->set_counter(amount, arg1); + break; + } + + case MSGC_GIVEITEM: + getitem(arg1); + break; + + case MSGC_TAKEITEM: + takeitem(arg1); + break; + + // Other codes + case MSGC_MIDI: + if(arg1==0) + music_stop(); + else + jukebox(arg1+(ZC_MIDI_COUNT-1)); + break; + + case MSGC_SFX: + sfx(arg1); + break; + } +} + +int Message::getNumControlCodeArgs(char code) const +{ + // MSGC_NEWLINE isn't handled here + switch(code) + { + case MSGC_GOTOIFGLOBAL: + case MSGC_GOTOIFCTRPC: + case MSGC_GOTOIFCTR: + return 3; + + case MSGC_COLOUR: + case MSGC_CTRUP: + case MSGC_CTRDN: + case MSGC_CTRSET: + case MSGC_CTRUPPC: + case MSGC_CTRDNPC: + case MSGC_CTRSETPC: + case MSGC_GOTOIF: + case MSGC_GOTOIFTRI: + case MSGC_GOTOIFTRICOUNT: + case MSGC_GOTOIFRAND: + return 2; + + case MSGC_SFX: + case MSGC_MIDI: + case MSGC_SPEED: + case MSGC_GIVEITEM: + case MSGC_TAKEITEM: + return 1; + + default: // Shouldn't happen + return 0; + } +} + +void Message::reset(const MsgStr* nextMsg) +{ + stream.reset(nextMsg->s); + msgX=nextMsg->x; + msgY=nextMsg->y; + textSFX=nextMsg->sfx; + wordWrappingEnabled=(nextMsg->stringflags&STRINGFLAG_WRAP)!=0; + + renderer.initialize(nextMsg); +} + +void Message::continueTo(const MsgStr* nextMsg) +{ + stream.reset(nextMsg->s); + textSFX=nextMsg->sfx; + renderer.loadContinuationStyle(nextMsg); +} + +void Message::draw(BITMAP* target, int yOffset) +{ + renderer.draw(target, msgX, msgY+yOffset); +} diff --git a/src/message.h b/src/message.h new file mode 100644 index 0000000000..5a93f23139 --- /dev/null +++ b/src/message.h @@ -0,0 +1,63 @@ +#ifndef _ZC_MESSAGE_H_ +#define _ZC_MESSAGE_H_ + +#include "messageStream.h" + +#include "fontClass.h" +#include "messageRenderer.h" + +struct BITMAP; +struct FONT; +class MessageManager; +struct MsgStr; + +class Message +{ +public: + enum updateSpeed { spd_normal, spd_fast, spd_instant }; + + Message(const MsgStr* msgstr, MessageManager& mm); + Message(int dmap, MessageManager& mm); + + void update(updateSpeed speed); + + /// Clear the current message and switch to a new one. + void reset(const MsgStr* nextMsg); + + /// Load a message as a continuation of the current one. + void continueTo(const MsgStr* nextMsg); + void draw(BITMAP* target, int yOffset); + + inline bool atEnd() const + { + return stream.atEnd(); + } + +private: + MessageManager& manager; + MessageStream stream; + MessageRenderer renderer; + + int msgX, msgY; + int textSFX; + int textSpeed; + bool wordWrappingEnabled; + int timer; + + void processNext(updateSpeed speed); + + /// Starts a new line if the next word won't fit on the current line. + /** Assumes the stream is at the beginning of a word, so this should + * be called after processing whitespace. + */ + void checkWordWrapping(); + + /// Executes a control code. + /** Arguments are read from the stream; it's assumed that the stream + * position is at the beginning of the first argument, if there are any. + */ + void executeControlCode(char code); + int getNumControlCodeArgs(char code) const; +}; + +#endif diff --git a/src/messageList.cpp b/src/messageList.cpp new file mode 100644 index 0000000000..7e47926d74 --- /dev/null +++ b/src/messageList.cpp @@ -0,0 +1,51 @@ +#include "messageList.h" +#include "types.h" +#include "zdefs.h" +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +extern word msg_count; +extern MsgStr* MsgStrings; + +int MessageList::getNumMessages() const +{ + return msg_count; +} + +int MessageList::getMessageNum(int listPos) const +{ + for(int i=0; i0 ? getMessageNum(listPos-1) : -1; + char buf[128]; + bool indent=msgNum>0 && MsgStrings[prevMsgNum].nextstring==msgNum; + snprintf(buf, 128, "%s%3d: %s", indent ? "--> " : "", msgNum, MsgStrings[msgNum].s); + buf[127]='\0'; + return buf; + +} diff --git a/src/messageList.h b/src/messageList.h new file mode 100644 index 0000000000..baecfac421 --- /dev/null +++ b/src/messageList.h @@ -0,0 +1,25 @@ +#ifndef _ZC_MESSAGELIST_H_ +#define _ZC_MESSAGELIST_H_ + +#include + +// A class to simplify message number lookups. +class MessageList +{ +public: + int getNumMessages() const; + + /// Get a ID of the message at the given list position. + int getMessageNum(int listPos) const; + + /// Get the list position of a message based on its actual ID number. + int getMessageListPos(int msgNum) const; + + /// Get the text of a message. + std::string getMessageText(int msgNum) const; + + /// Get the text of a message as displayed in a list. + std::string getListMessageText(int listPos) const; +}; + +#endif diff --git a/src/messageManager.cpp b/src/messageManager.cpp new file mode 100644 index 0000000000..56e81df0cf --- /dev/null +++ b/src/messageManager.cpp @@ -0,0 +1,212 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#include "precompiled.h" //always first + +#include "messageManager.h" +#include "link.h" +#include "message.h" +#include "weapons.h" +#include "zc_sys.h" +#include "zdefs.h" +#include "zelda.h" +#include + +extern LinkClass Link; + +namespace +{ + bool hasContinuation(const MsgStr* msg) + { + if(!msg || msg->nextstring==0) + return false; + + MsgStr* nextMsg=&MsgStrings[msg->nextstring]; + return (nextMsg->stringflags&STRINGFLAG_CONT)!=0; + } +} + +MessageManager::MessageManager(): + currMsgStr(0), + activeMessage(0) +{ +} + +MessageManager::~MessageManager() +{ + delete activeMessage; +} + +void MessageManager::showMessage(int id) +{ + if(onMessageEnd) + { + onMessageEnd(); + onMessageEnd.clear(); + } + delete activeMessage; + + currMsgStr=&MsgStrings[id]; + activeMessage=new Message(currMsgStr, *this); + + if(activeMessage->atEnd() && hasContinuation(currMsgStr)) + { + // Empty message that continues to another. It's also possible + // that one's also empty and has yet another continuation, + // so it needs to be checked in a loop. + do + { + currMsgStr=&MsgStrings[currMsgStr->nextstring]; + activeMessage->continueTo(currMsgStr); + } while(activeMessage->atEnd() && hasContinuation(currMsgStr)); + } + + // We'll just assume we didn't end up with an empty message. + // If that did happen, it'll be resolved on the first update. + state=mst_active; +} + +void MessageManager::showDMapIntro(int dmap) +{ + if(onMessageEnd) + { + onMessageEnd(); + onMessageEnd.clear(); + } + delete activeMessage; + currMsgStr=0; + activeMessage=new Message(dmap, *this); + state=mst_active; +} + +void MessageManager::clear(bool runCallback) +{ + if(onMessageEnd && runCallback) + { + onMessageEnd(); + onMessageEnd.clear(); + } + delete activeMessage; + activeMessage=0; + state=mst_inactive; +} + +void MessageManager::update() +{ + if(!activeMessage || state==mst_inactive) + return; + + if(state==mst_active) + { + Message::updateSpeed speed; + if(cBbtn() && get_bit(quest_rules,qr_ALLOWMSGBYPASS)) + speed=Message::spd_instant; + else if(cAbtn() && get_bit(quest_rules,qr_ALLOWFASTMSG)) + speed=Message::spd_fast; + else + speed=Message::spd_normal; + + activeMessage->update(speed); + while(activeMessage->atEnd() && hasContinuation(currMsgStr)) + { + // Continue to the next message. Check in a loop in case + // there's an empty continuation. + currMsgStr=&MsgStrings[currMsgStr->nextstring]; + activeMessage->continueTo(currMsgStr); + } + + if(activeMessage->atEnd()) + { + if(!currMsgStr || // DMap intro? + currMsgStr->nextstring!=0 || // Another message? + get_bit(quest_rules,qr_MSGDISAPPEAR)) // Messages disappear? + { + state=mst_waitingToAdvance; + timer=51; + } + else // Do nothing + { + state=mst_inactive; + if(onMessageEnd) + { + onMessageEnd(); + onMessageEnd.clear(); + } + } + } + } + else if(state==mst_waitingToAdvance) + { + timer--; + if(timer==0) + { + // Timer ran out; what to do next? + if(!currMsgStr) // DMap intro; clear it + { + delete activeMessage; + activeMessage=0; + state=mst_inactive; + // Currently, DMap intros will never use onMessageEnd, + // so it isn't checked + } + else // Must be something that needs the player to press A + state=mst_awaitingInput; + } + } + else // Awaiting input + { + if(cAbtn()) + { + // Proceed to the next message if there is one; otherwise, clear it + if(currMsgStr && currMsgStr->nextstring!=0) + switchTo(currMsgStr->nextstring); + else + { + delete activeMessage; + activeMessage=0; + state=mst_inactive; + if(onMessageEnd) + { + onMessageEnd(); + onMessageEnd.clear(); + } + } + } + } +} + +void MessageManager::switchTo(int msg) +{ + if(onMessageEnd) + { + onMessageEnd(); + onMessageEnd.clear(); + } + + if(msg<0 || msg>msg_count) + msg=0; // Currently shows "(none)" instead of nothing + currMsgStr=&MsgStrings[msg]; + activeMessage->reset(currMsgStr); + state=mst_active; +} + +void MessageManager::drawToScreen(BITMAP* target, int yOffset) +{ + if(activeMessage) + activeMessage->draw(target, yOffset); + + if(state==mst_awaitingInput) + { + // Draw "more..." icon + int moreX=zinit.msg_more_x; + int moreY=zinit.msg_more_y+yOffset; + if(zinit.msg_more_is_offset) + moreY+=currMsgStr->y; + putMiscSprite(target, iwMore, moreX, moreY); + } +} + +bool MessageManager::messageIsActive() const +{ + return (activeMessage && state!=mst_inactive); +} diff --git a/src/messageManager.h b/src/messageManager.h new file mode 100644 index 0000000000..bc994b276b --- /dev/null +++ b/src/messageManager.h @@ -0,0 +1,59 @@ +#ifndef _ZC_MESSAGEMANAGER_H_ +#define _ZC_MESSAGEMANAGER_H_ + +#include + +class Message; +struct MsgStr; +struct BITMAP; + +class MessageManager +{ +public: + MessageManager(); + ~MessageManager(); + + /// Displays a message. + /** If a message is already being displayed and a callback is set, + * the callback function will be called before switching to + * the new message. + */ + void showMessage(int id); + + /// Displays a DMap intro. + /** If a message is already being displayed and a callback is set, + * the callback function will be called before switching to the intro. + */ + void showDMapIntro(int dmap); + + /// Clears any messages being displayed. + void clear(bool runCallback); + void update(); + void drawToScreen(BITMAP* target, int yOffset); // const? + bool messageIsActive() const; + + /// Clear the current message and switch to a new one. + void switchTo(int msg); + + /// Set a function to be called when the current message is finished. + /** Call this after setting the message to display. + */ + inline void setMessageEndCallback(boost::function func) + { + // Should it be called immediately if the message is blank? + onMessageEnd=func; + } + +private: + enum msgState { + mst_inactive, mst_active, mst_waitingToAdvance, mst_awaitingInput + }; + + MsgStr* currMsgStr; + Message* activeMessage; + msgState state; + int timer; + boost::function onMessageEnd; +}; + +#endif diff --git a/src/messageRenderer.cpp b/src/messageRenderer.cpp new file mode 100644 index 0000000000..55f18371dc --- /dev/null +++ b/src/messageRenderer.cpp @@ -0,0 +1,104 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#include "precompiled.h" //always first +#include "messageRenderer.h" + +#include "subscr.h" +#include "zelda.h" +#include + +MessageRenderer::MessageRenderer(): + fullBmp(0), + textBmp(0) +{ +} + +MessageRenderer::~MessageRenderer() +{ + if(fullBmp) + { + destroy_bitmap(textBmp); + destroy_bitmap(fullBmp); + } +} + +void MessageRenderer::initialize(const MsgStr* msg) +{ + // If msg is null, initialize for DMap intros + int width, height; + if(msg) + { + font=Font::getByID(msg->font); + hSpace=msg->hspace; + vSpace=msg->vspace; + + width=msg->w; + height=msg->h; + } + else + { + font=Font::getByID(0); // Not sure what to put here, exactly + hSpace=0; + vSpace=0; + + width=192; + height=24; + } + + if(!fullBmp) + { + fullBmp=create_bitmap_ex(8, width+16, height+16); + textBmp=create_sub_bitmap(fullBmp, 8, 8, width, height); + } + else if(textBmp->w!=width || textBmp->h!=height) + { + destroy_bitmap(textBmp); + destroy_bitmap(fullBmp); + fullBmp=create_bitmap_ex(8, width+16, height+16); + textBmp=create_sub_bitmap(fullBmp, 8, 8, width, height); + } + + clear_bitmap(fullBmp); + if(msg && msg->tile!=0) + { + frame2x2(fullBmp, &QMisc, 0, 0, msg->tile, msg->cset, + fullBmp->w/8, fullBmp->h/8, 0, true, 0); + } + + color=QMisc.colors.msgtext; + cursorX=0; + cursorY=0; +} + +void MessageRenderer::loadContinuationStyle(const MsgStr* msg) +{ + font=Font::getByID(msg->font); + hSpace=msg->hspace; + vSpace=msg->vspace; +} + +bool MessageRenderer::wordFits(int wordWidth, int numChars) const +{ + wordWidth+=(numChars-1)*hSpace; + return cursorX+wordWidth<=textBmp->w; +} + +void MessageRenderer::putChar(char c) +{ + int width=font.getWidth(c); + if(cursorX+width>textBmp->w) + { + cursorX=0; + cursorY+=font.getHeight()+vSpace; + } + + char charStr[2]={c, 0}; + textout_ex(textBmp, font.get(), charStr, cursorX, cursorY, color, -1); + cursorX+=width+hSpace; +} + +void MessageRenderer::draw(BITMAP* target, int x, int y) +{ + masked_blit(fullBmp, target, 0, 0, x, y, fullBmp->w, fullBmp->h); +} diff --git a/src/messageRenderer.h b/src/messageRenderer.h new file mode 100644 index 0000000000..5ba9a9277c --- /dev/null +++ b/src/messageRenderer.h @@ -0,0 +1,68 @@ +#ifndef _ZC_MESSAGERENDERER_H_ +#define _ZC_MESSAGERENDERER_H_ + +#include "fontClass.h" +struct BITMAP; +struct MsgStr; + +class MessageRenderer +{ +public: + MessageRenderer(); + ~MessageRenderer(); + + /// Draws the message frame and loads the text settings. + /** \param msg A pointer to the message; if this is null, the renderer + * will set itself up to render DMap intros + */ + void initialize(const MsgStr* msg); + + /// Loads the data to render a message continuation + /** \param msg A pointer to the message; this must not be null + */ + void loadContinuationStyle(const MsgStr* msg); + + /// Check if a word will fit on the current line. + /** \param wordWidth The width of the word in pixels with no added space + * \param numChars The number of characters in the word + */ + bool wordFits(int wordWidth, int numChars) const; + void putChar(char c); + void draw(BITMAP* target, int x, int y); + + inline void startNewLine() + { + cursorX=0; + cursorY+=font.getHeight()+vSpace; + } + + inline void setColor(int newColor) + { + color=newColor; + } + + inline void setFont(int newFontID) + { + font=Font::getByID(newFontID); + } + + inline bool atLineStart() const + { + return cursorX==0; + } + + inline Font getFont() const + { + return font; + } + +private: + BITMAP* fullBmp; /// The frame is drawn here + BITMAP* textBmp; /// Sub-bitmap of fullBmp where text is drawn + Font font; + int color; + int hSpace, vSpace; + int cursorX, cursorY; +}; + +#endif diff --git a/src/messageStream.cpp b/src/messageStream.cpp new file mode 100644 index 0000000000..da822ab032 --- /dev/null +++ b/src/messageStream.cpp @@ -0,0 +1,42 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#include "precompiled.h" //always first +#include "messageStream.h" + +MessageStream::MessageStream(const char* text) +{ + reset(text); +} + +void MessageStream::reset(const char* text) +{ + rawText=text; + ptr=0; + lastNonSpace=-1; + + // Messages are padded with spaces, so the end is the last non-space + // character. It's possible a string control code argument will be + // interpreted as a space, but that shouldn't cause problems... + // as long as it's valid. We'll probably want to add validation later. + for(unsigned int i=0; text[i]!=0; i++) + { + if(text[i]!=' ') + lastNonSpace=i; + } +} + +int MessageStream::getControlCodeArgument() +{ + int arg=rawText[ptr]-1; + ptr++; + + // Three-byte argument? + if(rawText[ptr]==255) + { + arg+=254*rawText[ptr+1]; + ptr+=2; + } + + return arg; +} diff --git a/src/messageStream.h b/src/messageStream.h new file mode 100644 index 0000000000..4b12771cc2 --- /dev/null +++ b/src/messageStream.h @@ -0,0 +1,46 @@ +#ifndef _MESSAGE_STREAM_H_ +#define _MESSAGE_STREAM_H_ + +/** Used to interpret the string from a MsgStr as message text. Text can be + * read as individual characters or control code arguments. Trailing spaces + * are stripped. + */ +class MessageStream +{ +public: + MessageStream(const char* text); + void reset(const char* text); + + inline bool nextIsWhitespace() const + { + return (rawText[ptr]==' ' || rawText[ptr]==26); // MSGC_NEWLINE+1 + } + + inline char getCharacter() + { + return rawText[ptr++]; + } + + int getControlCodeArgument(); + + inline bool atEnd() const + { + return ptr>lastNonSpace; // There might be trailing spaces + } + + inline unsigned int tell() const + { + return ptr; + } + + inline void seek(unsigned int pos) + { + ptr=pos; + } + +private: + const char* rawText; + int ptr, lastNonSpace; +}; + +#endif diff --git a/src/midi.cpp b/src/midi.cpp new file mode 100644 index 0000000000..66841fa652 --- /dev/null +++ b/src/midi.cpp @@ -0,0 +1,433 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// midi.cc +// +// save_midi() and code for midi info. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +/* Allegro MIDI struct + + typedef struct MIDI // a midi file + { + int divisions; // number of ticks per quarter note + struct { + unsigned char *data; // MIDI message stream + int len; // length of the track data + } track[MIDI_TRACKS]; + } MIDI; + + */ + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include + + +#include "midi.h" +#include "zsys.h" +/* save_midi: + * Saves a standard MIDI file, returning 0 on success, + * or non-zero on error. + */ + +// snprintf is defined as _snprintf in windows stdio.h +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +int save_midi(char *filename, MIDI *midi) +{ + int c; + long len; + PACKFILE *fp; + int num_tracks = 0; + + if(!midi) + return 1; + + fp = pack_fopen_password(filename, F_WRITE,""); /* open the file */ + + if(!fp) + return 2; + + for(c=0; ctrack[c].len > 0) + num_tracks++; + + pack_fwrite((void *) "MThd", 4, fp); /* write midi header */ + + pack_mputl(6, fp); /* header chunk length = 6 */ + + pack_mputw((num_tracks==1) ? 0 : 1, fp); /* MIDI file type */ + + pack_mputw(num_tracks, fp); /* number of tracks */ + + pack_mputw(midi->divisions, fp); /* beat divisions (negatives?) */ + + for(c=0; ctrack[c].len; + pack_mputl(len, fp); /* length of track chunk */ + + if(pack_fwrite(midi->track[c].data, len, fp) != len) + goto err; + } + + pack_fclose(fp); + return 0; + + /* oh dear... */ +err: + pack_fclose(fp); + delete_file(filename); + return 3; +} + +/* --- All this code just to calculate the length of a MIDI song. --- */ + +/* + #define MAX_TEMPO_CHANGES 512 + + typedef struct midi_info + { + // midi info + int format; + int num_tracks; + int divisions; + int len_beats; + double len_sec; + int tempo_changes; + double tempo[MAX_TEMPO_CHANGES]; // tempo can change during song + dword tempo_c[MAX_TEMPO_CHANGES]; // store the total delta time before each change in tempo + + // MTrk event info (used by parse_mtrk()) + dword dt,nbytes; + byte event,running_status,type,byte2; + byte *buf; + + } midi_info; + + typedef struct mtrkevent + // sort of... it's actually not a true MTrk event because it can be a + // combination of events, such as a "note on" event plus a "note off" event + { + // basic mtrk event but with total time instead of delta-time + byte *buf; // buffer for extra data + dword t; // total time from start in delta-time units + word dur; // duration of note + word event; // event + extra byte of info + word nbytes; // number of bytes in "buf" or note off velocity + byte type; // meta type, note number, etc. + byte byte2; // byte 2 or note on velocity + } mtrkevent; + + */ + +dword getval(byte *buf,int nbytes) +{ + register dword value; + value=0; + + for(int i=0; i +{ + byte *start = *data; + + mi->dt = parse_var_len(data); + mi->event = **data; + (*data)++; + mi->type = 0; + mi->byte2 = 0; + mi->nbytes = 0; + mi->buf = NULL; + + if(mi->event<0x80 && mi->running_status>0) + { + mi->event = mi->running_status; + (*data)--; + } + + if(mi->event!=0xFF && mi->event!=0xF0 && mi->event!=0xF7) + mi->running_status = mi->event; + + switch(mi->event) + { + case 0xFF: // + mi->type = **data; + (*data)++; + + case 0xF0: + case 0xF7: // + mi->nbytes = parse_var_len(data); + mi->buf = *data; + (*data) += mi->nbytes; + break; + + case 0xF2: + (*data)+=2; + break; + + case 0xF3: + (*data)++; + break; + + default: + switch(mi->event&0xF0) + { + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + case 0xE0: + mi->type = **data; + (*data)++; + mi->byte2 = **data; + (*data)++; + break; + + case 0xC0: + case 0xD0: + mi->type = **data; + (*data)++; + break; + } + } + + return (*data) - start; +} + +bool eot(midi_info *mi) +{ + return (mi->event==0xFF && mi->type==0x2F); +} + +int beats(dword dt,int divs) +{ + if(divs<=0) + return 1; + + return dt/divs + ((dt%divs)?1:0); +} + +double tempo(byte *buf) +{ + double t = (double)getval(buf,3); + t /= 60e6; + + if(t==0) + return 1; + + return 1/t; +} + +double _runtime(int beats,double tempo) +{ + if(tempo==0) + return 0; + + return beats/tempo*60.0; +} + +double runtime(int beats,midi_info *mi) +{ + double t=0; + + int c=0; + + while(ctempo_changes) + { + if(beats < (int)mi->tempo_c[c]) + break; + + c++; + } + + for(int i=1; itempo_c[i] - mi->tempo_c[i-1],mi->tempo[i-1]); + + t += _runtime(beats - mi->tempo_c[c-1],mi->tempo[c-1]); + + return t; +} + +void get_midi_info(MIDI *midi, midi_info *mi) +{ + dword max_dt = 0; + mi->tempo_changes = 0; + bool gottempo = false; + + if(midi==NULL) + goto done; + + for(int i=0; midi->track[i].len>0; i++) + { + byte *data = midi->track[i].data; + + if(data==NULL) + break; + + dword total_dt=0; + mi->event=0; + mi->running_status = 0; + // tempo info should only be in first track, but sometimes it isn't + bool gettempo = (i==0)||(!gottempo); + + while(!eot(mi) && data - midi->track[i].data < midi->track[i].len) + { + parse_mtrk(&data,mi); + total_dt += mi->dt; + + if(gettempo && mi->event==0xFF && mi->type==0x51 && mi->tempo_changestempo[mi->tempo_changes] = tempo(mi->buf); + int tempo_c = mi->tempo_c[mi->tempo_changes] = beats(total_dt,midi->divisions); + + if(mi->tempo_changes==0 && tempo_c!=0) // make sure there is a tempo at beat 0 + { + mi->tempo_c[0] = 0; + mi->tempo_c[1] = tempo_c; + mi->tempo[1] = mi->tempo[0]; + mi->tempo_changes++; + } + + mi->tempo_changes++; + gottempo=true; + } + } + + max_dt = zc_max(max_dt,total_dt); + } + +done: + + if(mi->tempo_changes==0) // then guess + { + mi->tempo_changes=1; + mi->tempo[0]=120.0; + mi->tempo_c[0]=0; + } + + mi->len_beats = (midi==NULL) ? 0 : beats(max_dt,midi->divisions); + mi->len_sec = (midi==NULL) ? 0 : runtime(mi->len_beats,mi); +} + +char *timestr(double sec) +{ + static char buf[16]; + int min = (int)(sec/60); + sec -= min*60; + + if(sec>=59.5) + { + min++; + sec=0; + } + + sprintf(buf,"%02d:%02.0f",min,sec); + return buf; +} + +bool decode_text_event(char *s,int length, byte type,byte *buf) +{ + switch(type) + { + case 0x01: + snprintf(s,length,"T: %s\n",buf); + break; + + case 0x02: + snprintf(s,length,"C: %s\n",buf); + break; + + case 0x03: + snprintf(s,length,"N: %s\n",buf); + break; + + case 0x04: + snprintf(s,length,"I: %s\n",buf); + break; + + default: + return false; + } + + return true; +} + +void get_midi_text(MIDI *midi, midi_info *mi, char *text) +// must have called get_midi_info() first +{ + byte buf[1024]; + char *out = text; + int length=4096; + dword nbytes; + + text[0] = 0; + + for(int i=0; midi->track[i].len>0; i++) + { + byte *data = midi->track[i].data; + + if(data==NULL) + break; + + mi->event=0; + mi->running_status = 0; + + while(!eot(mi) && data - midi->track[i].data < midi->track[i].len) + { + parse_mtrk(&data,mi); + + if(mi->event==0xFF) + { + nbytes=zc_min(mi->nbytes, 1023); + memcpy(buf,mi->buf,nbytes); + buf[nbytes]=0; + + if(decode_text_event(out,length,mi->type,buf)) + { + length-=strlen(out); + out+=strlen(out); + } + } + } + } +} + diff --git a/src/midi.h b/src/midi.h new file mode 100644 index 0000000000..8fff60d318 --- /dev/null +++ b/src/midi.h @@ -0,0 +1,79 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// midi.cc +// +// save_midi() and code for midi info. +// +//-------------------------------------------------------- + +#ifndef _MIDI_H_ +#define _MIDI_H_ +#include "zdefs.h" +/* Allegro MIDI struct + + typedef struct MIDI // a midi file + { + int divisions; // number of ticks per quarter note + struct { + unsigned char *data; // MIDI message stream + int len; // length of the track data + } track[MIDI_TRACKS]; + } MIDI; + + */ + +int save_midi(char *filename, MIDI *midi); + +/* --- All this code just to calculate the length of a MIDI song. --- */ + +#define MAX_TEMPO_CHANGES 512 +typedef struct midi_info +{ + // midi info + int format; + int num_tracks; + int divisions; + int len_beats; + double len_sec; + int tempo_changes; + double tempo[MAX_TEMPO_CHANGES]; // tempo can change during song + dword tempo_c[MAX_TEMPO_CHANGES]; // store the total delta time before each change in tempo + + // MTrk event info (used by parse_mtrk()) + dword dt,nbytes; + byte event,running_status,type,byte2; + byte *buf; + +} midi_info; + +typedef struct mtrkevent + // sort of... it's actually not a true MTrk event because it can be a + // combination of events, such as a "note on" event plus a "note off" event +{ + // basic mtrk event but with total time instead of delta-time + byte *buf; // buffer for extra data + dword t; // total time from start in delta-time units + word dur; // duration of note + word event; // event + extra byte of info + word nbytes; // number of bytes in "buf" or note off velocity + byte type; // meta type, note number, etc. + byte byte2; // byte 2 or note on velocity +} mtrkevent; + +dword getval(byte *buf,int nbytes); +dword parse_var_len(byte **data); +// returns length of the +dword parse_mtrk(byte **data, midi_info *mi); +bool eot(midi_info *mi); +int beats(dword dt,int divs); +double tempo(byte *buf); +double _runtime(int beats,double tempo); +double runtime(int beats,midi_info *mi); +void get_midi_info(MIDI *midi, midi_info *mi); +char *timestr(double sec); +bool decode_text_event(char *s,byte type,byte *buf); +void get_midi_text(MIDI *midi, midi_info *mi, char *text); +#endif + diff --git a/src/mutex.h b/src/mutex.h new file mode 100644 index 0000000000..d0af2c7424 --- /dev/null +++ b/src/mutex.h @@ -0,0 +1,61 @@ +#ifndef _ZC_MUTEX_H_ +#define _ZC_MUTEX_H_ + +// pthread functions return a value, Windows equivalents don't. +// Shouldn't be an issue at the moment. + +#ifdef _WIN32 + +#include + +typedef CRITICAL_SECTION mutex; + +inline void mutex_init(CRITICAL_SECTION* m) +{ + return InitializeCriticalSection(m); +} + +inline void mutex_destroy(CRITICAL_SECTION* m) +{ + return DeleteCriticalSection(m); +} + +inline void mutex_lock(CRITICAL_SECTION* m) +{ + return EnterCriticalSection(m); +} + +inline void mutex_unlock(CRITICAL_SECTION* m) +{ + return LeaveCriticalSection(m); +} + +#else // Non-Windows + +#include + +typedef pthread_mutex_t mutex; + +inline int mutex_init(pthread_mutex_t* m) +{ + return pthread_mutex_init(m, 0); +} + +inline int mutex_destroy(pthread_mutex_t* m) +{ + return pthread_mutex_destroy(m); +} + +inline int mutex_lock(pthread_mutex_t* m) +{ + return pthread_mutex_lock(m); +} + +inline int mutex_unlock(pthread_mutex_t* m) +{ + return pthread_mutex_unlock(m); +} + +#endif + +#endif diff --git a/src/pal.cpp b/src/pal.cpp new file mode 100644 index 0000000000..4b085ea8e3 --- /dev/null +++ b/src/pal.cpp @@ -0,0 +1,513 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// pal.cc +// +// Palette code for ZC. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + + +#include "precompiled.h" //always first + +#include "zc_alleg.h" +#include "zdefs.h" +#include "maps.h" +#include "zelda.h" +#include "zc_sys.h" +#include "link.h" +#include "colors.h" +#include "zsys.h" +#include "pal.h" +#include "subscr.h" +#include "sound.h" + +extern LinkClass Link; + +int CSET_SIZE = 16; // this is only changed to 4 in the NES title screen +int CSET_SHFT = 4; // log2 of CSET_SIZE + +bool usingdrypal = false; //using dried up lake colors +RGB olddrypal; //palette to restore when lake rehydrates + +RGB _RGB(byte *si) +{ + RGB x; + x.r = si[0]; + x.g = si[1]; + x.b = si[2]; + x.filler=0; // Suppress warning "used undefined" + return x; +} + +RGB _RGB(int r,int g,int b) +{ + RGB x; + x.r = r; + x.g = g; + x.b = b; + x.filler=0; // Suppress warning "used undefined" + return x; +} + +RGB invRGB(RGB s) +{ + RGB x; + x.r = 63-s.r; + x.g = 63-s.g; + x.b = 63-s.b; + x.filler=0; // Suppress warning "used undefined" + return x; +} + +RGB mixRGB(int r1,int g1,int b1,int r2,int g2,int b2,int ratio) +{ + RGB x; + x.r = (r1*(64-ratio) + r2*ratio) >> 6; + x.g = (g1*(64-ratio) + g2*ratio) >> 6; + x.b = (b1*(64-ratio) + b2*ratio) >> 6; + x.filler=0; // Suppress warning "used undefined" + return x; +} + +void copy_pal(RGB *src,RGB *dest) +{ + for(int i=0; i<256; i++) + dest[i]=src[i]; +} + +void loadfullpal() +{ + for(int i=0; i<240; i++) + RAMpal[i]=_RGB(colordata+i*3); + + for(int i=240; i<255; i++) + RAMpal[i]=((RGB*)data[PAL_GUI].dat)[i]; + + refreshpal=true; +} + +/*void loadlvlpal256(int level) + { + byte *si = colordata + */ + +void loadlvlpal(int level) +{ + byte *si = colordata + CSET(level*pdLEVEL+poLEVEL)*3; + + for(int i=0; i<16*3; i++) + { + RAMpal[CSET(2)+i] = _RGB(si); + si+=3; + } + + for(int i=0; i<16; i++) + { + RAMpal[CSET(9)+i] = _RGB(si); + si+=3; + } + + if(!get_bit(quest_rules,qr_NOLEVEL3FIX) && level==3) + RAMpal[CSET(6)+2] = NESpal(0x37); + + create_rgb_table(&rgb_table, RAMpal, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; q-1) + { + loadpalset(6,itemsbuf[itemid].misc1 ? pSprite(zc_min(29,itemsbuf[itemid].misc1)):6); + } + else + { + loadpalset(6,6); + } + + refreshpal=true; +} + +void loadfadepal(int dataset) +{ + byte *si = colordata + CSET(dataset)*3; + + for(int i=0; i0) ? (Link.getSpecialCave()>=GUYCAVE) ? 10 : 11 : DMaps[currdmap].color, false, darkroom); + darkroom = newstate; + } + + if(setnaturaldark) + naturaldark = newstate; +} + +// Only used during Insta-Warps +void lightingInstant() +{ + bool newstate = ((TheMaps[currmap*MAPSCRS+currscr].flags&fDARK) != 0); + + if(darkroom != newstate) + { +int level = (Link.getSpecialCave()>0) ? (Link.getSpecialCave()>=GUYCAVE) ? 10 : 11 : DMaps[currdmap].color; + + if(darkroom) // Old room dark, new room lit + { + loadlvlpal(level); + + if(get_bit(quest_rules,qr_FADECS5)) + loadpalset(5,5); + } + else // Old room lit, new room dark + { + if(get_bit(quest_rules,qr_FADE)) + { + int last = CSET(5)-1; + int light; + + if(get_bit(quest_rules,qr_FADECS5)) + { + last += 16; + loadpalset(5,5); + } + + byte *si = colordata + CSET(level*pdLEVEL+poFADE1)*3; + + for(int j=0; j<16; ++j) + { + light = si[0]+si[1]+si[2]; + si+=3; + fade_interpolate(RAMpal,black_palette,RAMpal,light?32:64,CSET(2)+j,CSET(2)+j); + } + + fade_interpolate(RAMpal,black_palette,RAMpal,64,CSET(3),last); + } + else // No interpolated fading + loadfadepal(level*pdLEVEL+poFADE3); + } + + if(!get_bit(quest_rules,qr_NOLEVEL3FIX) && level==3) + RAMpal[CSET(6)+2] = NESpal(0x37); + + create_rgb_table(&rgb_table, RAMpal, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; q=88) + return; + + if((++whistleclk)&7) + return; + + if(whistleclk<88) + { + if(tmpscr->flags7 & fWHISTLEPAL) + { + if(!usingdrypal) + { + usingdrypal = true; + olddrypal = RAMpal[CSET(3)+3]; + } + + RAMpal[CSET(3)+3] = NESpal(drycolors[whistleclk>>3]); + refreshpal=true; + + } + } + else + { + if(tmpscr->flags & fWHISTLE) + { + if(hiddenstair(0,true)) + { + sfx(tmpscr->secretsfx); + } + } + } +} + +void rehydratelake(bool instant) +{ + if(whistleclk==-1) + return; + + if(instant && usingdrypal) + { + usingdrypal = false; + RAMpal[CSET(3)+3] = olddrypal; + refreshpal=true; + return; + } + + whistleclk&=0xF8; + + do + { + whistleclk-=8; + + if(usingdrypal) + { + RAMpal[CSET(3)+3] = NESpal(drycolors[whistleclk>>3]); + refreshpal=true; + } + + advanceframe(true); + + if(((whistleclk>>3)&3) == 1) + for(int i=0; i<4 && !Quit; i++) + advanceframe(true); + } + while(whistleclk!=0 && !Quit); + + whistleclk=-1; + + if(usingdrypal) + { + usingdrypal = false; + RAMpal[CSET(3)+3] = olddrypal; + refreshpal=true; + } +} + +static int palclk[3]; +static int palpos[3]; + +void reset_pal_cycling() +{ + for(int i=0; i<3; i++) + palclk[i]=palpos[i]=0; +} + +void cycle_palette() +{ + if(!get_bit(quest_rules,qr_FADE) || darkroom) + return; + + int level = (Link.getSpecialCave()==0) ? DMaps[currdmap].color : (Link.getSpecialCave()= c.speed) + { + palclk[i]=0; + + if(++palpos[i] >= (c.count>>4)) + palpos[i]=0; + + byte *si = colordata + CSET(level*pdLEVEL+poFADE1+1+palpos[i])*3; + si += (c.first&15)*3; + + for(int col=c.first&15; col<=(c.count&15); col++) + { + RAMpal[CSET(c.first>>4)+col] = _RGB(si); + si+=3; + } + + refreshpal=true; + } + } + } + + // No need to do handle refreshpal here; it's done in updatescr(). +} + +int reverse_NESpal(RGB c) +{ + int dist = 12000; + int index = 0; + + for(int i = 0; (i < 64) && (dist != 0); i++) + { + int r = (c.r - NESpal(i).r); + int g = (c.g - NESpal(i).g); + int b = (c.b - NESpal(i).b); + int d = r*r + g*g + b*b; + + if(d < dist) + { + dist = d; + index = i; + } + } + + return index; +} + +/* end of pal.cc */ + diff --git a/src/pal.h b/src/pal.h new file mode 100644 index 0000000000..8c7fe17448 --- /dev/null +++ b/src/pal.h @@ -0,0 +1,52 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// pal.h +// +// Palette code for ZC. +// +//-------------------------------------------------------- + +#ifndef _ZC_PAL_H_ +#define _ZC_PAL_H_ + +#include "zc_alleg.h" +#include "zdefs.h" +#include "colors.h" + +extern int CSET_SIZE; // this is only changed to 4 in the NES title screen +extern int CSET_SHFT; // log2 of CSET_SIZE + +#define CSET(x) ((x)<::iterator it; + + for(it = decls.begin(); it != decls.end(); it++) + { + delete *it; + } + + decls.clear(); +} + +void ASTDeclList::addDeclaration(ASTDecl *newdecl) +{ + decls.push_front(newdecl); +} + +ASTFuncDecl::~ASTFuncDecl() +{ + delete rettype; + delete block; + list::iterator it; + + for(it = params.begin(); it != params.end(); it++) + { + delete *it; + } + + params.clear(); +} + +ASTArrayDecl::~ASTArrayDecl() +{ + delete type; + delete list; + delete size; +} + +void ASTArrayList::addParam(ASTExpr *expr) +{ + exprs.push_back(expr); +} + +ASTArrayList::~ASTArrayList() +{ + list::iterator it; + + for(it = exprs.begin(); it != exprs.end(); it++) + { + delete *it; + } + + exprs.clear(); +} + +void ASTFuncDecl::addParam(ASTVarDecl *param) +{ + params.push_front(param); +} + +ASTVarDecl::~ASTVarDecl() +{ + delete type; +} + +ASTVarDeclInitializer::~ASTVarDeclInitializer() +{ + delete initial; +} + + +ASTFuncCall::~ASTFuncCall() +{ + list::iterator it; + + for(it = params.begin(); it != params.end(); it++) + { + delete *it; + } + + params.clear(); + delete name; +} + +void ASTBlock::addStatement(ASTStmt *stmt) +{ + statements.push_back(stmt); +} + +ASTBlock::~ASTBlock() +{ + list::iterator it; + + for(it=statements.begin(); it != statements.end(); it++) + { + delete *it; + } + + statements.clear(); +} + +ASTScript::~ASTScript() +{ + delete sblock; + delete type; +} + +pair ASTFloat::parseValue() +{ + string f = getValue(); + string intpart; + string fpart; + + switch(getType()) + { + case TYPE_DECIMAL: + { + bool founddot = false; + + for(unsigned int i=0; i 0) val2 *= -1; + + char temp[60]; + sprintf(temp, "%ld", val2); + intpart = temp; + fpart = ""; + break; + } + + case TYPE_BINARY: + { + //trim off the 'b' + f = f.substr(0,f.size()-1); + long val2=0; + + for(unsigned int i=0; i 0) val2 *= -1; + + char temp[60]; + sprintf(temp, "%ld", val2); + intpart = temp; + fpart = ""; + break; + } + } + + return pair(intpart, fpart); +} + diff --git a/src/parser/AST.h b/src/parser/AST.h new file mode 100644 index 0000000000..b93c165095 --- /dev/null +++ b/src/parser/AST.h @@ -0,0 +1,1777 @@ +#ifndef AST_H +#define AST_H + +class AST; +// for flex and bison +#define YYSTYPE AST* + +#include "y.tab.hpp" +#include "Compiler.h" +#include +#include +#include +#include + +using namespace std; + +#define RECURSIONLIMIT 30 + +extern string curfilename; +int go(const char *f); + +class ASTScript; +class ASTImportDecl; +class ASTConstDecl; +class ASTFuncDecl; +class ASTArrayDecl; +class ASTArrayList; +class ASTFloat; +class ASTString; +class ASTProgram; +class ASTDeclList; +class ASTDecl; +class ASTVarDecl; +class ASTType; +class ASTBlock; +class ASTTypeFloat; +class ASTTypeBool; +class ASTTypeVoid; +class ASTTypeFFC; +class ASTTypeItem; +class ASTTypeItemclass; +class ASTTypeGlobal; +class ASTTypeNPC; +class ASTTypeLWpn; +class ASTTypeEWpn; +class ASTVarDeclInitializer; +class ASTExpr; +class ASTExprAnd; +class ASTExprOr; +class ASTExprGT; +class ASTExprGE; +class ASTExprLT; +class ASTExprLE; +class ASTExprEQ; +class ASTExprNE; +class ASTExprPlus; +class ASTExprMinus; +class ASTExprTimes; +class ASTExprDivide; +class ASTExprNot; +class ASTExprNegate; +class ASTExprArrow; +class ASTExprArray; +class ASTNumConstant; +class ASTFuncCall; +class ASTBoolConstant; +class ASTBlock; +class ASTStmt; +class ASTStmtAssign; +class ASTExprDot; +class ASTStmtFor; +class ASTStmtIf; +class ASTStmtIfElse; +class ASTStmtReturn; +class ASTStmtReturnVal; +class ASTStmtEmpty; +class ASTScript; +class ASTStmtWhile; +class ASTStmtDo; +class ASTExprBitOr; +class ASTExprBitAnd; +class ASTExprBitXor; +class ASTExprLShift; +class ASTExprRShift; +class ASTExprModulo; +class ASTExprBitNot; +class ASTExprIncrement; +class ASTExprPreIncrement; +class ASTExprDecrement; +class ASTExprPreDecrement; +class ASTStmtBreak; +class ASTStmtContinue; + +class ASTVisitor +{ +public: + virtual void caseDefault(void *param)=0; + virtual void caseProgram(ASTProgram &, void *param) + { + caseDefault(param); + } + virtual void caseFloat(ASTFloat &, void *param) + { + caseDefault(param); + } + virtual void caseString(ASTString &, void *param) + { + caseDefault(param); + } + virtual void caseDeclList(ASTDeclList &, void *param) + { + caseDefault(param); + } + virtual void caseImportDecl(ASTImportDecl &, void *param) + { + caseDefault(param); + } + virtual void caseConstDecl(ASTConstDecl &, void *param) + { + caseDefault(param); + } + virtual void caseFuncDecl(ASTFuncDecl &, void *param) + { + caseDefault(param); + } + virtual void caseArrayDecl(ASTArrayDecl &, void *param) + { + caseDefault(param); + } + virtual void caseTypeFloat(ASTTypeFloat &, void *param) + { + caseDefault(param); + } + virtual void caseTypeBool(ASTTypeBool &, void *param) + { + caseDefault(param); + } + virtual void caseTypeVoid(ASTTypeVoid &, void *param) + { + caseDefault(param); + } + virtual void caseTypeFFC(ASTTypeFFC &, void *param) + { + caseDefault(param); + } + virtual void caseTypeItem(ASTTypeItem &, void *param) + { + caseDefault(param); + } + virtual void caseTypeItemclass(ASTTypeItemclass &, void *param) + { + caseDefault(param); + } + virtual void caseTypeNPC(ASTTypeNPC &, void *param) + { + caseDefault(param); + } + virtual void caseTypeLWpn(ASTTypeLWpn &, void *param) + { + caseDefault(param); + } + virtual void caseTypeEWpn(ASTTypeEWpn &, void *param) + { + caseDefault(param); + } + virtual void caseTypeGlobal(ASTTypeGlobal &, void *param) + { + caseDefault(param); + } + virtual void caseVarDecl(ASTVarDecl &, void *param) + { + caseDefault(param); + } + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &, void *param) + { + caseDefault(param); + } + virtual void caseExprAnd(ASTExprAnd &, void *param) + { + caseDefault(param); + } + virtual void caseExprOr(ASTExprOr &, void *param) + { + caseDefault(param); + } + virtual void caseExprGT(ASTExprGT &, void *param) + { + caseDefault(param); + } + virtual void caseExprGE(ASTExprGE &, void *param) + { + caseDefault(param); + } + virtual void caseExprLT(ASTExprLT &, void *param) + { + caseDefault(param); + } + virtual void caseExprLE(ASTExprLE &, void *param) + { + caseDefault(param); + } + virtual void caseExprEQ(ASTExprEQ &, void *param) + { + caseDefault(param); + } + virtual void caseExprNE(ASTExprNE &, void *param) + { + caseDefault(param); + } + virtual void caseExprPlus(ASTExprPlus &, void *param) + { + caseDefault(param); + } + virtual void caseExprMinus(ASTExprMinus &, void *param) + { + caseDefault(param); + } + virtual void caseExprTimes(ASTExprTimes &, void *param) + { + caseDefault(param); + } + virtual void caseExprDivide(ASTExprDivide &, void *param) + { + caseDefault(param); + } + virtual void caseExprNot(ASTExprNot &, void *param) + { + caseDefault(param); + } + virtual void caseExprArrow(ASTExprArrow &, void *param) + { + caseDefault(param); + } + virtual void caseExprArray(ASTExprArray &, void *param) + { + caseDefault(param); + } + virtual void caseExprNegate(ASTExprNegate &, void *param) + { + caseDefault(param); + } + virtual void caseNumConstant(ASTNumConstant &, void *param) + { + caseDefault(param); + } + virtual void caseFuncCall(ASTFuncCall &, void *param) + { + caseDefault(param); + } + virtual void caseBoolConstant(ASTBoolConstant &, void *param) + { + caseDefault(param); + } + virtual void caseBlock(ASTBlock &, void *param) + { + caseDefault(param); + } + virtual void caseStmtAssign(ASTStmtAssign &, void *param) + { + caseDefault(param); + } + virtual void caseExprDot(ASTExprDot &, void *param) + { + caseDefault(param); + } + virtual void caseStmtFor(ASTStmtFor &, void *param) + { + caseDefault(param); + } + virtual void caseStmtIf(ASTStmtIf &, void *param) + { + caseDefault(param); + } + virtual void caseStmtIfElse(ASTStmtIfElse &, void *param) + { + caseDefault(param); + } + virtual void caseStmtReturn(ASTStmtReturn &, void *param) + { + caseDefault(param); + } + virtual void caseStmtReturnVal(ASTStmtReturnVal &, void *param) + { + caseDefault(param); + } + virtual void caseStmtEmpty(ASTStmtEmpty &, void *param) + { + caseDefault(param); + } + virtual void caseScript(ASTScript &, void *param) + { + caseDefault(param); + } + virtual void caseStmtWhile(ASTStmtWhile &, void *param) + { + caseDefault(param); + } + virtual void caseStmtDo(ASTStmtDo &, void *param) + { + caseDefault(param); + } + virtual void caseExprBitOr(ASTExprBitOr &, void *param) + { + caseDefault(param); + } + virtual void caseExprBitXor(ASTExprBitXor &, void *param) + { + caseDefault(param); + } + virtual void caseExprBitAnd(ASTExprBitAnd &, void *param) + { + caseDefault(param); + } + virtual void caseExprLShift(ASTExprLShift &, void *param) + { + caseDefault(param); + } + virtual void caseExprRShift(ASTExprRShift &, void *param) + { + caseDefault(param); + } + virtual void caseExprBitNot(ASTExprBitNot &, void *param) + { + caseDefault(param); + } + virtual void caseExprIncrement(ASTExprIncrement &, void *param) + { + caseDefault(param); + } + virtual void caseExprPreIncrement(ASTExprPreIncrement &, void *param) + { + caseDefault(param); + } + virtual void caseExprDecrement(ASTExprDecrement &, void *param) + { + caseDefault(param); + } + virtual void caseExprPreDecrement(ASTExprPreDecrement &, void *param) + { + caseDefault(param); + } + virtual void caseExprModulo(ASTExprModulo &, void *param) + { + caseDefault(param); + } + virtual void caseStmtBreak(ASTStmtBreak &, void *param) + { + caseDefault(param); + } + virtual void caseStmtContinue(ASTStmtContinue &, void *param) + { + caseDefault(param); + } + virtual ~ASTVisitor() {} +}; + +////////////////////////////////////////////////////////////////////////////// +class LocationData +{ +public: + LocationData(YYLTYPE loc) + { + first_line = loc.first_line; + last_line = loc.last_line; + first_column = loc.first_column; + last_column = loc.last_column; + fname = curfilename; + } + int first_line; + int last_line; + int first_column; + int last_column; + string fname; +}; +////////////////////////////////////////////////////////////////////////////// +class AST +{ +public: + AST(LocationData Loc) : loc(Loc) {} + virtual void execute(ASTVisitor &visitor, void *param)=0; + virtual ~AST() {} + LocationData &getLocation() + { + return loc; + } +private: + LocationData loc; + //NOT IMPLEMENTED - do not use + AST(AST &other); + AST &operator=(AST &other); +}; + +class ASTStmt : public AST +{ +public: + ASTStmt(LocationData Loc) : AST(Loc) {} + virtual ~ASTStmt() {} +}; + +class ASTProgram : public AST +{ +public: + ASTProgram(ASTDeclList *Decls, LocationData Loc) : AST(Loc), decls(Decls) {}; + + ASTDeclList *getDeclarations() + { + return decls; + } + + ~ASTProgram(); + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseProgram(*this,param); + } +private: + ASTDeclList *decls; +}; + +class ASTFloat : public AST +{ +public: + ASTFloat(char *Value, int Type, LocationData Loc) : AST(Loc), type(Type), negative(false) + { + val = string(Value); + } + ASTFloat(const char *Value, int Type, LocationData Loc) : AST(Loc), type(Type), negative(false) + { + val = string(Value); + } + ASTFloat(long Value, int Type, LocationData Loc) : AST(Loc), type(Type), negative(false) + { + char tmp[15]; + sprintf(tmp, "%ld", Value); + val = string(tmp); + } + string getValue() + { + return val; + } + pair parseValue(); + int getType() + { + return type; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseFloat(*this, param); + } + void set_negative(bool neg) + { + negative = neg; + } + static const int TYPE_DECIMAL=0; + static const int TYPE_BINARY=1; + static const int TYPE_HEX=2; +private: + int type; + string val; + bool negative; +}; + +class ASTString : public AST +{ +public: + ASTString(const char *strval, LocationData Loc) : AST(Loc) + { + str = string(strval); + } + string getValue() + { + return str; + } + + void execute(ASTVisitor &visitor, void *param) + { + return visitor.caseString(*this,param); + } +private: + string str; +}; + +class ASTDeclList : public AST +{ +public: + ASTDeclList(LocationData Loc) : AST(Loc), decls() {} + ~ASTDeclList(); + + void addDeclaration(ASTDecl *newdecl); + + list &getDeclarations() + { + return decls; + } + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseDeclList(*this, param); + } +private: + list decls; +}; + +class ASTDecl : public ASTStmt +{ +public: + ASTDecl(LocationData Loc) : ASTStmt(Loc) {} + virtual ~ASTDecl() {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTDecl(ASTDecl &); + ASTDecl &operator=(ASTDecl &); +}; + +class ASTImportDecl : public ASTDecl +{ +public: + ASTImportDecl(string file, LocationData Loc) : ASTDecl(Loc), filename(file) {} + + string getFilename() + { + return filename; + } + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseImportDecl(*this,param); + } +private: + string filename; + //NOT IMPLEMENTED; DO NOT USE + ASTImportDecl(ASTImportDecl &); + ASTImportDecl &operator=(ASTImportDecl &); +}; + +class ASTConstDecl : public ASTDecl +{ +public: + ASTConstDecl(string Name, ASTFloat *Val, LocationData Loc) : ASTDecl(Loc), name(Name), val(Val) {} + string getName() + { + return name; + } + ASTFloat *getValue() + { + return val; + } + ~ASTConstDecl() + { + delete val; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseConstDecl(*this,param); + } +private: + string name; + ASTFloat *val; + //NOT IMPLEMENTED; DO NOT USE + ASTConstDecl(ASTConstDecl &); + ASTConstDecl &operator=(ASTConstDecl &); +}; + +class ASTFuncDecl : public ASTDecl +{ +public: + ASTFuncDecl(LocationData Loc) : ASTDecl(Loc), params() + { + + } + + void setName(string n) + { + name=n; + } + void setReturnType(ASTType *type) + { + rettype=type; + } + void setBlock(ASTBlock *b) + { + block=b; + } + + ~ASTFuncDecl(); + void addParam(ASTVarDecl *param); + list &getParams() + { + return params; + } + ASTType *getReturnType() + { + return rettype; + } + ASTBlock *getBlock() + { + return block; + } + string getName() + { + return name; + } + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseFuncDecl(*this,param); + } +private: + string name; + list params; + ASTType *rettype; + ASTBlock *block; +}; + +class ASTArrayDecl : public ASTDecl +{ +public: + ASTArrayDecl(ASTType *Type, string Name, AST *Size, bool isReg, ASTArrayList *List, LocationData Loc) : + ASTDecl(Loc), name(Name), list(List), size(Size), type(Type), reg(isReg) { } + ~ASTArrayDecl(); + ASTType *getType() + { + return type; + } + string getName() + { + return name; + } + //If reg, size is an ASTExpr. If not, it's an ASTFloat + AST *getSize() + { + return size; + } + bool isRegister() + { + return reg; + } + ASTArrayList *getList() + { + return list; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseArrayDecl(*this,param); + } +private: + string name; + ASTArrayList *list; + AST *size; + ASTType *type; + + bool reg; + + //NOT IMPLEMENTED; DO NOT USE + ASTArrayDecl(ASTArrayDecl &); + ASTArrayDecl &operator=(ASTArrayDecl &); +}; + +class ASTArrayList : public AST +{ +public: + ASTArrayList(LocationData Loc) : AST(Loc), listIsString(false) {} + ~ASTArrayList(); + list &getList() + { + return exprs; + } + void addParam(ASTExpr *expr); + bool isString() + { + return listIsString; + } + void makeString() + { + listIsString = true; + } + //Just to allow us to instantiate the object + void execute(ASTVisitor &, void *) { } +private: + list exprs; + bool listIsString; + + //NOT IMPLEMENTED + ASTArrayList(ASTArrayList &); + ASTArrayList &operator=(ASTArrayList &); +}; + +class ASTType : public AST +{ +public: + ASTType(LocationData Loc) : AST(Loc) {} + virtual void execute(ASTVisitor &visitor, void *param)=0; +}; + +class ASTTypeFloat : public ASTType +{ +public: + ASTTypeFloat(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeFloat(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeFloat(ASTTypeFloat &); + ASTTypeFloat &operator=(ASTTypeFloat &); +}; + +class ASTTypeBool : public ASTType +{ +public: + ASTTypeBool(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeBool(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeBool(ASTTypeBool &); + ASTTypeBool &operator =(ASTTypeBool &); +}; + +class ASTTypeVoid : public ASTType +{ +public: + ASTTypeVoid(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeVoid(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeVoid(ASTTypeVoid &); + ASTTypeVoid &operator=(ASTTypeVoid &); +}; + +class ASTTypeFFC : public ASTType +{ +public: + ASTTypeFFC(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeFFC(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeFFC(ASTTypeFFC &); + ASTTypeFFC &operator=(ASTTypeFFC &); +}; + +class ASTTypeGlobal : public ASTType +{ +public: + ASTTypeGlobal(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeGlobal(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeGlobal(ASTTypeGlobal &); + ASTTypeGlobal &operator=(ASTTypeGlobal &); +}; + +class ASTTypeItem : public ASTType +{ +public: + ASTTypeItem(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeItem(*this,param); + } +private: + ASTTypeItem(ASTTypeItem &); + ASTTypeItem &operator=(ASTTypeItem &); +}; + +class ASTTypeItemclass : public ASTType +{ +public: + ASTTypeItemclass(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeItemclass(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeItemclass(ASTTypeItemclass &); + ASTTypeItemclass &operator=(ASTTypeItemclass &); +}; + +class ASTTypeNPC : public ASTType +{ +public: + ASTTypeNPC(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeNPC(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeNPC(ASTTypeNPC &); + ASTTypeNPC &operator=(ASTTypeNPC &); +}; + +class ASTTypeLWpn : public ASTType +{ +public: + ASTTypeLWpn(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeLWpn(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeLWpn(ASTTypeLWpn &); + ASTTypeLWpn &operator=(ASTTypeLWpn &); +}; + +class ASTTypeEWpn : public ASTType +{ +public: + ASTTypeEWpn(LocationData Loc) : ASTType(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseTypeEWpn(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTTypeEWpn(ASTTypeEWpn &); + ASTTypeEWpn &operator=(ASTTypeEWpn &); +}; + +class ASTVarDecl : public ASTDecl +{ +public: + ASTVarDecl(ASTType *Type, string Name, LocationData Loc) : ASTDecl(Loc), type(Type), name(Name) {} + ASTType *getType() + { + return type; + } + string getName() + { + return name; + } + virtual ~ASTVarDecl(); + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseVarDecl(*this, param); + } +private: + ASTType *type; + string name; +}; + +class ASTVarDeclInitializer : public ASTVarDecl +{ +public: + ASTVarDeclInitializer(ASTType *Type, string Name, ASTExpr *Initial, LocationData Loc) : + ASTVarDecl(Type,Name,Loc), initial(Initial) {} + ~ASTVarDeclInitializer(); + ASTExpr *getInitializer() + { + return initial; + } + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseVarDeclInitializer(*this,param); + } +private: + ASTExpr *initial; + //NOT IMPLEMENTED; DO NOT USE + ASTVarDeclInitializer(ASTVarDeclInitializer &); + ASTVarDeclInitializer &operator=(ASTVarDeclInitializer &); +}; + +class ASTExpr : public ASTStmt +{ +public: + ASTExpr(LocationData Loc) : ASTStmt(Loc), hasval(false), intval(0), type(-1) {} + virtual ~ASTExpr() {} + long getIntValue() + { + return intval; + } + bool hasIntValue() + { + return hasval; + } + int getType() + { + return type; + } + void setIntValue(long val) + { + hasval = true; + intval=val; + } + void setType(int t) + { + type=t; + } +private: + bool hasval; + long intval; + int type; + //NOT IMPLEMENTED; DO NOT USE + ASTExpr(ASTExpr &); + ASTExpr &operator=(ASTExpr &); +}; + +class ASTUnaryExpr : public ASTExpr +{ +public: + ASTUnaryExpr(LocationData Loc) : ASTExpr(Loc) {} + virtual ~ASTUnaryExpr() + { + delete operand; + } + + void setOperand(ASTExpr *e) + { + operand=e; + } + ASTExpr *getOperand() + { + return operand; + } +private: + ASTExpr *operand; + //NOT IMPLEMENTED; DO NOT USE + ASTUnaryExpr(ASTUnaryExpr &); + ASTUnaryExpr&operator=(ASTUnaryExpr&); +}; + +class ASTBinaryExpr : public ASTExpr +{ +public: + ASTBinaryExpr(LocationData Loc) : ASTExpr(Loc) {} + virtual ~ASTBinaryExpr() + { + delete first; + delete second; + } + void setFirstOperand(ASTExpr *e) + { + first=e; + } + void setSecondOperand(ASTExpr *e) + { + second=e; + } + ASTExpr *getFirstOperand() + { + return first; + } + ASTExpr *getSecondOperand() + { + return second; + } +private: + ASTExpr *first; + ASTExpr *second; +}; + +class ASTLogExpr : public ASTBinaryExpr +{ +public: + ASTLogExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTLogExpr(ASTLogExpr &); + ASTLogExpr &operator=(ASTLogExpr &); +}; + +class ASTBitExpr : public ASTBinaryExpr +{ +public: + ASTBitExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTBitExpr &operator=(ASTBitExpr &); + ASTBitExpr(ASTBitExpr &); +}; + +class ASTShiftExpr : public ASTBinaryExpr +{ +public: + ASTShiftExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTShiftExpr(ASTShiftExpr &); + ASTShiftExpr &operator=(ASTShiftExpr &); +}; + +class ASTExprAnd : public ASTLogExpr +{ +public: + ASTExprAnd(LocationData Loc) : ASTLogExpr(Loc) {} + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprAnd(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTExprAnd(ASTExprAnd &); + ASTExprAnd &operator=(ASTExprAnd &); +}; + +class ASTExprOr : public ASTLogExpr +{ +public: + ASTExprOr(LocationData Loc) : ASTLogExpr(Loc) {} + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprOr(*this,param); + } +}; + +class ASTRelExpr : public ASTBinaryExpr +{ +public: + ASTRelExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTRelExpr(ASTRelExpr &); + ASTRelExpr &operator=(ASTRelExpr&); +}; + +class ASTExprGT : public ASTRelExpr +{ +public: + ASTExprGT(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprGT(*this, param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTExprGT(ASTExprGT &); + ASTExprGT &operator=(ASTExprGT &); +}; + +class ASTExprGE : public ASTRelExpr +{ +public: + ASTExprGE(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprGE(*this, param); + } +}; + +class ASTExprLT : public ASTRelExpr +{ +public: + ASTExprLT(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprLT(*this, param); + } +}; + +class ASTExprLE : public ASTRelExpr +{ +public: + ASTExprLE(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprLE(*this, param); + } +}; + +class ASTExprEQ : public ASTRelExpr +{ +public: + ASTExprEQ(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprEQ(*this, param); + } +}; + +class ASTExprNE : public ASTRelExpr +{ +public: + ASTExprNE(LocationData Loc) : ASTRelExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprNE(*this, param); + } +}; + +class ASTAddExpr : public ASTBinaryExpr +{ +public: + ASTAddExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTAddExpr(ASTAddExpr &); + ASTAddExpr &operator=(ASTAddExpr &); +}; + +class ASTExprPlus : public ASTAddExpr +{ +public: + ASTExprPlus(LocationData Loc) : ASTAddExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprPlus(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTExprPlus(ASTExprPlus &); + ASTExprPlus &operator=(ASTExprPlus &); +}; + +class ASTExprMinus : public ASTAddExpr +{ +public: + ASTExprMinus(LocationData Loc) : ASTAddExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprMinus(*this, param); + } +}; + +class ASTMultExpr : public ASTBinaryExpr +{ +public: + ASTMultExpr(LocationData Loc) : ASTBinaryExpr(Loc) {} +private: + //NOT IMPLEMENTED; DO NOT USE + ASTMultExpr(ASTMultExpr &); + ASTMultExpr &operator=(ASTMultExpr &); +}; + +class ASTExprTimes : public ASTMultExpr +{ +public: + ASTExprTimes(LocationData Loc) : ASTMultExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprTimes(*this, param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTExprTimes(ASTExprTimes &); + ASTExprTimes &operator=(ASTExprTimes &); +}; + +class ASTExprDivide : public ASTMultExpr +{ +public: + ASTExprDivide(LocationData Loc) : ASTMultExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprDivide(*this,param); + } +}; + +class ASTExprBitOr : public ASTBitExpr +{ +public: + ASTExprBitOr(LocationData Loc) : ASTBitExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprBitOr(*this,param); + } +}; + +class ASTExprBitXor : public ASTBitExpr +{ +public: + ASTExprBitXor(LocationData Loc) : ASTBitExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprBitXor(*this,param); + } +}; + +class ASTExprBitAnd : public ASTBitExpr +{ +public: + ASTExprBitAnd(LocationData Loc) : ASTBitExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprBitAnd(*this,param); + } +}; + +class ASTExprLShift : public ASTShiftExpr +{ +public: + ASTExprLShift(LocationData Loc) : ASTShiftExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprLShift(*this,param); + } +}; + +class ASTExprRShift : public ASTShiftExpr +{ +public: + ASTExprRShift(LocationData Loc) : ASTShiftExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprRShift(*this,param); + } +}; + +class ASTExprNegate : public ASTUnaryExpr +{ +public: + ASTExprNegate(LocationData Loc) : ASTUnaryExpr(Loc) {} + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprNegate(*this,param); + } +}; + +class ASTExprNot : public ASTUnaryExpr +{ +public: + ASTExprNot(LocationData Loc) : ASTUnaryExpr(Loc) {} + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprNot(*this,param); + } +}; + +class ASTExprBitNot : public ASTUnaryExpr +{ +public: + ASTExprBitNot(LocationData Loc) : ASTUnaryExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprBitNot(*this,param); + } +}; + +class ASTExprIncrement : public ASTUnaryExpr +{ +public: + ASTExprIncrement(LocationData Loc) : ASTUnaryExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprIncrement(*this,param); + } +}; + +class ASTExprPreIncrement : public ASTUnaryExpr +{ +public: + ASTExprPreIncrement(LocationData Loc) : ASTUnaryExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprPreIncrement(*this,param); + } +}; + +class ASTExprDecrement : public ASTUnaryExpr +{ +public: + ASTExprDecrement(LocationData Loc) : ASTUnaryExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprDecrement(*this,param); + } +}; + +class ASTExprPreDecrement : public ASTUnaryExpr +{ +public: + ASTExprPreDecrement(LocationData Loc) : ASTUnaryExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprPreDecrement(*this,param); + } +}; + +class ASTExprModulo : public ASTMultExpr +{ +public: + ASTExprModulo(LocationData Loc) : ASTMultExpr(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprModulo(*this,param); + } +}; + +class ASTNumConstant : public ASTExpr +{ +public: + ASTNumConstant(ASTFloat *value, LocationData Loc) : ASTExpr(Loc), val(value) {} + + ASTFloat *getValue() + { + return val; + } + + ~ASTNumConstant() + { + delete val; + } + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseNumConstant(*this,param); + } +private: + ASTFloat *val; +}; + +class ASTFuncCall : public ASTExpr +{ +public: + ASTFuncCall(LocationData Loc) : ASTExpr(Loc), params() {} + + list &getParams() + { + return params; + } + + void setName(ASTExpr *n) + { + name=n; + } + ASTExpr * getName() + { + return name; + } + void addParam(ASTExpr *param) + { + params.push_front(param); + } + + ~ASTFuncCall(); + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseFuncCall(*this,param); + } +private: + ASTExpr *name; + list params; +}; + +class ASTBoolConstant : public ASTExpr +{ +public: + ASTBoolConstant(bool Value, LocationData Loc) : ASTExpr(Loc), value(Value) {} + bool getValue() + { + return value; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseBoolConstant(*this, param); + } +private: + bool value; +}; + +class ASTBlock : public ASTStmt +{ +public: + ASTBlock(LocationData Loc) : ASTStmt(Loc), statements() {} + ~ASTBlock(); + + list &getStatements() + { + return statements; + } + list *getArrayRefs() + { + return &arrayRefs; + } + void addStatement(ASTStmt *Stmt); + + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseBlock(*this,param); + } +private: + list statements; + list arrayRefs; + //NOT IMPLEMENTED; DO NOT USE + ASTBlock(ASTBlock &); + ASTBlock &operator=(ASTBlock &); +}; + +class ASTStmtAssign : public ASTStmt +{ +public: + ASTStmtAssign(ASTStmt *Lval, ASTExpr *Rval, LocationData Loc) : ASTStmt(Loc), lval(Lval), rval(Rval) {} + ASTStmt *getLVal() + { + return lval; + } + ASTExpr *getRVal() + { + return rval; + } + ~ASTStmtAssign() + { + delete lval; + delete rval; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtAssign(*this,param); + } +private: + ASTStmt *lval; + ASTExpr *rval; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtAssign(ASTStmtAssign &); + ASTStmtAssign &operator=(ASTStmtAssign &); +}; + +class ASTExprDot : public ASTExpr +{ +public: + ASTExprDot(string Nspace, string Name, LocationData Loc) : ASTExpr(Loc), name(Name), nspace(Nspace) {} + string getName() + { + return name; + } + string getNamespace() + { + return nspace; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprDot(*this,param); + } +private: + string name; + string nspace; +}; + +class ASTExprArrow : public ASTExpr +{ +public: + ASTExprArrow(ASTExpr *Lval, string Rval, LocationData Loc) : ASTExpr(Loc), lval(Lval), rval(Rval), index(NULL) {} + string getName() + { + return rval; + } + ASTExpr *getLVal() + { + return lval; + } + ~ASTExprArrow() + { + delete lval; + + if(index) delete index; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprArrow(*this,param); + } + ASTExpr *getIndex() + { + return index; + } + void setIndex(ASTExpr *e) + { + index = e; + } +private: + ASTExpr *lval; + string rval; + ASTExpr *index; +}; + +class ASTExprArray : public ASTExpr +{ +public: + ASTExprArray(string Nspace, string Name, LocationData Loc) : ASTExpr(Loc), name(Name), index(NULL), nspace(Nspace) {} + string getName() + { + return name; + } + string getNamespace() + { + return nspace; + } + ~ASTExprArray() + { + if(index) delete index; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseExprArray(*this,param); + } + ASTExpr *getIndex() + { + return index; + } + void setIndex(ASTExpr *e) + { + index = e; + } +private: + string name; + ASTExpr *index; + string nspace; +}; + +class ASTStmtFor : public ASTStmt +{ +public: + ASTStmtFor(ASTStmt *Prec, ASTExpr *Term, ASTStmt *Incr, ASTStmt *Stmt, LocationData Loc) : + ASTStmt(Loc), prec(Prec), term(Term), incr(Incr), stmt(Stmt) {} + ~ASTStmtFor() + { + delete prec; + delete term; + delete incr; + delete stmt; + } + ASTStmt *getPrecondition() + { + return prec; + } + ASTExpr *getTerminationCondition() + { + return term; + } + ASTStmt *getIncrement() + { + return incr; + } + ASTStmt *getStmt() + { + return stmt; + } + void execute(ASTVisitor &visitor, void *param) + { + return visitor.caseStmtFor(*this,param); + } +private: + ASTStmt *prec; + ASTExpr *term; + ASTStmt *incr; + ASTStmt *stmt; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtFor(ASTStmtFor &); + ASTStmtFor &operator=(ASTStmtFor &); +}; + +class ASTStmtIf : public ASTStmt +{ +public: + ASTStmtIf(ASTExpr *Cond, ASTStmt *Stmt, LocationData Loc) : ASTStmt(Loc), cond(Cond), stmt(Stmt) {} + ASTExpr *getCondition() + { + return cond; + } + ASTStmt *getStmt() + { + return stmt; + } + virtual ~ASTStmtIf() + { + delete cond; + delete stmt; + } + void execute(ASTVisitor &visitor, void *param) + { + return visitor.caseStmtIf(*this,param); + } +private: + ASTExpr *cond; + ASTStmt *stmt; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtIf(ASTStmtIf &); + ASTStmtIf &operator=(ASTStmtIf &); +}; + +class ASTStmtIfElse : public ASTStmtIf +{ +public: + ASTStmtIfElse(ASTExpr *Cond, ASTStmt *Ifstmt, ASTStmt *Elsestmt, LocationData Loc) : + ASTStmtIf(Cond,Ifstmt,Loc), elsestmt(Elsestmt) {} + ~ASTStmtIfElse() + { + delete elsestmt; + } + ASTStmt *getElseStmt() + { + return elsestmt; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtIfElse(*this, param); + } +private: + ASTStmt *elsestmt; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtIfElse(ASTStmtIfElse &); + ASTStmtIfElse &operator=(ASTStmtIfElse &); +}; + +class ASTStmtReturn : public ASTStmt +{ +public: + ASTStmtReturn(LocationData Loc) : ASTStmt(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtReturn(*this, param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTStmtReturn(ASTStmtReturn &); + ASTStmtReturn &operator=(ASTStmtReturn &); +}; + +class ASTStmtReturnVal : public ASTStmt +{ +public: + ASTStmtReturnVal(ASTExpr *Retval, LocationData Loc) : ASTStmt(Loc), retval(Retval) {} + ASTExpr *getReturnValue() + { + return retval; + } + ~ASTStmtReturnVal() + { + delete retval; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtReturnVal(*this,param); + } +private: + ASTExpr *retval; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtReturnVal(ASTStmtReturnVal &); + ASTStmtReturnVal &operator=(ASTStmtReturnVal &); +}; + +class ASTStmtBreak : public ASTStmt +{ +public: + ASTStmtBreak(LocationData Loc) : ASTStmt(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtBreak(*this,param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTStmtBreak(ASTStmtBreak &); + ASTStmtBreak &operator=(ASTStmtBreak &); +}; + +class ASTStmtContinue : public ASTStmt +{ +public: + ASTStmtContinue(LocationData Loc) : ASTStmt(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtContinue(*this, param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTStmtContinue(ASTStmtContinue &); + ASTStmtContinue &operator=(ASTStmtContinue &); +}; + +class ASTStmtEmpty : public ASTStmt +{ +public: + ASTStmtEmpty(LocationData Loc) : ASTStmt(Loc) {} + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtEmpty(*this, param); + } +private: + //NOT IMPLEMENTED; DO NOT USE + ASTStmtEmpty(ASTStmtEmpty &); + ASTStmtEmpty &operator=(ASTStmtEmpty&); +}; + +class ASTScript : public ASTDecl +{ +public: + ASTScript(ASTType *Type, string Name, ASTDeclList *Sblock, LocationData Loc) : ASTDecl(Loc), type(Type), name(Name), sblock(Sblock) {} + ~ASTScript(); + ASTDeclList *getScriptBlock() + { + return sblock; + } + ASTType *getType() + { + return type; + } + string getName() + { + return name; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseScript(*this,param); + } +private: + ASTType *type; + string name; + ASTDeclList *sblock; +}; + +class ASTStmtWhile : public ASTStmt +{ +public: + ASTStmtWhile(ASTExpr *Cond, ASTStmt *Stmt, LocationData Loc) : ASTStmt(Loc), cond(Cond), stmt(Stmt) {} + ~ASTStmtWhile() + { + delete cond; + delete stmt; + } + ASTExpr *getCond() + { + return cond; + } + ASTStmt *getStmt() + { + return stmt; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtWhile(*this,param); + } +private: + ASTExpr *cond; + ASTStmt *stmt; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtWhile(ASTStmtWhile &); + ASTStmtWhile &operator=(ASTStmtWhile &); +}; + +class ASTStmtDo : public ASTStmt +{ +public: + ASTStmtDo(ASTExpr *Cond, ASTStmt *Stmt, LocationData Loc) : ASTStmt(Loc), cond(Cond), stmt(Stmt) {} + ~ASTStmtDo() + { + delete cond; + delete stmt; + } + ASTExpr *getCond() + { + return cond; + } + ASTStmt *getStmt() + { + return stmt; + } + void execute(ASTVisitor &visitor, void *param) + { + visitor.caseStmtDo(*this,param); + } +private: + ASTExpr *cond; + ASTStmt *stmt; + //NOT IMPLEMENTED; DO NOT USE + ASTStmtDo(ASTStmtDo &); + ASTStmtDo &operator=(ASTStmtDo &); +}; +#endif + diff --git a/src/parser/BuildVisitors.cpp b/src/parser/BuildVisitors.cpp new file mode 100644 index 0000000000..4d79fecfd3 --- /dev/null +++ b/src/parser/BuildVisitors.cpp @@ -0,0 +1,1249 @@ + +#include "../precompiled.h" //always first + +#include "BuildVisitors.h" +#include +#include "ParseError.h" + +void BuildOpcodes::caseDefault(void *) +{ + //unreachable + assert(false); +} + +void BuildOpcodes::caseFuncDecl(ASTFuncDecl &host, void *param) +{ + returnlabelid = ScriptParser::getUniqueLabelID(); + host.getBlock()->execute(*this,param); +} + +void BuildOpcodes::caseVarDecl(ASTVarDecl &host, void *param) +{ + //initialize to 0 + OpcodeContext *c = (OpcodeContext *)param; + int globalid = c->linktable->getGlobalID(c->symbols->getID(&host)); + + if(globalid != -1) + { + //it's a global var + //just set it to 0 + result.push_back(new OSetImmediate(new GlobalArgument(globalid), new LiteralArgument(0))); + return; + } + + //it's a local var + //set it to 0 on the stack + int offset = c->stackframe->getOffset(c->symbols->getID(&host)); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); +} + +void BuildOpcodes::caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *) param; + //compute the value of the initializer + host.getInitializer()->execute(*this,param); + //value of expr now stored in EXP1 + int globalid = c->linktable->getGlobalID(c->symbols->getID(&host)); + + if(globalid != -1) + { + //it's a global var + result.push_back(new OSetRegister(new GlobalArgument(globalid), new VarArgument(EXP1))); + return; + } + + //it's a local var + //set it on the stack + int offset = c->stackframe->getOffset(c->symbols->getID(&host)); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); +} + +void BuildOpcodes::caseArrayDecl(ASTArrayDecl &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *) param; + + //Check if the array is global or not + int globalid = c->linktable->getGlobalID(c->symbols->getID(&host)); + int RAMtype = (globalid == -1) ? SCRIPTRAM: GLOBALRAM; + + //Size is an expression + if(host.isRegister()) + { + //Push size + ((ASTExpr *) host.getSize())->execute(*this, param); + + //Allocate + if(RAMtype == GLOBALRAM) + { + result.push_back(new OAllocateGlobalMemRegister(new VarArgument(EXP1), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new GlobalArgument(globalid), new VarArgument(EXP1))); + } + else + { + result.push_back(new OAllocateMemRegister(new VarArgument(EXP1), new VarArgument(EXP1))); + int offset = c->stackframe->getOffset(c->symbols->getID(&host)); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); + } + } + //Size is a number + else + { + //Get size + pair size = ScriptParser::parseLong(((ASTFloat *) host.getSize())->parseValue()); + + if(!size.second) + printErrorMsg(&host, CONSTTRUNC, ((ASTFloat *) host.getSize())->getValue()); + + if(size.first < 10000) + { + failure = true; + printErrorMsg(&host, ARRAYTOOSMALL, ""); + return; + } + + //Check if we've allocated enough memory for the initialiser + if(host.getList() != NULL && host.getList()->getList().size() >= size_t(size.first)) + { + failure = true; + + if(host.getList()->isString()) + printErrorMsg(&host, ARRAYLISTSTRINGTOOLARGE, ""); + else + printErrorMsg(&host, ARRAYLISTTOOLARGE, ""); + + return; + } + + //Allocate + if(RAMtype == GLOBALRAM) + { + result.push_back(new OAllocateGlobalMemImmediate(new VarArgument(EXP1), new LiteralArgument(size.first))); + result.push_back(new OSetRegister(new GlobalArgument(globalid), new VarArgument(EXP1))); + } + else + { + result.push_back(new OAllocateMemImmediate(new VarArgument(EXP1), new LiteralArgument(size.first))); + int offset = c->stackframe->getOffset(c->symbols->getID(&host)); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); + } + } + + //Initialise + if(host.getList() != NULL) + { + result.push_back(new OSetRegister(new VarArgument(INDEX), new VarArgument(EXP1))); + result.push_back(new OSetImmediate(new VarArgument(INDEX2), new LiteralArgument(-10000))); + + for(list::iterator it = host.getList()->getList().begin(); it != host.getList()->getList().end(); it++) + { + result.push_back(new OAddImmediate(new VarArgument(INDEX2), new LiteralArgument(10000))); + (*it)->execute(*this, param); + result.push_back(new OSetRegister(new VarArgument(RAMtype), new VarArgument(EXP1))); + } + } +} + +void BuildOpcodes::castFromBool(vector &res, int reg) +{ + res.push_back(new OCompareImmediate(new VarArgument(reg), new LiteralArgument(0))); + res.push_back(new OSetFalse(new VarArgument(reg))); +} + +void BuildOpcodes::caseExprAnd(ASTExprAnd &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + castFromBool(result, EXP1); + castFromBool(result, EXP2); + result.push_back(new OAddRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(2))); + result.push_back(new OSetMore(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprOr(ASTExprOr &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OAddRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(1))); + result.push_back(new OSetMore(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprGT(ASTExprGT &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OCompareRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetLess(new VarArgument(EXP1))); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OSetTrue(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprGE(ASTExprGE &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OCompareRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetMore(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprLT(ASTExprLT &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OCompareRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetMore(new VarArgument(EXP1))); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OSetTrue(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprLE(ASTExprLE &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OCompareRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetLess(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprEQ(ASTExprEQ &host, void *param) +{ + //special case for booleans + bool isBoolean = (host.getFirstOperand()->getType() == ScriptParser::TYPE_BOOL); + + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + + if(isBoolean) + { + castFromBool(result, EXP1); + castFromBool(result, EXP2); + } + + result.push_back(new OCompareRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + result.push_back(new OSetTrue(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprNE(ASTExprNE &host, void *param) +{ + //special case for booleans + bool isBoolean = (host.getFirstOperand()->getType() == ScriptParser::TYPE_BOOL); + + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + + if(isBoolean) + { + castFromBool(result, EXP1); + castFromBool(result, EXP2); + } + + result.push_back(new OCompareRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + result.push_back(new OSetFalse(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprPlus(ASTExprPlus &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OAddRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprMinus(ASTExprMinus &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OSubRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprTimes(ASTExprTimes &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OMultRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprDivide(ASTExprDivide &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new ODivRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprModulo(ASTExprModulo &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OModuloRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprBitOr(ASTExprBitOr &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OOrRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprBitXor(ASTExprBitXor &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OXorRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprBitAnd(ASTExprBitAnd &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OAndRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprLShift(ASTExprLShift &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new OLShiftRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprRShift(ASTExprRShift &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + //compute both sides + host.getFirstOperand()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + host.getSecondOperand()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(EXP2))); + result.push_back(new ORShiftRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprNot(ASTExprNot &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + host.getOperand()->execute(*this,param); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OSetTrue(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprNegate(ASTExprNegate &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + host.getOperand()->execute(*this,param); + result.push_back(new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0))); + result.push_back(new OSubRegister(new VarArgument(EXP2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(EXP2))); +} + +void BuildOpcodes::caseExprBitNot(ASTExprBitNot &host, void *param) +{ + if(host.hasIntValue()) + { + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + return; + } + + host.getOperand()->execute(*this,param); + result.push_back(new ONot(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseExprIncrement(ASTExprIncrement &host, void *param) +{ + //annoying + OpcodeContext *c = (OpcodeContext *)param; + //load value of the variable into EXP1 + //except if it is an arrow expr, in which case the gettor function is stored + //in this AST* + bool isdotexpr; + IsDotExpr temp; + host.getOperand()->execute(temp, &isdotexpr); + + if(isdotexpr) + { + host.getOperand()->execute(*this,param); + } + else + { + int oldid = c->symbols->getID(host.getOperand()); + c->symbols->putAST(host.getOperand(), c->symbols->getID(&host)); + host.getOperand()->execute(*this,param); + c->symbols->putAST(host.getOperand(), oldid); + } + + result.push_back(new OPushRegister(new VarArgument(EXP1))); + + //increment EXP1 + result.push_back(new OAddImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + //store it + LValBOHelper helper; + host.getOperand()->execute(helper, param); + vector subcode = helper.getResult(); + + for(vector::iterator it = subcode.begin(); it != subcode.end(); it++) + { + result.push_back(*it); + } + + //pop EXP1 + result.push_back(new OPopRegister(new VarArgument(EXP1))); +} +void BuildOpcodes::caseExprPreIncrement(ASTExprPreIncrement &host, void *param) +{ + //annoying + OpcodeContext *c = (OpcodeContext *)param; + //load value of the variable into EXP1 + //except if it is an arrow expr, in which case the gettor function is stored + //in this AST* + bool isdotexpr; + IsDotExpr temp; + host.getOperand()->execute(temp, &isdotexpr); + + if(isdotexpr) + { + host.getOperand()->execute(*this,param); + } + else + { + int oldid = c->symbols->getID(host.getOperand()); + c->symbols->putAST(host.getOperand(), c->symbols->getID(&host)); + host.getOperand()->execute(*this,param); + c->symbols->putAST(host.getOperand(), oldid); + } + + //increment EXP1 + result.push_back(new OAddImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + //store it + LValBOHelper helper; + host.getOperand()->execute(helper, param); + vector subcode = helper.getResult(); + + for(vector::iterator it = subcode.begin(); it != subcode.end(); it++) + { + result.push_back(*it); + } +} + +void BuildOpcodes::caseExprPreDecrement(ASTExprPreDecrement &host, void *param) +{ + //annoying + OpcodeContext *c = (OpcodeContext *)param; + //load value of the variable into EXP1 + //except if it is an arrow expr, in which case the gettor function is stored + //in this AST* + bool isdotexpr; + IsDotExpr temp; + host.getOperand()->execute(temp, &isdotexpr); + + if(isdotexpr) + { + host.getOperand()->execute(*this,param); + } + else + { + int oldid = c->symbols->getID(host.getOperand()); + c->symbols->putAST(host.getOperand(), c->symbols->getID(&host)); + host.getOperand()->execute(*this,param); + c->symbols->putAST(host.getOperand(), oldid); + } + + //dencrement EXP1 + result.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + //store it + LValBOHelper helper; + host.getOperand()->execute(helper, param); + vector subcode = helper.getResult(); + + for(vector::iterator it = subcode.begin(); it != subcode.end(); it++) + { + result.push_back(*it); + } +} + +void BuildOpcodes::caseExprDecrement(ASTExprDecrement &host, void *param) +{ + //annoying + OpcodeContext *c = (OpcodeContext *)param; + //load value of the variable into EXP1 + //except if it is an arrow expr, in which case the gettor function is stored + //in this AST* + bool isdotexpr; + IsDotExpr temp; + host.getOperand()->execute(temp, &isdotexpr); + + if(isdotexpr) + { + host.getOperand()->execute(*this,param); + } + else + { + int oldid = c->symbols->getID(host.getOperand()); + c->symbols->putAST(host.getOperand(), c->symbols->getID(&host)); + host.getOperand()->execute(*this,param); + c->symbols->putAST(host.getOperand(), oldid); + } + + result.push_back(new OPushRegister(new VarArgument(EXP1))); + + //decrement EXP1 + result.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + //store it + LValBOHelper helper; + host.getOperand()->execute(helper, param); + vector subcode = helper.getResult(); + + for(vector::iterator it = subcode.begin(); it != subcode.end(); it++) + { + result.push_back(*it); + } + + //pop EXP1 + result.push_back(new OPopRegister(new VarArgument(EXP1))); +} + +void BuildOpcodes::caseFuncCall(ASTFuncCall &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int funclabel = c->linktable->functionToLabel(c->symbols->getID(&host)); + //push the stack frame pointer + result.push_back(new OPushRegister(new VarArgument(SFRAME))); + //push the return address + int returnaddr = ScriptParser::getUniqueLabelID(); + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LabelArgument(returnaddr))); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + //if the function is a pointer function (->func()) we need to push the left-hand-side + bool isdotexpr; + IsDotExpr temp; + host.getName()->execute(temp, &isdotexpr); + + if(!isdotexpr) + { + //load the value of the left-hand of the arrow into EXP1 + ((ASTExprArrow *)host.getName())->getLVal()->execute(*this,param); + //host.getName()->execute(*this,param); + //push it onto the stack + result.push_back(new OPushRegister(new VarArgument(EXP1))); + } + + //push the parameters, in forward order + for(list::iterator it = host.getParams().begin(); it != host.getParams().end(); it++) + { + (*it)->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + } + + //goto + result.push_back(new OGotoImmediate(new LabelArgument(funclabel))); + //pop the stack frame pointer + Opcode *next = new OPopRegister(new VarArgument(SFRAME)); + next->setLabel(returnaddr); + result.push_back(next); +} + +void BuildOpcodes::caseStmtAssign(ASTStmtAssign &host, void *param) +{ + //load the rval into EXP1 + host.getRVal()->execute(*this,param); + //and store it + LValBOHelper helper; + host.getLVal()->execute(helper, param); + vector subcode = helper.getResult(); + + for(vector::iterator it = subcode.begin(); it != subcode.end(); it++) + { + result.push_back(*it); + } +} + +void BuildOpcodes::caseExprDot(ASTExprDot &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int vid = c->symbols->getID(&host); + + if(vid == -1) + { + //constant, just load its value + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(c->symbols->getConstantVal(host.getName())))); + return; + } + + int globalid = c->linktable->getGlobalID(vid); + + if(globalid != -1) + { + //global variable, so just get its value + result.push_back(new OSetRegister(new VarArgument(EXP1), new GlobalArgument(globalid))); + return; + } + + //local variable, get its value from the stack + int offset = c->stackframe->getOffset(vid); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OLoadIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); +} + +void BuildOpcodes::caseExprArrow(ASTExprArrow &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + bool isIndexed = host.getIndex() != NULL; + //this is actually a function call + //to the appropriate gettor method + //so, set that up: + //push the stack frame + result.push_back(new OPushRegister(new VarArgument(SFRAME))); + int returnlabel = ScriptParser::getUniqueLabelID(); + //push the return address + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LabelArgument(returnlabel))); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + //get the rhs of the arrow + host.getLVal()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + + //if indexed, push the index + if(isIndexed) + { + host.getIndex()->execute(*this,param); + result.push_back(new OPushRegister(new VarArgument(EXP1))); + } + + //call the function + int label = c->linktable->functionToLabel(c->symbols->getID(&host)); + result.push_back(new OGotoImmediate(new LabelArgument(label))); + //pop the stack frame + Opcode *next = new OPopRegister(new VarArgument(SFRAME)); + next->setLabel(returnlabel); + result.push_back(next); +} + +void BuildOpcodes::caseExprArray(ASTExprArray &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int aid = c->symbols->getID(&host); + int globalid = c->linktable->getGlobalID(aid); + + if(globalid != -1) + { + //global variable, so just get its value + result.push_back(new OSetRegister(new VarArgument(EXP1), new GlobalArgument(globalid))); + result.push_back(new OPushRegister(new VarArgument(EXP1))); //Push on the pointer so we can have a[b[i]] + host.getIndex()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(INDEX))); //Pop back off + result.push_back(new OSetRegister(new VarArgument(INDEX2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(GLOBALRAM))); + return; + } + + //local variable, get its value from the stack + int offset = c->stackframe->getOffset(aid); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OLoadIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); + result.push_back(new OPushRegister(new VarArgument(EXP1))); //Push on the pointer so we can have a[b[i]] + host.getIndex()->execute(*this,param); + result.push_back(new OPopRegister(new VarArgument(INDEX))); //Pop back off + result.push_back(new OSetRegister(new VarArgument(INDEX2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(SCRIPTRAM))); + +} + +void BuildOpcodes::caseBlock(ASTBlock &host, void *param) +{ + list l = host.getStatements(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + { + (*it)->execute(*this,param); + bool IsArray=false; + IsArrayDecl temp; + (*it)->execute(temp,&IsArray); + + if(IsArray) + { + OpcodeContext *c = (OpcodeContext *)param; + int globalid = c->linktable->getGlobalID(c->symbols->getID(*it)); + + if(globalid == -1) + { + int offset = c->stackframe->getOffset(c->symbols->getID(*it)); + host.getArrayRefs()->push_back(offset); + arrayRefs.push_back(offset); + } + } + } + + for(list::reverse_iterator it = host.getArrayRefs()->rbegin(); it != host.getArrayRefs()->rend(); it++) + { + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(*it))); + result.push_back(new OLoadIndirect(new VarArgument(EXP2), new VarArgument(SFTEMP))); + result.push_back(new ODeallocateMemRegister(new VarArgument(EXP2))); + arrayRefs.pop_back(); + } +} + +void BuildOpcodes::caseStmtFor(ASTStmtFor &host, void *param) +{ + //run the precondition + host.getPrecondition()->execute(*this,param); + int loopstart = ScriptParser::getUniqueLabelID(); + int loopend = ScriptParser::getUniqueLabelID(); + int loopincr = ScriptParser::getUniqueLabelID(); + //nop + Opcode *next = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + next->setLabel(loopstart); + result.push_back(next); + //test the termination condition + host.getTerminationCondition()->execute(*this,param); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OGotoTrueImmediate(new LabelArgument(loopend))); + //run the loop body + //save the old break and continue values + int oldbreak = breaklabelid; + int oldcontinue = continuelabelid; + list *oldbRef = breakRef; + breaklabelid = loopend; + continuelabelid = loopincr; + bool IsB = false; + IsBlock temp; + host.getStmt()->execute(temp,&IsB); + + if(IsB) breakRef = (((ASTBlock *)host.getStmt())->getArrayRefs()); + + host.getStmt()->execute(*this,param); + breaklabelid = oldbreak; + continuelabelid = oldcontinue; + breakRef = oldbRef; + //run the increment + //nop + next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); + next->setLabel(loopincr); + result.push_back(next); + host.getIncrement()->execute(*this,param); + result.push_back(new OGotoImmediate(new LabelArgument(loopstart))); + //nop + next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); + next->setLabel(loopend); + result.push_back(next); +} + +void BuildOpcodes::caseStmtIf(ASTStmtIf &host, void *param) +{ + //run the test + host.getCondition()->execute(*this,param); + int endif = ScriptParser::getUniqueLabelID(); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OGotoTrueImmediate(new LabelArgument(endif))); + //run the block + host.getStmt()->execute(*this,param); + //nop + Opcode *next = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + next->setLabel(endif); + result.push_back(next); +} + +void BuildOpcodes::caseStmtWhile(ASTStmtWhile &host, void *param) +{ + int startlabel = ScriptParser::getUniqueLabelID(); + int endlabel = ScriptParser::getUniqueLabelID(); + //run the test + //nop to label start + Opcode *start = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + start->setLabel(startlabel); + result.push_back(start); + host.getCond()->execute(*this,param); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OGotoTrueImmediate(new LabelArgument(endlabel))); + int oldbreak = breaklabelid; + int oldcontinue = continuelabelid; + list *oldbRef = breakRef; + breaklabelid = endlabel; + continuelabelid = startlabel; + bool IsB = false; + IsBlock temp; + host.getStmt()->execute(temp,&IsB); + + if(IsB) breakRef = (((ASTBlock *)host.getStmt())->getArrayRefs()); + + host.getStmt()->execute(*this,param); + breaklabelid = oldbreak; + continuelabelid = oldcontinue; + breakRef = oldbRef; + result.push_back(new OGotoImmediate(new LabelArgument(startlabel))); + //nop to end while + Opcode *end = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + end->setLabel(endlabel); + result.push_back(end); +} + +void BuildOpcodes::caseStmtDo(ASTStmtDo &host, void *param) +{ + int startlabel = ScriptParser::getUniqueLabelID(); + int endlabel = ScriptParser::getUniqueLabelID(); + int continuelabel = ScriptParser::getUniqueLabelID(); + //nop to label start + Opcode *start = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + start->setLabel(startlabel); + result.push_back(start); + + int oldbreak = breaklabelid; + int oldcontinue = continuelabelid; + list *oldbRef = breakRef; + breaklabelid = endlabel; + continuelabelid = continuelabel; + bool IsB = false; + IsBlock temp; + host.getStmt()->execute(temp,&IsB); + + if(IsB) breakRef = (((ASTBlock *)host.getStmt())->getArrayRefs()); + + host.getStmt()->execute(*this,param); + breaklabelid = oldbreak; + continuelabelid = oldcontinue; + breakRef = oldbRef; + + start = new OSetImmediate(new VarArgument(NUL), new LiteralArgument(0)); + start->setLabel(continuelabel); + result.push_back(start); + host.getCond()->execute(*this,param); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OGotoTrueImmediate(new LabelArgument(endlabel))); + result.push_back(new OGotoImmediate(new LabelArgument(startlabel))); + //nop to end dowhile + Opcode *end = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + end->setLabel(endlabel); + result.push_back(end); +} + +void BuildOpcodes::caseStmtIfElse(ASTStmtIfElse &host, void *param) +{ + //run the test + host.getCondition()->execute(*this,param); + int elseif = ScriptParser::getUniqueLabelID(); + int endif = ScriptParser::getUniqueLabelID(); + result.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + result.push_back(new OGotoTrueImmediate(new LabelArgument(elseif))); + //run if blocl + host.getStmt()->execute(*this,param); + result.push_back(new OGotoImmediate(new LabelArgument(endif))); + Opcode *next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); + next->setLabel(elseif); + result.push_back(next); + host.getElseStmt()->execute(*this,param); + next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); + next->setLabel(endif); + result.push_back(next); +} + +void BuildOpcodes::caseStmtReturn(ASTStmtReturn &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + void *temp; + temp=&host; + param=param; + + for(list::reverse_iterator it = arrayRefs.rbegin(); it != arrayRefs.rend(); it++) + { + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(*it))); + result.push_back(new OLoadIndirect(new VarArgument(EXP2), new VarArgument(SFTEMP))); + result.push_back(new ODeallocateMemRegister(new VarArgument(EXP2))); + } + + result.push_back(new OGotoImmediate(new LabelArgument(returnlabelid))); +} + +void BuildOpcodes::caseStmtReturnVal(ASTStmtReturnVal &host, void *param) +{ + host.getReturnValue()->execute(*this,param); + + for(list::reverse_iterator it = arrayRefs.rbegin(); it != arrayRefs.rend(); it++) + { + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(*it))); + result.push_back(new OLoadIndirect(new VarArgument(EXP2), new VarArgument(SFTEMP))); + result.push_back(new ODeallocateMemRegister(new VarArgument(EXP2))); + } + + result.push_back(new OGotoImmediate(new LabelArgument(returnlabelid))); +} + +void BuildOpcodes::caseStmtEmpty(ASTStmtEmpty &, void *) +{ + //empty +} + +void BuildOpcodes::caseNumConstant(ASTNumConstant &host, void *) +{ + if(host.hasIntValue()) + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); + else + { + pair val = ScriptParser::parseLong(host.getValue()->parseValue()); + + if(!val.second) + printErrorMsg(&host, CONSTTRUNC, host.getValue()->getValue()); + + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(val.first))); + } +} + +void BuildOpcodes::caseBoolConstant(ASTBoolConstant &host, void *) +{ + result.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(host.getIntValue()))); +} + +void BuildOpcodes::caseStmtBreak(ASTStmtBreak &host, void *) +{ + if(breaklabelid == -1) + { + printErrorMsg(&host, BREAKBAD); + failure = true; + return; + } + + for(list::reverse_iterator it = breakRef->rbegin(); it != breakRef->rend(); it++) + { + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(*it))); + result.push_back(new OLoadIndirect(new VarArgument(EXP2), new VarArgument(SFTEMP))); + result.push_back(new ODeallocateMemRegister(new VarArgument(EXP2))); + } + + result.push_back(new OGotoImmediate(new LabelArgument(breaklabelid))); +} + +void BuildOpcodes::caseStmtContinue(ASTStmtContinue &host, void *) +{ + if(continuelabelid == -1) + { + printErrorMsg(&host, CONTINUEBAD); + failure = true; + return; + } + + for(list::reverse_iterator it = breakRef->rbegin(); it != breakRef->rend(); it++) + { + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(*it))); + result.push_back(new OLoadIndirect(new VarArgument(EXP2), new VarArgument(SFTEMP))); + result.push_back(new ODeallocateMemRegister(new VarArgument(EXP2))); + } + + result.push_back(new OGotoImmediate(new LabelArgument(continuelabelid))); +} +///////////////////////////////////////////////////////////////////////////////// +void LValBOHelper::caseDefault(void *) +{ + //Shouldn't happen + assert(false); +} + +void LValBOHelper::caseExprDot(ASTExprDot &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int vid = c->symbols->getID(&host); + int globalid = c->linktable->getGlobalID(vid); + + if(globalid != -1) + { + //global variable + result.push_back(new OSetRegister(new GlobalArgument(globalid), new VarArgument(EXP1))); + return; + } + + //set the stack + int offset = c->stackframe->getOffset(vid); + + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); +} + +void LValBOHelper::caseExprArrow(ASTExprArrow &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int isIndexed = (host.getIndex() != NULL); + //this is actually implemented as a settor function call + //so do that + //push the stack frame + result.push_back(new OPushRegister(new VarArgument(SFRAME))); + int returnlabel = ScriptParser::getUniqueLabelID(); + //push the return address + result.push_back(new OSetImmediate(new VarArgument(EXP2), new LabelArgument(returnlabel))); + result.push_back(new OPushRegister(new VarArgument(EXP2))); + //push the lhs of the arrow + //but first save the value of EXP1 + result.push_back(new OPushRegister(new VarArgument(EXP1))); + vector toadd; + BuildOpcodes oc; + host.getLVal()->execute(oc, param); + toadd = oc.getResult(); + + for(vector::iterator it = toadd.begin(); it != toadd.end(); it++) + { + result.push_back(*it); + } + + //pop the old value of EXP1 + result.push_back(new OPopRegister(new VarArgument(EXP2))); + //and push the lhs + result.push_back(new OPushRegister(new VarArgument(EXP1))); + //and push the old value of EXP1 + result.push_back(new OPushRegister(new VarArgument(EXP2))); + + //and push the index, if indexed + if(isIndexed) + { + BuildOpcodes oc2; + host.getIndex()->execute(oc2, param); + toadd = oc2.getResult(); + + for(vector::iterator it = toadd.begin(); it != toadd.end(); it++) + { + result.push_back(*it); + } + + result.push_back(new OPushRegister(new VarArgument(EXP1))); + } + + //finally, goto! + int label = c->linktable->functionToLabel(c->symbols->getID(&host)); + result.push_back(new OGotoImmediate(new LabelArgument(label))); + //pop the stack frame + Opcode *next = new OPopRegister(new VarArgument(SFRAME)); + next->setLabel(returnlabel); + result.push_back(next); +} + +void LValBOHelper::caseExprArray(ASTExprArray &host, void *param) +{ + OpcodeContext *c = (OpcodeContext *)param; + int RAMtype = SCRIPTRAM; + int vid = c->symbols->getID(&host); + int globalid = c->linktable->getGlobalID(vid); + + //Get the pointer + if(globalid != -1) + { + //global array + result.push_back(new OSetRegister(new VarArgument(INDEX), new GlobalArgument(globalid))); + RAMtype = GLOBALRAM; + } + else + { + int offset = c->stackframe->getOffset(vid); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OLoadIndirect(new VarArgument(INDEX), new VarArgument(SFTEMP))); + } + + result.push_back(new OSetRegister(new VarArgument(NUL), new VarArgument(EXP1))); + result.push_back(new OPushRegister(new VarArgument(INDEX))); //Push on the pointer (might change inside the index expression) + + //Get the index + BuildOpcodes oc; + host.getIndex()->execute(oc, param); + vector toadd; + toadd = oc.getResult(); + + for(vector::iterator it = toadd.begin(); it != toadd.end(); it++) + { + result.push_back(*it); + } + + //Go + result.push_back(new OPopRegister(new VarArgument(INDEX))); //Pop back off + result.push_back(new OSetRegister(new VarArgument(INDEX2), new VarArgument(EXP1))); + result.push_back(new OSetRegister(new VarArgument(RAMtype), new VarArgument(NUL))); +} + +void LValBOHelper::caseVarDecl(ASTVarDecl &host, void *param) +{ + //cannot be a global variable, so just stuff it in the stack + OpcodeContext *c = (OpcodeContext *)param; + int vid = c->symbols->getID(&host); + int offset = c->stackframe->getOffset(vid); + result.push_back(new OSetRegister(new VarArgument(SFTEMP), new VarArgument(SFRAME))); + result.push_back(new OAddImmediate(new VarArgument(SFTEMP), new LiteralArgument(offset))); + result.push_back(new OStoreIndirect(new VarArgument(EXP1), new VarArgument(SFTEMP))); +} + diff --git a/src/parser/BuildVisitors.h b/src/parser/BuildVisitors.h new file mode 100644 index 0000000000..09308dbf66 --- /dev/null +++ b/src/parser/BuildVisitors.h @@ -0,0 +1,156 @@ +#ifndef BUILDVISITORS_H +#define BUILDVISITORS_H + +#include "AST.h" +#include "UtilVisitors.h" +#include "ByteCode.h" + +class BuildOpcodes : public RecursiveVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseFuncDecl(ASTFuncDecl &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + virtual void caseBlock(ASTBlock &host, void *param); + virtual void caseExprAnd(ASTExprAnd &host, void *param); + virtual void caseExprOr(ASTExprOr &host, void *param); + virtual void caseExprGT(ASTExprGT &host, void *param); + virtual void caseExprGE(ASTExprGE &host, void *param); + virtual void caseExprLT(ASTExprLT &host, void *param); + virtual void caseExprLE(ASTExprLE &host, void *param); + virtual void caseExprEQ(ASTExprEQ &host, void *param); + virtual void caseExprNE(ASTExprNE &host, void *param); + virtual void caseExprPlus(ASTExprPlus &host, void *param); + virtual void caseExprMinus(ASTExprMinus &host, void *param); + virtual void caseExprTimes(ASTExprTimes &host, void *param); + virtual void caseExprDivide(ASTExprDivide &host, void *param); + virtual void caseExprNot(ASTExprNot &host, void *param); + virtual void caseExprNegate(ASTExprNegate &host, void *param); + virtual void caseFuncCall(ASTFuncCall &host, void *param); + virtual void caseStmtAssign(ASTStmtAssign &host, void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + virtual void caseStmtFor(ASTStmtFor &host, void *param); + virtual void caseStmtIf(ASTStmtIf &host, void *param); + virtual void caseStmtIfElse(ASTStmtIfElse &host, void *param); + virtual void caseStmtReturn(ASTStmtReturn &host, void *param); + virtual void caseStmtReturnVal(ASTStmtReturnVal &host, void *param); + virtual void caseStmtEmpty(ASTStmtEmpty &host, void *param); + virtual void caseNumConstant(ASTNumConstant &host, void *param); + virtual void caseBoolConstant(ASTBoolConstant &host, void *param); + virtual void caseStmtWhile(ASTStmtWhile &host, void *param); + virtual void caseStmtDo(ASTStmtDo &host, void *param); + virtual void caseExprBitOr(ASTExprBitOr &host, void *param); + virtual void caseExprBitXor(ASTExprBitXor &host, void *param); + virtual void caseExprBitAnd(ASTExprBitAnd &host, void *param); + virtual void caseExprLShift(ASTExprLShift &host, void *param); + virtual void caseExprRShift(ASTExprRShift &host, void *param); + virtual void caseExprModulo(ASTExprModulo &host, void *param); + virtual void caseExprBitNot(ASTExprBitNot &host, void *param); + virtual void caseExprIncrement(ASTExprIncrement &host, void *param); + virtual void caseExprPreIncrement(ASTExprPreIncrement &host, void *param); + virtual void caseExprDecrement(ASTExprDecrement &host, void *param); + virtual void caseExprPreDecrement(ASTExprPreDecrement &host, void *param); + virtual void caseStmtBreak(ASTStmtBreak &host, void *param); + virtual void caseStmtContinue(ASTStmtContinue &host, void *param); + vector getResult() + { + return result; + } + int getReturnLabelID() + { + return returnlabelid; + } + list *getArrayRefs() + { + return &arrayRefs; + } + BuildOpcodes() : continuelabelid(-1), breaklabelid(-1), failure(false) {} + bool isOK() + { + return !failure; + } + void castFromBool(vector &result, int reg); +private: + vector result; + int returnlabelid; + int continuelabelid; + int breaklabelid; + list *breakRef; + list arrayRefs; + bool failure; +}; + +class CountStackSymbols : public RecursiveVisitor +{ +public: + virtual void caseDefault(void *) { } + virtual void caseVarDecl(ASTVarDecl &host, void *param) + { + pair *, SymbolTable *> *p = (pair *, SymbolTable *> *)param; + int vid = p->second->getID(&host); + p->first->push_back(vid); + } + virtual void caseArrayDecl(ASTArrayDecl &host, void *param) + { + pair *, SymbolTable *> *p = (pair *, SymbolTable *> *)param; + int vid = p->second->getID(&host); + p->first->push_back(vid); + } + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) + { + caseVarDecl(host, param); + } +}; + +class LValBOHelper : public ASTVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + vector getResult() + { + return result; + } +private: + vector result; +}; + +class GetLabels : public ArgumentVisitor +{ +public: + void caseLabel(LabelArgument &host, void *param) + { + map *labels = (map *)param; + (*labels)[host.getID()] = true; + } +}; + +class SetLabels : public ArgumentVisitor +{ +public: + void caseLabel(LabelArgument &host, void *param) + { + map *labels = (map *)param; + int lineno = (*labels)[host.getID()]; + + if(lineno==0) + { + char temp[200]; + sprintf(temp,"Internal error: couldn't find function label %d", host.getID()); + box_out(temp); + box_eol(); + } + + host.setLineNo(lineno); + } +}; + +#endif + diff --git a/src/parser/ByteCode.cpp b/src/parser/ByteCode.cpp new file mode 100644 index 0000000000..817700a40f --- /dev/null +++ b/src/parser/ByteCode.cpp @@ -0,0 +1,1878 @@ + +#include "../precompiled.h" //always first + +#include "ByteCode.h" +#include "DataStructs.h" +#include "ParseError.h" +#include "../zsyssimple.h" +#include +#include +#include + +string LiteralArgument::toString() +{ + char temp[40]; + string sign = value < 0 ? "-" : ""; + sprintf(temp,"%ld", abs(value)/10000); + string first = string(temp); + + if(value % 10000 == 0) + return sign + first; + + sprintf(temp,"%ld", abs(value)%10000); + string second = string(temp); + + while(second.length() < 4) + second = "0" + second; + + return sign + first + "." + second; +} + +string VarArgument::toString() +{ + char temp[40]; + + switch(ID) + { + case SP: + return "SP"; + + case DATA: + return "DATA"; + + case FFSCRIPT: + return "FFSCRIPT"; + + case FCSET: + return "CSET"; + + case DELAY: + return "DELAY"; + + case FX: + return "X"; + + case FY: + return "Y"; + + case XD: + return "XD"; + + case YD: + return "YD"; + + case XD2: + return "XD2"; + + case YD2: + return "YD2"; + + case LINKX: + return "LINKX"; + + case LINKY: + return "LINKY"; + + case LINKZ: + return "LINKZ"; + + case LINKJUMP: + return "LINKJUMP"; + + case LINKDIR: + return "LINKDIR"; + + case LINKHITDIR: + return "LINKHITDIR"; + + case LINKSWORDJINX: + return "LINKSWORDJINX"; + + case LINKITEMJINX: + return "LINKITEMJINX"; + + case LINKHP: + return "LINKHP"; + + case LINKMP: + return "LINKMP"; + + case LINKMAXHP: + return "LINKMAXHP"; + + case LINKMAXMP: + return "LINKMAXMP"; + + case LINKACTION: + return "LINKACTION"; + + case LINKHELD: + return "LINKHELD"; + + case LINKINVIS: + return "LINKINVIS"; + + case LINKINVINC: + return "LINKINVINC"; + + case LINKMISCD: + return "LINKMISCD"; + + case LINKTILE: + return "LINKTILE"; + + case LINKFLIP: + return "LINKFLIP"; + + case INPUTSTART: + return "INPUTSTART"; + + case INPUTMAP: + return "INPUTMAP"; + + case INPUTUP: + return "INPUTUP"; + + case INPUTDOWN: + return "INPUTDOWN"; + + case INPUTLEFT: + return "INPUTLEFT"; + + case INPUTRIGHT: + return "INPUTRIGHT"; + + case INPUTA: + return "INPUTA"; + + case INPUTB: + return "INPUTB"; + + case INPUTL: + return "INPUTL"; + + case INPUTR: + return "INPUTR"; + + case INPUTEX1: + return "INPUTEX1"; + + case INPUTEX2: + return "INPUTEX2"; + + case INPUTEX3: + return "INPUTEX3"; + + case INPUTEX4: + return "INPUTEX4"; + + case INPUTAXISUP: + return "INPUTAXISUP"; + + case INPUTAXISDOWN: + return "INPUTAXISDOWN"; + + case INPUTAXISLEFT: + return "INPUTAXISLEFT"; + + case INPUTAXISRIGHT: + return "INPUTAXISRIGHT"; + + case INPUTPRESSSTART: + return "INPUTPRESSSTART"; + + case INPUTPRESSMAP: + return "INPUTPRESSMAP"; + + case INPUTPRESSUP: + return "INPUTPRESSUP"; + + case INPUTPRESSDOWN: + return "INPUTPRESSDOWN"; + + case INPUTPRESSLEFT: + return "INPUTPRESSLEFT"; + + case INPUTPRESSRIGHT: + return "INPUTPRESSRIGHT"; + + case INPUTPRESSA: + return "INPUTPRESSA"; + + case INPUTPRESSB: + return "INPUTPRESSB"; + + case INPUTPRESSL: + return "INPUTPRESSL"; + + case INPUTPRESSR: + return "INPUTPRESSR"; + + case INPUTPRESSEX1: + return "INPUTPRESSEX1"; + + case INPUTPRESSEX2: + return "INPUTPRESSEX2"; + + case INPUTPRESSEX3: + return "INPUTPRESSEX3"; + + case INPUTPRESSEX4: + return "INPUTPRESSEX4"; + + case INPUTPRESSAXISUP: + return "PRESSAXISUP"; + + case INPUTPRESSAXISDOWN: + return "PRESSAXISDOWN"; + + case INPUTPRESSAXISLEFT: + return "PRESSAXISLEFT"; + + case INPUTPRESSAXISRIGHT: + return "PRESSAXISRIGHT"; + + case INPUTMOUSEX: + return "INPUTMOUSEX"; + + case INPUTMOUSEY: + return "INPUTMOUSEY"; + + case INPUTMOUSEZ: + return "INPUTMOUSEZ"; + + case INPUTMOUSEB: + return "INPUTMOUSEB"; + + case SDD: + return "SDD"; + + case SCREENFLAGSD: + return "SCREENFLAGSD"; + + case SCREENEFLAGSD: + return "SCREENEFLAGSD"; + + case COMBODD: + return "COMBODD"; + + case COMBOCD: + return "COMBOCD"; + + case COMBOFD: + return "COMBOFD"; + + case COMBODDM: + return "COMBODDM"; + + case COMBOCDM: + return "COMBOCDM"; + + case COMBOFDM: + return "COMBOFDM"; + + case REFFFC: + return "REFFFC"; + + case REFITEM: + return "REFITEM"; + + case ITEMCOUNT: + return "ITEMCOUNT"; + + case ITEMX: + return "ITEMX"; + + case ITEMY: + return "ITEMY"; + + case ITEMZ: + return "ITEMZ"; + + case ITEMJUMP: + return "ITEMJUMP"; + + case ITEMDRAWTYPE: + return "ITEMDRAWTYPE"; + + case ITEMID: + return "ITEMID"; + + case ITEMTILE: + return "ITEMTILE"; + + case ITEMCSET: + return "ITEMCSET"; + + case ITEMFLASHCSET: + return "ITEMFLASHCSET"; + + case ITEMFRAMES: + return "ITEMFRAMES"; + + case ITEMFRAME: + return "ITEMFRAME"; + + case ITEMASPEED: + return "ITEMASPEED"; + + case ITEMDELAY: + return "ITEMDELAY"; + + case ITEMFLASH: + return "ITEMFLASH"; + + case ITEMFLIP: + return "ITEMFLIP"; + + case ITEMEXTEND: + return "ITEMEXTEND"; + + case ITEMPICKUP: + return "ITEMPICKUP"; + + case ITEMMISCD: + return "ITEMMISCD"; + + case ITEMCLASSFAMILY: + return "IDATAFAMILY"; + + case ITEMCLASSFAMTYPE: + return "IDATALEVEL"; + + case ITEMCLASSAMOUNT: + return "IDATAAMOUNT"; + + case ITEMCLASSMAX: + return "IDATAMAX"; + + case ITEMCLASSSETMAX: + return "IDATASETMAX"; + + case ITEMCLASSSETGAME: + return "IDATAKEEP"; + + case ITEMCLASSCOUNTER: + return "IDATACOUNTER"; + + case ITEMCLASSUSESOUND: + return "IDATAUSESOUND"; + + case ITEMCLASSPOWER: + return "IDATAPOWER"; + + case ITEMCLASSINITDD: + return "IDATAINITDD"; + + case REFITEMCLASS: + return "REFITEMCLASS"; + + case COMBOID: + return "COMBOID"; + + case COMBOTD: + return "COMBOTD"; + + case COMBOSD: + return "COMBOSD"; + + case COMBOIDM: + return "COMBOIDM"; + + case COMBOTDM: + return "COMBOTDM"; + + case COMBOSDM: + return "COMBOSDM"; + + case GETMIDI: + return "GETMIDI"; + + case CURSCR: + return "CURSCR"; + + case CURDSCR: + return "CURDSCR"; + + case CURMAP: + return "CURMAP"; + + case CURDMAP: + return "CURDMAP"; + + case CURLEVEL: + return "CURLEVEL"; + + case GAMEDEATHS: + return "GAMEDEATHS"; + + case GAMECHEAT: + return "GAMECHEAT"; + + case GAMETIME: + return "GAMETIME"; + + case GAMEHASPLAYED: + return "GAMEHASPLAYED"; + + case GAMESTANDALONE: + return "GAMESTANDALONE"; + + case GAMETIMEVALID: + return "GAMETIMEVALID"; + + case GAMEGUYCOUNT: + return "GAMEGUYCOUNT"; + + case GAMECONTSCR: + return "GAMECONTSCR"; + + case GAMECONTDMAP: + return "GAMECONTDMAP"; + + case GAMEENTRSCR: + return "GAMEENTRSCR"; + + case GAMEENTRDMAP: + return "GAMEENTRDMAP"; + + case GAMECOUNTERD: + return "GAMECOUNTERD"; + + case GAMEMCOUNTERD: + return "GAMEMCOUNTERD"; + + case GAMEDCOUNTERD: + return "GAMEDCOUNTERD"; + + case GAMEGENERICD: + return "GAMEGENERICD"; + + case GAMEITEMSD: + return "GAMEITEMSD"; + + case GAMELITEMSD: + return "GAMELITEMSD"; + + case GAMELKEYSD: + return "GAMELKEYSD"; + + case SCREENSTATED: + return "SCREENSTATED"; + + case SCREENSTATEDD: + return "SCREENSTATEDD"; + + case DMAPFLAGSD: + return "DMAPFLAGSD"; + + case DMAPLEVELD: + return "DMAPLEVELD"; + + case DMAPCOMPASSD: + return "DMAPCOMPASSD"; + + case DMAPCONTINUED: + return "DMAPCONTINUED"; + + case DMAPMIDID: + return "DMAPMIDID"; + + case DMAPOFFSET: + return "DMAPOFFSET"; + + case DMAPMAP: + return "DMAPMAP"; + + case SDDD: + return "SDDD"; + + case SDDDD: + return "SDDDD"; + + case GAMECLICKFREEZE: + return "GAMECLICKFREEZE"; + + case FFFLAGSD: + return "FFFLAGSD"; + + case FFTWIDTH: + return "FFTWIDTH"; + + case FFTHEIGHT: + return "FFTHEIGHT"; + + case FFCWIDTH: + return "FFCWIDTH"; + + case FFCHEIGHT: + return "FFCHEIGHT"; + + case FFLINK: + return "FFLINK"; + + case FFMISCD: + return "FFMISCD"; + + case FFINITDD: + return "FFINITDD"; + + /*case FFDD: + return "FFDD";*/ + case LINKITEMD: + return "LINKITEMD"; + + case REFNPC: + return "REFNPC"; + + case NPCCOUNT: + return "NPCCOUNT"; + + case NPCX: + return "NPCX"; + + case NPCY: + return "NPCY"; + + case NPCZ: + return "NPCZ"; + + case NPCJUMP: + return "NPCJUMP"; + + case NPCDIR: + return "NPCDIR"; + + case NPCRATE: + return "NPCRATE"; + + case NPCHOMING: + return "NPCHOMING"; + + case NPCFRAMERATE: + return "NPCFRAMERATE"; + + case NPCHALTRATE: + return "NPCHALTRATE"; + + case NPCDRAWTYPE: + return "NPCDRAWTYPE"; + + case NPCHP: + return "NPCHP"; + + case NPCID: + return "NPCID"; + + case NPCTYPE: + return "NPCTYPE"; + + case NPCDP: + return "NPCDP"; + + case NPCWDP: + return "NPCWDP"; + + case NPCTILE: + return "NPCTILE"; + + case NPCOTILE: + return "NPCOTILE"; + + case NPCWEAPON: + return "NPCWEAPON"; + + case NPCITEMSET: + return "NPCITEMSET"; + + case NPCCSET: + return "NPCCSET"; + + case NPCBOSSPAL: + return "NPCBOSSPAL"; + + case NPCBGSFX: + return "NPCBGSFX"; + + case NPCEXTEND: + return "NPCEXTEND"; + + case NPCSTEP: + return "NPCSTEP"; + + case NPCDEFENSED: + return "NPCDEFENSED"; + + case NPCMISCD: + return "NPCMISCD"; + + case NPCDD: + return "NPCDD"; + + case NPCMFLAGS: + return "NPCMFLAGS"; + + case NPCCOLLDET: + return "NPCCOLLDET"; + + case NPCSTUN: + return "NPCSTUN"; + + case NPCHUNGER: + return "NPCHUNGER"; + + case SCRDOORD: + return "SCRDOORD"; + + case LIT: + return "LIT"; + + case WAVY: + return "WAVY"; + + case QUAKE: + return "QUAKE"; + + case ITEMOTILE: + return "ITEMOTILE"; + + case REFLWPN: + return "REFLWPN"; + + case LWPNCOUNT: + return "LWPNCOUNT"; + + case LWPNX: + return "LWPNX"; + + case LWPNY: + return "LWPNY"; + + case LWPNZ: + return "LWPNZ"; + + case LWPNJUMP: + return "LWPNJUMP"; + + case LWPNDIR: + return "LWPNDIR"; + + case LWPNANGLE: + return "LWPNANGLE"; + + case LWPNSTEP: + return "LWPNSTEP"; + + case LWPNFRAMES: + return "LWPNFRAMES"; + + case LWPNFRAME: + return "LWPNFRAME"; + + case LWPNDRAWTYPE: + return "LWPNDRAWTYPE"; + + case LWPNPOWER: + return "LWPNPOWER"; + + case LWPNID: + return "LWPNID"; + + case LWPNANGULAR: + return "LWPNANGULAR"; + + case LWPNBEHIND: + return "LWPNBEHIND"; + + case LWPNASPEED: + return "LWPNASPEED"; + + case LWPNTILE: + return "LWPNTILE"; + + case LWPNFLASHCSET: + return "LWPNFLASHCSET"; + + case LWPNDEAD: + return "LWPNDEAD"; + + case LWPNCSET: + return "LWPNCSET"; + + case LWPNFLASH: + return "LWPNFLASH"; + + case LWPNFLIP: + return "LWPNFLIP"; + + case LWPNOTILE: + return "LWPNOTILE"; + + case LWPNOCSET: + return "LWPNOCSET"; + + case LWPNEXTEND: + return "LWPNEXTEND"; + + case LWPNCOLLDET: + return "LWPNCOLLDET"; + + case REFEWPN: + return "REFEWPN"; + + case EWPNCOUNT: + return "EWPNCOUNT"; + + case EWPNX: + return "EWPNX"; + + case EWPNY: + return "EWPNY"; + + case EWPNZ: + return "EWPNZ"; + + case EWPNJUMP: + return "EWPNJUMP"; + + case EWPNDIR: + return "EWPNDIR"; + + case EWPNANGLE: + return "EWPNANGLE"; + + case EWPNSTEP: + return "EWPNSTEP"; + + case EWPNFRAMES: + return "EWPNFRAMES"; + + case EWPNFRAME: + return "EWPNFRAME"; + + case EWPNDRAWTYPE: + return "EWPNDRAWTYPE"; + + case EWPNPOWER: + return "EWPNPOWER"; + + case EWPNID: + return "EWPNID"; + + case EWPNANGULAR: + return "EWPNANGULAR"; + + case EWPNBEHIND: + return "EWPNBEHIND"; + + case EWPNASPEED: + return "EWPNASPEED"; + + case EWPNTILE: + return "EWPNTILE"; + + case EWPNFLASHCSET: + return "EWPNFLASHCSET"; + + case EWPNDEAD: + return "EWPNDEAD"; + + case EWPNCSET: + return "EWPNCSET"; + + case EWPNFLASH: + return "EWPNFLASH"; + + case EWPNFLIP: + return "EWPNFLIP"; + + case EWPNOTILE: + return "EWPNOTILE"; + + case EWPNOCSET: + return "EWPNOCSET"; + + case EWPNEXTEND: + return "EWPNEXTEND"; + + case EWPNCOLLDET: + return "EWPNCOLLDET"; + + case SCRIPTRAM: + return "SCRIPTRAM"; + + case GLOBALRAM: + return "GLOBALRAM"; + + case SCRIPTRAMD: + return "SCRIPTRAMD"; + + case GLOBALRAMD: + return "GLOBALRAMD"; + + case LWPNHXOFS: + return "LWPNHXOFS"; + + case LWPNHYOFS: + return "LWPNHYOFS"; + + case LWPNXOFS: + return "LWPNXOFS"; + + case LWPNYOFS: + return "LWPNYOFS"; + + case LWPNZOFS: + return "LWPNZOFS"; + + case LWPNHXSZ: + return "LWPNHXSZ"; + + case LWPNHYSZ: + return "LWPNHYSZ"; + + case LWPNHZSZ: + return "LWPNHZSZ"; + + case LWPNTXSZ: + return "LWPNTXSZ"; + + case LWPNTYSZ: + return "LWPNTYSZ"; + + case LWPNMISCD: + return "LWPNMISCD"; + + case EWPNHXOFS: + return "EWPNHXOFS"; + + case EWPNHYOFS: + return "EWPNHYOFS"; + + case EWPNXOFS: + return "EWPNXOFS"; + + case EWPNYOFS: + return "EWPNYOFS"; + + case EWPNZOFS: + return "EWPNZOFS"; + + case EWPNHXSZ: + return "EWPNHXSZ"; + + case EWPNHYSZ: + return "EWPNHYSZ"; + + case EWPNHZSZ: + return "EWPNHZSZ"; + + case EWPNTXSZ: + return "EWPNTXSZ"; + + case EWPNTYSZ: + return "EWPNTYSZ"; + + case EWPNMISCD: + return "EWPNMISCD"; + + case NPCHXOFS: + return "NPCHXOFS"; + + case NPCHYOFS: + return "NPCHYOFS"; + + case NPCXOFS: + return "NPCXOFS"; + + case NPCYOFS: + return "NPCYOFS"; + + case NPCZOFS: + return "NPCZOFS"; + + case NPCHXSZ: + return "NPCHXSZ"; + + case NPCHYSZ: + return "NPCHYSZ"; + + case NPCHZSZ: + return "NPCHZSZ"; + + case NPCTXSZ: + return "NPCTXSZ"; + + case NPCTYSZ: + return "NPCTYSZ"; + + case ITEMHXOFS: + return "ITEMHXOFS"; + + case ITEMHYOFS: + return "ITEMHYOFS"; + + case ITEMXOFS: + return "ITEMXOFS"; + + case ITEMYOFS: + return "ITEMYOFS"; + + case ITEMZOFS: + return "ITEMZOFS"; + + case ITEMHXSZ: + return "ITEMHXSZ"; + + case ITEMHYSZ: + return "ITEMHYSZ"; + + case ITEMHZSZ: + return "ITEMHZSZ"; + + case ITEMTXSZ: + return "ITEMTXSZ"; + + case ITEMTYSZ: + return "ITEMTYSZ"; + + case LINKHXOFS: + return "LINKHXOFS"; + + case LINKHYOFS: + return "LINKHYOFS"; + + case LINKXOFS: + return "LINKXOFS"; + + case LINKYOFS: + return "LINKYOFS"; + + case LINKZOFS: + return "LINKZOFS"; + + case LINKHXSZ: + return "LINKHXSZ"; + + case LINKHYSZ: + return "LINKHYSZ"; + + case LINKHZSZ: + return "LINKHZSZ"; + + case LINKTXSZ: + return "LINKTXSZ"; + + case LINKTYSZ: + return "LINKTYSZ"; + + case LINKDRUNK: + return "LINKDRUNK"; + + case LINKEQUIP: + return "LINKEQUIP"; + + case LINKLADDERX: + return "LINKLADDERX"; + + case LINKLADDERY: + return "LINKLADDERY"; + + case ROOMTYPE: + return "ROOMTYPE"; + + case ROOMDATA: + return "ROOMDATA"; + + case PUSHBLOCKX: + return "PUSHBLOCKX"; + + case PUSHBLOCKY: + return "PUSHBLOCKY"; + + case PUSHBLOCKCOMBO: + return "PUSHBLOCKCOMBO"; + + case PUSHBLOCKCSET: + return "PUSHBLOCKCSET"; + + case UNDERCOMBO: + return "UNDERCOMBO"; + + case UNDERCSET: + return "UNDERCSET"; + + default: + { + sprintf(temp, "d%d", ID); + return string(temp); + } + } +} + +string GlobalArgument::toString() +{ + char temp[40]; + sprintf(temp, "gd%d", ID); + return string(temp); +} + +string LabelArgument::toString() +{ + if(!haslineno) + { + char temp[40]; + sprintf(temp, "l%d", ID); + return string(temp); + } + else + { + char temp[40]; + sprintf(temp, "%d", lineno); + return string(temp); + } +} + +string OSetTrue::toString() +{ + return "SETTRUE " + getArgument()->toString(); +} + +string OSetFalse::toString() +{ + return "SETFALSE " + getArgument()->toString(); +} + +string OSetMore::toString() +{ + return "SETMORE " + getArgument()->toString(); +} + +string OSetLess::toString() +{ + return "SETLESS " + getArgument()->toString(); +} + +string OSetImmediate::toString() +{ + return "SETV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSetRegister::toString() +{ + return "SETR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAddImmediate::toString() +{ + return "ADDV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAddRegister::toString() +{ + return "ADDR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSubImmediate::toString() +{ + return "SUBV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSubRegister::toString() +{ + return "SUBR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OMultImmediate::toString() +{ + return "MULTV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + + +string OMultRegister::toString() +{ + return "MULTR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ODivImmediate::toString() +{ + return "DIVV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ODivRegister::toString() +{ + return "DIVR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OCompareImmediate::toString() +{ + return "COMPAREV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OCompareRegister::toString() +{ + return "COMPARER " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OWaitframe::toString() +{ + return "WAITFRAME"; +} + +string OWaitdraw::toString() +{ + return "WAITDRAW"; +} + +string OGotoImmediate::toString() +{ + return "GOTO " + getArgument()->toString(); +} + +string OGotoTrueImmediate::toString() +{ + return "GOTOTRUE " + getArgument()->toString(); +} + +string OGotoFalseImmediate::toString() +{ + return "GOTOFALSE " + getArgument()->toString(); +} + +string OGotoMoreImmediate::toString() +{ + return "GOTOMORE " + getArgument()->toString(); +} + +string OGotoLessImmediate::toString() +{ + return "GOTOLESS " + getArgument()->toString(); +} + +string OPushRegister::toString() +{ + return "PUSHR " + getArgument()->toString(); +} + +string OPopRegister::toString() +{ + return "POP " + getArgument()->toString(); +} + +string OLoadIndirect::toString() +{ + return "LOADI " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OStoreIndirect::toString() +{ + return "STOREI " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OQuit::toString() +{ + return "QUIT"; +} + +string OGotoRegister::toString() +{ + return "GOTOR " + getArgument()->toString(); +} + +string OAndImmediate::toString() +{ + return "ANDV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAndRegister::toString() +{ + return "ANDR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OOrImmediate::toString() +{ + return "ORV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OOrRegister::toString() +{ + return "ORR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OXorImmediate::toString() +{ + return "XORV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OXorRegister::toString() +{ + return "XORR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSinRegister::toString() +{ + return "SINR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OCosRegister::toString() +{ + return "COSR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OTanRegister::toString() +{ + return "TANR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OATanRegister::toString() +{ + return "ARCTANR " + getArgument()->toString(); +} + +string OArcCosRegister::toString() +{ + return "ARCCOSR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OArcSinRegister::toString() +{ + return "ARCSINR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OMinRegister::toString() +{ + return "MINR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OMaxRegister::toString() +{ + return "MAXR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OPowRegister::toString() +{ + return "POWERR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OInvPowRegister::toString() +{ + return "IPOWERR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OFactorial::toString() +{ + return "FACTORIAL " + getArgument()->toString(); +} + +string OAbsRegister::toString() +{ + return "ABS " + getArgument()->toString(); +} + +string OLog10Register::toString() +{ + return "LOG10 " + getArgument()->toString(); +} + +string OLogERegister::toString() +{ + return "LOGE " + getArgument()->toString(); +} + +string OArraySize::toString() +{ + return "ARRAYSIZE " + getArgument()->toString(); +} + +string OCalcSplineRegister::toString() +{ + return "CALCSPLINER" + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSetColorRegister::toString() +{ + return "SETCOLORR"; +} + +string OSetDepthRegister::toString() +{ + return "SETDEPTHR"; +} + +string OCollisionRectRegister::toString() +{ + return "COLLISIONRECTR" + getArgument()->toString(); +} + +string OCollisionBoxRegister::toString() +{ + return "COLLISIONBOXR" + getArgument()->toString(); +} + +string OLShiftImmediate::toString() +{ + return "LSHIFTV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OLShiftRegister::toString() +{ + return "LSHIFTR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ORShiftImmediate::toString() +{ + return "RSHIFTV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ORShiftRegister::toString() +{ + return "RSHIFTR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OModuloImmediate::toString() +{ + return "MODV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OModuloRegister::toString() +{ + return "MODR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ONot::toString() +{ + return "BITNOT " + getArgument()->toString(); +} + +string OTraceRegister::toString() +{ + return "TRACER " + getArgument()->toString(); +} + +string OTrace2Register::toString() +{ + return "TRACE2R " + getArgument()->toString(); +} + +string OTrace3::toString() +{ + return "TRACE3"; +} + +string OTrace4::toString() +{ + return "TRACE4"; +} + +string OTrace5Register::toString() +{ + return "TRACE5"; +} + +string OTrace6Register::toString() +{ + return "TRACE6 " + getArgument()->toString(); +} + + +string ORandRegister::toString() +{ + return "RNDR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OCheckTrig::toString() +{ + return "CHECKTRIG"; +} + +string OWarp::toString() +{ + return "WARPR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OPitWarp::toString() +{ + return "PITWARPR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSqrtRegister::toString() +{ + return "SQROOTR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OCreateItemRegister::toString() +{ + return "CREATEITEMR " + getArgument()->toString(); +} + +string OCreateNPCRegister::toString() +{ + return "CREATENPCR " + getArgument()->toString(); +} + +string OCreateLWpnRegister::toString() +{ + return "CREATELWEAPONR " + getArgument()->toString(); +} + +string OCreateEWpnRegister::toString() +{ + return "CREATEEWEAPONR " + getArgument()->toString(); +} + +string OLoadItemRegister::toString() +{ + return "LOADITEMR " + getArgument()->toString(); +} + +string OLoadItemDataRegister::toString() +{ + return "LOADITEMDATAR " + getArgument()->toString(); +} + +string OLoadNPCRegister::toString() +{ + return "LOADNPCR " + getArgument()->toString(); +} + +string OLoadLWpnRegister::toString() +{ + return "LOADLWEAPONR " + getArgument()->toString(); +} + +string OLoadEWpnRegister::toString() +{ + return "LOADEWEAPONR " + getArgument()->toString(); +} + +string OPlaySoundRegister::toString() +{ + return "PLAYSOUNDR " + getArgument()->toString(); +} + +string OPlayMIDIRegister::toString() +{ + return "PLAYMIDIR " + getArgument()->toString(); +} + +string OPlayEnhancedMusic::toString() +{ + return "PLAYENHMUSIC " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OGetDMapMusicFilename::toString() +{ + return "GETMUSICFILE " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OGetDMapMusicTrack::toString() +{ + return "GETMUSICTRACK " + getArgument()->toString(); +} + +string OSetDMapEnhancedMusic::toString() +{ + return "SETDMAPENHMUSIC"; +} + +string OGetSaveName::toString() +{ + return "GETSAVENAME " + getArgument()->toString(); +} + +string OSetSaveName::toString() +{ + return "SETSAVENAME " + getArgument()->toString(); +} + +string OGetDMapName::toString() +{ + return "GETDMAPNAME " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OGetDMapTitle::toString() +{ + return "GETDMAPTITLE " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OGetDMapIntro::toString() +{ + return "GETDMAPINTRO " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OGetItemName::toString() +{ + return "ITEMNAME " + getArgument()->toString(); +} + +string OGetNPCName::toString() +{ + return "NPCNAME " + getArgument()->toString(); +} + +string OGetMessage::toString() +{ + return "GETMESSAGE " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OClearSpritesRegister::toString() +{ + return "CLEARSPRITESR " + getArgument()->toString(); +} + +string ORectangleRegister::toString() +{ + return "RECT"; +} + +string OCircleRegister::toString() +{ + return "CIRCLE"; +} + +string OArcRegister::toString() +{ + return "ARC"; +} + +string OEllipseRegister::toString() +{ + return "ELLIPSE"; +} + +string OLineRegister::toString() +{ + return "LINE"; +} + +string OSplineRegister::toString() +{ + return "SPLINE"; +} + +string OPutPixelRegister::toString() +{ + return "PUTPIXEL"; +} + +string ODrawCharRegister::toString() +{ + return "DRAWCHAR"; +} + +string ODrawIntRegister::toString() +{ + return "DRAWINT"; +} + +string ODrawTileRegister::toString() +{ + return "DRAWTILE"; +} + +string ODrawComboRegister::toString() +{ + return "DRAWCOMBO"; +} + +string OFastTileRegister::toString() +{ + return "FASTTILE"; +} + +string OFastComboRegister::toString() +{ + return "FASTCOMBO"; +} + +string ODrawStringRegister::toString() +{ + return "DRAWSTRING"; +} + +string ODrawBitmapRegister::toString() +{ + return "DRAWBITMAP"; +} + +string OSetRenderTargetRegister::toString() +{ + return "SETRENDERTARGET"; +} + +string OSetDepthBufferRegister::toString() +{ + return "SETDEPTHB"; +} + +string OGetDepthBufferRegister::toString() +{ + return "GETDEPTHB"; +} + +string OSetColorBufferRegister::toString() +{ + return "SETCOLORB"; +} + +string OGetColorBufferRegister::toString() +{ + return "GETCOLORB"; +} + +string OQuadRegister::toString() +{ + return "QUAD"; +} + +string OTriangleRegister::toString() +{ + return "TRIANGLE"; +} + + +string OQuad3DRegister::toString() +{ + return "QUAD3D"; +} + +string OTriangle3DRegister::toString() +{ + return "TRIANGLE3D"; +} + +string ODrawLayerRegister::toString() +{ + return "DRAWLAYER"; +} + +string ODrawScreenRegister::toString() +{ + return "DRAWSCREEN"; +} + +string OMessageRegister::toString() +{ + return "MSGSTRR " + getArgument()->toString(); +} + +string OIsSolid::toString() +{ + return "ISSOLID " + getArgument()->toString(); +} + +string OSetSideWarpRegister::toString() +{ + return "SETSIDEWARP"; +} + +string OGetSideWarpDMap::toString() +{ + return "GETSIDEWARPDMAP " + getArgument()->toString(); +} + +string OGetSideWarpScreen::toString() +{ + return "GETSIDEWARPSCR " + getArgument()->toString(); +} + +string OGetSideWarpType::toString() +{ + return "GETSIDEWARPTYPE " + getArgument()->toString(); +} + +string OGetTileWarpDMap::toString() +{ + return "GETTILEWARPDMAP " + getArgument()->toString(); +} + +string OGetTileWarpScreen::toString() +{ + return "GETTILEWARPSCR " + getArgument()->toString(); +} + +string OGetTileWarpType::toString() +{ + return "GETTILEWARPTYPE " + getArgument()->toString(); +} + +string OSetTileWarpRegister::toString() +{ + return "SETTILEWARP"; +} + +string OLayerScreenRegister::toString() +{ + return "LAYERSCREEN " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OLayerMapRegister::toString() +{ + return "LAYERMAP " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OTriggerSecrets::toString() +{ + return "SECRETS"; +} + +string OIsValidItem::toString() +{ + return "ISVALIDITEM " + getArgument()->toString(); +} + +string OIsValidNPC::toString() +{ + return "ISVALIDNPC " + getArgument()->toString(); +} + +string OCopyTileRegister::toString() +{ + return "COPYTILERR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OSwapTileRegister::toString() +{ + return "SWAPTILERR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OClearTileRegister::toString() +{ + return "CLEARTILER " + getArgument()->toString(); +} + +string OIsValidLWpn::toString() +{ + return "ISVALIDLWPN " + getArgument()->toString(); +} + +string OIsValidEWpn::toString() +{ + return "ISVALIDEWPN " + getArgument()->toString(); +} + +string OUseSpriteLWpn::toString() +{ + return "LWPNUSESPRITER " + getArgument()->toString(); +} + +string OUseSpriteEWpn::toString() +{ + return "EWPNUSESPRITER " + getArgument()->toString(); +} + +string OAllocateMemRegister::toString() +{ + return "ALLOCATEMEMR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAllocateMemImmediate::toString() +{ + return "ALLOCATEMEMV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAllocateGlobalMemImmediate::toString() +{ + return "ALLOCATEGMEMV " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OAllocateGlobalMemRegister::toString() +{ + return "ALLOCATEGMEMR " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string ODeallocateMemRegister::toString() +{ + return "DEALLOCATEMEMR " + getArgument()->toString(); +} + +string ODeallocateMemImmediate::toString() +{ + return "DEALLOCATEMEMV " + getArgument()->toString(); +} + +string OSave::toString() +{ + return "SAVE"; +} + +string OGetScreenFlags::toString() +{ + return "GETSCREENFLAGS " + getArgument()->toString(); +} + +string OGetScreenEFlags::toString() +{ + return "GETSCREENEFLAGS " + getArgument()->toString(); +} + +string OEnd::toString() +{ + return "GAMEEND"; +} + +string OComboTile::toString() +{ + return "COMBOTILE " + getFirstArgument()->toString() + "," + getSecondArgument()->toString(); +} + +string OBreakShield::toString() +{ + return "BREAKSHIELD " + getArgument()->toString(); +} + +string OShowSaveScreen::toString() +{ + return "SAVESCREEN " + getArgument()->toString(); +} + +string OShowSaveQuitScreen::toString() +{ + return "SAVEQUITSCREEN"; +} + +string OSelectAWeaponRegister::toString() +{ + return "SELECTAWPNR " + getArgument()->toString(); +} + +string OSelectBWeaponRegister::toString() +{ + return "SELECTBWPNR " + getArgument()->toString(); +} + +string OGetFFCScript::toString() +{ + return "GETFFCSCRIPT " + getArgument()->toString(); +} + +////////////////////////////////////////////////////////////////////////////////////// + +int LinkTable::functionToLabel(int fid) +{ + map::iterator it = funcLabels.find(fid); + + if(it != funcLabels.end()) + return (*it).second; + + int newid = ScriptParser::getUniqueLabelID(); + funcLabels[fid]=newid; + return newid; +} + +int LinkTable::getGlobalID(int vid) +{ + map::iterator it = globalIDs.find(vid); + + if(it == globalIDs.end()) + return -1; + + return it->second; +} + +int LinkTable::addGlobalVar(int vid) +{ + int newid = ScriptParser::getUniqueGlobalID(); + globalIDs[vid]=newid; + return newid; +} diff --git a/src/parser/ByteCode.h b/src/parser/ByteCode.h new file mode 100644 index 0000000000..9b9d48d237 --- /dev/null +++ b/src/parser/ByteCode.h @@ -0,0 +1,2275 @@ +#ifndef BYTECODE_H +#define BYTECODE_H + +//#include "ScriptParser.h" +#include "AST.h" +#include "UtilVisitors.h" +#include "DataStructs.h" +#include "Compiler.h" +#include "../zsyssimple.h" + +#include + +using namespace std; + +/* + I will reserve the registers in the following scheme: + SP - stack pointer + D4 - stack frame pointer + D6 - stack frame offset accumulator + D2 - expression accumulator #1 + D3 - expression accumulator #2 + D0 - array index accumulator + D1 - secondary array index accumulator + D5 - pure SETR sink + */ +#define INDEX 0 +#define INDEX2 1 +#define EXP1 2 +#define EXP2 3 +#define SFRAME 4 +#define NUL 5 +#define SFTEMP 6 +#define WHAT_NO_7 7 // What, no 7? +#define WHAT_NO_8 8 // What, no 8? +#define WHAT_NO_9 9 // What, no 9? +#define SP 10 +#define DATA 11 +#define FCSET 12 +#define DELAY 13 +#define FX 14 +#define FY 15 +#define XD 16 +#define YD 17 +#define XD2 18 +#define YD2 19 +#define LINKX 20 +#define LINKY 21 +#define LINKDIR 22 +#define LINKHP 23 +#define LINKMP 24 +#define LINKMAXHP 25 +#define LINKMAXMP 26 +#define LINKACTION 27 +#define INPUTSTART 28 +#define INPUTUP 29 +#define INPUTDOWN 30 +#define INPUTLEFT 31 +#define INPUTRIGHT 32 +#define INPUTA 33 +#define INPUTB 34 +#define INPUTL 35 +#define INPUTR 36 +#define SDD 37 // 8 of these +#define COMBODD 38 // 176 of these +#define COMBOCD 39 // 176 of these +#define COMBOFD 40 // 176 of these +#define REFFFC 41 +#define REFITEM 42 +#define ITEMCOUNT 43 +#define ITEMX 44 +#define ITEMY 45 +#define ITEMDRAWTYPE 46 +#define ITEMID 47 +#define ITEMTILE 48 +#define ITEMCSET 49 +#define ITEMFLASHCSET 50 +#define ITEMFRAMES 51 +#define ITEMFRAME 52 +#define ITEMASPEED 53 +#define ITEMDELAY 54 +#define ITEMFLASH 55 +#define ITEMFLIP 56 +#define ITEMEXTEND 57 +#define ITEMCLASSFAMILY 58 +#define ITEMCLASSFAMTYPE 59 +#define ITEMCLASSAMOUNT 60 +#define ITEMCLASSMAX 61 +#define ITEMCLASSSETMAX 62 +#define ITEMCLASSSETGAME 63 +#define ITEMCLASSCOUNTER 64 +#define REFITEMCLASS 65 +#define LINKZ 66 +#define LINKJUMP 67 +#define ITEMZ 68 +#define ITEMJUMP 69 +#define NPCZ 70 +#define NPCJUMP 71 +#define WHAT_NO_72 72 // What, no 72? +#define LINKSWORDJINX 73 +#define LINKITEMJINX 74 +#define COMBOID 75 +#define COMBOTD 76 +#define COMBOSD 77 +#define CURSCR 78 +#define CURMAP 79 +#define CURDMAP 80 +#define GAMEDEATHS 81 +#define GAMECHEAT 82 +#define GAMETIME 83 +#define GAMEHASPLAYED 84 +#define GAMETIMEVALID 85 +#define GAMEGUYCOUNT 86 +#define GAMECONTSCR 87 +#define GAMECONTDMAP 88 +#define GAMECOUNTERD 89 +#define GAMEMCOUNTERD 90 +#define GAMEDCOUNTERD 91 +#define GAMEGENERICD 92 +#define GAMEITEMSD 93 +#define GAMELITEMSD 94 +#define GAMELKEYSD 95 +#define SCREENSTATED 96 +#define SCREENSTATEDD 97 +#define SDDD 98 +#define FFFLAGSD 99 +#define FFTWIDTH 100 +#define FFTHEIGHT 101 +#define FFCWIDTH 102 +#define FFCHEIGHT 103 +#define FFLINK 104 +#define LINKITEMD 105 +#define REFNPC 106 +#define NPCCOUNT 107 +#define NPCX 108 +#define NPCY 109 +#define NPCDIR 110 +#define NPCRATE 111 +#define NPCFRAMERATE 112 +#define NPCHALTRATE 113 +#define NPCDRAWTYPE 114 +#define NPCHP 115 +#define NPCDP 116 +#define NPCWDP 117 +#define NPCOTILE 118 +#define NPCWEAPON 119 +#define NPCITEMSET 120 +#define NPCCSET 121 +#define NPCBOSSPAL 122 +#define NPCBGSFX 123 +#define NPCEXTEND 124 +#define SCRDOORD 125 +#define CURDSCR 126 +#define LINKHELD 127 +#define NPCSTEP 128 +#define ITEMOTILE 129 +#define INPUTMOUSEX 130 +#define INPUTMOUSEY 131 +#define QUAKE 132 +#define WAVY 133 +#define NPCID 134 +#define ITEMCLASSUSESOUND 135 +#define INPUTMOUSEZ 136 +#define INPUTMOUSEB 137 +#define REFLWPN 138 +#define LWPNCOUNT 139 +#define LWPNX 140 +#define LWPNY 141 +#define LWPNDIR 142 +#define LWPNSTEP 143 +#define LWPNANGULAR 144 +#define LWPNANGLE 145 +#define LWPNDRAWTYPE 146 +#define LWPNPOWER 147 +#define LWPNDEAD 148 +#define LWPNID 149 +#define LWPNTILE 150 +#define LWPNCSET 151 +#define LWPNFLASHCSET 152 +#define LWPNFRAMES 153 +#define LWPNFRAME 154 +#define LWPNASPEED 155 +#define LWPNFLASH 156 +#define LWPNFLIP 157 +#define LWPNEXTEND 158 +#define LWPNOTILE 159 +#define LWPNOCSET 160 +#define LWPNZ 161 +#define LWPNJUMP 162 +#define REFEWPN 163 +#define EWPNX 164 +#define EWPNY 165 +#define EWPNDIR 166 +#define EWPNSTEP 167 +#define EWPNANGULAR 168 +#define EWPNANGLE 169 +#define EWPNDRAWTYPE 170 +#define EWPNPOWER 171 +#define EWPNDEAD 172 +#define EWPNID 173 +#define EWPNTILE 174 +#define EWPNCSET 175 +#define EWPNFLASHCSET 176 +#define EWPNFRAMES 177 +#define EWPNFRAME 178 +#define EWPNASPEED 179 +#define EWPNFLASH 180 +#define EWPNFLIP 181 +#define EWPNCOUNT 182 +#define EWPNEXTEND 183 +#define EWPNOTILE 184 +#define EWPNOCSET 185 +#define EWPNZ 186 +#define EWPNJUMP 187 +#define COMBODDM 188 // 176 of these +#define COMBOCDM 189 // 176 of these +#define COMBOFDM 190 // 176 of these +#define COMBOIDM 191 // 176 of these +#define COMBOTDM 192 // 176 of these +#define COMBOSDM 193 // 176 of these +#define SCRIPTRAM 194 +#define GLOBALRAM 195 +#define SCRIPTRAMD 196 +#define GLOBALRAMD 197 +#define WHAT_NO_198 198 //What, no 198? +#define LWPNHXOFS 199 +#define LWPNHYOFS 200 +#define LWPNXOFS 201 +#define LWPNYOFS 202 +#define LWPNZOFS 203 +#define LWPNHXSZ 204 +#define LWPNHYSZ 205 +#define LWPNHZSZ 206 +#define EWPNHXOFS 207 +#define EWPNHYOFS 208 +#define EWPNXOFS 209 +#define EWPNYOFS 210 +#define EWPNZOFS 211 +#define EWPNHXSZ 212 +#define EWPNHYSZ 213 +#define EWPNHZSZ 214 +#define NPCHXOFS 215 +#define NPCHYOFS 216 +#define NPCXOFS 217 +#define NPCYOFS 218 +#define NPCZOFS 219 +#define NPCHXSZ 220 +#define NPCHYSZ 221 +#define NPCHZSZ 222 +#define ITEMHXOFS 223 +#define ITEMHYOFS 224 +#define ITEMXOFS 225 +#define ITEMYOFS 226 +#define ITEMZOFS 227 +#define ITEMHXSZ 228 +#define ITEMHYSZ 229 +#define ITEMHZSZ 230 +#define LWPNTXSZ 231 +#define LWPNTYSZ 232 +#define EWPNTXSZ 233 +#define EWPNTYSZ 234 +#define NPCTXSZ 235 +#define NPCTYSZ 236 +#define ITEMTXSZ 237 +#define ITEMTYSZ 238 +#define LINKHXOFS 239 +#define LINKHYOFS 240 +#define LINKXOFS 241 +#define LINKYOFS 242 +#define LINKZOFS 243 +#define LINKHXSZ 244 +#define LINKHYSZ 245 +#define LINKHZSZ 246 +#define LINKTXSZ 247 +#define LINKTYSZ 248 +#define LINKDRUNK 249 +#define NPCTILE 250 +#define LWPNBEHIND 251 +#define EWPNBEHIND 252 +#define SDDDD 253 +#define CURLEVEL 254 +#define ITEMPICKUP 255 +#define INPUTMAP 256 +#define LIT 257 +#define INPUTEX1 258 +#define INPUTEX2 259 +#define INPUTEX3 260 +#define INPUTEX4 261 +#define INPUTPRESSSTART 262 +#define INPUTPRESSUP 263 +#define INPUTPRESSDOWN 264 +#define INPUTPRESSLEFT 265 +#define INPUTPRESSRIGHT 266 +#define INPUTPRESSA 267 +#define INPUTPRESSB 268 +#define INPUTPRESSL 269 +#define INPUTPRESSR 270 +#define INPUTPRESSEX1 271 +#define INPUTPRESSEX2 272 +#define INPUTPRESSEX3 273 +#define INPUTPRESSEX4 274 +#define LWPNMISCD 275 //16 of these +#define EWPNMISCD 276 //16 of these +#define NPCMISCD 277 //16 of these +#define ITEMMISCD 278 //16 of these +#define FFMISCD 279 //16 of these +#define GETMIDI 280 +#define NPCHOMING 281 +#define NPCDD 282 //10 of these +#define LINKEQUIP 283 + +#define INPUTAXISUP 284 +#define INPUTAXISDOWN 285 +#define INPUTAXISLEFT 286 +#define INPUTAXISRIGHT 287 +#define INPUTPRESSAXISUP 288 +#define INPUTPRESSAXISDOWN 289 +#define INPUTPRESSAXISLEFT 290 +#define INPUTPRESSAXISRIGHT 291 + +#define NPCTYPE 292 +#define FFSCRIPT 293 +#define SCREENFLAGSD 294 //10 of these +#define LINKINVIS 295 +#define LINKINVINC 296 +#define SCREENEFLAGSD 297 //3 of these +#define NPCMFLAGS 298 +#define FFINITDD 299 //8 of these +#define LINKMISCD 300 //16 of these +#define DMAPFLAGSD 301 //2 of these +#define LWPNCOLLDET 302 +#define EWPNCOLLDET 303 +#define NPCCOLLDET 304 +#define LINKLADDERX 305 +#define LINKLADDERY 306 +#define NPCSTUN 307 +#define NPCDEFENSED 308 +#define ITEMCLASSPOWER 309 +#define DMAPLEVELD 310 //512 of these +#define DMAPCOMPASSD 311 //512 of these +#define DMAPCONTINUED 312 //512 of these +#define DMAPMIDID 313 //512 of these +#define ITEMCLASSINITDD 314 //8 of these +#define LINKHITDIR 315 +#define ROOMTYPE 316 +#define ROOMDATA 317 +#define LINKTILE 318 +#define LINKFLIP 319 +#define INPUTPRESSMAP 320 +#define NPCHUNGER 321 +#define GAMESTANDALONE 322 +#define GAMEENTRSCR 323 +#define GAMEENTRDMAP 324 +#define GAMECLICKFREEZE 325 +#define PUSHBLOCKX 326 +#define PUSHBLOCKY 327 +#define PUSHBLOCKCOMBO 328 +#define PUSHBLOCKCSET 329 +#define UNDERCOMBO 330 +#define UNDERCSET 331 +#define DMAPOFFSET 332 //512 of these +#define DMAPMAP 333 //512 of these +//#define FFDD 309 //8 of these + +class LiteralArgument; +class VarArgument; +class LabelArgument; +class GlobalArgument; + +class ArgumentVisitor +{ +public: + virtual void caseLiteral(LiteralArgument &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual void caseVar(VarArgument &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual void caseLabel(LabelArgument &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual void caseGlobal(GlobalArgument &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual ~ArgumentVisitor() {} +}; + +class Argument +{ +public: + virtual string toString()=0; + virtual void execute(ArgumentVisitor &host, void *param)=0; + virtual Argument *clone()=0; + virtual ~Argument() {} +}; + +class LiteralArgument : public Argument +{ +public: + LiteralArgument(long Value) : value(Value) {} + string toString(); + void execute(ArgumentVisitor &host, void *param) + { + host.caseLiteral(*this, param); + } + Argument *clone() + { + return new LiteralArgument(value); + } +private: + long value; +}; + +class VarArgument : public Argument +{ +public: + VarArgument(int id) : ID(id) {} + string toString(); + void execute(ArgumentVisitor &host, void *param) + { + host.caseVar(*this,param); + } + Argument *clone() + { + return new VarArgument(ID); + } +private: + int ID; +}; + +class GlobalArgument : public Argument +{ +public: + GlobalArgument(int id) : ID(id) {} + string toString(); + void execute(ArgumentVisitor &host, void *param) + { + host.caseGlobal(*this,param); + } + Argument *clone() + { + return new GlobalArgument(ID); + } +private: + int ID; +}; + +class LabelArgument : public Argument +{ +public: + LabelArgument(int id) : ID(id), haslineno(false) {} + string toString(); + void execute(ArgumentVisitor &host, void *param) + { + host.caseLabel(*this,param); + } + Argument *clone() + { + return new LabelArgument(ID); + } + int getID() + { + return ID; + } + void setLineNo(int l) + { + haslineno=true; + lineno=l; + } +private: + int ID; + int lineno; + bool haslineno; +}; + +class UnaryOpcode : public Opcode +{ +public: + UnaryOpcode(Argument *A) : a(A) {} + ~UnaryOpcode() + { + delete a; + } + Argument *getArgument() + { + return a; + } + void execute(ArgumentVisitor &host, void *param) + { + a->execute(host, param); + } +protected: + Argument *a; +}; + +class BinaryOpcode : public Opcode +{ +public: + BinaryOpcode(Argument *A, Argument *B) : a(A), b(B) {} + ~BinaryOpcode() + { + delete a; + delete b; + } + Argument *getFirstArgument() + { + return a; + } + Argument *getSecondArgument() + { + return b; + } + void execute(ArgumentVisitor &host, void *param) + { + a->execute(host, param); + b->execute(host, param); + } +protected: + Argument *a; + Argument *b; +}; + +class OSetTrue : public UnaryOpcode +{ +public: + OSetTrue(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSetTrue(a->clone()); + } +}; + +class OSetFalse : public UnaryOpcode +{ +public: + OSetFalse(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSetFalse(a->clone()); + } +}; + +class OSetMore : public UnaryOpcode +{ +public: + OSetMore(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSetMore(a->clone()); + } +}; + +class OSetLess : public UnaryOpcode +{ +public: + OSetLess(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSetLess(a->clone()); + } +}; + +class OSetImmediate : public BinaryOpcode +{ +public: + OSetImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSetImmediate(a->clone(),b->clone()); + } +}; + +class OSetRegister : public BinaryOpcode +{ +public: + OSetRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSetRegister(a->clone(),b->clone()); + } +}; + +class OAddImmediate : public BinaryOpcode +{ +public: + OAddImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAddImmediate(a->clone(),b->clone()); + } +}; + +class OAddRegister : public BinaryOpcode +{ +public: + OAddRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAddRegister(a->clone(),b->clone()); + } +}; + +class OSubImmediate : public BinaryOpcode +{ +public: + OSubImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSubImmediate(a->clone(),b->clone()); + } +}; + +class OSubRegister : public BinaryOpcode +{ +public: + OSubRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSubRegister(a->clone(),b->clone()); + } +}; + +class OMultImmediate : public BinaryOpcode +{ +public: + OMultImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OMultImmediate(a->clone(),b->clone()); + } +}; + +class OMultRegister : public BinaryOpcode +{ +public: + OMultRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OMultRegister(a->clone(),b->clone()); + } +}; + +class ODivImmediate : public BinaryOpcode +{ +public: + ODivImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new ODivImmediate(a->clone(),b->clone()); + } +}; + +class ODivRegister : public BinaryOpcode +{ +public: + ODivRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new ODivRegister(a->clone(),b->clone()); + } +}; + +class OCompareImmediate : public BinaryOpcode +{ +public: + OCompareImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OCompareImmediate(a->clone(),b->clone()); + } +}; + +class OCompareRegister : public BinaryOpcode +{ +public: + OCompareRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OCompareRegister(a->clone(),b->clone()); + } +}; + +class OWaitframe : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OWaitframe(); + } +}; + +class OWaitdraw : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OWaitdraw(); + } +}; + +class OGotoImmediate : public UnaryOpcode +{ +public: + OGotoImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoImmediate(a->clone()); + } +}; + +class OGotoTrueImmediate: public UnaryOpcode +{ +public: + OGotoTrueImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoTrueImmediate(a->clone()); + } +}; + +class OGotoFalseImmediate: public UnaryOpcode +{ +public: + OGotoFalseImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoFalseImmediate(a->clone()); + } +}; + +class OGotoMoreImmediate : public UnaryOpcode +{ +public: + OGotoMoreImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoMoreImmediate(a->clone()); + } +}; + +class OGotoLessImmediate : public UnaryOpcode +{ +public: + OGotoLessImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoLessImmediate(a->clone()); + } +}; + +class OPushRegister : public UnaryOpcode +{ +public: + OPushRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OPushRegister(a->clone()); + } +}; + +class OPopRegister : public UnaryOpcode +{ +public: + OPopRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OPopRegister(a->clone()); + } +}; + +class OLoadIndirect : public BinaryOpcode +{ +public: + OLoadIndirect(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OLoadIndirect(a->clone(),b->clone()); + } +}; + +class OStoreIndirect : public BinaryOpcode +{ +public: + OStoreIndirect(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OStoreIndirect(a->clone(),b->clone()); + } +}; + +class OQuit : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OQuit(); + } +}; + +class OGotoRegister : public UnaryOpcode +{ +public: + OGotoRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGotoRegister(a->clone()); + } +}; + +class OTraceRegister : public UnaryOpcode +{ +public: + OTraceRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OTraceRegister(a->clone()); + } +}; + +class OTrace2Register : public UnaryOpcode +{ +public: + OTrace2Register(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OTrace2Register(a->clone()); + } +}; + +class OTrace3 : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTrace3(); + } +}; + +class OTrace4 : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTrace4(); + } +}; + +class OTrace5Register : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTrace5Register(); + } +}; + +class OTrace6Register : public UnaryOpcode +{ +public: + OTrace6Register(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OTrace6Register(a->clone()); + } +}; + +class OAndImmediate : public BinaryOpcode +{ +public: + OAndImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAndImmediate(a->clone(),b->clone()); + } +}; + +class OAndRegister : public BinaryOpcode +{ +public: + OAndRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAndRegister(a->clone(),b->clone()); + } +}; + +class OOrImmediate : public BinaryOpcode +{ +public: + OOrImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OOrImmediate(a->clone(),b->clone()); + } +}; + +class OOrRegister : public BinaryOpcode +{ +public: + OOrRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OOrRegister(a->clone(),b->clone()); + } +}; + +class OXorImmediate : public BinaryOpcode +{ +public: + OXorImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OXorImmediate(a->clone(), b->clone()); + } +}; + +class OXorRegister : public BinaryOpcode +{ +public: + OXorRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OXorRegister(a->clone(), b->clone()); + } +}; + +class ONot : public UnaryOpcode +{ +public: + ONot(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new ONot(a->clone()); + } +}; + +class OLShiftImmediate : public BinaryOpcode +{ +public: + OLShiftImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OLShiftImmediate(a->clone(), b->clone()); + } +}; + +class OLShiftRegister : public BinaryOpcode +{ +public: + OLShiftRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OLShiftRegister(a->clone(), b->clone()); + } +}; + +class ORShiftImmediate : public BinaryOpcode +{ +public: + ORShiftImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new ORShiftImmediate(a->clone(), b->clone()); + } +}; + +class ORShiftRegister : public BinaryOpcode +{ +public: + ORShiftRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new ORShiftRegister(a->clone(), b->clone()); + } +}; + +class OModuloImmediate : public BinaryOpcode +{ +public: + OModuloImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OModuloImmediate(a->clone(), b->clone()); + } +}; + +class OModuloRegister : public BinaryOpcode +{ +public: + OModuloRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OModuloRegister(a->clone(), b->clone()); + } +}; + +class OSinRegister : public BinaryOpcode +{ +public: + OSinRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSinRegister(a->clone(), b->clone()); + } +}; + +class OArcSinRegister : public BinaryOpcode +{ +public: + OArcSinRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OArcSinRegister(a->clone(), b->clone()); + } +}; + +class OCosRegister : public BinaryOpcode +{ +public: + OCosRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OCosRegister(a->clone(), b->clone()); + } +}; + +class OArcCosRegister : public BinaryOpcode +{ +public: + OArcCosRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OArcCosRegister(a->clone(), b->clone()); + } +}; + +class OTanRegister : public BinaryOpcode +{ +public: + OTanRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OTanRegister(a->clone(), b->clone()); + } +}; + +class OATanRegister : public UnaryOpcode +{ +public: + OATanRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OATanRegister(a->clone()); + } +}; + +class OMaxRegister : public BinaryOpcode +{ +public: + OMaxRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OMaxRegister(a->clone(), b->clone()); + } +}; + +class OMinRegister : public BinaryOpcode +{ +public: + OMinRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OMinRegister(a->clone(), b->clone()); + } +}; + +class OPowRegister : public BinaryOpcode +{ +public: + OPowRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OPowRegister(a->clone(), b->clone()); + } +}; + +class OInvPowRegister : public BinaryOpcode +{ +public: + OInvPowRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OInvPowRegister(a->clone(), b->clone()); + } +}; + +class OFactorial : public UnaryOpcode +{ +public: + OFactorial(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OFactorial(a->clone()); + } +}; + +class OAbsRegister : public UnaryOpcode +{ +public: + OAbsRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OAbsRegister(a->clone()); + } +}; + +class OLog10Register : public UnaryOpcode +{ +public: + OLog10Register(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLog10Register(a->clone()); + } +}; + +class OLogERegister : public UnaryOpcode +{ +public: + OLogERegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLogERegister(a->clone()); + } +}; + +class OArraySize : public UnaryOpcode +{ +public: + OArraySize(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OArraySize(a->clone()); + } +}; + +class OCheckTrig : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OCheckTrig(); + } +}; + +class ORandRegister : public BinaryOpcode +{ +public: + ORandRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new ORandRegister(a->clone(), b->clone()); + } +}; + +class OSqrtRegister : public BinaryOpcode +{ +public: + OSqrtRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSqrtRegister(a->clone(),b->clone()); + } +}; + +class OCalcSplineRegister : public BinaryOpcode +{ +public: + OCalcSplineRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OCalcSplineRegister(a->clone(),b->clone()); + } +}; + +class OSetColorRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetColorRegister(); + } +}; + +class OSetDepthRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetDepthRegister(); + } +}; + +class OCollisionRectRegister : public UnaryOpcode +{ +public: + OCollisionRectRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCollisionRectRegister(a->clone()); + } +}; + +class OCollisionBoxRegister : public UnaryOpcode +{ +public: + OCollisionBoxRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCollisionBoxRegister(a->clone()); + } +}; + +class OWarp : public BinaryOpcode +{ +public: + OWarp(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OWarp(a->clone(), b->clone()); + } +}; + +class OPitWarp : public BinaryOpcode +{ +public: + OPitWarp(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OPitWarp(a->clone(), b->clone()); + } +}; + +class OCreateItemRegister : public UnaryOpcode +{ +public: + OCreateItemRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCreateItemRegister(a->clone()); + } +}; + +class OCreateNPCRegister : public UnaryOpcode +{ +public: + OCreateNPCRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCreateNPCRegister(a->clone()); + } +}; + +class OCreateLWpnRegister : public UnaryOpcode +{ +public: + OCreateLWpnRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCreateLWpnRegister(a->clone()); + } +}; + +class OCreateEWpnRegister : public UnaryOpcode +{ +public: + OCreateEWpnRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OCreateEWpnRegister(a->clone()); + } +}; + +class OLoadItemRegister : public UnaryOpcode +{ +public: + OLoadItemRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLoadItemRegister(a->clone()); + } +}; + +class OLoadItemDataRegister : public UnaryOpcode +{ +public: + OLoadItemDataRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLoadItemDataRegister(a->clone()); + } +}; + +class OLoadNPCRegister : public UnaryOpcode +{ +public: + OLoadNPCRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLoadNPCRegister(a->clone()); + } +}; + +class OLoadLWpnRegister : public UnaryOpcode +{ +public: + OLoadLWpnRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLoadLWpnRegister(a->clone()); + } +}; + +class OLoadEWpnRegister : public UnaryOpcode +{ +public: + OLoadEWpnRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OLoadEWpnRegister(a->clone()); + } +}; + +class OPlaySoundRegister : public UnaryOpcode +{ +public: + OPlaySoundRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OPlaySoundRegister(a->clone()); + } +}; + +class OPlayMIDIRegister : public UnaryOpcode +{ +public: + OPlayMIDIRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OPlayMIDIRegister(a->clone()); + } +}; + +class OPlayEnhancedMusic : public BinaryOpcode +{ +public: + OPlayEnhancedMusic(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OPlayEnhancedMusic(a->clone(), b->clone()); + } +}; + +class OGetDMapMusicFilename : public BinaryOpcode +{ +public: + OGetDMapMusicFilename(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OGetDMapMusicFilename(a->clone(), b->clone()); + } +}; + +class OGetDMapMusicTrack : public UnaryOpcode +{ +public: + OGetDMapMusicTrack(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetDMapMusicTrack(a->clone()); + } +}; + +class OSetDMapEnhancedMusic : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetDMapEnhancedMusic(); + } +}; + +class OGetSaveName : public UnaryOpcode +{ +public: + OGetSaveName(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetSaveName(a->clone()); + } +}; + +class OGetDMapName : public BinaryOpcode +{ +public: + OGetDMapName(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OGetDMapName(a->clone(), b->clone()); + } +}; + +class OGetDMapIntro : public BinaryOpcode +{ +public: + OGetDMapIntro(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OGetDMapIntro(a->clone(), b->clone()); + } +}; + +class OGetDMapTitle : public BinaryOpcode +{ +public: + OGetDMapTitle(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OGetDMapTitle(a->clone(), b->clone()); + } +}; + +class OSetSaveName : public UnaryOpcode +{ +public: + OSetSaveName(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSetSaveName(a->clone()); + } +}; + +class OGetItemName : public UnaryOpcode +{ +public: + OGetItemName(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetItemName(a->clone()); + } +}; + +class OGetNPCName : public UnaryOpcode +{ +public: + OGetNPCName(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetNPCName(a->clone()); + } +}; + +class OGetMessage : public BinaryOpcode +{ +public: + OGetMessage(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OGetMessage(a->clone(), b->clone()); + } +}; + +class OClearSpritesRegister : public UnaryOpcode +{ +public: + OClearSpritesRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OClearSpritesRegister(a->clone()); + } +}; + +class OMessageRegister : public UnaryOpcode +{ +public: + OMessageRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OMessageRegister(a->clone()); + } +}; + +class OIsSolid : public UnaryOpcode +{ +public: + OIsSolid(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OIsSolid(a->clone()); + } +}; + +class OSetSideWarpRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetSideWarpRegister(); + } +}; + +class OSetTileWarpRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetTileWarpRegister(); + } +}; + +class OGetSideWarpDMap : public UnaryOpcode +{ +public: + OGetSideWarpDMap(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetSideWarpDMap(a->clone()); + } +}; + +class OGetSideWarpScreen : public UnaryOpcode +{ +public: + OGetSideWarpScreen(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetSideWarpScreen(a->clone()); + } +}; + +class OGetSideWarpType : public UnaryOpcode +{ +public: + OGetSideWarpType(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetSideWarpType(a->clone()); + } +}; + +class OGetTileWarpDMap : public UnaryOpcode +{ +public: + OGetTileWarpDMap(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetTileWarpDMap(a->clone()); + } +}; + +class OGetTileWarpScreen : public UnaryOpcode +{ +public: + OGetTileWarpScreen(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetTileWarpScreen(a->clone()); + } +}; + +class OGetTileWarpType : public UnaryOpcode +{ +public: + OGetTileWarpType(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetTileWarpType(a->clone()); + } +}; + +class OLayerScreenRegister : public BinaryOpcode +{ +public: + OLayerScreenRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OLayerScreenRegister(a->clone(), b->clone()); + } +}; + +class OLayerMapRegister : public BinaryOpcode +{ +public: + OLayerMapRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OLayerMapRegister(a->clone(), b->clone()); + } +}; + +class OTriggerSecrets : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTriggerSecrets(); + } +}; + +class OIsValidItem : public UnaryOpcode +{ +public: + OIsValidItem(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OIsValidItem(a->clone()); + } +}; + +class OIsValidNPC : public UnaryOpcode +{ +public: + OIsValidNPC(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OIsValidNPC(a->clone()); + } +}; + +class OIsValidLWpn : public UnaryOpcode +{ +public: + OIsValidLWpn(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OIsValidLWpn(a->clone()); + } +}; + +class OIsValidEWpn : public UnaryOpcode +{ +public: + OIsValidEWpn(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OIsValidEWpn(a->clone()); + } +}; + +class OUseSpriteLWpn : public UnaryOpcode +{ +public: + OUseSpriteLWpn(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OUseSpriteLWpn(a->clone()); + } +}; + +class OUseSpriteEWpn : public UnaryOpcode +{ +public: + OUseSpriteEWpn(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OUseSpriteEWpn(a->clone()); + } +}; + +class ORectangleRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ORectangleRegister(); + } +}; + +class OCircleRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OCircleRegister(); + } +}; + +class OArcRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OArcRegister(); + } +}; + +class OEllipseRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OEllipseRegister(); + } +}; + +class OLineRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OLineRegister(); + } +}; + +class OSplineRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSplineRegister(); + } +}; + +class OPutPixelRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OPutPixelRegister(); + } +}; + +class ODrawCharRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawCharRegister(); + } +}; + +class ODrawIntRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawIntRegister(); + } +}; + +class ODrawTileRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawTileRegister(); + } +}; + +class ODrawComboRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawComboRegister(); + } +}; + +class OQuadRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OQuadRegister(); + } +}; + +class OTriangleRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTriangleRegister(); + } +}; + +class OQuad3DRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OQuad3DRegister(); + } +}; + +class OTriangle3DRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OTriangle3DRegister(); + } +}; + +class OFastTileRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OFastTileRegister(); + } +}; + +class OFastComboRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OFastComboRegister(); + } +}; + +class ODrawStringRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawStringRegister(); + } +}; + +class ODrawLayerRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawLayerRegister(); + } +}; + +class ODrawScreenRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawScreenRegister(); + } +}; + +class ODrawBitmapRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new ODrawBitmapRegister(); + } +}; + +class OSetRenderTargetRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetRenderTargetRegister(); + } +}; + +class OSetDepthBufferRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetDepthBufferRegister(); + } +}; + +class OGetDepthBufferRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OGetDepthBufferRegister(); + } +}; + +class OSetColorBufferRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSetColorBufferRegister(); + } +}; + +class OGetColorBufferRegister : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OGetColorBufferRegister(); + } +}; + +class OCopyTileRegister : public BinaryOpcode +{ +public: + OCopyTileRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OCopyTileRegister(a->clone(),b->clone()); + } +}; + +class OSwapTileRegister : public BinaryOpcode +{ +public: + OSwapTileRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OSwapTileRegister(a->clone(),b->clone()); + } +}; + +class OClearTileRegister : public UnaryOpcode +{ +public: + OClearTileRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OClearTileRegister(a->clone()); + } +}; + +class OAllocateMemRegister : public BinaryOpcode +{ +public: + OAllocateMemRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAllocateMemRegister(a->clone(),b->clone()); + } +}; + +class OAllocateMemImmediate : public BinaryOpcode +{ +public: + OAllocateMemImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAllocateMemImmediate(a->clone(),b->clone()); + } +}; + +class OAllocateGlobalMemImmediate : public BinaryOpcode +{ +public: + OAllocateGlobalMemImmediate(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAllocateGlobalMemImmediate(a->clone(),b->clone()); + } +}; + +class OAllocateGlobalMemRegister : public BinaryOpcode +{ +public: + OAllocateGlobalMemRegister(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OAllocateGlobalMemRegister(a->clone(),b->clone()); + } +}; + +class ODeallocateMemRegister : public UnaryOpcode +{ +public: + ODeallocateMemRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new ODeallocateMemRegister(a->clone()); + } +}; + +class ODeallocateMemImmediate : public UnaryOpcode +{ +public: + ODeallocateMemImmediate(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new ODeallocateMemImmediate(a->clone()); + } +}; + +class OSave : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OSave(); + } +}; + +class OGetScreenFlags : public UnaryOpcode +{ +public: + OGetScreenFlags(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetScreenFlags(a->clone()); + } +}; + +class OGetScreenEFlags : public UnaryOpcode +{ +public: + OGetScreenEFlags(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetScreenEFlags(a->clone()); + } +}; + +class OEnd : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OEnd(); + } +}; + +class OComboTile : public BinaryOpcode +{ +public: + OComboTile(Argument *A, Argument *B) : BinaryOpcode(A,B) {} + string toString(); + Opcode *clone() + { + return new OComboTile(a->clone(), b->clone()); + } +}; + +class OBreakShield : public UnaryOpcode +{ +public: + OBreakShield(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OBreakShield(a->clone()); + } +}; + +class OShowSaveScreen : public UnaryOpcode +{ +public: + OShowSaveScreen(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OShowSaveScreen(a->clone()); + } +}; + +class OShowSaveQuitScreen : public Opcode +{ +public: + string toString(); + Opcode *clone() + { + return new OShowSaveQuitScreen(); + } +}; + +class OSelectAWeaponRegister : public UnaryOpcode +{ +public: + OSelectAWeaponRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSelectAWeaponRegister(a->clone()); + } +}; + +class OSelectBWeaponRegister : public UnaryOpcode +{ +public: + OSelectBWeaponRegister(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OSelectBWeaponRegister(a->clone()); + } +}; + +class OGetFFCScript : public UnaryOpcode +{ +public: + OGetFFCScript(Argument *A) : UnaryOpcode(A) {} + string toString(); + Opcode *clone() + { + return new OGetFFCScript(a->clone()); + } +}; + +#endif + diff --git a/src/parser/Compiler.h b/src/parser/Compiler.h new file mode 100644 index 0000000000..67a9554a16 --- /dev/null +++ b/src/parser/Compiler.h @@ -0,0 +1,176 @@ +#ifndef COMPILER_H +#define COMPILER_H + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include +#include +#include +#include + + +class ArgumentVisitor; + +class Opcode +{ +public: + Opcode() : label(-1) {} + virtual ~Opcode() {} + virtual std::string toString()=0; + int getLabel() + { + return label; + } + void setLabel(int l) + { + label=l; + } + std::string printLine(bool showlabel = false) + { + char buf[100]; + + if(label == -1) + return " " + toString() + "\n"; + + sprintf(buf, "l%d:", label); + return (showlabel ? std::string(buf) : " ")+ toString() + "\n"; + } + Opcode * makeClone() + { + Opcode *dup = clone(); + dup->setLabel(label); + return dup; + } + virtual void execute(ArgumentVisitor &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } +protected: + virtual Opcode *clone()=0; +private: + int label; +}; + +struct ScriptsData +{ + std::map > theScripts; + std::map scriptTypes; +}; + +ScriptsData *compile(const char *filename); + + +struct SymbolData; +struct FunctionData; +struct IntermediateData; + +class AST; + +class ScriptParser +{ +public: + static int getUniqueVarID() + { + return vid++; + } + static int getUniqueFuncID() + { + return fid++; + } + static int getUniqueLabelID() + { + return lid++; + } + static int getUniqueGlobalID() + { + return gid++; + } + static const int TYPE_FLOAT = 0; + static const int TYPE_BOOL = 1; + static const int TYPE_VOID = 2; + static const int TYPE_FFC = 3; + static const int TYPE_LINK = 4; + static const int TYPE_SCREEN = 5; + static const int TYPE_GLOBAL = 6; + static const int TYPE_ITEM = 7; + static const int TYPE_ITEMCLASS = 8; + static const int TYPE_GAME = 9; + static const int TYPE_NPC = 10; + static const int TYPE_LWPN = 11; + static const int TYPE_EWPN = 12; + static bool preprocess(AST *theAST, int reclevel, std::map *constants); + static SymbolData *buildSymbolTable(AST *theAST, std::map *constants); + static FunctionData *typeCheck(SymbolData *sdata); + static IntermediateData *generateOCode(FunctionData *fdata); + static ScriptsData *assemble(IntermediateData *id); + static void resetState() + { + vid=0; + fid=0; + gid=1; + lid=0; + } + static std::pair parseLong(std::pair parts); + static std::string printType(int type) + { + switch(type) + { + case TYPE_FLOAT: + return "float"; + + case TYPE_BOOL: + return "bool"; + + case TYPE_VOID: + return "void"; + + case TYPE_FFC: + return "ffc"; + + case TYPE_LINK: + return "link"; + + case TYPE_SCREEN: + return "screen"; + + case TYPE_GLOBAL: + return "global"; + + case TYPE_ITEM: + return "item"; + + case TYPE_ITEMCLASS: + return "itemdata"; + + case TYPE_GAME: + return "game"; + + case TYPE_NPC: + return "npc"; + + case TYPE_LWPN: + return "lweapon"; + + case TYPE_EWPN: + return "eweapon"; + + default: + return "wtf"; + } + } +private: + static std::string trimQuotes(std::string quoteds); + static std::vector assembleOne(std::vector script, std::map > &otherfuncs, int numparams); + static int vid; + static int fid; + static int gid; + static int lid; +}; + + +#endif + diff --git a/src/parser/DataStructs.cpp b/src/parser/DataStructs.cpp new file mode 100644 index 0000000000..6b8552ae1e --- /dev/null +++ b/src/parser/DataStructs.cpp @@ -0,0 +1,242 @@ + +#include "../precompiled.h" //always first + +#include "DataStructs.h" +#include "../zsyssimple.h" +#include +#include + +int StackFrame::getOffset(int vid) +{ + map::iterator it = stackoffset.find(vid); + + if(it == stackoffset.end()) + { + box_out("Internal Error: Can't find stack offset for variable!"); + box_eol(); + return 0; + } + + return stackoffset[vid]; +} + +int SymbolTable::getVarType(AST *obj) +{ + map::iterator it = astToID.find(obj); + + if(it == astToID.end()) + { + box_out("Internal Error: Can't find the AST ID!"); + box_eol(); + return -1; + } + + return getVarType(it->second); +} + +int SymbolTable::getVarType(int varID) +{ + map::iterator it = varTypes.find(varID); + + if(it == varTypes.end()) + { + box_out("Internal Error: Can't find the variable type!"); + box_eol(); + return -1; + } + + return it->second; +} + +bool SymbolTable::isConstant(string name) +{ + return constants->find(name) != constants->end(); +} + +long SymbolTable::getConstantVal(string name) +{ + return (*constants)[name]; +} + +int VariableSymbols::addVariable(string name, int type) +{ + + map >::iterator it = symbols.find(name); + + if(it != symbols.end()) + return -1; + + int id = ScriptParser::getUniqueVarID(); + symbols[name] = pair(type, id); + return id; +} + +bool VariableSymbols::containsVariable(string name) +{ + return (symbols.find(name) != symbols.end()); +} + +int VariableSymbols::getID(string name) +{ + map >::iterator it = symbols.find(name); + assert(it != symbols.end()); + return it->second.second; +} + +int FunctionSymbols::addFunction(string name, int rettype, vector paramtype) +{ + map >, pair >::iterator it = symbols.find(pair >(name, paramtype)); + + if(it != symbols.end()) + return -1; + + int id = ScriptParser::getUniqueFuncID(); + symbols[pair >(name, paramtype)] = pair(rettype, id); + map >::iterator it2 = ambiguous.find(name); + + if(it2 == ambiguous.end()) + { + vector newv; + newv.push_back(id); + ambiguous[name] = newv; + } + else + { + (*it2).second.push_back(id); + } + + return id; +} + +bool FunctionSymbols::containsFunction(string name, vector ¶ms) +{ + return symbols.find(pair >(name,params)) != symbols.end(); +} + +int FunctionSymbols::getID(string name, vector ¶ms) +{ + map >, pair >::iterator it = symbols.find(pair >(name, params)); + assert(it != symbols.end()); + return it->second.second; +} + +vector FunctionSymbols::getFuncIDs(string name) +{ + map >::iterator it = ambiguous.find(name); + + if(it == ambiguous.end()) + return vector(); + + return it->second; +} + +bool Scope::addNamedChild(string name, Scope *child) +{ + map::iterator it = namedChildren.find(name); + + if(it != namedChildren.end()) + return false; + + namedChildren[name]=child; + return true; +} + +Scope::~Scope() +{ + map::iterator it; + + for(it = namedChildren.begin(); it != namedChildren.end(); it++) + { + delete it->second; + } + + namedChildren.clear(); +} + +int Scope::getVarInScope(string nspace, string name) +{ + if(nspace == "" && getVarSymbols().containsVariable(name)) + return getVarSymbols().getID(name); + + map::iterator it = namedChildren.find(nspace); + + if(it != namedChildren.end()) + { + int id = (*it).second->getVarInScope("", name); + + if(id != -1) + return id; + } + + if(parent == NULL) + return -1; + + return parent->getVarInScope(nspace, name); +} + +vector Scope::getFuncsInScope(string nspace, string name) +{ + vector rval; + + if(nspace == "") + { + vector thisscope = getFuncSymbols().getFuncIDs(name); + + for(vector::iterator it = thisscope.begin(); it != thisscope.end(); it++) + { + rval.push_back(*it); + } + } + + map::iterator it = namedChildren.find(nspace); + + if(it != namedChildren.end()) + { + vector childscope = (*it).second->getFuncsInScope("", name); + + for(vector::iterator it2 = childscope.begin(); it2 != childscope.end(); it2++) + { + rval.push_back(*it2); + } + } + + if(parent != NULL) + { + vector abovescope = parent->getFuncsInScope(nspace,name); + + for(vector::iterator it2 = abovescope.begin(); it2 != abovescope.end(); it2++) + { + rval.push_back(*it2); + } + } + + return rval; +} + +Scope *Scope::getNamedChild(string name) +{ + return namedChildren[name]; +} + +void SymbolTable::putFunc(int ID, int type) +{ + funcTypes[ID]=type; +} + +void SymbolTable::putAST(AST *obj, int ID) +{ + astToID[obj]=ID; +} + +int SymbolTable::getFuncType(AST *obj) +{ + return getFuncType(astToID[obj]); +} + +void SymbolTable::printDiagnostics() +{ + cout << (unsigned int)varTypes.size() << " variable symbols" << endl; + cout << (unsigned int)funcTypes.size() << " function symbols" << endl; + cout << (unsigned int)funcParams.size() << " function declarations (should = function symbols)" << endl; +} + diff --git a/src/parser/DataStructs.h b/src/parser/DataStructs.h new file mode 100644 index 0000000000..1755cb724f --- /dev/null +++ b/src/parser/DataStructs.h @@ -0,0 +1,199 @@ +#ifndef DATASTRUCTS_H +#define DATASTRUCTS_H + +#include "AST.h" +#include +#include +#include + +using std::string; +using std::map; +using std::vector; +using std::pair; + +class VariableSymbols +{ +public: + VariableSymbols() : symbols() {} + int addVariable(string name, int type); + bool containsVariable(string name); + int getID(string name); +private: + map > symbols; +}; + +class FunctionSymbols +{ +public: + FunctionSymbols() : symbols(), ambiguous() {} + int addFunction(string name, int rettype, vector paramtype); + bool containsFunction(string name, vector ¶ms); + int getID(string name, vector ¶ms); + vector getFuncIDs(string name); +private: + map >, pair > symbols; + map > ambiguous; +}; + +class SymbolTable +{ +public: + SymbolTable(map *consts) : varTypes(), funcTypes(), astToID(), funcParams(), constants(consts) {} + int getVarType(int varID); + int getFuncType(int funcID) + { + return funcTypes[funcID]; + } + void putVar(int ID, int type) + { + varTypes[ID]=type; + } + void putFunc(int ID, int type); + void putFuncDecl(int ID, vector params) + { + funcParams[ID]=params; + } + void putAST(AST *obj, int ID); + void putAmbiguousFunc(AST *func, vector possibleIDs) + { + astToAmbiguousFuncIDs[func]=possibleIDs; + } + int getVarType(AST *obj); + int getFuncType(AST *obj); + vector getFuncParams(int funcID) + { + return funcParams[funcID]; + } + vector getAmbiguousFuncs(AST *func) + { + return astToAmbiguousFuncIDs[func]; + } + int getID(AST *obj) + { + return astToID[obj]; + } + void printDiagnostics(); + vector &getGlobalPointers(void) + { + return globalPointers; + } + void addGlobalPointer(int vid) + { + globalPointers.push_back(vid); + } + bool isConstant(string name); + long getConstantVal(string name); +private: + map varTypes; + map funcTypes; + map astToID; + map > astToAmbiguousFuncIDs; + map > funcParams; + vector globalPointers; + map *constants; +}; + +class Scope +{ +public: + Scope(Scope *Parent) : namedChildren(), parent(Parent), vars(), funcs() {} + ~Scope(); + VariableSymbols &getVarSymbols() + { + return vars; + } + FunctionSymbols &getFuncSymbols() + { + return funcs; + } + bool addNamedChild(string name, Scope *child); + int getVarInScope(string nspace, string name); + vector getFuncsInScope(string nspace, string name); + Scope *getNamedChild(string name); +private: + map namedChildren; + Scope *parent; + VariableSymbols vars; + FunctionSymbols funcs; +}; +struct SymbolData +{ + SymbolTable *symbols; + vector globalFuncs; + vector globalVars; + vector globalArrays; + vector scripts; + map runsymbols; + map numParams; + map scriptTypes; + map thisPtr; +}; + +struct FunctionData +{ + SymbolTable *symbols; + vector functions; + vector globalVars; + vector newGlobalVars; + vector globalArrays; + vector newGlobalArrays; + map scriptRunSymbols; + map numParams; + map scriptTypes; + map thisPtr; +}; + +struct IntermediateData +{ + map > funcs; + vector globalsInit; + vector globalasInit; + map scriptRunLabels; + map numParams; + map scriptTypes; + map thisPtr; +}; + +class LinkTable +{ +public: + int functionToLabel(int fid); + int getGlobalID(int vid); + int addGlobalVar(int vid); + void addGlobalPointer(int vid) + { + globalIDs[vid]=0; + } +private: + map funcLabels; + map globalIDs; +}; + +class StackFrame +{ +public: + void addToFrame(int vid, int offset) + { + stackoffset[vid] = offset; + } + int getOffset(int vid); +private: + map stackoffset; +}; + +struct OpcodeContext +{ + StackFrame *stackframe; + LinkTable *linktable; + SymbolTable *symbols; +}; + +struct BFSParam +{ + Scope *scope; + SymbolTable *table; + int type; +}; + +#endif + diff --git a/src/parser/GlobalSymbols.cpp b/src/parser/GlobalSymbols.cpp new file mode 100644 index 0000000000..e7cb26a1d2 --- /dev/null +++ b/src/parser/GlobalSymbols.cpp @@ -0,0 +1,3383 @@ + +#include "../precompiled.h" //always first + +#include "GlobalSymbols.h" +#include "ByteCode.h" +#include "../zsyssimple.h" +#include + +const int radsperdeg = 572958; + + +//sanity underflow +#define typeVOID ScriptParser::TYPE_VOID +#define S ScriptParser::TYPE_SCREEN +#define F ScriptParser::TYPE_FLOAT + +#define ARGS_4(t, arg1, arg2, arg3, arg4) \ + { t, arg1, arg2, arg3, arg4, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 } +#define ARGS_6(t, arg1, arg2, arg3, arg4, arg5, arg6) \ + { t, arg1, arg2, arg3, arg4, arg5, arg6, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 } +#define ARGS_8(t, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ + { t, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 } + +#define POP_ARGS(num_args, t) \ + for(int _i(0); _i < num_args; ++_i) \ + code.push_back(new OPopRegister(new VarArgument(t))) + + + +void LibrarySymbols::addSymbolsToScope(Scope *scope, SymbolTable *t) +{ + //waste an ID, OH WELL + memberids.clear(); + firstid = ScriptParser::getUniqueFuncID()+1; + int id = firstid; + + for(int i=0; table[i].name != ""; i++,id++) + { + vector param; + + for(int k=0; table[i].params[k] != -1 && k<20; k++) + param.push_back(table[i].params[k]); + + string name = table[i].name; + scope->getFuncSymbols().addFunction(name, table[i].rettype,param); + t->putFunc(id, table[i].rettype); + t->putFuncDecl(id, param); + memberids[name]=id; + } +} + +pair > LibrarySymbols::matchFunction(string name, SymbolTable *t) +{ + pair > rval; + int id = -1; + map::iterator it = memberids.find(name); + + if(it != memberids.end()) + id = it->second; + + if(id == -1) + { + rval.first = -1; + return rval; + } + + //else we're good + rval.first = id; + rval.second = t->getFuncParams(id); + return rval; +} + +map > LibrarySymbols::addSymbolsCode(LinkTable <) +{ + map > rval; + + for(int i=0; table[i].name != ""; i++) + { + int var = table[i].var; + string name = table[i].name; + bool isIndexed = table[i].numindex > 1; + int id = memberids[name]; + int label = lt.functionToLabel(id); + + switch(table[i].setorget) + { + case GETTER: + if(isIndexed) + rval[label] = getIndexedVariable(lt, id, var); + else + rval[label] = getVariable(lt, id, var); + + break; + + case SETTER: + { + if(isIndexed) + { + rval[label] = setIndexedVariable(lt, id, var); + } + else + { + if(table[i].params[1] == ScriptParser::TYPE_BOOL) + { + rval[label] = setBoolVariable(lt, id, var); + } + else + { + rval[label] = setVariable(lt, id, var); + } + } + + break; + } + } + } + + return rval; +} + +vector LibrarySymbols::getVariable(LinkTable <, int id, int var) +{ + int label = lt.functionToLabel(id); + vector code; + //pop object pointer + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //load object pointer into ref register + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(var))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + return code; +} + +vector LibrarySymbols::getIndexedVariable(LinkTable <, int id, int var) +{ + int label = lt.functionToLabel(id); + vector code; + //pop index + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + //pop object pointer + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //load object pointer into ref register + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(var))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + return code; +} + +vector LibrarySymbols::setVariable(LinkTable <, int id, int var) +{ + int label = lt.functionToLabel(id); + vector code; + //pop off the value to set to + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop object pointer + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //load object pointer into ref register + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(var), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + return code; +} + +vector LibrarySymbols::setBoolVariable(LinkTable <, int id, int var) +{ + int label = lt.functionToLabel(id); + vector code; + //pop off the value to set to + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //renormalize true to 1 + int donerenorm = ScriptParser::getUniqueLabelID(); + code.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + code.push_back(new OGotoTrueImmediate(new LabelArgument(donerenorm))); + code.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + + //pop object pointer + Opcode *next = new OPopRegister(new VarArgument(EXP2)); + next->setLabel(donerenorm); + code.push_back(next); + //load object pointer into ref register + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(var), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + return code; +} + +vector LibrarySymbols::setIndexedVariable(LinkTable <, int id, int var) +{ + int label = lt.functionToLabel(id); + vector code; + //pop off index + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + //pop off the value to set to + code.push_back(new OPopRegister(new VarArgument(EXP1))); + //pop object pointer + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //load object pointer into ref register + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(var), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + return code; +} + +LibrarySymbols::~LibrarySymbols() +{ + return; +} + +GlobalSymbols GlobalSymbols::singleton; + +static AccessorTable GlobalTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "Rand", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Quit", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Waitframe", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Waitdraw", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Trace", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "TraceB", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "TraceS", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "TraceNL", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ClearTrace", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "TraceToBase", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "Sin", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Cos", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Tan", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ArcTan", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ArcSin", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ArcCos", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "RadianSin", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "RadianCos", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "RadianTan", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Max", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Min", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Pow", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "InvPow", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Factorial", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Abs", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Log10", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Ln", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Sqrt", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, +// { "CalculateSpline", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, +// { "CollisionRect", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, +// { "CollisionBox", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "CopyTile", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SwapTile", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ClearTile", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetScriptRAM", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetScriptRAM", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetGlobalRAM", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetGlobalRAM", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetColorBuffer", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "SetDepthBuffer", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "GetColorBuffer", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "GetDepthBuffer", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "SizeOfArray", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +GlobalSymbols::GlobalSymbols() +{ + table = GlobalTable; + refVar = NUL; +} + +map > GlobalSymbols::addSymbolsCode(LinkTable <) +{ + map > rval; + int id; + //int Rand(int maxval) + { + id = memberids["Rand"]; + int label = lt.functionToLabel(id); + vector code; + //pop maxval + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new ORandRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void Quit() + { + id = memberids["Quit"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OQuit()); + rval[label]=code; + } + //void Waitframe() + { + id = memberids["Waitframe"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OWaitframe(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Waitdraw() + { + id = memberids["Waitdraw"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OWaitdraw(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Trace(int val) + { + id = memberids["Trace"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OTraceRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void TraceB(bool val) + { + id = memberids["TraceB"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OTrace2Register(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void TraceS(bool val) + { + id = memberids["TraceS"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OTrace6Register(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void TraceNL() + { + id = memberids["TraceNL"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OTrace3(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void ClearTrace() + { + id = memberids["ClearTrace"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OTrace4(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void TraceToBase(float, float, float) + { + id = memberids["TraceToBase"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OTrace5Register(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Sin(int val) + { + id = memberids["Sin"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OSinRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int RadianSin(int val) + { + id = memberids["RadianSin"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OMultImmediate(new VarArgument(EXP2), new LiteralArgument(radsperdeg))); + code.push_back(new OSinRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int ArcSin(int val) + { + id = memberids["ArcSin"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OArcSinRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Cos(int val) + { + id = memberids["Cos"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OCosRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int RadianCos(int val) + { + id = memberids["RadianCos"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OMultImmediate(new VarArgument(EXP2), new LiteralArgument(radsperdeg))); + code.push_back(new OCosRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int ArcCos(int val) + { + id = memberids["ArcCos"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OArcCosRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Tan(int val) + { + id = memberids["Tan"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OTanRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int ArcTan(int X, int Y) + { + id = memberids["ArcTan"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(INDEX2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OATanRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int RadianTan(int val) + { + id = memberids["RadianTan"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OMultImmediate(new VarArgument(EXP2), new LiteralArgument(radsperdeg))); + code.push_back(new OTanRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Max(int first, int second) + { + id = memberids["Max"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OMaxRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Min(int first, int second) + { + id = memberids["Min"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OMinRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Pow(int first, int second) + { + id = memberids["Pow"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPowRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int InvPow(int first, int second) + { + id = memberids["InvPow"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OInvPowRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Factorial(int val) + { + id = memberids["Factorial"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OFactorial(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Abs(int val) + { + id = memberids["Abs"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OAbsRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Log10(int val) + { + id = memberids["Log10"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OLog10Register(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Ln(int val) + { + id = memberids["Ln"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OLogERegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int Sqrt(int val) + { + id = memberids["Sqrt"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OSqrtRegister(new VarArgument(EXP1), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + + + //int CopyTile(int source, int dest) + { + id = memberids["CopyTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OCopyTileRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int SwapTile(int first, int second) + { + id = memberids["SwapTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OSwapTileRegister(new VarArgument(EXP1), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void ClearTile(int tile) + { + id = memberids["ClearTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OClearTileRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void GetGlobalRAM(int) + { + int id2 = memberids["GetGlobalRAM"]; + int label = lt.functionToLabel(id2); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(GLOBALRAMD))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetGlobalRAM(int, int) + { + int id2 = memberids["SetGlobalRAM"]; + int label = lt.functionToLabel(id2); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OSetRegister(new VarArgument(GLOBALRAMD), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void GetScriptRAM(int) + { + int id2 = memberids["GetScriptRAM"]; + int label = lt.functionToLabel(id2); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + //code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(SCRIPTRAMD))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetScriptRAM(int, int) + { + int id2 = memberids["SetScriptRAM"]; + int label = lt.functionToLabel(id2); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OSetRegister(new VarArgument(SCRIPTRAMD), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetColorBuffer(int amount, int offset, int stride, int *ptr) + { + id = memberids["SetColorBuffer"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetColorBufferRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void SetDepthBuffer(int amount, int offset, int stride, int *ptr) + { + id = memberids["SetDepthBuffer"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetDepthBufferRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void GetColorBuffer(int amount, int offset, int stride, int *ptr) + { + id = memberids["GetColorBuffer"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OGetColorBufferRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void GetDepthBuffer(int amount, int offset, int stride, int *ptr) + { + id = memberids["GetDepthBuffer"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OGetDepthBufferRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int SizeOfArray(int val) + { + id = memberids["SizeOfArray"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OArraySize(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + return rval; +} + +FFCSymbols FFCSymbols::singleton = FFCSymbols(); + +static AccessorTable FFCTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getData", ScriptParser::TYPE_FLOAT, GETTER, DATA, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setData", ScriptParser::TYPE_VOID, SETTER, DATA, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getScript", ScriptParser::TYPE_FLOAT, GETTER, FFSCRIPT, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setScript", ScriptParser::TYPE_VOID, SETTER, FFSCRIPT, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCSet", ScriptParser::TYPE_FLOAT, GETTER, FCSET, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCSet", ScriptParser::TYPE_VOID, SETTER, FCSET, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDelay", ScriptParser::TYPE_FLOAT, GETTER, DELAY, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDelay", ScriptParser::TYPE_VOID, SETTER, DELAY, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getX", ScriptParser::TYPE_FLOAT, GETTER, FX, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, FX, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, FY, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, FY, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getVx", ScriptParser::TYPE_FLOAT, GETTER, XD, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setVx", ScriptParser::TYPE_VOID, SETTER, XD, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getVy", ScriptParser::TYPE_FLOAT, GETTER, YD, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setVy", ScriptParser::TYPE_VOID, SETTER, YD, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAx", ScriptParser::TYPE_FLOAT, GETTER, XD2, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAx", ScriptParser::TYPE_VOID, SETTER, XD2, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAy", ScriptParser::TYPE_FLOAT, GETTER, YD2, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAy", ScriptParser::TYPE_VOID, SETTER, YD2, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + //{ "WasTriggered", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlags[]", ScriptParser::TYPE_BOOL, GETTER, FFFLAGSD, 2, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlags[]", ScriptParser::TYPE_VOID, SETTER, FFFLAGSD, 2, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, FFTWIDTH, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, FFTWIDTH, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, FFTHEIGHT, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, FFTHEIGHT, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getEffectWidth", ScriptParser::TYPE_FLOAT, GETTER, FFCWIDTH, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setEffectWidth", ScriptParser::TYPE_VOID, SETTER, FFCWIDTH, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getEffectHeight", ScriptParser::TYPE_FLOAT, GETTER, FFCHEIGHT, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setEffectHeight", ScriptParser::TYPE_VOID, SETTER, FFCHEIGHT, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLink", ScriptParser::TYPE_FLOAT, GETTER, FFLINK, 1, { ScriptParser::TYPE_FFC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLink", ScriptParser::TYPE_VOID, SETTER, FFLINK, 1, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, FFMISCD, 16, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, FFMISCD, 16, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInitD[]", ScriptParser::TYPE_FLOAT, GETTER, FFINITDD, 8, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInitD[]", ScriptParser::TYPE_VOID, SETTER, FFINITDD, 8, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + //{ "getD[]", ScriptParser::TYPE_FLOAT, GETTER, FFDD, 8, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + //{ "setD[]", ScriptParser::TYPE_VOID, SETTER, FFDD, 8, { ScriptParser::TYPE_FFC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +FFCSymbols::FFCSymbols() +{ + table = FFCTable; + refVar = REFFFC; +} + +map > FFCSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //bool WasTriggered(ffc) + /*{ + int id = memberids["WasTriggered"]; + int label = lt.functionToLabel(id); + vector code; + //pop ffc + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //if ffc = -1, it is "this" + int thislabel = ScriptParser::getUniqueLabelID(); + code.push_back(new OCompareImmediate(new VarArgument(EXP2), new LiteralArgument(-1))); + code.push_back(new OGotoTrueImmediate(new LabelArgument(thislabel))); + //if not this + //NOT POSSIBLE YET + //QUIT + code.push_back(new OQuit()); + //if "this" + code.push_back(new OCheckTrig()); + int truelabel = ScriptParser::getUniqueLabelID(); + code.push_back(new OGotoTrueImmediate(new LabelArgument(truelabel))); + code.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + Opcode *next = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(1)); + next->setLabel(truelabel); + code.push_back(next); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + }*/ + return rval; +} + +LinkSymbols LinkSymbols::singleton = LinkSymbols(); + +static AccessorTable LinkSTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getX", ScriptParser::TYPE_FLOAT, GETTER, LINKX, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, LINKX, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, LINKY, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, LINKY, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getZ", ScriptParser::TYPE_FLOAT, GETTER, LINKZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setZ", ScriptParser::TYPE_VOID, SETTER, LINKZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getJump", ScriptParser::TYPE_FLOAT, GETTER, LINKJUMP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setJump", ScriptParser::TYPE_VOID, SETTER, LINKJUMP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDir", ScriptParser::TYPE_FLOAT, GETTER, LINKDIR, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDir", ScriptParser::TYPE_VOID, SETTER, LINKDIR, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitDir", ScriptParser::TYPE_FLOAT, GETTER, LINKHITDIR, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitDir", ScriptParser::TYPE_VOID, SETTER, LINKHITDIR, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getSwordJinx", ScriptParser::TYPE_FLOAT, GETTER, LINKSWORDJINX, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setSwordJinx", ScriptParser::TYPE_VOID, SETTER, LINKSWORDJINX, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getItemJinx", ScriptParser::TYPE_FLOAT, GETTER, LINKITEMJINX, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setItemJinx", ScriptParser::TYPE_VOID, SETTER, LINKITEMJINX, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHP", ScriptParser::TYPE_FLOAT, GETTER, LINKHP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHP", ScriptParser::TYPE_VOID, SETTER, LINKHP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMP", ScriptParser::TYPE_FLOAT, GETTER, LINKMP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMP", ScriptParser::TYPE_VOID, SETTER, LINKMP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMaxHP", ScriptParser::TYPE_FLOAT, GETTER, LINKMAXHP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMaxHP", ScriptParser::TYPE_VOID, SETTER, LINKMAXHP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMaxMP", ScriptParser::TYPE_FLOAT, GETTER, LINKMAXMP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMaxMP", ScriptParser::TYPE_VOID, SETTER, LINKMAXMP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAction", ScriptParser::TYPE_FLOAT, GETTER, LINKACTION, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAction", ScriptParser::TYPE_VOID, SETTER, LINKACTION, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHeldItem", ScriptParser::TYPE_FLOAT, GETTER, LINKHELD, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHeldItem", ScriptParser::TYPE_VOID, SETTER, LINKHELD, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Warp", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "PitWarp", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputStart", ScriptParser::TYPE_BOOL, GETTER, INPUTSTART, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputStart", ScriptParser::TYPE_VOID, SETTER, INPUTSTART, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputMap", ScriptParser::TYPE_BOOL, GETTER, INPUTMAP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputMap", ScriptParser::TYPE_VOID, SETTER, INPUTMAP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputUp", ScriptParser::TYPE_BOOL, GETTER, INPUTUP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputUp", ScriptParser::TYPE_VOID, SETTER, INPUTUP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputDown", ScriptParser::TYPE_BOOL, GETTER, INPUTDOWN, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputDown", ScriptParser::TYPE_VOID, SETTER, INPUTDOWN, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputLeft", ScriptParser::TYPE_BOOL, GETTER, INPUTLEFT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputLeft", ScriptParser::TYPE_VOID, SETTER, INPUTLEFT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputRight", ScriptParser::TYPE_BOOL, GETTER, INPUTRIGHT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputRight", ScriptParser::TYPE_VOID, SETTER, INPUTRIGHT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputA", ScriptParser::TYPE_BOOL, GETTER, INPUTA, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputA", ScriptParser::TYPE_VOID, SETTER, INPUTA, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputB", ScriptParser::TYPE_BOOL, GETTER, INPUTB, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputB", ScriptParser::TYPE_VOID, SETTER, INPUTB, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputL", ScriptParser::TYPE_BOOL, GETTER, INPUTL, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputL", ScriptParser::TYPE_VOID, SETTER, INPUTL, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputR", ScriptParser::TYPE_BOOL, GETTER, INPUTR, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputR", ScriptParser::TYPE_VOID, SETTER, INPUTR, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputEx1", ScriptParser::TYPE_BOOL, GETTER, INPUTEX1, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputEx1", ScriptParser::TYPE_VOID, SETTER, INPUTEX1, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputEx2", ScriptParser::TYPE_BOOL, GETTER, INPUTEX2, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputEx2", ScriptParser::TYPE_VOID, SETTER, INPUTEX2, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputEx3", ScriptParser::TYPE_BOOL, GETTER, INPUTEX3, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputEx3", ScriptParser::TYPE_VOID, SETTER, INPUTEX3, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputEx4", ScriptParser::TYPE_BOOL, GETTER, INPUTEX4, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputEx4", ScriptParser::TYPE_VOID, SETTER, INPUTEX4, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressStart", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSSTART, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressStart", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSSTART, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressUp", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSUP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressUp", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSUP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressDown", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSDOWN, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressDown", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSDOWN, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressLeft", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSLEFT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressLeft", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSLEFT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressRight", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSRIGHT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressRight", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSRIGHT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressA", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSA, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressA", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSA, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressB", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSB, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressB", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSB, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressL", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSL, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressL", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSL, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressR", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSR, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressR", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSR, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressEx1", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSEX1, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressEx1", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSEX1, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressEx2", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSEX2, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressEx2", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSEX2, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressEx3", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSEX3, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressEx3", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSEX3, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressEx4", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSEX4, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressEx4", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSEX4, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputMouseX", ScriptParser::TYPE_FLOAT, GETTER, INPUTMOUSEX, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputMouseX", ScriptParser::TYPE_VOID, SETTER, INPUTMOUSEX, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputMouseY", ScriptParser::TYPE_FLOAT, GETTER, INPUTMOUSEY, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputMouseY", ScriptParser::TYPE_VOID, SETTER, INPUTMOUSEY, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputMouseZ", ScriptParser::TYPE_FLOAT, GETTER, INPUTMOUSEZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputMouseZ", ScriptParser::TYPE_VOID, SETTER, INPUTMOUSEZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputMouseB", ScriptParser::TYPE_FLOAT, GETTER, INPUTMOUSEB, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputMouseB", ScriptParser::TYPE_VOID, SETTER, INPUTMOUSEB, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getItem[]", ScriptParser::TYPE_BOOL, GETTER, LINKITEMD, 256, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setItem[]", ScriptParser::TYPE_VOID, SETTER, LINKITEMD, 256, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitWidth", ScriptParser::TYPE_FLOAT, GETTER, LINKHXSZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitWidth", ScriptParser::TYPE_VOID, SETTER, LINKHXSZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitHeight", ScriptParser::TYPE_FLOAT, GETTER, LINKHYSZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitHeight", ScriptParser::TYPE_VOID, SETTER, LINKHYSZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitZHeight", ScriptParser::TYPE_FLOAT, GETTER, LINKHZSZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitZHeight", ScriptParser::TYPE_VOID, SETTER, LINKHZSZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, LINKTXSZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, LINKTXSZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, LINKTYSZ, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, LINKTYSZ, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawXOffset", ScriptParser::TYPE_FLOAT, GETTER, LINKXOFS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawXOffset", ScriptParser::TYPE_VOID, SETTER, LINKXOFS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawYOffset", ScriptParser::TYPE_FLOAT, GETTER, LINKYOFS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawYOffset", ScriptParser::TYPE_VOID, SETTER, LINKYOFS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawZOffset", ScriptParser::TYPE_FLOAT, GETTER, LINKZOFS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawZOffset", ScriptParser::TYPE_VOID, SETTER, LINKZOFS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitXOffset", ScriptParser::TYPE_FLOAT, GETTER, LINKHXOFS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitXOffset", ScriptParser::TYPE_VOID, SETTER, LINKHXOFS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitYOffset", ScriptParser::TYPE_FLOAT, GETTER, LINKHYOFS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitYOffset", ScriptParser::TYPE_VOID, SETTER, LINKHYOFS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrunk", ScriptParser::TYPE_FLOAT, GETTER, LINKDRUNK, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrunk", ScriptParser::TYPE_VOID, SETTER, LINKDRUNK, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getEquipment", ScriptParser::TYPE_FLOAT, GETTER, LINKEQUIP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setEquipment", ScriptParser::TYPE_VOID, SETTER, LINKEQUIP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputAxisUp", ScriptParser::TYPE_BOOL, GETTER, INPUTAXISUP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputAxisUp", ScriptParser::TYPE_VOID, SETTER, INPUTAXISUP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputAxisDown", ScriptParser::TYPE_BOOL, GETTER, INPUTAXISDOWN, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputAxisDown", ScriptParser::TYPE_VOID, SETTER, INPUTAXISDOWN, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputAxisLeft", ScriptParser::TYPE_BOOL, GETTER, INPUTAXISLEFT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputAxisLeft", ScriptParser::TYPE_VOID, SETTER, INPUTAXISLEFT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInputAxisRight", ScriptParser::TYPE_BOOL, GETTER, INPUTAXISRIGHT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInputAxisRight", ScriptParser::TYPE_VOID, SETTER, INPUTAXISRIGHT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressAxisUp", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSAXISUP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressAxisUp", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSAXISUP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressAxisDown", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSAXISDOWN, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressAxisDown", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSAXISDOWN, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressAxisLeft", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSAXISLEFT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressAxisLeft", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSAXISLEFT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressAxisRight", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSAXISRIGHT, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressAxisRight", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSAXISRIGHT, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInvisible", ScriptParser::TYPE_FLOAT, GETTER, LINKINVIS, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInvisible", ScriptParser::TYPE_VOID, SETTER, LINKINVIS, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCollDetection", ScriptParser::TYPE_FLOAT, GETTER, LINKINVINC, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCollDetection", ScriptParser::TYPE_VOID, SETTER, LINKINVINC, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, LINKMISCD, 16, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, LINKMISCD, 16, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLadderX", ScriptParser::TYPE_FLOAT, GETTER, LINKLADDERX, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLadderY", ScriptParser::TYPE_FLOAT, GETTER, LINKLADDERY, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTile", ScriptParser::TYPE_FLOAT, GETTER, LINKTILE, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTile", ScriptParser::TYPE_VOID, SETTER, LINKTILE, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlip", ScriptParser::TYPE_FLOAT, GETTER, LINKFLIP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlip", ScriptParser::TYPE_VOID, SETTER, LINKFLIP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPressMap", ScriptParser::TYPE_BOOL, GETTER, INPUTPRESSMAP, 1, { ScriptParser::TYPE_LINK, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPressMap", ScriptParser::TYPE_VOID, SETTER, INPUTPRESSMAP, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SelectAWeapon", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SelectBWeapon", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_LINK, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, +}; + +LinkSymbols::LinkSymbols() +{ + table = LinkSTable; + refVar = NUL; +} + +map > LinkSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //Warp(link, int, int) + { + int id = memberids["Warp"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop ffc, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + //ffc must be this (link is not a user-accessible type) + code.push_back(new OWarp(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //PitWarp(link, int, int) + { + int id = memberids["PitWarp"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop ffc, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + //ffc must be this (link is not a user-accessible type) + code.push_back(new OPitWarp(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //SelectAWeapon(link, int) + { + int id = memberids["SelectAWeapon"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSelectAWeaponRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //SelectBWeapon(link, int) + { + int id = memberids["SelectBWeapon"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSelectBWeaponRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + + return rval; +} + +ScreenSymbols ScreenSymbols::singleton = ScreenSymbols(); + +static AccessorTable ScreenTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getD[]", ScriptParser::TYPE_FLOAT, GETTER, SDD, 8, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setD[]", ScriptParser::TYPE_VOID, SETTER, SDD, 8, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboD[]", ScriptParser::TYPE_FLOAT, GETTER, COMBODD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboD[]", ScriptParser::TYPE_VOID, SETTER, COMBODD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboC[]", ScriptParser::TYPE_FLOAT, GETTER, COMBOCD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboC[]", ScriptParser::TYPE_VOID, SETTER, COMBOCD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboF[]", ScriptParser::TYPE_FLOAT, GETTER, COMBOFD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboF[]", ScriptParser::TYPE_VOID, SETTER, COMBOFD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboI[]", ScriptParser::TYPE_FLOAT, GETTER, COMBOID, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboI[]", ScriptParser::TYPE_VOID, SETTER, COMBOID, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboT[]", ScriptParser::TYPE_FLOAT, GETTER, COMBOTD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboT[]", ScriptParser::TYPE_VOID, SETTER, COMBOTD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getComboS[]", ScriptParser::TYPE_FLOAT, GETTER, COMBOSD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setComboS[]", ScriptParser::TYPE_VOID, SETTER, COMBOSD, 176, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDoor[]", ScriptParser::TYPE_FLOAT, GETTER, SCRDOORD, 4, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDoor[]", ScriptParser::TYPE_VOID, SETTER, SCRDOORD, 4, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getState[]", ScriptParser::TYPE_BOOL, GETTER, SCREENSTATED, 32, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setState[]", ScriptParser::TYPE_VOID, SETTER, SCREENSTATED, 32, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLit", ScriptParser::TYPE_BOOL, GETTER, LIT, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLit", ScriptParser::TYPE_VOID, SETTER, LIT, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getWavy", ScriptParser::TYPE_FLOAT, GETTER, WAVY, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setWavy", ScriptParser::TYPE_VOID, SETTER, WAVY, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getQuake", ScriptParser::TYPE_FLOAT, GETTER, QUAKE, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setQuake", ScriptParser::TYPE_VOID, SETTER, QUAKE, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "NumItems", ScriptParser::TYPE_FLOAT, GETTER, ITEMCOUNT, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadItem", ScriptParser::TYPE_ITEM, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "CreateItem", ScriptParser::TYPE_ITEM, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadFFC", ScriptParser::TYPE_FFC, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "NumNPCs", ScriptParser::TYPE_FLOAT, GETTER, NPCCOUNT, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadNPC", ScriptParser::TYPE_NPC, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "CreateNPC", ScriptParser::TYPE_NPC, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ClearSprites", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Rectangle", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, } }, + { "Circle", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "Arc", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, } }, + { "Ellipse", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, } }, + { "Line", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "Spline", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "PutPixel", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "DrawCharacter", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "DrawInteger", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "DrawTile", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, } }, + { "DrawCombo", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, ScriptParser::TYPE_FLOAT, -1, -1, -1, } }, + { "Quad", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, } }, + { "Triangle", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, } }, + { "Quad3D", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "Triangle3D", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "FastTile", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "FastCombo", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "DrawString", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "DrawLayer", typeVOID, FUNCTION, 0, 1, ARGS_8(S,F,F,F,F,F,F,F,F) }, + { "DrawScreen", typeVOID, FUNCTION, 0, 1, ARGS_6(S,F,F,F,F,F,F) }, + { "DrawBitmap", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, } }, + { "SetRenderTarget", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Message", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "NumLWeapons", ScriptParser::TYPE_FLOAT, GETTER, LWPNCOUNT, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadLWeapon", ScriptParser::TYPE_LWPN, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "CreateLWeapon", ScriptParser::TYPE_LWPN, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "NumEWeapons", ScriptParser::TYPE_FLOAT, GETTER, EWPNCOUNT, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadEWeapon", ScriptParser::TYPE_EWPN, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "CreateEWeapon", ScriptParser::TYPE_EWPN, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "isSolid", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetSideWarp", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "SetTileWarp", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "LayerScreen", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LayerMap", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlags[]", ScriptParser::TYPE_FLOAT, GETTER, SCREENFLAGSD, 10, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlags[]", ScriptParser::TYPE_VOID, SETTER, SCREENFLAGSD, 10, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getEFlags[]", ScriptParser::TYPE_FLOAT, GETTER, SCREENEFLAGSD, 3, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setEFlags[]", ScriptParser::TYPE_VOID, SETTER, SCREENEFLAGSD, 3, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "TriggerSecrets", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getRoomType", ScriptParser::TYPE_FLOAT, GETTER, ROOMTYPE, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + //{ "setRoomType", ScriptParser::TYPE_VOID, SETTER, SCREENTYPE, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getRoomData", ScriptParser::TYPE_FLOAT, GETTER, ROOMDATA, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setRoomData", ScriptParser::TYPE_VOID, SETTER, ROOMDATA, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMovingBlockX", ScriptParser::TYPE_FLOAT, GETTER, PUSHBLOCKX, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMovingBlockX", ScriptParser::TYPE_VOID, SETTER, PUSHBLOCKX, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMovingBlockY", ScriptParser::TYPE_FLOAT, GETTER, PUSHBLOCKY, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMovingBlockY", ScriptParser::TYPE_VOID, SETTER, PUSHBLOCKY, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMovingBlockCombo", ScriptParser::TYPE_FLOAT, GETTER, PUSHBLOCKCOMBO, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMovingBlockCombo", ScriptParser::TYPE_VOID, SETTER, PUSHBLOCKCOMBO, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMovingBlockCSet", ScriptParser::TYPE_FLOAT, GETTER, PUSHBLOCKCSET, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMovingBlockCSet", ScriptParser::TYPE_VOID, SETTER, PUSHBLOCKCSET, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getUnderCombo", ScriptParser::TYPE_FLOAT, GETTER, UNDERCOMBO, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setUnderCombo", ScriptParser::TYPE_VOID, SETTER, UNDERCOMBO, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getUnderCSet", ScriptParser::TYPE_FLOAT, GETTER, UNDERCSET, 1, { ScriptParser::TYPE_SCREEN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setUnderCSet", ScriptParser::TYPE_VOID, SETTER, UNDERCSET, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetSideWarpDMap", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetSideWarpScreen", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetSideWarpType", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetTileWarpDMap", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetTileWarpScreen", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetTileWarpType", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_SCREEN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + + +ScreenSymbols::ScreenSymbols() +{ + table = ScreenTable; + refVar = NUL; +} + +map > ScreenSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //item LoadItem(screen, int) + { + int id = memberids["LoadItem"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + //convert from 1-index to 0-index + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OLoadItemRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFITEM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //item CreateItem(screen, int) + { + int id = memberids["CreateItem"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OCreateItemRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFITEM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //ffc LoadFFC(screen, int) + { + int id = memberids["LoadFFC"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + //code.push_back(new OSetRegister(new VarArgument(REFFFC), new VarArgument(EXP1))); + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //npc LoadNPC(screen, int) + { + int id = memberids["LoadNPC"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + //convert from 1-index to 0-index + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OLoadNPCRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFNPC))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //npc CreateNPC(screen, int) + { + int id = memberids["CreateNPC"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OCreateNPCRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFNPC))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //npc LoadLWeapon(screen, int) + { + int id = memberids["LoadLWeapon"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + //convert from 1-index to 0-index + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OLoadLWpnRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFLWPN))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //npc CreateLWeapon(screen, int) + { + int id = memberids["CreateLWeapon"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OCreateLWpnRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFLWPN))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //ewpn LoadEWeapon(screen, int) + { + int id = memberids["LoadEWeapon"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + //convert from 1-index to 0-index + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OLoadEWpnRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFEWPN))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //ewpn CreateEWeapon(screen, int) + { + int id = memberids["CreateEWeapon"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OCreateEWpnRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFEWPN))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void ClearSprites(screen, int) + { + int id = memberids["ClearSprites"]; + + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OClearSpritesRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFNPC))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void Rectangle(screen, float, float, float, float, float, float, float, float, float, float, bool, float) + { + int id = memberids["Rectangle"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ORectangleRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(12, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + + rval[label]=code; + } + //void Circle(screen, float, float, float, float, float, float, float, float, float, bool, float) + { + int id = memberids["Circle"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OCircleRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(11, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Arc(screen, float, float, float, float, float, float, float, float, float, float, float, bool, bool, float) + { + int id = memberids["Arc"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OArcRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(14, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Ellipse(screen, float, float, float, float, float, bool, float, float, float) + { + int id = memberids["Ellipse"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OEllipseRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(12, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Line(screen, float, float, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Line"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OLineRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(11, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Spline(screen, float, float, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Spline"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSplineRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(11, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void PutPixel(screen, float, float, float, float, float, float, float, float) + { + int id = memberids["PutPixel"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPutPixelRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(8, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawCharacter(screen, float, float, float, float, float, float, float, float, float, float) + { + int id = memberids["DrawCharacter"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawCharRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(10, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawInteger(screen, float, float, float, float, float, float, float, float, float, float, float) + { + int id = memberids["DrawInteger"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawIntRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(11, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawTile(screen, float, float, float, float, float, bool, float, float, float) + { + int id = memberids["DrawTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawTileRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(15, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawCombo(screen, float, float, float, float, float, bool, float, float, float) + { + int id = memberids["DrawCombo"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawComboRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(16, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Quad(screen, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Quad"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OQuadRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(15, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Triangle(screen, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Triangle"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OTriangleRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(13, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + + //void Quad3D(screen, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Quad3D"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OQuad3DRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(8, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Triangle3D(screen, float, float, float, float, float, float, float, float, float) + { + int id = memberids["Triangle3D"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OTriangle3DRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(8, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + + //void FastTile(screen, float, float, float, float, float) + { + int id = memberids["FastTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OFastTileRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(6, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void FastCombo(screen, float, float, float, float, float) + { + int id = memberids["FastCombo"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OFastComboRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(6, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawString(screen, float, float, float, float, float, float, float, int *string) + { + int id = memberids["DrawString"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawStringRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(9, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawLayer(screen, float, float, float, float, float, float, float, float) + { + int id = memberids["DrawLayer"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawLayerRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(8, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawScreen(screen, float, float, float, float, float, float) + { + int id = memberids["DrawScreen"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawScreenRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(6, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void DrawBitmap(screen, float, float, float, float, float, float, float, float, float, bool) + { + int id = memberids["DrawBitmap"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new ODrawBitmapRegister(); + first->setLabel(label); + code.push_back(first); + POP_ARGS(12, EXP2); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void SetRenderTarget(bitmap) + { + int id = memberids["SetRenderTarget"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetRenderTargetRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void Message(screen, float) + { + int id = memberids["Message"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OMessageRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //bool isSolid(screen, int, int) + { + int id = memberids["isSolid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OIsSolid(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetSideWarp(screen, float, float, float, float) + { + int id = memberids["SetSideWarp"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetSideWarpRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void SetTileWarp(screen, float, float, float, float) + { + int id = memberids["SetTileWarp"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetTileWarpRegister(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //float LayerScreen(screen, float) + { + int id = memberids["LayerScreen"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OLayerScreenRegister(new VarArgument(EXP1),new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //float LayerMap(screen, float) + { + int id = memberids["LayerMap"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OLayerMapRegister(new VarArgument(EXP1),new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void TriggerSecrets(screen) + { + int id = memberids["TriggerSecrets"]; + int label = lt.functionToLabel(id); + vector code; + //pop pointer, and ignore it + Opcode *first = new OPopRegister(new VarArgument(NUL)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OTriggerSecrets()); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetSideWarpDMap(screen, int) + { + int id = memberids["GetSideWarpDMap"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetSideWarpDMap(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetSideWarpScreen(screen, int) + { + int id = memberids["GetSideWarpScreen"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetSideWarpScreen(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetSideWarpType(screen, int) + { + int id = memberids["GetSideWarpType"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetSideWarpType(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetTileWarpDMap(screen, int) + { + int id = memberids["GetTileWarpDMap"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetTileWarpDMap(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetTileWarpScreen(screen, int) + { + int id = memberids["GetTileWarpScreen"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetTileWarpScreen(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetTileWarpType(screen, int) + { + int id = memberids["GetTileWarpType"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetTileWarpType(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + return rval; +} + +ItemSymbols ItemSymbols::singleton = ItemSymbols(); + +static AccessorTable itemTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getX", ScriptParser::TYPE_FLOAT, GETTER, ITEMX, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, ITEMX, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, ITEMY, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, ITEMY, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getZ", ScriptParser::TYPE_FLOAT, GETTER, ITEMZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setZ", ScriptParser::TYPE_VOID, SETTER, ITEMZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getJump", ScriptParser::TYPE_FLOAT, GETTER, ITEMJUMP, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setJump", ScriptParser::TYPE_VOID, SETTER, ITEMJUMP, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawStyle", ScriptParser::TYPE_FLOAT, GETTER, ITEMDRAWTYPE, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawStyle", ScriptParser::TYPE_VOID, SETTER, ITEMDRAWTYPE, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getID", ScriptParser::TYPE_FLOAT, GETTER, ITEMID, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setID", ScriptParser::TYPE_VOID, SETTER, ITEMID, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTile", ScriptParser::TYPE_FLOAT, GETTER, ITEMTILE, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTile", ScriptParser::TYPE_VOID, SETTER, ITEMTILE, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalTile", ScriptParser::TYPE_FLOAT, GETTER, ITEMOTILE, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "setOriginalTile", ScriptParser::TYPE_VOID, SETTER, ITEMOTILE, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, } }, + { "getCSet", ScriptParser::TYPE_FLOAT, GETTER, ITEMCSET, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCSet", ScriptParser::TYPE_VOID, SETTER, ITEMCSET, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlashCSet", ScriptParser::TYPE_FLOAT, GETTER, ITEMFLASHCSET, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlashCSet", ScriptParser::TYPE_VOID, SETTER, ITEMFLASHCSET, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getNumFrames", ScriptParser::TYPE_FLOAT, GETTER, ITEMFRAMES, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setNumFrames", ScriptParser::TYPE_VOID, SETTER, ITEMFRAMES, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFrame", ScriptParser::TYPE_FLOAT, GETTER, ITEMFRAME, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFrame", ScriptParser::TYPE_VOID, SETTER, ITEMFRAME, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getASpeed", ScriptParser::TYPE_FLOAT, GETTER, ITEMASPEED, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setASpeed", ScriptParser::TYPE_VOID, SETTER, ITEMASPEED, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDelay", ScriptParser::TYPE_FLOAT, GETTER, ITEMDELAY, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDelay", ScriptParser::TYPE_VOID, SETTER, ITEMDELAY, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlash", ScriptParser::TYPE_BOOL, GETTER, ITEMFLASH, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlash", ScriptParser::TYPE_VOID, SETTER, ITEMFLASH, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlip", ScriptParser::TYPE_FLOAT, GETTER, ITEMFLIP, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlip", ScriptParser::TYPE_VOID, SETTER, ITEMFLIP, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getExtend", ScriptParser::TYPE_FLOAT, GETTER, ITEMEXTEND, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setExtend", ScriptParser::TYPE_VOID, SETTER, ITEMEXTEND, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitWidth", ScriptParser::TYPE_FLOAT, GETTER, ITEMHXSZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitWidth", ScriptParser::TYPE_VOID, SETTER, ITEMHXSZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitHeight", ScriptParser::TYPE_FLOAT, GETTER, ITEMHYSZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitHeight", ScriptParser::TYPE_VOID, SETTER, ITEMHYSZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitZHeight", ScriptParser::TYPE_FLOAT, GETTER, ITEMHZSZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitZHeight", ScriptParser::TYPE_VOID, SETTER, ITEMHZSZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, ITEMTXSZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, ITEMTXSZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, ITEMTYSZ, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, ITEMTYSZ, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawXOffset", ScriptParser::TYPE_FLOAT, GETTER, ITEMXOFS, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawXOffset", ScriptParser::TYPE_VOID, SETTER, ITEMXOFS, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawYOffset", ScriptParser::TYPE_FLOAT, GETTER, ITEMYOFS, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawYOffset", ScriptParser::TYPE_VOID, SETTER, ITEMYOFS, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawZOffset", ScriptParser::TYPE_FLOAT, GETTER, ITEMZOFS, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawZOffset", ScriptParser::TYPE_VOID, SETTER, ITEMZOFS, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitXOffset", ScriptParser::TYPE_FLOAT, GETTER, ITEMHXOFS, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitXOffset", ScriptParser::TYPE_VOID, SETTER, ITEMHXOFS, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitYOffset", ScriptParser::TYPE_FLOAT, GETTER, ITEMHYOFS, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitYOffset", ScriptParser::TYPE_VOID, SETTER, ITEMHYOFS, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPickup", ScriptParser::TYPE_FLOAT, GETTER, ITEMPICKUP, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPickup", ScriptParser::TYPE_VOID, SETTER, ITEMPICKUP, 1, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "isValid", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_ITEM, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, ITEMMISCD, 16, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, ITEMMISCD, 16, { ScriptParser::TYPE_ITEM, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +ItemSymbols::ItemSymbols() +{ + table = itemTable; + refVar = REFITEM; +} + +map > ItemSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //bool isValid(item) + { + int id = memberids["isValid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the pointer + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //Check validity + code.push_back(new OIsValidItem(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + return rval; +} + +ItemclassSymbols ItemclassSymbols::singleton = ItemclassSymbols(); + +static AccessorTable itemclassTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getFamily", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSFAMILY, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFamily", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSFAMILY, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLevel", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSFAMTYPE, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLevel", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSFAMTYPE, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAmount", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSAMOUNT, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAmount", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSAMOUNT, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMax", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSMAX, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMax", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSMAX, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMaxIncrement", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSSETMAX, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMaxIncrement", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSSETMAX, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getKeep", ScriptParser::TYPE_BOOL, GETTER, ITEMCLASSSETGAME, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setKeep", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSSETGAME, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCounter", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSCOUNTER, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCounter", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSCOUNTER, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getUseSound", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSUSESOUND, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setUseSound", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSUSESOUND, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getPower", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSPOWER, 1, { ScriptParser::TYPE_ITEMCLASS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setPower", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSPOWER, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getInitD[]", ScriptParser::TYPE_FLOAT, GETTER, ITEMCLASSINITDD, 2, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setInitD[]", ScriptParser::TYPE_VOID, SETTER, ITEMCLASSINITDD, 2, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetName", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_ITEMCLASS, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +ItemclassSymbols::ItemclassSymbols() +{ + table = itemclassTable; + refVar = REFITEMCLASS; +} +map > ItemclassSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //void GetName(itemclass, int) + { + int id = memberids["GetName"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetItemName(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + return rval; +} + +GameSymbols GameSymbols::singleton = GameSymbols(); + +static AccessorTable gameTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "GetCurScreen", ScriptParser::TYPE_FLOAT, GETTER, CURSCR, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetCurDMapScreen", ScriptParser::TYPE_FLOAT, GETTER, CURDSCR, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetCurMap", ScriptParser::TYPE_FLOAT, GETTER, CURMAP, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetCurDMap", ScriptParser::TYPE_FLOAT, GETTER, CURDMAP, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetCurLevel", ScriptParser::TYPE_FLOAT, GETTER, CURLEVEL, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getNumDeaths", ScriptParser::TYPE_FLOAT, GETTER, GAMEDEATHS, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setNumDeaths", ScriptParser::TYPE_VOID, SETTER, GAMEDEATHS, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCheat", ScriptParser::TYPE_FLOAT, GETTER, GAMECHEAT, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCheat", ScriptParser::TYPE_VOID, SETTER, GAMECHEAT, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTime", ScriptParser::TYPE_FLOAT, GETTER, GAMETIME, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTime", ScriptParser::TYPE_VOID, SETTER, GAMETIME, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHasPlayed", ScriptParser::TYPE_BOOL, GETTER, GAMEHASPLAYED, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHasPlayed", ScriptParser::TYPE_VOID, SETTER, GAMEHASPLAYED, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTimeValid", ScriptParser::TYPE_BOOL, GETTER, GAMETIMEVALID, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTimeValid", ScriptParser::TYPE_VOID, SETTER, GAMETIMEVALID, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getGuyCount[]", ScriptParser::TYPE_FLOAT, GETTER, GAMEGUYCOUNT, 2, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setGuyCount[]", ScriptParser::TYPE_VOID, SETTER, GAMEGUYCOUNT, 2, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getContinueScreen", ScriptParser::TYPE_FLOAT, GETTER, GAMECONTSCR, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setContinueScreen", ScriptParser::TYPE_VOID, SETTER, GAMECONTSCR, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getContinueDMap", ScriptParser::TYPE_FLOAT, GETTER, GAMECONTDMAP, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setContinueDMap", ScriptParser::TYPE_VOID, SETTER, GAMECONTDMAP, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCounter[]", ScriptParser::TYPE_FLOAT, GETTER, GAMECOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCounter[]", ScriptParser::TYPE_VOID, SETTER, GAMECOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMCounter[]", ScriptParser::TYPE_FLOAT, GETTER, GAMEMCOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMCounter[]", ScriptParser::TYPE_VOID, SETTER, GAMEMCOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDCounter[]", ScriptParser::TYPE_FLOAT, GETTER, GAMEDCOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDCounter[]", ScriptParser::TYPE_VOID, SETTER, GAMEDCOUNTERD, 32, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getGeneric[]", ScriptParser::TYPE_FLOAT, GETTER, GAMEGENERICD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setGeneric[]", ScriptParser::TYPE_VOID, SETTER, GAMEGENERICD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLItems[]", ScriptParser::TYPE_FLOAT, GETTER, GAMELITEMSD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLItems[]", ScriptParser::TYPE_VOID, SETTER, GAMELITEMSD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLKeys[]", ScriptParser::TYPE_FLOAT, GETTER, GAMELKEYSD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLKeys[]", ScriptParser::TYPE_VOID, SETTER, GAMELKEYSD, 256, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetScreenState", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetScreenState", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetScreenD", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetScreenD", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapScreenD", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetDMapScreenD", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "LoadItemData", ScriptParser::TYPE_ITEMCLASS, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "PlaySound", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "PlayMIDI", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "PlayEnhancedMusic", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapMusicFilename", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapMusicTrack", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetDMapEnhancedMusic", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboData", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboData", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboCSet", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboCSet", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboFlag", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboFlag", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboType", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboType", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboInherentFlag", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboInherentFlag", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetComboSolid", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetComboSolid", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetMIDI", ScriptParser::TYPE_FLOAT, GETTER, GETMIDI, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetScreenFlags", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetScreenEFlags", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapFlags[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPFLAGSD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapFlags[]", ScriptParser::TYPE_VOID, SETTER, DMAPFLAGSD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapLevel[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPLEVELD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapLevel[]", ScriptParser::TYPE_VOID, SETTER, DMAPLEVELD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapCompass[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPCOMPASSD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapCompass[]", ScriptParser::TYPE_VOID, SETTER, DMAPCOMPASSD, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapContinue[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPCONTINUED, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapContinue[]", ScriptParser::TYPE_VOID, SETTER, DMAPCONTINUED, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapMIDI[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPMIDID, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapMIDI[]", ScriptParser::TYPE_VOID, SETTER, DMAPMIDID, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "Save", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "End", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ComboTile", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetSaveName", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "SetSaveName", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetMessage", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapName", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapTitle", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetDMapIntro", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getStandalone", ScriptParser::TYPE_BOOL, GETTER, GAMESTANDALONE, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setStandalone", ScriptParser::TYPE_VOID, SETTER, GAMESTANDALONE, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ShowSaveScreen", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "ShowSaveQuitScreen", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLastEntranceScreen", ScriptParser::TYPE_FLOAT, GETTER, GAMEENTRSCR, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLastEntranceScreen", ScriptParser::TYPE_VOID, SETTER, GAMEENTRSCR, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getLastEntranceDMap", ScriptParser::TYPE_FLOAT, GETTER, GAMEENTRDMAP, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setLastEntranceDMap", ScriptParser::TYPE_VOID, SETTER, GAMEENTRDMAP, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getClickToFreezeEnabled",ScriptParser::TYPE_BOOL, GETTER, GAMECLICKFREEZE, 1, { ScriptParser::TYPE_GAME, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setClickToFreezeEnabled",ScriptParser::TYPE_VOID, SETTER, GAMECLICKFREEZE, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapOffset[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPOFFSET, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapOffset[]", ScriptParser::TYPE_VOID, SETTER, DMAPOFFSET, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDMapMap[]", ScriptParser::TYPE_FLOAT, GETTER, DMAPMAP, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDMapMap[]", ScriptParser::TYPE_VOID, SETTER, DMAPMAP, 512, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetFFCScript", ScriptParser::TYPE_FLOAT, FUNCTION, 0, 1, { ScriptParser::TYPE_GAME, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +GameSymbols::GameSymbols() +{ + table = gameTable; + refVar = NUL; +} + +map > GameSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //itemclass LoadItemData(game, int) + { + int id = memberids["LoadItemData"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OLoadItemDataRegister(new VarArgument(EXP1))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(REFITEMCLASS))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //bool GetScreenState(game, int,int,int) + { + int id = memberids["GetScreenState"]; + int label = lt.functionToLabel(id); + int done = ScriptParser::getUniqueLabelID(); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OMultImmediate(new VarArgument(EXP1), new LiteralArgument(1360000))); + code.push_back(new OAddRegister(new VarArgument(INDEX), new VarArgument(EXP1))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(SCREENSTATEDD))); + code.push_back(new OCompareImmediate(new VarArgument(EXP1), new LiteralArgument(0))); + code.push_back(new OGotoTrueImmediate(new LabelArgument(done))); + code.push_back(new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OGotoImmediate(new LabelArgument(done))); + Opcode *next = new OPopRegister(new VarArgument(EXP2)); + next->setLabel(done); + code.push_back(next); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetScreenState(game, int,int,int,bool) + { + int id = memberids["SetScreenState"]; + int label = lt.functionToLabel(id); + int done = ScriptParser::getUniqueLabelID(); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(SFTEMP)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OSubImmediate(new VarArgument(EXP1), new LiteralArgument(10000))); + code.push_back(new OMultImmediate(new VarArgument(EXP1), new LiteralArgument(1360000))); + code.push_back(new OAddRegister(new VarArgument(INDEX), new VarArgument(EXP1))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OCompareImmediate(new VarArgument(SFTEMP), new LiteralArgument(0))); + code.push_back(new OGotoTrueImmediate(new LabelArgument(done))); + code.push_back(new OSetImmediate(new VarArgument(SFTEMP), new LiteralArgument(10000))); + Opcode *next = new OSetRegister(new VarArgument(SCREENSTATEDD), new VarArgument(SFTEMP)); + next->setLabel(done); + code.push_back(next); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetScreenD(game, int,int) + { + int id = memberids["GetScreenD"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(SDDD))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetScreenD(game, int,int,int) + { + int id = memberids["SetScreenD"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(SFTEMP)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(SDDD), new VarArgument(SFTEMP))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetDMapScreenD(game, int,int,int) + { + int id = memberids["GetDMapScreenD"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(SFTEMP)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(SDDDD))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetDMapScreenD(game, int,int,int,int) + { + int id = memberids["SetDMapScreenD"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(SFTEMP)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(SDDDD), new VarArgument(SFTEMP))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void PlaySound(game, int) + { + int id = memberids["PlaySound"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OPlaySoundRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void PlayMIDI(game, int) + { + int id = memberids["PlayMIDI"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OPlayMIDIRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void PlayEnhancedMusic(game, int, int) + { + int id = memberids["PlayEnhancedMusic"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OPlayEnhancedMusic(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void GetDMapMusicFilename(game, int, int) + { + int id = memberids["GetDMapMusicFilename"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetDMapMusicFilename(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetDMapMusicTrack(game, int) + { + int id = memberids["GetDMapMusicTrack"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetDMapMusicTrack(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void SetDMapEnhancedMusic(game, int,int,int) + { + int id = memberids["SetDMapEnhancedMusic"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OSetDMapEnhancedMusic(); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int GetComboData(int,int,int) + { + int id = memberids["GetComboData"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBODDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboData(int,int,int,int) + { + int id = memberids["SetComboData"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBODDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetComboCSet(int,int,int) + { + int id = memberids["GetComboCSet"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBOCDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboCSet(int,int,int,int) + { + int id = memberids["SetComboCSet"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBOCDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetComboFlag(int,int,int) + { + int id = memberids["GetComboFlag"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBOFDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboFlag(int,int,int,int) + { + int id = memberids["SetComboFlag"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBOFDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetComboType(int,int,int) + { + int id = memberids["GetComboType"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBOTDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboType(int,int,int,int) + { + int id = memberids["SetComboType"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBOTDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetComboInherentFlag(int,int,int) + { + int id = memberids["GetComboInherentFlag"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBOIDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboInherentFlag(int,int,int,int) + { + int id = memberids["SetComboInherentFlag"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBOIDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetComboCollision(int,int,int) + { + int id = memberids["GetComboSolid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(EXP1), new VarArgument(COMBOSDM))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void SetComboCollision(int,int,int,int) + { + int id = memberids["SetComboSolid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetRegister(new VarArgument(COMBOSDM), new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetScreenFlags(game,int,int,int) + { + int id = memberids["GetScreenFlags"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetScreenFlags(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //int GetScreenEFlags(game,int,int,int) + { + int id = memberids["GetScreenEFlags"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(INDEX)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(INDEX2))); + code.push_back(new OPopRegister(new VarArgument(EXP1))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetScreenEFlags(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void Save(game) + { + int id = memberids["Save"]; + int label = lt.functionToLabel(id); + vector code; + //pop pointer, and ignore it + Opcode *first = new OPopRegister(new VarArgument(NUL)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OSave()); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void End(game) + { + int id = memberids["End"]; + int label = lt.functionToLabel(id); + vector code; + //pop pointer, and ignore it + Opcode *first = new OPopRegister(new VarArgument(NUL)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OEnd()); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //int ComboTile(game,int) + { + int id = memberids["ComboTile"]; + int label = lt.functionToLabel(id); + vector code; + Opcode *first = new OPopRegister(new VarArgument(EXP2)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OComboTile(new VarArgument(EXP1),new VarArgument(EXP2))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + //void GetSaveName(game, int) + { + int id = memberids["GetSaveName"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetSaveName(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void GetSaveName(game, int) + { + int id = memberids["SetSaveName"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OSetSaveName(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //GetMessage(game, int, int) + { + int id = memberids["GetMessage"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + code.push_back(new OGetMessage(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //GetDMapName(game, int, int) + { + int id = memberids["GetDMapName"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + code.push_back(new OGetDMapName(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //GetDMapTitle(game, int, int) + { + int id = memberids["GetDMapTitle"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + code.push_back(new OGetDMapTitle(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //GetDMapIntro(game, int, int) + { + int id = memberids["GetDMapIntro"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the params + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(SFTEMP))); + code.push_back(new OGetDMapIntro(new VarArgument(EXP2), new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + + //bool ShowSaveScreen(game) + { + int id = memberids["ShowSaveScreen"]; + int label = lt.functionToLabel(id); + vector code; + //pop pointer, and ignore it + Opcode *first = new OPopRegister(new VarArgument(NUL)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OShowSaveScreen(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + + //void ShowSaveQuitScreen(game) + { + int id = memberids["ShowSaveQuitScreen"]; + int label = lt.functionToLabel(id); + vector code; + //pop pointer, and ignore it + Opcode *first = new OPopRegister(new VarArgument(NUL)); + first->setLabel(label); + code.push_back(first); + code.push_back(new OShowSaveQuitScreen()); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + + //int GetFFCScript(game, int) + { + int id = memberids["GetFFCScript"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetFFCScript(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label]=code; + } + return rval; +} + +NPCSymbols NPCSymbols::singleton = NPCSymbols(); + +static AccessorTable npcTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getX", ScriptParser::TYPE_FLOAT, GETTER, NPCX, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, NPCX, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, NPCY, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, NPCY, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getZ", ScriptParser::TYPE_FLOAT, GETTER, NPCZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setZ", ScriptParser::TYPE_VOID, SETTER, NPCZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getJump", ScriptParser::TYPE_FLOAT, GETTER, NPCJUMP, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setJump", ScriptParser::TYPE_VOID, SETTER, NPCJUMP, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDir", ScriptParser::TYPE_FLOAT, GETTER, NPCDIR, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDir", ScriptParser::TYPE_VOID, SETTER, NPCDIR, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getRate", ScriptParser::TYPE_FLOAT, GETTER, NPCRATE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setRate", ScriptParser::TYPE_VOID, SETTER, NPCRATE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHoming", ScriptParser::TYPE_FLOAT, GETTER, NPCHOMING, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHoming", ScriptParser::TYPE_VOID, SETTER, NPCHOMING, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getStep", ScriptParser::TYPE_FLOAT, GETTER, NPCSTEP, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setStep", ScriptParser::TYPE_VOID, SETTER, NPCSTEP, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getASpeed", ScriptParser::TYPE_FLOAT, GETTER, NPCFRAMERATE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setASpeed", ScriptParser::TYPE_VOID, SETTER, NPCFRAMERATE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHaltrate", ScriptParser::TYPE_FLOAT, GETTER, NPCHALTRATE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHaltrate", ScriptParser::TYPE_VOID, SETTER, NPCHALTRATE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawStyle", ScriptParser::TYPE_FLOAT, GETTER, NPCDRAWTYPE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawStyle", ScriptParser::TYPE_VOID, SETTER, NPCDRAWTYPE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHP", ScriptParser::TYPE_FLOAT, GETTER, NPCHP, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHP", ScriptParser::TYPE_VOID, SETTER, NPCHP, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getID", ScriptParser::TYPE_FLOAT, GETTER, NPCID, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setID", ScriptParser::TYPE_VOID, SETTER, NPCID, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getType", ScriptParser::TYPE_FLOAT, GETTER, NPCTYPE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setType", ScriptParser::TYPE_VOID, SETTER, NPCTYPE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDamage", ScriptParser::TYPE_FLOAT, GETTER, NPCDP, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDamage", ScriptParser::TYPE_VOID, SETTER, NPCDP, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getWeaponDamage", ScriptParser::TYPE_FLOAT, GETTER, NPCWDP, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setWeaponDamage", ScriptParser::TYPE_VOID, SETTER, NPCWDP, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTile", ScriptParser::TYPE_FLOAT, GETTER, NPCTILE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTile", ScriptParser::TYPE_VOID, SETTER, NPCTILE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalTile", ScriptParser::TYPE_FLOAT, GETTER, NPCOTILE, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setOriginalTile", ScriptParser::TYPE_VOID, SETTER, NPCOTILE, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getWeapon", ScriptParser::TYPE_FLOAT, GETTER, NPCWEAPON, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setWeapon", ScriptParser::TYPE_VOID, SETTER, NPCWEAPON, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getItemSet", ScriptParser::TYPE_FLOAT, GETTER, NPCITEMSET, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setItemSet", ScriptParser::TYPE_VOID, SETTER, NPCITEMSET, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCSet", ScriptParser::TYPE_FLOAT, GETTER, NPCCSET, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCSet", ScriptParser::TYPE_VOID, SETTER, NPCCSET, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getBossPal", ScriptParser::TYPE_FLOAT, GETTER, NPCBOSSPAL, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setBossPal", ScriptParser::TYPE_VOID, SETTER, NPCBOSSPAL, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getSFX", ScriptParser::TYPE_FLOAT, GETTER, NPCBGSFX, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setSFX", ScriptParser::TYPE_VOID, SETTER, NPCBGSFX, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getExtend", ScriptParser::TYPE_FLOAT, GETTER, NPCEXTEND, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setExtend", ScriptParser::TYPE_VOID, SETTER, NPCEXTEND, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitWidth", ScriptParser::TYPE_FLOAT, GETTER, NPCHXSZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitWidth", ScriptParser::TYPE_VOID, SETTER, NPCHXSZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitHeight", ScriptParser::TYPE_FLOAT, GETTER, NPCHYSZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitHeight", ScriptParser::TYPE_VOID, SETTER, NPCHYSZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitZHeight", ScriptParser::TYPE_FLOAT, GETTER, NPCHZSZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitZHeight", ScriptParser::TYPE_VOID, SETTER, NPCHZSZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, NPCTXSZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, NPCTXSZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, NPCTYSZ, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, NPCTYSZ, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawXOffset", ScriptParser::TYPE_FLOAT, GETTER, NPCXOFS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawXOffset", ScriptParser::TYPE_VOID, SETTER, NPCXOFS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawYOffset", ScriptParser::TYPE_FLOAT, GETTER, NPCYOFS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawYOffset", ScriptParser::TYPE_VOID, SETTER, NPCYOFS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawZOffset", ScriptParser::TYPE_FLOAT, GETTER, NPCZOFS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawZOffset", ScriptParser::TYPE_VOID, SETTER, NPCZOFS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitXOffset", ScriptParser::TYPE_FLOAT, GETTER, NPCHXOFS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitXOffset", ScriptParser::TYPE_VOID, SETTER, NPCHXOFS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitYOffset", ScriptParser::TYPE_FLOAT, GETTER, NPCHYOFS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitYOffset", ScriptParser::TYPE_VOID, SETTER, NPCHYOFS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "isValid", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, NPCMISCD, 16, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, NPCMISCD, 16, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAttributes[]", ScriptParser::TYPE_FLOAT, GETTER, NPCDD, 10, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAttributes[]", ScriptParser::TYPE_VOID, SETTER, NPCDD, 10, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMiscFlags", ScriptParser::TYPE_FLOAT, GETTER, NPCMFLAGS, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMiscFlags", ScriptParser::TYPE_VOID, SETTER, NPCMFLAGS, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCollDetection", ScriptParser::TYPE_FLOAT, GETTER, NPCCOLLDET, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCollDetection", ScriptParser::TYPE_VOID, SETTER, NPCCOLLDET, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getStun", ScriptParser::TYPE_FLOAT, GETTER, NPCSTUN, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setStun", ScriptParser::TYPE_VOID, SETTER, NPCSTUN, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDefense[]", ScriptParser::TYPE_FLOAT, GETTER, NPCDEFENSED, 16, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDefense[]", ScriptParser::TYPE_VOID, SETTER, NPCDEFENSED, 16, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "GetName", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHunger", ScriptParser::TYPE_FLOAT, GETTER, NPCHUNGER, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHunger", ScriptParser::TYPE_VOID, SETTER, NPCHUNGER, 1, { ScriptParser::TYPE_NPC, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "BreakShield", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_NPC, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +NPCSymbols::NPCSymbols() +{ + table = npcTable; + refVar = REFNPC; +} + +map > NPCSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + //bool isValid(npc) + { + int id = memberids["isValid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the pointer + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //Check validity + code.push_back(new OIsValidNPC(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void GetName(npc, int) + { + int id = memberids["GetName"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the param + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop pointer, and ignore it + code.push_back(new OPopRegister(new VarArgument(NUL))); + code.push_back(new OGetNPCName(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void BreakShield(npc) + { + int id = memberids["BreakShield"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the pointer + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //Break shield + code.push_back(new OBreakShield(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + return rval; +} + +LinkWeaponSymbols LinkWeaponSymbols::singleton = LinkWeaponSymbols(); + +static AccessorTable lwpnTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getX", ScriptParser::TYPE_FLOAT, GETTER, LWPNX, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, LWPNX, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, LWPNY, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, LWPNY, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getZ", ScriptParser::TYPE_FLOAT, GETTER, LWPNZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setZ", ScriptParser::TYPE_VOID, SETTER, LWPNZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getJump", ScriptParser::TYPE_FLOAT, GETTER, LWPNJUMP, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setJump", ScriptParser::TYPE_VOID, SETTER, LWPNJUMP, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDir", ScriptParser::TYPE_FLOAT, GETTER, LWPNDIR, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDir", ScriptParser::TYPE_VOID, SETTER, LWPNDIR, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAngle", ScriptParser::TYPE_FLOAT, GETTER, LWPNANGLE, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAngle", ScriptParser::TYPE_VOID, SETTER, LWPNANGLE, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getStep", ScriptParser::TYPE_FLOAT, GETTER, LWPNSTEP, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setStep", ScriptParser::TYPE_VOID, SETTER, LWPNSTEP, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getNumFrames", ScriptParser::TYPE_FLOAT, GETTER, LWPNFRAMES, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setNumFrames", ScriptParser::TYPE_VOID, SETTER, LWPNFRAMES, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFrame", ScriptParser::TYPE_FLOAT, GETTER, LWPNFRAME, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFrame", ScriptParser::TYPE_VOID, SETTER, LWPNFRAME, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawStyle", ScriptParser::TYPE_FLOAT, GETTER, LWPNDRAWTYPE, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawStyle", ScriptParser::TYPE_VOID, SETTER, LWPNDRAWTYPE, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDamage", ScriptParser::TYPE_FLOAT, GETTER, LWPNPOWER, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDamage", ScriptParser::TYPE_VOID, SETTER, LWPNPOWER, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getID", ScriptParser::TYPE_FLOAT, GETTER, LWPNID, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setID", ScriptParser::TYPE_VOID, SETTER, LWPNID, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAngular", ScriptParser::TYPE_BOOL, GETTER, LWPNANGULAR, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAngular", ScriptParser::TYPE_VOID, SETTER, LWPNANGULAR, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getBehind", ScriptParser::TYPE_BOOL, GETTER, LWPNBEHIND, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setBehind", ScriptParser::TYPE_VOID, SETTER, LWPNBEHIND, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getASpeed", ScriptParser::TYPE_FLOAT, GETTER, LWPNASPEED, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setASpeed", ScriptParser::TYPE_VOID, SETTER, LWPNASPEED, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTile", ScriptParser::TYPE_FLOAT, GETTER, LWPNTILE, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTile", ScriptParser::TYPE_VOID, SETTER, LWPNTILE, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlashCSet", ScriptParser::TYPE_FLOAT, GETTER, LWPNFLASHCSET, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlashCSet", ScriptParser::TYPE_VOID, SETTER, LWPNFLASHCSET, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDeadState", ScriptParser::TYPE_FLOAT, GETTER, LWPNDEAD, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDeadState", ScriptParser::TYPE_VOID, SETTER, LWPNDEAD, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCSet", ScriptParser::TYPE_FLOAT, GETTER, LWPNCSET, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCSet", ScriptParser::TYPE_VOID, SETTER, LWPNCSET, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlash", ScriptParser::TYPE_BOOL, GETTER, LWPNFLASH, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlash", ScriptParser::TYPE_VOID, SETTER, LWPNFLASH, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlip", ScriptParser::TYPE_FLOAT, GETTER, LWPNFLIP, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlip", ScriptParser::TYPE_VOID, SETTER, LWPNFLIP, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalTile", ScriptParser::TYPE_FLOAT, GETTER, LWPNOTILE, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setOriginalTile", ScriptParser::TYPE_VOID, SETTER, LWPNOTILE, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalCSet", ScriptParser::TYPE_FLOAT, GETTER, LWPNOCSET, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setOriginalCSet", ScriptParser::TYPE_VOID, SETTER, LWPNOCSET, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getExtend", ScriptParser::TYPE_FLOAT, GETTER, LWPNEXTEND, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setExtend", ScriptParser::TYPE_VOID, SETTER, LWPNEXTEND, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitWidth", ScriptParser::TYPE_FLOAT, GETTER, LWPNHXSZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitWidth", ScriptParser::TYPE_VOID, SETTER, LWPNHXSZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitHeight", ScriptParser::TYPE_FLOAT, GETTER, LWPNHYSZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitHeight", ScriptParser::TYPE_VOID, SETTER, LWPNHYSZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitZHeight", ScriptParser::TYPE_FLOAT, GETTER, LWPNHZSZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitZHeight", ScriptParser::TYPE_VOID, SETTER, LWPNHZSZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, LWPNTXSZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, LWPNTXSZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, LWPNTYSZ, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, LWPNTYSZ, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawXOffset", ScriptParser::TYPE_FLOAT, GETTER, LWPNXOFS, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawXOffset", ScriptParser::TYPE_VOID, SETTER, LWPNXOFS, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawYOffset", ScriptParser::TYPE_FLOAT, GETTER, LWPNYOFS, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawYOffset", ScriptParser::TYPE_VOID, SETTER, LWPNYOFS, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawZOffset", ScriptParser::TYPE_FLOAT, GETTER, LWPNZOFS, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawZOffset", ScriptParser::TYPE_VOID, SETTER, LWPNZOFS, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitXOffset", ScriptParser::TYPE_FLOAT, GETTER, LWPNHXOFS, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitXOffset", ScriptParser::TYPE_VOID, SETTER, LWPNHXOFS, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitYOffset", ScriptParser::TYPE_FLOAT, GETTER, LWPNHYOFS, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitYOffset", ScriptParser::TYPE_VOID, SETTER, LWPNHYOFS, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "isValid", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "UseSprite", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, LWPNMISCD, 16, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, LWPNMISCD, 16, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCollDetection", ScriptParser::TYPE_FLOAT, GETTER, LWPNCOLLDET, 1, { ScriptParser::TYPE_LWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCollDetection", ScriptParser::TYPE_VOID, SETTER, LWPNCOLLDET, 1, { ScriptParser::TYPE_LWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +LinkWeaponSymbols::LinkWeaponSymbols() +{ + table = lwpnTable; + refVar = REFLWPN; +} + +map > LinkWeaponSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + int id=-1; + //bool isValid(lweapon) + { + id = memberids["isValid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the pointer + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //Check validity + code.push_back(new OIsValidLWpn(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void UseSprite(lweapon, int val) + { + id = memberids["UseSprite"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the val + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop off the pointer + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OUseSpriteLWpn(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + return rval; +} + +EnemyWeaponSymbols EnemyWeaponSymbols::singleton = EnemyWeaponSymbols(); + +static AccessorTable ewpnTable[] = +{ + //name, rettype, setorget, var, numindex, params + { "getX", ScriptParser::TYPE_FLOAT, GETTER, EWPNX, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setX", ScriptParser::TYPE_VOID, SETTER, EWPNX, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getY", ScriptParser::TYPE_FLOAT, GETTER, EWPNY, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setY", ScriptParser::TYPE_VOID, SETTER, EWPNY, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getZ", ScriptParser::TYPE_FLOAT, GETTER, EWPNZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setZ", ScriptParser::TYPE_VOID, SETTER, EWPNZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getJump", ScriptParser::TYPE_FLOAT, GETTER, EWPNJUMP, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setJump", ScriptParser::TYPE_VOID, SETTER, EWPNJUMP, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDir", ScriptParser::TYPE_FLOAT, GETTER, EWPNDIR, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDir", ScriptParser::TYPE_VOID, SETTER, EWPNDIR, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAngle", ScriptParser::TYPE_FLOAT, GETTER, EWPNANGLE, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAngle", ScriptParser::TYPE_VOID, SETTER, EWPNANGLE, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getStep", ScriptParser::TYPE_FLOAT, GETTER, EWPNSTEP, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setStep", ScriptParser::TYPE_VOID, SETTER, EWPNSTEP, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getNumFrames", ScriptParser::TYPE_FLOAT, GETTER, EWPNFRAMES, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setNumFrames", ScriptParser::TYPE_VOID, SETTER, EWPNFRAMES, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFrame", ScriptParser::TYPE_FLOAT, GETTER, EWPNFRAME, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFrame", ScriptParser::TYPE_VOID, SETTER, EWPNFRAME, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawStyle", ScriptParser::TYPE_FLOAT, GETTER, EWPNDRAWTYPE, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawStyle", ScriptParser::TYPE_VOID, SETTER, EWPNDRAWTYPE, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDamage", ScriptParser::TYPE_FLOAT, GETTER, EWPNPOWER, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDamage", ScriptParser::TYPE_VOID, SETTER, EWPNPOWER, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getID", ScriptParser::TYPE_FLOAT, GETTER, EWPNID, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setID", ScriptParser::TYPE_VOID, SETTER, EWPNID, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getAngular", ScriptParser::TYPE_BOOL, GETTER, EWPNANGULAR, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setAngular", ScriptParser::TYPE_VOID, SETTER, EWPNANGULAR, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getBehind", ScriptParser::TYPE_BOOL, GETTER, EWPNBEHIND, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setBehind", ScriptParser::TYPE_VOID, SETTER, EWPNBEHIND, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getASpeed", ScriptParser::TYPE_FLOAT, GETTER, EWPNASPEED, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setASpeed", ScriptParser::TYPE_VOID, SETTER, EWPNASPEED, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTile", ScriptParser::TYPE_FLOAT, GETTER, EWPNTILE, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTile", ScriptParser::TYPE_VOID, SETTER, EWPNTILE, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlashCSet", ScriptParser::TYPE_FLOAT, GETTER, EWPNFLASHCSET, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlashCSet", ScriptParser::TYPE_VOID, SETTER, EWPNFLASHCSET, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDeadState", ScriptParser::TYPE_FLOAT, GETTER, EWPNDEAD, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDeadState", ScriptParser::TYPE_VOID, SETTER, EWPNDEAD, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCSet", ScriptParser::TYPE_FLOAT, GETTER, EWPNCSET, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCSet", ScriptParser::TYPE_VOID, SETTER, EWPNCSET, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlash", ScriptParser::TYPE_BOOL, GETTER, EWPNFLASH, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlash", ScriptParser::TYPE_VOID, SETTER, EWPNFLASH, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getFlip", ScriptParser::TYPE_FLOAT, GETTER, EWPNFLIP, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setFlip", ScriptParser::TYPE_VOID, SETTER, EWPNFLIP, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalTile", ScriptParser::TYPE_FLOAT, GETTER, EWPNOTILE, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setOriginalTile", ScriptParser::TYPE_VOID, SETTER, EWPNOTILE, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getOriginalCSet", ScriptParser::TYPE_FLOAT, GETTER, EWPNOCSET, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setOriginalCSet", ScriptParser::TYPE_VOID, SETTER, EWPNOCSET, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getExtend", ScriptParser::TYPE_FLOAT, GETTER, EWPNEXTEND, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setExtend", ScriptParser::TYPE_VOID, SETTER, EWPNEXTEND, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitWidth", ScriptParser::TYPE_FLOAT, GETTER, EWPNHXSZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitWidth", ScriptParser::TYPE_VOID, SETTER, EWPNHXSZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitHeight", ScriptParser::TYPE_FLOAT, GETTER, EWPNHYSZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitHeight", ScriptParser::TYPE_VOID, SETTER, EWPNHYSZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitZHeight", ScriptParser::TYPE_FLOAT, GETTER, EWPNHZSZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitZHeight", ScriptParser::TYPE_VOID, SETTER, EWPNHZSZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileWidth", ScriptParser::TYPE_FLOAT, GETTER, EWPNTXSZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileWidth", ScriptParser::TYPE_VOID, SETTER, EWPNTXSZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getTileHeight", ScriptParser::TYPE_FLOAT, GETTER, EWPNTYSZ, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setTileHeight", ScriptParser::TYPE_VOID, SETTER, EWPNTYSZ, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawXOffset", ScriptParser::TYPE_FLOAT, GETTER, EWPNXOFS, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawXOffset", ScriptParser::TYPE_VOID, SETTER, EWPNXOFS, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawYOffset", ScriptParser::TYPE_FLOAT, GETTER, EWPNYOFS, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawYOffset", ScriptParser::TYPE_VOID, SETTER, EWPNYOFS, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getDrawZOffset", ScriptParser::TYPE_FLOAT, GETTER, EWPNZOFS, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setDrawZOffset", ScriptParser::TYPE_VOID, SETTER, EWPNZOFS, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitXOffset", ScriptParser::TYPE_FLOAT, GETTER, EWPNHXOFS, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitXOffset", ScriptParser::TYPE_VOID, SETTER, EWPNHXOFS, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getHitYOffset", ScriptParser::TYPE_FLOAT, GETTER, EWPNHYOFS, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setHitYOffset", ScriptParser::TYPE_VOID, SETTER, EWPNHYOFS, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "isValid", ScriptParser::TYPE_BOOL, FUNCTION, 0, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "UseSprite", ScriptParser::TYPE_VOID, FUNCTION, 0, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getMisc[]", ScriptParser::TYPE_FLOAT, GETTER, EWPNMISCD, 16, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setMisc[]", ScriptParser::TYPE_VOID, SETTER, EWPNMISCD, 16, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_FLOAT, ScriptParser::TYPE_FLOAT, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "getCollDetection", ScriptParser::TYPE_FLOAT, GETTER, EWPNCOLLDET, 1, { ScriptParser::TYPE_EWPN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "setCollDetection", ScriptParser::TYPE_VOID, SETTER, EWPNCOLLDET, 1, { ScriptParser::TYPE_EWPN, ScriptParser::TYPE_BOOL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } }, + { "", -1, -1, -1, -1, { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } +}; + +EnemyWeaponSymbols::EnemyWeaponSymbols() +{ + table = ewpnTable; + refVar = REFEWPN; +} + +map > EnemyWeaponSymbols::addSymbolsCode(LinkTable <) +{ + map > rval = LibrarySymbols::addSymbolsCode(lt); + int id=-1; + //bool isValid(eweapon) + { + id = memberids["isValid"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the pointer + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //Check validity + code.push_back(new OIsValidEWpn(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + //void UseSprite(eweapon, int val) + { + id = memberids["UseSprite"]; + int label = lt.functionToLabel(id); + vector code; + //pop off the val + Opcode *first = new OPopRegister(new VarArgument(EXP1)); + first->setLabel(label); + code.push_back(first); + //pop off the pointer + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OSetRegister(new VarArgument(refVar), new VarArgument(EXP2))); + code.push_back(new OUseSpriteEWpn(new VarArgument(EXP1))); + code.push_back(new OPopRegister(new VarArgument(EXP2))); + code.push_back(new OGotoRegister(new VarArgument(EXP2))); + rval[label] = code; + } + return rval; +} + diff --git a/src/parser/GlobalSymbols.h b/src/parser/GlobalSymbols.h new file mode 100644 index 0000000000..49f9e82ff6 --- /dev/null +++ b/src/parser/GlobalSymbols.h @@ -0,0 +1,187 @@ +#ifndef GLOBALSYMBOLS_H +#define GLOBALSYMBOLS_H + +#include "DataStructs.h" +#include +#include +#include + +using std::string; +using std::map; +using std::vector; + +class Scope; +class SymbolTable; + +static const int SETTER = 0; +static const int GETTER = 1; +static const int FUNCTION = 2; + +struct AccessorTable +{ + string name; + int rettype; + int setorget; + int var; + int numindex; + int params[20]; +}; + +class LibrarySymbols +{ +public: + virtual void addSymbolsToScope(Scope *scope, SymbolTable *t); + virtual map > addSymbolsCode(LinkTable <); + virtual pair > matchFunction(string name, SymbolTable *t); + virtual ~LibrarySymbols(); +protected: + AccessorTable *table; + LibrarySymbols() {} + int firstid; + int refVar; + map memberids; + virtual vector getVariable(LinkTable <, int id, int var); + virtual vector setVariable(LinkTable <, int id, int var); + virtual vector setBoolVariable(LinkTable <, int id, int var); + virtual vector getIndexedVariable(LinkTable <, int id, int var); + virtual vector setIndexedVariable(LinkTable <, int id, int var); + +}; + +class GlobalSymbols : public LibrarySymbols +{ +public: + static GlobalSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static GlobalSymbols singleton; + GlobalSymbols(); +}; + +class FFCSymbols : public LibrarySymbols +{ +public: + static FFCSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static FFCSymbols singleton; + FFCSymbols(); +}; + +class LinkSymbols : public LibrarySymbols +{ +public: + static LinkSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static LinkSymbols singleton; + LinkSymbols(); +}; + +class ScreenSymbols : public LibrarySymbols +{ +public: + static ScreenSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static ScreenSymbols singleton; + ScreenSymbols(); +}; + +class ItemSymbols : public LibrarySymbols +{ +public: + static ItemSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +protected: +private: + static ItemSymbols singleton; + ItemSymbols(); +}; + +class ItemclassSymbols : public LibrarySymbols +{ +public: + static ItemclassSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static ItemclassSymbols singleton; + ItemclassSymbols(); +}; + +class GameSymbols : public LibrarySymbols +{ +public: + static GameSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +private: + static GameSymbols singleton; + GameSymbols(); +}; + +class NPCSymbols : public LibrarySymbols +{ +public: + static NPCSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +protected: +private: + static NPCSymbols singleton; + NPCSymbols(); +}; + +class LinkWeaponSymbols : public LibrarySymbols +{ +public: + static LinkWeaponSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +protected: +private: + static LinkWeaponSymbols singleton; + LinkWeaponSymbols(); +}; + +class EnemyWeaponSymbols : public LibrarySymbols +{ +public: + static EnemyWeaponSymbols &getInst() + { + return singleton; + } + map > addSymbolsCode(LinkTable <); +protected: +private: + static EnemyWeaponSymbols singleton; + EnemyWeaponSymbols(); +}; + + +#endif + diff --git a/src/parser/ParseError.cpp b/src/parser/ParseError.cpp new file mode 100644 index 0000000000..23fb3a340b --- /dev/null +++ b/src/parser/ParseError.cpp @@ -0,0 +1,217 @@ + +#include "../precompiled.h" //always first + +#include "ParseError.h" +#include "../zsyssimple.h" +#include +#include +#include +#include +using namespace std; +void printErrorMsg(AST *offender, int errorID, string param) +{ + ostringstream oss; + + if(offender) + { + LocationData d = offender->getLocation(); + oss << d.fname << ", line " << d.first_line << ": "; + } + + switch(errorID) + { + case CANTOPENSOURCE: + oss << "Fatal Error P00: Can't open or parse input file!"; + break; + + case CANTOPENIMPORT: + oss << "Error P01 : Failure to parse imported file " << param.c_str() << "."; + break; + + case IMPORTRECURSION: + oss << "Fatal Error P02: Recursion limit of " << RECURSIONLIMIT << " hit while preprocessing. Perhaps you have circular imports?"; + break; + + case IMPORTBADSCOPE: + oss << "Error P03: You may only place import statements at file scope."; + break; + + case FUNCTIONREDEF: + oss << "Error S04: Function " << param << " was already declared with that type signature." ; + break; + + case FUNCTIONVOIDPARAM: + oss << "Error S05: Function parameter " << param << " cannot have void type." ; + break; + + case SCRIPTREDEF: + oss << "Error S06: Duplicate script with name " << param << " already exists." ; + break; + + case VOIDVAR: + oss << "Error S07: Variable " << param << " can't have type void." ; + break; + + case VOIDARR: + oss << "Error S39: Array " << param << " can't have type void." ; + break; + + case VARREDEF: + oss << "Error S08: There is already a variable with name " << param << " defined in this scope." ; + break; + + case ARRREDEF: + oss << "Error S41: There is already an array with name " << param << " defined in this scope." ; + break; + + case VARUNDECLARED: + oss << "Error S09: Variable " << param << " is undeclared." ; + break; + + case FUNCUNDECLARED: + oss << "Error S10: Function " << param << " is undeclared." ; + break; + + case SCRIPTNORUN: + oss << "Error S11: Script " << param << " must implement void run()." ; + break; + + case SCRIPTRUNNOTVOID: + oss << "Error S12: Script " << param << "'s run() must have return type void." ; + break; + + case SCRIPTNUMNOTINT: + oss << "Error T13: Script " << param << " has id that's not an integer." ; + break; + + case SCRIPTNUMTOOBIG: + oss << "Error T14: Script " << param << "'s id must be between 0 and 255." ; + break; + + case SCRIPTNUMREDEF: + oss << "Error T15: Script " << param << "'s id is already in use." ; + break; + + case IMPLICITCAST: + oss << "Warning T16: Cast from " << param << "." ; + break; + + case ILLEGALCAST: + oss << "Error T17: Cannot cast from " << param << "." ; + break; + + case VOIDEXPR: + oss << "Error T18: Operand is void." ; + break; + + case DIVBYZERO: + oss << "Error T19: Constant division by zero." ; + break; + + case CONSTTRUNC: + oss << "Warning T20: Truncation of constant " << param << "." ; + break; + + case NOFUNCMATCH: + oss << "Error T21: Could not match type signature " << param << "." ; + break; + + case TOOFUNCMATCH: + oss << "Error T22: Two or more functions match type signature " << param << "." ; + break; + + case FUNCBADRETURN: + oss << "Error T23: This function must return a value." ; + break; + + case TOOMANYGLOBAL: + oss << "Error L24: Too many global variables." ; + break; + + case SHIFTNOTINT: + oss << "Warning T25: Constant bitshift by noninteger amount; truncating to nearest integer." ; + break; + + case REFVAR: + oss << "Error S26: Pointer types (ffc, etc) cannot be declared as global variables." ; + break; + + case ARROWNOTPOINTER: + oss << "Error T27: Left of the arrow (->) operator must be a pointer type (ffc, etc)." ; + break; + + case ARROWNOFUNC: + oss << "Error T28: That pointer type does not have a function " << param << "." ; + break; + + case ARROWNOVAR: + oss << "Error T29: That pointer type does not have a variable " << param << "." ; + break; + + case TOOMANYRUN: + oss << "Error S30: Script " << param << " may have only one run method." ; + break; + + case INDEXNOTINT: + oss << "Error T31: The index of " << param << " must be an integer." ; + break; + + case SCRIPTBADTYPE: + oss << "Error S32: Script " << param << " is of illegal type."; + break; + + case BREAKBAD: + oss << "Error G33: Break must lie inside of an enclosing for or while loop."; + break; + + case CONTINUEBAD: + oss << "Error G34: Continue must lie inside of an enclosing for or while loop."; + break; + + case CONSTREDEF: + oss << "Error P35: There is already a constant with name " << param << " defined."; + break; + + case LVALCONST: + oss << "Error T36: Cannot change the value of constant variable " << param << "."; + break; + + case BADGLOBALINIT: + oss << "Error T37: Global variables can only be initialized to constants or globals declared in the same script."; + break; + + case DEPRECATEDGLOBAL: + oss << "Warning S38: Script-scope global variable declaration syntax is deprecated; put declarations at file scope instead."; + break; + + case REFARR: + oss << "Error S40: Pointer types (ffc, etc) cannot be declared as global arrays." ; + break; + + case ARRAYTOOSMALL: + oss << "Error O1: Array is too small." ; + break; + + case ARRAYLISTTOOLARGE: + oss << "Error O2: Array initializer larger than specified dimensions." ; + break; + + case ARRAYLISTSTRINGTOOLARGE: + oss << "Error O3: String array initializer larger than specified dimensions, space must be allocated for NULL terminator." ; + break; + + case NONINTEGERARRAYSIZE: + oss << "Error T38: Arrays can only be initialized to numerical values" ; + + default: + oss << "FATAL FATAL ERROR I0: bad internal error code" ; + assert(false); + break; + } + +#ifndef SCRIPTPARSER_COMPILE + box_out(oss.str().c_str()); + box_eol(); +#endif +} + diff --git a/src/parser/ParseError.h b/src/parser/ParseError.h new file mode 100644 index 0000000000..54ef815c1e --- /dev/null +++ b/src/parser/ParseError.h @@ -0,0 +1,58 @@ +#ifndef PARSEERROR_H +#define PARSEERROR_H + +#include "AST.h" +#include + +using std::string; + +void printErrorMsg(AST *offender, int errorID, string param=string()); + +#define CANTOPENSOURCE 0 +#define CANTOPENIMPORT 1 +#define IMPORTRECURSION 2 +#define IMPORTBADSCOPE 3 //DEPRECATED +#define FUNCTIONREDEF 4 +#define FUNCTIONVOIDPARAM 5 +#define SCRIPTREDEF 6 +#define VOIDVAR 7 +#define VARREDEF 8 +#define VARUNDECLARED 9 +#define FUNCUNDECLARED 10 +#define SCRIPTNORUN 11 +#define SCRIPTRUNNOTVOID 12 +#define SCRIPTNUMNOTINT 13 //DEPRECATED +#define SCRIPTNUMTOOBIG 14 //DEPRECATED +#define SCRIPTNUMREDEF 15 //DEPRECATED +#define IMPLICITCAST 16 +#define ILLEGALCAST 17 +#define VOIDEXPR 18 //DEPRECATED +#define DIVBYZERO 19 +#define CONSTTRUNC 20 +#define NOFUNCMATCH 21 +#define TOOFUNCMATCH 22 +#define FUNCBADRETURN 23 +#define TOOMANYGLOBAL 24 +#define SHIFTNOTINT 25 +#define REFVAR 26 +#define ARROWNOTPOINTER 27 +#define ARROWNOFUNC 28 +#define ARROWNOVAR 29 +#define TOOMANYRUN 30 +#define INDEXNOTINT 31 //DEPRECATED +#define SCRIPTBADTYPE 32 +#define BREAKBAD 33 +#define CONTINUEBAD 34 +#define CONSTREDEF 35 +#define LVALCONST 36 +#define BADGLOBALINIT 37 +#define DEPRECATEDGLOBAL 38 +#define VOIDARR 39 +#define REFARR 40 +#define ARRREDEF 41 +#define ARRAYTOOSMALL 42 +#define ARRAYLISTTOOLARGE 43 +#define ARRAYLISTSTRINGTOOLARGE 44 +#define NONINTEGERARRAYSIZE 45 +#endif + diff --git a/src/parser/Scope.cpp b/src/parser/Scope.cpp new file mode 100644 index 0000000000..a5ef2cff55 --- /dev/null +++ b/src/parser/Scope.cpp @@ -0,0 +1,189 @@ +#include "ScriptParser.h" +#include +#include +#include +#include +using namespace std; + +int VariableSymbols::addVariable(string name, int type) +{ + + map >::iterator it = symbols.find(name); + + if(it != symbols.end()) + return -1; + + int id = ScriptParser::getUniqueVarID(); + symbols[name] = pair(type, id); + return id; +} + +bool VariableSymbols::containsVariable(string name) +{ + return (symbols.find(name) != symbols.end()); +} + +int VariableSymbols::getID(string name) +{ + map >::iterator it = symbols.find(name); + assert(it != symbols.end()); + return it->second.second; +} + +int FunctionSymbols::addFunction(string name, int rettype, vector paramtype) +{ + map >, pair >::iterator it = symbols.find(pair >(name, paramtype)); + + if(it != symbols.end()) + return -1; + + int id = ScriptParser::getUniqueFuncID(); + symbols[pair >(name, paramtype)] = pair(rettype, id); + map >::iterator it2 = ambiguous.find(name); + + if(it2 == ambiguous.end()) + { + vector newv; + newv.push_back(id); + ambiguous[name] = newv; + } + else + { + (*it2).second.push_back(id); + } + + return id; +} + +bool FunctionSymbols::containsFunction(string name, vector ¶ms) +{ + return symbols.find(pair >(name,params)) != symbols.end(); +} + +int FunctionSymbols::getID(string name, vector ¶ms) +{ + map >, pair >::iterator it = symbols.find(pair >(name, params)); + assert(it != symbols.end()); + return it->second.second; +} + +vector FunctionSymbols::getFuncIDs(string name) +{ + map >::iterator it = ambiguous.find(name); + + if(it == ambiguous.end()) + return vector(); + + return it->second; +} + +bool Scope::addNamedChild(string name, Scope *child) +{ + map::iterator it = namedChildren.find(name); + + if(it != namedChildren.end()) + return false; + + namedChildren[name]=child; + return true; +} + +Scope::~Scope() +{ + map::iterator it; + + for(it = namedChildren.begin(); it != namedChildren.end(); it++) + { + delete it->second; + } + + namedChildren.clear(); +} + +int Scope::getVarInScope(string nspace, string name) +{ + if(nspace == "" && getVarSymbols().containsVariable(name)) + return getVarSymbols().getID(name); + + map::iterator it = namedChildren.find(nspace); + + if(it != namedChildren.end()) + { + int id = (*it).second->getVarInScope("", name); + + if(id != -1) + return id; + } + + if(parent == NULL) + return -1; + + return parent->getVarInScope(nspace, name); +} + +vector Scope::getFuncsInScope(string nspace, string name) +{ + vector rval; + + if(nspace == "") + { + vector thisscope = getFuncSymbols().getFuncIDs(name); + + for(vector::iterator it = thisscope.begin(); it != thisscope.end(); it++) + { + rval.push_back(*it); + } + } + + map::iterator it = namedChildren.find(nspace); + + if(it != namedChildren.end()) + { + vector childscope = (*it).second->getFuncsInScope("", name); + + for(vector::iterator it2 = childscope.begin(); it2 != childscope.end(); it2++) + { + rval.push_back(*it2); + } + } + + if(parent != NULL) + { + vector abovescope = parent->getFuncsInScope(nspace,name); + + for(vector::iterator it = abovescope.begin(); it != abovescope.end(); it++) + { + rval.push_back(*it); + } + } + + return rval; +} + +Scope *Scope::getNamedChild(string name) +{ + return namedChildren[name]; +} + +void SymbolTable::putFunc(int ID, int type) +{ + funcTypes[ID]=type; +} + +void SymbolTable::putAST(AST *obj, int ID) +{ + astToID[obj]=ID; +} + +int SymbolTable::getFuncType(AST *obj) +{ + return getFuncType(astToID[obj]); +} + +void SymbolTable::printDiagnostics() +{ + cout << (unsigned int)varTypes.size() << " variable symbols" << endl; + cout << (unsigned int)funcTypes.size() << " function symbols" << endl; + cout << (unsigned int)funcParams.size() << " function declarations (should = function symbols)" << endl; +} + diff --git a/src/parser/ScriptParser.cpp b/src/parser/ScriptParser.cpp new file mode 100644 index 0000000000..b4e74e8905 --- /dev/null +++ b/src/parser/ScriptParser.cpp @@ -0,0 +1,1406 @@ + +#include "../precompiled.h" //always first + +#include "ParseError.h" +#include "y.tab.hpp" +#include "TypeChecker.h" +#include "GlobalSymbols.h" +#include "ByteCode.h" +#include "../zsyssimple.h" +#include +#include +#include +#include + +#include "DataStructs.h" +#include "SymbolVisitors.h" +#include "UtilVisitors.h" +#include "AST.h" +#include "BuildVisitors.h" +using namespace std; +//#define PARSER_DEBUG + +AST *resAST; + +ScriptsData * compile(char *filename); + +#ifdef PARSER_DEBUG +int main(int argc, char *argv[]) +{ + if(argc < 2) + return -1; + + compile(argv[1]); +} +#endif + +ScriptsData * compile(const char *filename) +{ + ScriptParser::resetState(); +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 1: Parsing"); + box_eol(); +#endif + + if(go(filename) != 0 || !resAST) + { + printErrorMsg(NULL, CANTOPENSOURCE); + return NULL; + } + + AST *theAST = resAST; + +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 2: Preprocessing"); + box_eol(); +#endif + map *consts = new map(); + + if(!ScriptParser::preprocess(theAST, RECURSIONLIMIT,consts)) + { + delete theAST; + delete consts; + return NULL; + } + +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 3: Building symbol tables"); + box_eol(); +#endif + SymbolData *d = ScriptParser::buildSymbolTable(theAST,consts); + + if(d==NULL) + { + //delete theAST; + delete consts; + return NULL; + } + + //d->symbols->printDiagnostics(); +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 4: Type-checking/Completing function symbol tables/Constant folding"); + box_eol(); +#endif + FunctionData *fd = ScriptParser::typeCheck(d); + + if(fd == NULL) + { + //delete theAST; + delete consts; + /*if(d->symbols) delete d->symbols; + for(vector::iterator it2 = d->globalFuncs.begin(); it2 != d->globalFuncs.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->scripts.begin(); it2 != d->scripts.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalVars.begin(); it2 != d->globalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalArrays.begin(); it2 != d->globalArrays.end(); it2++)\ + { + delete *it2; + } + delete d;*/ + return NULL; + } + +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 5: Generating object code"); + box_eol(); +#endif + + IntermediateData *id = ScriptParser::generateOCode(fd); + + if(id == NULL) + { + //delete theAST; + delete consts; + /*if(d->symbols) delete d->symbols; + for(vector::iterator it2 = d->globalFuncs.begin(); it2 != d->globalFuncs.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->scripts.begin(); it2 != d->scripts.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalVars.begin(); it2 != d->globalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalArrays.begin(); it2 != d->globalArrays.end(); it2++)\ + { + delete *it2; + } + delete d;*/ + /*if(fd->symbols) delete fd->symbols; + for(vector::iterator it2 = fd->functions.begin(); it2 != fd->functions.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->newGlobalVars.begin(); it2 != fd->newGlobalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->globalVars.begin(); it2 != fd->globalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->newGlobalArrays.begin(); it2 != fd->newGlobalArrays.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->globalArrays.begin(); it2 != fd->globalArrays.end(); it2++)\ + { + delete *it2; + } + delete fd;*/ + return NULL; + } + +#ifndef SCRIPTPARSER_COMPILE + box_out("Pass 6: Assembling"); + box_eol(); +#endif + ScriptsData *final = ScriptParser::assemble(id); + box_out("Success!"); + box_eol(); + + //delete theAST; + delete consts; + /*if(d->symbols) delete d->symbols; + for(vector::iterator it2 = d->globalFuncs.begin(); it2 != d->globalFuncs.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->scripts.begin(); it2 != d->scripts.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalVars.begin(); it2 != d->globalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = d->globalArrays.begin(); it2 != d->globalArrays.end(); it2++)\ + { + delete *it2; + } + delete d; + if(fd->symbols) delete fd->symbols; + for(vector::iterator it2 = fd->functions.begin(); it2 != fd->functions.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->newGlobalVars.begin(); it2 != fd->newGlobalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->globalVars.begin(); it2 != fd->globalVars.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->newGlobalArrays.begin(); it2 != fd->newGlobalArrays.end(); it2++) + { + delete *it2; + } + for(vector::iterator it2 = fd->globalArrays.begin(); it2 != fd->globalArrays.end(); it2++)\ + { + delete *it2; + } + delete fd;*/ + /*for(map >::iterator it = id->funcs.begin(); it != id->funcs.end(); it++) + { + for(vector::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + delete *it2; + } + } + for(vector::iterator it = id->globalsInit.begin(); it != id->globalsInit.end(); it++) + { + delete *it; + } + for(vector::iterator it = id->globalasInit.begin(); it != id->globalasInit.end(); it++) + { + delete *it; + } + delete id;*/ + + return final; +} + +int ScriptParser::vid = 0; +int ScriptParser::fid = 0; +int ScriptParser::gid = 1; +int ScriptParser::lid = 0; + +// The following is NOT AT ALL compliant with the C++ standard +// but apparently required by the MingW gcc... +#ifndef _MSC_VER +const int ScriptParser::TYPE_FLOAT; +const int ScriptParser::TYPE_BOOL; +const int ScriptParser::TYPE_VOID; +const int ScriptParser::TYPE_LINK; +const int ScriptParser::TYPE_FFC; +const int ScriptParser::TYPE_ITEM; +const int ScriptParser::TYPE_ITEMCLASS; +const int ScriptParser::TYPE_SCREEN; +const int ScriptParser::TYPE_GLOBAL; +const int ScriptParser::TYPE_GAME; +const int ScriptParser::TYPE_NPC; +const int ScriptParser::TYPE_LWPN; +const int ScriptParser::TYPE_EWPN; +#endif + +string ScriptParser::trimQuotes(string quoteds) +{ + string rval = quoteds.substr(1,quoteds.size()-2); + return rval; +} + +bool ScriptParser::preprocess(AST *theAST, int reclimit, map *constants) +{ + if(reclimit == 0) + { + printErrorMsg(NULL, IMPORTRECURSION); + return false; + } + + //Repeat parsing process for each of import files + GetImports gi; + theAST->execute(gi, NULL); + vector imports = gi.getResult(); + + for(vector::iterator it = imports.begin(); it != imports.end(); it++) + { + string fn = trimQuotes((*it)->getFilename()); + + for(int i=0; fn[i]; i++) + { +#ifdef _ALLEGRO_WINDOWS + + if(fn[i]=='/') + fn[i]='\\'; + +#else + + if(fn[i]=='\\') + fn[i]='/'; + +#endif + } + + if(go(fn.c_str()) != 0 || !resAST) + { + printErrorMsg(*it,CANTOPENIMPORT, fn); + + for(vector::iterator it2 = imports.begin(); it2 != imports.end(); it2++) + { + delete *it2; + } + + return false; + } + + AST *recAST = resAST; + + if(!preprocess(recAST, reclimit-1,constants)) + { + for(vector::iterator it2 = imports.begin(); it2 != imports.end(); it2++) + { + delete *it2; + } + + delete recAST; + return false; + } + + //Put the imported code into theAST + MergeASTs temp; + theAST->execute(temp, recAST); + } + + for(vector::iterator it2 = imports.begin(); it2 != imports.end(); it2++) + { + delete *it2; + } + + //check that there are no more stupidly placed imports in the file + CheckForExtraneousImports c; + theAST->execute(c, NULL); + + if(!c.isOK()) + return false; + + //get the constants + GetConsts gc; + theAST->execute(gc,NULL); + vector consts = gc.getResult(); + bool failure = false; + + for(vector::iterator it = consts.begin(); it != consts.end(); it++) + { + map::iterator find = constants->find((*it)->getName()); + + if(find != constants->end()) + { + printErrorMsg(*it, CONSTREDEF, (*it)->getName()); + failure=true; + } + else + { + pair parts = (*it)->getValue()->parseValue(); + pair val = ScriptParser::parseLong(parts); + + if(!val.second) + { + printErrorMsg(*it, CONSTTRUNC, (*it)->getValue()->getValue()); + } + + (*constants)[(*it)->getName()] = val.first; + } + + delete *it; + } + + if(failure) + { + return false; + } + + return true; +} + +SymbolData *ScriptParser::buildSymbolTable(AST *theAST, map *constants) +{ + SymbolData *rval = new SymbolData(); + SymbolTable *t = new SymbolTable(constants); + Scope *globalScope = new Scope(NULL); + bool failure = false; + + //ADD LIBRARY FUNCTIONS TO THE GLOBAL SCOPE HERE + GlobalSymbols::getInst().addSymbolsToScope(globalScope, t); + FFCSymbols::getInst().addSymbolsToScope(globalScope,t); + ItemSymbols::getInst().addSymbolsToScope(globalScope,t); + ItemclassSymbols::getInst().addSymbolsToScope(globalScope,t); + LinkSymbols::getInst().addSymbolsToScope(globalScope,t); + ScreenSymbols::getInst().addSymbolsToScope(globalScope,t); + GameSymbols::getInst().addSymbolsToScope(globalScope,t); + NPCSymbols::getInst().addSymbolsToScope(globalScope,t); + LinkWeaponSymbols::getInst().addSymbolsToScope(globalScope,t); + EnemyWeaponSymbols::getInst().addSymbolsToScope(globalScope,t); + + //strip the global functions from the AST + GetGlobalFuncs gc; + theAST->execute(gc, NULL); + vector fds = gc.getResult(); + + //add these functions to the global scope + for(vector::iterator it = fds.begin(); it != fds.end(); it++) + { + vector params; + + for(list::iterator it2 = (*it)->getParams().begin(); + it2 != (*it)->getParams().end(); it2++) + { + int type; + ExtractType temp; + (*it2)->getType()->execute(temp, &type); + + if(type == ScriptParser::TYPE_VOID) + { + printErrorMsg(*it2, FUNCTIONVOIDPARAM, (*it2)->getName()); + failure=true; + } + + params.push_back(type); + } + + int rettype; + ExtractType temp; + (*it)->getReturnType()->execute(temp, &rettype); + int id = globalScope->getFuncSymbols().addFunction((*it)->getName(), rettype, params); + + if(id == -1) + { + printErrorMsg(*it, FUNCTIONREDEF, (*it)->getName()); + failure=true; + } + + if(failure) + { + for(vector::iterator it2 = fds.begin(); it2 != fds.end(); it2++) + { + delete *it2; + } + + delete globalScope; + delete t; + delete rval; + delete theAST; + return NULL; + } + + t->putAST(*it, id); + t->putFunc(id, rettype); + t->putFuncDecl(id, params); + + } + + rval->globalFuncs = fds; + + + + //add global pointers + int vid2; + + //add a Link global variable + vid2 = globalScope->getVarSymbols().addVariable("Link", ScriptParser::TYPE_LINK); + t->putVar(vid2, ScriptParser::TYPE_LINK); + t->addGlobalPointer(vid2); + //add a Screen global variable + vid2 = globalScope->getVarSymbols().addVariable("Screen", ScriptParser::TYPE_SCREEN); + t->putVar(vid2, ScriptParser::TYPE_SCREEN); + t->addGlobalPointer(vid2); + //add a Game global variable + vid2 = globalScope->getVarSymbols().addVariable("Game", ScriptParser::TYPE_GAME); + t->putVar(vid2, ScriptParser::TYPE_GAME); + t->addGlobalPointer(vid2); + + //strip the global variables from the AST + GetGlobalVars gv; + theAST->execute(gv, NULL); + vector gvs = gv.getResult(); + vector gvas = gv.getResultA(); + + //add the variables to the global scope + for(vector::iterator it = gvs.begin(); it != gvs.end(); it++) + { + BuildScriptSymbols bss; + pair param(globalScope, t); + (*it)->execute(bss, ¶m); + + if(!bss.isOK()) + failure = true; + } + + for(vector::iterator it = gvas.begin(); it != gvas.end(); it++) + { + BuildScriptSymbols bss; + pair param(globalScope, t); + (*it)->execute(bss, ¶m); + + if(!bss.isOK()) + failure = true; + } + + vector scripts; + + if(!failure) + { + //put script variables and functions in their script subscopes + GetScripts gs; + theAST->execute(gs, NULL); + scripts = gs.getResult(); + + for(vector::iterator it = scripts.begin(); it != scripts.end(); it++) + { + int scripttype; + ExtractType et; + (*it)->getType()->execute(et, &scripttype); + + if(!(scripttype == ScriptParser::TYPE_FFC || scripttype == ScriptParser::TYPE_ITEMCLASS + || scripttype == ScriptParser::TYPE_GLOBAL)) + { + printErrorMsg(*it, SCRIPTBADTYPE, (*it)->getName()); + failure = true; + continue; + } + + Scope *subscope = new Scope(globalScope); + + if(!globalScope->addNamedChild((*it)->getName(), subscope)) + { + printErrorMsg(*it, SCRIPTREDEF, (*it)->getName()); + failure = true; + delete subscope; + continue; + } + + pair param(subscope, t); + BuildScriptSymbols bss; + bss.enableDeprecationWarnings(); + (*it)->execute(bss, ¶m); + + if(!bss.isOK()) + failure=true; + else + { + //find the start symbol + vector possibleruns = subscope->getFuncsInScope((*it)->getName(), "run"); + int runid = -1; + + if(possibleruns.size() > 1) + { + printErrorMsg(*it, TOOMANYRUN, (*it)->getName()); + failure = true; + } + else if(possibleruns.size() == 1) + runid = possibleruns[0]; + + if(!failure) + { + if(runid == -1) + { + printErrorMsg(*it, SCRIPTNORUN, (*it)->getName()); + failure = true; + } + else + { + int type = t->getFuncType(runid); + + if(type != ScriptParser::TYPE_VOID) + { + printErrorMsg(*it, SCRIPTRUNNOTVOID, (*it)->getName()); + failure = true; + } + else + { + rval->runsymbols[*it] = runid; + rval->numParams[*it] = (int)t->getFuncParams(runid).size(); + rval->scriptTypes[*it] = scripttype; + } + } + } + } + } + } + + //all non-local variables have been added to the table, so process all function + //declarations and add their local variables. As well, look up the symbol id of + //all variables and functions accessed and called within that function + + //starting with global functions + if(!failure) + { + for(vector::iterator it = fds.begin(); it != fds.end(); it++) + { + Scope *subscope = new Scope(globalScope); + BFSParam param = {subscope, t,ScriptParser::TYPE_VOID}; + BuildFunctionSymbols bfs; + (*it)->execute(bfs, ¶m); + + if(!bfs.isOK()) + failure = true; + + delete subscope; + } + } + + //now do script function + if(!failure) + { + for(vector::iterator it = scripts.begin(); it != scripts.end(); it++) + { + Scope *subscope = globalScope->getNamedChild((*it)->getName()); + Scope *newscope = new Scope(subscope); + BFSParam param = {newscope, t,rval->scriptTypes[*it]}; + list decls = (*it)->getScriptBlock()->getDeclarations(); + + for(list::iterator it2 = decls.begin(); it2 != decls.end(); it2++) + { + bool isfuncdecl; + IsFuncDecl temp; + (*it2)->execute(temp, &isfuncdecl); + + if(isfuncdecl) + { + BuildFunctionSymbols bfs; + (*it2)->execute(bfs, ¶m); + + if(!bfs.isOK()) + failure = true; + + if(bfs.getThisVID() != -1) + rval->thisPtr[*it]=bfs.getThisVID(); + } + + } + + delete newscope; + } + } + + if(failure) + { + for(vector::iterator it2 = fds.begin(); it2 != fds.end(); it2++) + { + delete *it2; + } + + for(vector::iterator it2 = scripts.begin(); it2 != scripts.end(); it2++) + { + delete *it2; + } + + for(vector::iterator it2 = gvs.begin(); it2 != gvs.end(); it2++) + delete *it2; + + for(vector::iterator it2 = gvas.begin(); it2 != gvas.end(); it2++) + delete *it2; + + delete globalScope; + delete t; + delete rval; + delete theAST; + return NULL; + } + + delete globalScope; + delete theAST; + rval->symbols = t; + rval->scripts = scripts; + rval->globalFuncs = fds; + rval->globalVars = gvs; + rval->globalArrays = gvas; + + return rval; +} + +FunctionData *ScriptParser::typeCheck(SymbolData *sdata) +{ + //build the functiondata + FunctionData *fd = new FunctionData; + fd->symbols = sdata->symbols; + fd->newGlobalVars = sdata->globalVars; + fd->newGlobalArrays = sdata->globalArrays; + vector scripts = sdata->scripts; + vector funcs = sdata->globalFuncs; + map runsymbols = sdata->runsymbols; + map numparams = sdata->numParams; + map scripttypes = sdata->scriptTypes; + map thisptr = sdata->thisPtr; + delete sdata; + bool failure = false; + map usednums; + + //strip var and func decls from the scripts + for(vector::iterator it = scripts.begin(); it != scripts.end(); it++) + { + fd->scriptRunSymbols[(*it)->getName()] = runsymbols[*it]; + fd->numParams[(*it)->getName()] = numparams[*it]; + fd->scriptTypes[(*it)->getName()] = scripttypes[*it]; + fd->thisPtr[(*it)->getName()] = thisptr[*it]; + //strip vars and funcs + list &stuff = (*it)->getScriptBlock()->getDeclarations(); + + for(list::iterator it2 = stuff.begin(); it2 != stuff.end();) + { + bool isFunc = false; + IsFuncDecl temp; + (*it2)->execute(temp, &isFunc); + + if(isFunc) + { + fd->functions.push_back((ASTFuncDecl *)*it2); + } + + bool IsArray = false; + IsArrayDecl temp2; + (*it2)->execute(temp2, &IsArray); + + if(IsArray) + { + fd->globalArrays.push_back((ASTArrayDecl *)*it2); + } + + if(!isFunc && !IsArray) + { + fd->globalVars.push_back((ASTVarDecl *)*it2); + } + + it2 = stuff.erase(it2); + } + } + + for(vector::iterator it = scripts.begin(); it != scripts.end(); it++) + { + delete *it; + } + + for(vector::iterator it = funcs.begin(); it != funcs.end(); it++) + { + fd->functions.push_back(*it); + } + + if(failure) + { + //delete stuff + for(vector::iterator it = fd->globalVars.begin(); it != fd->globalVars.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->globalArrays.begin(); it != fd->globalArrays.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->functions.begin(); it != fd->functions.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->newGlobalVars.begin(); it != fd->newGlobalVars.end(); it++) + delete *it; + + for(vector::iterator it = fd->newGlobalArrays.begin(); it != fd->newGlobalArrays.end(); it++) + delete *it; + + delete fd->symbols; + delete fd; + return NULL; + } + + //fd is now loaded with all the info + //so run type-checker visitor + for(vector::iterator it = fd->globalVars.begin(); it != fd->globalVars.end(); it++) + { + pair param = pair(fd->symbols, -1); + TypeCheck tc; + (*it)->execute(tc, ¶m); + + if(!tc.isOK()) + failure = true; + } + + for(vector::iterator it = fd->globalArrays.begin(); it != fd->globalArrays.end(); it++) + { + pair param = pair(fd->symbols, -1); + TypeCheck tc; + (*it)->execute(tc, ¶m); + + if(!tc.isOK()) + failure = true; + } + + for(vector::iterator it = fd->newGlobalVars.begin(); it != fd->newGlobalVars.end(); it++) + { + pair param = pair(fd->symbols, -1); + TypeCheck tc; + (*it)->execute(tc, ¶m); + + if(!tc.isOK()) + failure = true; + } + + for(vector::iterator it = fd->newGlobalArrays.begin(); it != fd->newGlobalArrays.end(); it++) + { + pair param = pair(fd->symbols, -1); + TypeCheck tc; + (*it)->execute(tc, ¶m); + + if(!tc.isOK()) + failure = true; + } + + for(vector::iterator it = fd->functions.begin(); it != fd->functions.end(); it++) + { + int rettype = fd->symbols->getFuncType(*it); + pair param = pair(fd->symbols, rettype); + TypeCheck tc; + (*it)->execute(tc, ¶m); + + if(!tc.isOK()) + failure = true; + } + + if(fd->globalVars.size() + fd->newGlobalVars.size() > 256) + { + printErrorMsg(NULL, TOOMANYGLOBAL); + failure = true; + } + + if(failure) + { + //delete stuff + for(vector::iterator it = fd->globalVars.begin(); it != fd->globalVars.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->globalArrays.begin(); it != fd->globalArrays.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->functions.begin(); it != fd->functions.end(); it++) + { + delete *it; + } + + for(vector::iterator it = fd->newGlobalVars.begin(); it != fd->newGlobalVars.end(); it++) + delete *it; + + for(vector::iterator it = fd->newGlobalArrays.begin(); it != fd->newGlobalArrays.end(); it++) + delete *it; + + delete fd->symbols; + delete fd; + return NULL; + } + + return fd; +} + +IntermediateData *ScriptParser::generateOCode(FunctionData *fdata) +{ + //Z_message("yes"); + bool failure = false; + vector funcs = fdata->functions; + vector globals = fdata->globalVars; + vector globalas = fdata->globalArrays; + + //we have no need of newglobals at this point anymore + for(vector::iterator it = fdata->newGlobalVars.begin(); it != fdata->newGlobalVars.end(); it++) + globals.push_back(*it); + + for(vector::iterator it = fdata->newGlobalArrays.begin(); it != fdata->newGlobalArrays.end(); it++) + globalas.push_back(*it); + + map runsymbols = fdata->scriptRunSymbols; + SymbolTable *symbols = fdata->symbols; + map numparams = fdata->numParams; + map scripttypes = fdata->scriptTypes; + map thisptr = fdata->thisPtr; + delete fdata; + LinkTable lt; + + for(vector::iterator it = globals.begin(); it != globals.end(); it++) + { + int vid2 = symbols->getID(*it); + lt.addGlobalVar(vid2); + } + + for(vector::iterator it = globalas.begin(); it != globalas.end(); it++) + { + int vid2 = symbols->getID(*it); + lt.addGlobalVar(vid2); + } + + //Z_message("yes"); + //and add the this pointers + for(vector::iterator it = symbols->getGlobalPointers().begin(); it != symbols->getGlobalPointers().end(); it++) + { + lt.addGlobalPointer(*it); + } + + for(vector::iterator it = funcs.begin(); it != funcs.end(); it++) + { + int fid2 = symbols->getID(*it); + lt.functionToLabel(fid2); + } + + //Z_message("yes"); + + //we now have labels for the functions and ids for the global variables. + //we can now generate the code to intialize the globals + IntermediateData *rval = new IntermediateData(); + + //Link against the global symbols, and add their labels + map > globalcode = GlobalSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = FFCSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = ItemSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = ItemclassSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = LinkSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = ScreenSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = GameSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = NPCSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = LinkWeaponSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + globalcode = EnemyWeaponSymbols::getInst().addSymbolsCode(lt); + + for(map >::iterator it = globalcode.begin(); it != globalcode.end(); it++) + { + rval->funcs[it->first] = it->second; + } + + //Z_message("yes"); + + for(vector::iterator it = globals.begin(); it != globals.end(); it++) + { + OpcodeContext oc; + oc.linktable = < + oc.symbols = symbols; + oc.stackframe = NULL; + BuildOpcodes bo; + (*it)->execute(bo, &oc); + + if(!bo.isOK()) + { + failure = true; + } + + vector code = bo.getResult(); + + for(vector::iterator it2 = code.begin(); it2!= code.end(); it2++) + { + rval->globalsInit.push_back(*it2); + } + + delete *it; //say so long to our lovely data structure the AST + } + + //Z_message("yes"); + for(vector::iterator it = globalas.begin(); it != globalas.end(); it++) + { + OpcodeContext oc; + oc.linktable = < + oc.symbols = symbols; + oc.stackframe = NULL; + BuildOpcodes bo; + (*it)->execute(bo, &oc); + + if(!bo.isOK()) + { + failure = true; + } + + vector code = bo.getResult(); + + for(vector::iterator it2 = code.begin(); it2!= code.end(); it2++) + { + rval->globalasInit.push_back(*it2); + } + + delete *it; //say so long to our lovely data structure the AST + } + + //Z_message("yes"); + + //globals have been initialized, now we repeat for the functions + for(vector::iterator it = funcs.begin(); it != funcs.end(); it++) + { + bool isarun = false; + string scriptname; + + for(map::iterator it2 = runsymbols.begin(); it2 != runsymbols.end(); it2++) + { + if(it2->second == symbols->getID(*it)) + { + isarun=true; + scriptname = it2->first; + break; + } + } + + vector funccode; + //count the number of stack-allocated variables + vector stackvars; + pair *, SymbolTable *> param = pair *, SymbolTable *>(&stackvars, symbols); + CountStackSymbols temp; + (*it)->execute(temp, ¶m); + int offset = 0; + StackFrame sf; + + //if this is a run, there is the this pointer + if(isarun) + { + sf.addToFrame(thisptr[scriptname], offset); + offset += 10000; + } + + //the params are now the first elements of this list + //so assign them depths in reverse order + for(vector::reverse_iterator it2 = stackvars.rbegin(); it2 != stackvars.rend(); it2++) + { + sf.addToFrame(*it2, offset); + offset += 10000; + } + + //start of the function + Opcode *first = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); + first->setLabel(lt.functionToLabel(symbols->getID(*it))); + funccode.push_back(first); + //push on the 0s + int numtoallocate = (unsigned int)stackvars.size()-(unsigned int)symbols->getFuncParams(symbols->getID(*it)).size(); + + for(int i = 0; i < numtoallocate; i++) + { + funccode.push_back(new OPushRegister(new VarArgument(EXP1))); + } + + //push on the this, if a script + if(isarun) + { + switch(scripttypes[scriptname]) + { + case ScriptParser::TYPE_FFC: + funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFFFC))); + break; + + case ScriptParser::TYPE_ITEMCLASS: + funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFITEMCLASS))); + break; + + case ScriptParser::TYPE_GLOBAL: + //don't care, we don't have a valid this pointer + break; + } + + funccode.push_back(new OPushRegister(new VarArgument(EXP2))); + } + + //set up the stack frame register + funccode.push_back(new OSetRegister(new VarArgument(SFRAME), new VarArgument(SP))); + OpcodeContext oc; + oc.linktable = < + oc.symbols = symbols; + oc.stackframe = &sf; + BuildOpcodes bo; + (*it)->execute(bo, &oc); + + if(!bo.isOK()) + failure = true; + + vector code = bo.getResult(); + + for(vector::iterator it2 = code.begin(); it2 != code.end(); it2++) + { + funccode.push_back(*it2); + } + + //add appendix code + //nop label + Opcode *next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); + next->setLabel(bo.getReturnLabelID()); + funccode.push_back(next); + + //pop off everything + for(unsigned int i=0; i< stackvars.size(); i++) + { + funccode.push_back(new OPopRegister(new VarArgument(EXP2))); + } + + //if it's a main script, quit. + if(isarun) + funccode.push_back(new OQuit()); + else + { + //pop off the return address + funccode.push_back(new OPopRegister(new VarArgument(EXP2))); + //and return + funccode.push_back(new OGotoRegister(new VarArgument(EXP2))); + } + + rval->funcs[lt.functionToLabel(symbols->getID(*it))]=funccode; + delete *it; + } + + //Z_message("yes"); + + //update the run symbols + for(map::iterator it = runsymbols.begin(); it != runsymbols.end(); it++) + { + int labelid = lt.functionToLabel(it->second); + rval->scriptRunLabels[it->first] = labelid; + rval->numParams[it->first] = numparams[it->first]; + rval->scriptTypes[it->first] = scripttypes[it->first]; + } + + delete symbols; //and so long to our beloved ;) symbol table + //Z_message("yes"); + + if(failure) + { + //delete all kinds of crap if there was a problem :-/ + for(map >::iterator it = rval->funcs.begin(); it != rval->funcs.end(); it++) + { + for(vector::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + delete *it2; + } + } + + for(vector::iterator it = rval->globalsInit.begin(); it != rval->globalsInit.end(); it++) + { + delete *it; + } + + for(vector::iterator it = rval->globalasInit.begin(); it != rval->globalasInit.end(); it++) + { + delete *it; + } + + delete rval; + return NULL; + } + + //Z_message("yes"); + return rval; +} + +ScriptsData *ScriptParser::assemble(IntermediateData *id) +{ + //finally, finish off this bitch + ScriptsData *rval = new ScriptsData; + map > funcs = id->funcs; + vector ginit = id->globalsInit; + { + vector temp = id->globalasInit; + + //push global array allocations onto the global variable allocations + for(vector::iterator i = temp.begin(); i != temp.end(); i++) + ginit.push_back(*i); + } + map scripts = id->scriptRunLabels; + map numparams = id->numParams; + map scripttypes = id->scriptTypes; + delete id; + + //do the global inits + //if there's a global script called "Init", append it to ~Init: + map::iterator it = scripts.find("Init"); + + if(it != scripts.end() && scripttypes["Init"] == ScriptParser::TYPE_GLOBAL) + { + //append + //get label + int label = funcs[scripts["Init"]][0]->getLabel(); + ginit.push_back(new OGotoImmediate(new LabelArgument(label))); + } + + rval->theScripts["~Init"] = assembleOne(ginit, funcs, 0); + rval->scriptTypes["~Init"] = ScriptParser::TYPE_GLOBAL; + + for(map::iterator it2 = scripts.begin(); it2 != scripts.end(); it2++) + { + vector code = funcs[it2->second]; + rval->theScripts[it2->first] = assembleOne(code, funcs, numparams[it2->first]); + rval->scriptTypes[it2->first] = scripttypes[it2->first]; + } + + for(vector::iterator it2 = ginit.begin(); it2 != ginit.end(); it2++) + { + delete *it2; + } + + for(map >::iterator it2 = funcs.begin(); it2 != funcs.end(); it2++) + { + for(vector::iterator it3 = it2->second.begin(); it3 != it2->second.end(); it3++) + { + delete *it3; + } + } + + return rval; +} + +vector ScriptParser::assembleOne(vector script, map > &otherfuncs, int numparams) +{ + vector rval; + //first, push on the params to the run + int i; + + for(i=0; i labels; + + for(vector::iterator it = script.begin(); it != script.end(); it++) + { + GetLabels temp; + (*it)->execute(temp, &labels); + } + + //do some fixed-point bullshit + size_t oldnumlabels = 0; + + while(oldnumlabels != labels.size()) + { + oldnumlabels = labels.size(); + + for(map::iterator lit = labels.begin(); lit != labels.end(); lit++) + { + map >::iterator it = otherfuncs.find(lit->first); + + if(it == otherfuncs.end()) + continue; + + for(vector::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + GetLabels temp; + (*it2)->execute(temp, &labels); + } + } + } + + //make the rval + for(vector::iterator it = script.begin(); it != script.end(); it++) + { + rval.push_back((*it)->makeClone()); + } + + for(map::iterator it = labels.begin(); it != labels.end(); it++) + { + map >::iterator it2 = otherfuncs.find(it->first); + + if(it2 != otherfuncs.end()) + { + for(vector::iterator it3 = (*it2).second.begin(); it3 != (*it2).second.end(); it3++) + { + rval.push_back((*it3)->makeClone()); + } + } + } + + //set the label line numbers + map linenos; + int lineno=1; + + for(vector::iterator it = rval.begin(); it != rval.end(); it++) + { + if((*it)->getLabel() != -1) + { + linenos[(*it)->getLabel()]=lineno; + } + + lineno++; + } + + //now fill in those labels + for(vector::iterator it = rval.begin(); it != rval.end(); it++) + { + SetLabels temp; + (*it)->execute(temp, &linenos); + } + + return rval; +} + +pair ScriptParser::parseLong(pair parts) +{ + // Not sure if this should really check for negative numbers; + // in most contexts, that's checked beforehand. parts only + // includes the minus if this is a constant. - Saf + bool negative=false; + pair rval; + rval.second=true; + + if(parts.first.data()[0]=='-') + { + negative=true; + parts.first = parts.first.substr(1); + } + + if(parts.second.size() > 4) + { + rval.second = false; + parts.second = parts.second.substr(0,4); + } + + if(parts.first.size() > 6) + { + rval.second = false; + parts.first = parts.first.substr(0,6); + } + + int firstpart = atoi(parts.first.c_str()); + + if(firstpart > 214747) + { + firstpart = 214747; + rval.second = false; + } + + long intval = ((long)(firstpart))*10000; + //add fractional part; tricky! + int fpart = 0; + + while(parts.second.length() < 4) + parts.second += "0"; + + for(unsigned int i = 0; i < 4; i++) + { + fpart *= 10; + fpart += parts.second[i] - '0'; + } + + /*for(unsigned int i=0; i<4; i++) + { + fpart*=10; + char tmp[2]; + tmp[0] = parts.second.at(i); + tmp[1] = 0; + fpart += atoi(tmp); + }*/ + rval.first = intval + fpart; + if(negative) + rval.first = -rval.first; + return rval; +} + diff --git a/src/parser/SymbolVisitors.cpp b/src/parser/SymbolVisitors.cpp new file mode 100644 index 0000000000..aaeb4d06a3 --- /dev/null +++ b/src/parser/SymbolVisitors.cpp @@ -0,0 +1,447 @@ + +#include "../precompiled.h" //always first + +#include "SymbolVisitors.h" +#include "DataStructs.h" +#include "UtilVisitors.h" +#include "ParseError.h" +#include + + +void BuildScriptSymbols::caseDefault(void *) +{ +} + +void BuildScriptSymbols::caseScript(ASTScript &host,void *param) +{ + list ad = host.getScriptBlock()->getDeclarations(); + + for(list::iterator it = ad.begin(); it != ad.end(); it++) + { + (*it)->execute(*this,param); + } +} + +void BuildScriptSymbols::caseFuncDecl(ASTFuncDecl &host, void *param) +{ + pair *p = (pair *)param; + string name = host.getName(); + vector params; + list vds = host.getParams(); + + for(list::iterator it = vds.begin(); it != vds.end(); it++) + { + int type; + ExtractType temp; + (*it)->getType()->execute(temp, &type); + params.push_back(type); + + if(type == ScriptParser::TYPE_VOID) + { + failure=true; + printErrorMsg(&host, FUNCTIONVOIDPARAM, name); + } + } + + int rettype; + ExtractType temp; + host.getReturnType()->execute(temp, &rettype); + int id = p->first->getFuncSymbols().addFunction(name,rettype,params); + + if(id == -1) + { + failure = true; + printErrorMsg(&host, FUNCTIONREDEF, name); + return; + } + + p->second->putAST(&host, id); + p->second->putFunc(id, rettype); + p->second->putFuncDecl(id, params); +} + +void BuildScriptSymbols::caseVarDecl(ASTVarDecl &host, void *param) +{ + pair *p = (pair *)param; + string name = host.getName(); + int type; + ExtractType temp; + host.getType()->execute(temp, &type); + + if(type == ScriptParser::TYPE_VOID) + { + failure = true; + printErrorMsg(&host, VOIDVAR, name); + } + + if(type == ScriptParser::TYPE_FFC || type == ScriptParser::TYPE_ITEM + || type == ScriptParser::TYPE_ITEMCLASS || type == ScriptParser::TYPE_NPC + || type == ScriptParser::TYPE_LWPN || type == ScriptParser::TYPE_EWPN) + { + failure = true; + printErrorMsg(&host, REFVAR, name); + } + + //var is always visible + int id = p->first->getVarSymbols().addVariable(name, type); + + if(id == -1) + { + failure = true; + printErrorMsg(&host, VARREDEF, name); + return; + } + + p->second->putAST(&host, id); + p->second->putVar(id, type); + + if(this->deprecateGlobals) + { + printErrorMsg(&host, DEPRECATEDGLOBAL, name); + } +} + +void BuildScriptSymbols::caseArrayDecl(ASTArrayDecl &host, void *param) +{ + pair *p = (pair *)param; + string name = host.getName(); + int type; + ExtractType temp; + host.getType()->execute(temp, &type); + + if(type == ScriptParser::TYPE_VOID) + { + failure = true; + printErrorMsg(&host, VOIDARR, name); + } + + if(type == ScriptParser::TYPE_FFC || type == ScriptParser::TYPE_ITEM + || type == ScriptParser::TYPE_ITEMCLASS || type == ScriptParser::TYPE_NPC + || type == ScriptParser::TYPE_LWPN || type == ScriptParser::TYPE_EWPN) + { + failure = true; + printErrorMsg(&host, REFARR, name); + } + + //var is always visible + int id = p->first->getVarSymbols().addVariable(name, type); + + if(id == -1) + { + failure = true; + printErrorMsg(&host, ARRREDEF, name); + return; + } + + p->second->putAST(&host, id); + p->second->putVar(id, type); + + if(this->deprecateGlobals) + { + printErrorMsg(&host, DEPRECATEDGLOBAL, name); + } + + if(host.isRegister()) + ((ASTExpr *) host.getSize())->execute(*this, param); + + if(host.getList() != NULL) + { + for(list::iterator it = host.getList()->getList().begin(); it != host.getList()->getList().end(); it++) + { + (*it)->execute(*this,param); + } + } +} + +void BuildScriptSymbols::caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) +{ + host.getInitializer()->execute(*this,param); + caseVarDecl(host, param); +} + +void BuildScriptSymbols::caseExprDot(ASTExprDot &host, void *param) +{ + pair *p = (pair *)param; + BuildFunctionSymbols bfs; + BFSParam newp = {p->first,p->second,ScriptParser::TYPE_VOID}; + host.execute(bfs, &newp); + + if(!bfs.isOK()) + { + failure=true; + } +} + +void BuildScriptSymbols::caseExprArray(ASTExprArray &host, void *param) +{ + pair *p = (pair *)param; + BuildFunctionSymbols bfs; + BFSParam newp = {p->first,p->second,ScriptParser::TYPE_VOID}; + host.execute(bfs, &newp); + + if(!bfs.isOK()) + { + failure=true; + } + + host.getIndex()->execute(bfs, &newp); +} + +void BuildScriptSymbols::caseExprArrow(ASTExprArrow &host, void *) +{ + printErrorMsg(&host, BADGLOBALINIT, ""); + failure=true; +} + +void BuildScriptSymbols::caseFuncCall(ASTFuncCall &host, void *) +{ + printErrorMsg(&host, BADGLOBALINIT, ""); + failure=true; +} + +////////////////////////////////////////////////////////////// + +void BuildFunctionSymbols::caseFuncDecl(ASTFuncDecl &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + //push in the scope + Scope *subscope = new Scope(p->scope); + BFSParam newparam = {subscope,p->table,p->type}; + //if it's a run method, add this + ExtractType et; + int rtype; + host.getReturnType()->execute(et, &rtype); + + if(host.getName() == "run" && rtype == ScriptParser::TYPE_VOID) + { + int vid = subscope->getVarSymbols().addVariable("this", p->type); + newparam.table->putVar(vid, p->type); + thisvid=vid; + } + + //add the params + list vars = host.getParams(); + + for(list::iterator it = vars.begin(); it != vars.end(); it++) + { + string name = (*it)->getName(); + int type; + ExtractType temp; + (*it)->getType()->execute(temp, &type); + int id = subscope->getVarSymbols().addVariable(name,type); + + if(id == -1) + { + printErrorMsg(*it, VARREDEF, name); + failure = true; + delete subscope; + return; + } + + p->table->putVar(id, type); + p->table->putAST(*it, id); + } + + //shortcut the block + list stmts = host.getBlock()->getStatements(); + + for(list::iterator it = stmts.begin(); it != stmts.end(); it++) + { + (*it)->execute(*this, &newparam); + } + + delete subscope; +} + +void BuildFunctionSymbols::caseVarDecl(ASTVarDecl &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + string name = host.getName(); + int type; + ExtractType temp; + host.getType()->execute(temp, &type); + int id = p->scope->getVarSymbols().addVariable(name, type); + + if(id == -1) + { + printErrorMsg(&host, VARREDEF, name); + failure = true; + return; + } + + p->table->putAST(&host, id); + p->table->putVar(id, type); +} + +void BuildFunctionSymbols::caseArrayDecl(ASTArrayDecl &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + string name = host.getName(); + int type; + ExtractType temp; + host.getType()->execute(temp, &type); + int id = p->scope->getVarSymbols().addVariable(name, type); + + if(id == -1) + { + printErrorMsg(&host, ARRREDEF, name); + failure = true; + return; + } + + p->table->putAST(&host, id); + p->table->putVar(id, type); + + if(host.isRegister()) + ((ASTExpr *) host.getSize())->execute(*this, param); + + if(host.getList() != NULL) + { + for(list::iterator it = host.getList()->getList().begin(); it != host.getList()->getList().end(); it++) + { + (*it)->execute(*this,param); + } + } +} + +void BuildFunctionSymbols::caseBlock(ASTBlock &host, void *param) +{ + //push in a new scope + BFSParam *p = (BFSParam *)param; + Scope *newscope = new Scope(p->scope); + BFSParam newparam = {newscope, p->table,p->type}; + list stmts = host.getStatements(); + + for(list::iterator it = stmts.begin(); it != stmts.end(); it++) + { + (*it)->execute(*this, &newparam); + } + + delete newscope; +} + +void BuildFunctionSymbols::caseStmtFor(ASTStmtFor &host, void *param) +{ + //push in new scope + //in accordance with C++ scoping + BFSParam *p = (BFSParam *)param; + Scope *newscope = new Scope(p->scope); + BFSParam newparam = {newscope, p->table, p->type}; + host.getPrecondition()->execute(*this, &newparam); + host.getTerminationCondition()->execute(*this, &newparam); + host.getIncrement()->execute(*this, &newparam); + ASTStmt * stmt = host.getStmt(); + + stmt->execute(*this,&newparam); + delete newscope; +} + +void BuildFunctionSymbols::caseFuncCall(ASTFuncCall &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + ASTExpr *ident = host.getName(); + //ident could be a dotexpr, or an arrow exp. + //if an arrow exp, it is not my problem right now + bool isdot = false; + IsDotExpr temp; + ident->execute(temp, &isdot); + + if(!isdot) + { + //recur to get any dotexprs inside + ident->execute(*this,param); + } + else + { + //resolve the possible functions + ASTExprDot *dotname = (ASTExprDot *)host.getName(); + string name = dotname->getName(); + string nspace = dotname->getNamespace(); + vector possibleFuncs = p->scope->getFuncsInScope(nspace, name); + + if(possibleFuncs.size() == 0) + { + string fullname; + + if(nspace == "") + fullname=name; + else + fullname = nspace + "." + name; + + printErrorMsg(&host, FUNCUNDECLARED, fullname); + failure = true; + return; + } + + p->table->putAmbiguousFunc(&host, possibleFuncs); + } + + for(list::iterator it = host.getParams().begin(); it != host.getParams().end(); it++) + { + (*it)->execute(*this,param); + } +} + +void BuildFunctionSymbols::caseExprDot(ASTExprDot &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + string name = host.getName(); + string nspace = host.getNamespace(); + int id = p->scope->getVarInScope(nspace, name); + + if(id == -1 && !(nspace == "" && p->table->isConstant(name))) + { + string fullname; + + if(nspace == "") + fullname=name; + else + fullname = nspace + "." + name; + + printErrorMsg(&host, VARUNDECLARED, fullname); + failure = true; + return; + } + + p->table->putAST(&host, id); +} + +void BuildFunctionSymbols::caseExprArrow(ASTExprArrow &host, void *param) +{ + //recur on the name + host.getLVal()->execute(*this,param); + + //recur on the index, if it exists + if(host.getIndex()) + host.getIndex()->execute(*this,param); + + //wait for type-checking to do rest of work +} + +void BuildFunctionSymbols::caseExprArray(ASTExprArray &host, void *param) +{ + BFSParam *p = (BFSParam *)param; + string name = host.getName(); + string nspace = host.getNamespace(); + int id = p->scope->getVarInScope(nspace, name); + + if(id == -1 && !(nspace == "" && p->table->isConstant(name))) + { + string fullname; + + if(nspace == "") + fullname=name; + else + fullname = nspace + "." + name; + + printErrorMsg(&host, VARUNDECLARED, fullname); + failure = true; + return; + } + + p->table->putAST(&host, id); + + if(host.getIndex()) + host.getIndex()->execute(*this,param); +} + diff --git a/src/parser/SymbolVisitors.h b/src/parser/SymbolVisitors.h new file mode 100644 index 0000000000..e254d8fdd5 --- /dev/null +++ b/src/parser/SymbolVisitors.h @@ -0,0 +1,72 @@ +#ifndef SYMBOLVISITORS_H +#define SYMBOLVISITORS_H + +#include "AST.h" +#include "UtilVisitors.h" + +//builds the global symbols (functions and variables) for a script. +//param should be a pair pointer. +class BuildScriptSymbols : public RecursiveVisitor +{ +public: + BuildScriptSymbols() : failure(false), deprecateGlobals(false) {} + virtual void caseDefault(void *); + virtual void caseScript(ASTScript &host,void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param); + virtual void caseFuncDecl(ASTFuncDecl &host, void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + virtual void caseFuncCall(ASTFuncCall &host, void *param); + bool isOK() + { + return !failure; + } + void enableDeprecationWarnings() + { + deprecateGlobals = true; + } +private: + bool failure; + bool deprecateGlobals; +}; + +class BuildFunctionSymbols : public RecursiveVisitor +{ +public: + BuildFunctionSymbols() : failure(false), thisvid(-1) {} + virtual void caseDefault(void *param) + { + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual void caseFuncDecl(ASTFuncDecl &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) + { + host.getInitializer()->execute(*this,param); + caseVarDecl(host, param); + } + virtual void caseBlock(ASTBlock &host, void *param); + virtual void caseStmtFor(ASTStmtFor &host, void *param); + virtual void caseFuncCall(ASTFuncCall &host, void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + bool isOK() + { + return !failure; + } + int getThisVID() + { + return thisvid; + } +private: + bool failure; + int thisvid; +}; + +#endif + diff --git a/src/parser/TypeChecker.cpp b/src/parser/TypeChecker.cpp new file mode 100644 index 0000000000..6486e1bd44 --- /dev/null +++ b/src/parser/TypeChecker.cpp @@ -0,0 +1,1602 @@ + +#include "../precompiled.h" //always first + +#include "TypeChecker.h" +#include "ParseError.h" +#include "GlobalSymbols.h" +#include "../zsyssimple.h" +#include +#include + +//godawful template type, I'm sorry :-/ +typedef pair *>, int *> GLVT ; + +void GetLValType::caseDefault(void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + assert(false); +} + +void GetLValType::caseExprArrow(ASTExprArrow &host, void *param) +{ + GLVT *p = (GLVT *)param; + //sigh + //get the l-hand type + host.getLVal()->execute(*p->first.first, p->first.second); + + if(!p->first.first->isOK()) + return; + + int type = host.getLVal()->getType(); + bool isIndexed = (host.getIndex()!=0); + + if(isIndexed) + { + host.getIndex()->execute(*p->first.first, p->first.second); + + if(!p->first.first->isOK()) + return; + + if(!p->first.first->standardCheck(ScriptParser::TYPE_FLOAT, host.getIndex()->getType(),host.getIndex())) + { + p->first.first->fail(); + return; + } + } + + string name = "set" + host.getName(); + + if(isIndexed) + name += "[]"; + + pair > fidparam; + + switch(type) + { + case ScriptParser::TYPE_FFC: + fidparam = FFCSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_LINK: + fidparam = LinkSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_SCREEN: + fidparam = ScreenSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_GAME: + fidparam = GameSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_ITEM: + fidparam = ItemSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_ITEMCLASS: + fidparam = ItemclassSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_NPC: + fidparam = NPCSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_LWPN: + fidparam = LinkWeaponSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + case ScriptParser::TYPE_EWPN: + fidparam = EnemyWeaponSymbols::getInst().matchFunction(name, p->first.second->first); + break; + + default: + p->first.first->fail(); + printErrorMsg(&host, ARROWNOTPOINTER); + return; + } + + if(fidparam.first == -1 || (int)fidparam.second.size() != (isIndexed ? 3 : 2) || fidparam.second[0] != type) + { + printErrorMsg(&host, ARROWNOVAR, host.getName() + (isIndexed ? "[]" : "")); + p->first.first->fail(); + return; + } + + p->first.second->first->putAST(&host, fidparam.first); + *(p->second) = fidparam.second[(isIndexed ? 2 : 1)]; +} + +void GetLValType::caseExprDot(ASTExprDot &host, void *param) +{ + GLVT *p = (GLVT *)param; + host.execute(*(p->first.first), p->first.second); + int vid = p->first.second->first->getID(&host); + + if(vid == -1) + { + printErrorMsg(&host, LVALCONST, host.getName()); + p->first.first->fail(); + return; + } + + *(p->second) = p->first.second->first->getVarType(&host); +} + +void GetLValType::caseExprArray(ASTExprArray &host, void *param) +{ + GLVT *p = (GLVT *)param; + host.execute(*(p->first.first), p->first.second); + int vid = p->first.second->first->getID(&host); + + if(vid == -1) + { + printErrorMsg(&host, LVALCONST, host.getName()); + p->first.first->fail(); + return; + } + + *(p->second) = p->first.second->first->getVarType(&host); + + if(host.getIndex()) + { + host.getIndex()->execute(*p->first.first, p->first.second); + + if(!p->first.first->isOK()) + return; + + if(!p->first.first->standardCheck(ScriptParser::TYPE_FLOAT, host.getIndex()->getType(),host.getIndex())) + { + p->first.first->fail(); + return; + } + } +} + +void GetLValType::caseVarDecl(ASTVarDecl &host, void *param) +{ + GLVT *p = (GLVT *)param; + host.execute(*(p->first.first), p->first.second); + *(p->second) = p->first.second->first->getVarType(&host); +} + +bool TypeCheck::standardCheck(int firsttype, int secondtype, AST *toblame) +{ + switch(firsttype) + { + case ScriptParser::TYPE_BOOL: + { + switch(secondtype) + { + case ScriptParser::TYPE_BOOL: + return true; + + case ScriptParser::TYPE_FLOAT: + //Seeing as we're using float as int, this fits better with C + /*{ + if(toblame) + printErrorMsg(toblame, IMPLICITCAST, "float to bool"); + }*/ + return true; + + default: + { + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to bool"); + + return false; + } + } + } + + case ScriptParser::TYPE_FLOAT: + { + switch(secondtype) + { + case ScriptParser::TYPE_BOOL: + { + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, "bool to float"); + + return false; + } + + case ScriptParser::TYPE_FLOAT: + return true; + + default: + { + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to float"); + + return false; + } + } + } + + case ScriptParser::TYPE_VOID: + { + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to void"); + + return false; + } + + case ScriptParser::TYPE_FFC: + { + if(secondtype == ScriptParser::TYPE_FFC) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to ffc"); + + return false; + } + + case ScriptParser::TYPE_LINK: + { + if(secondtype == ScriptParser::TYPE_LINK) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to link"); + + return false; + } + + case ScriptParser::TYPE_SCREEN: + { + if(secondtype == ScriptParser::TYPE_SCREEN) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to screen"); + + return false; + } + + case ScriptParser::TYPE_GAME: + { + if(secondtype == ScriptParser::TYPE_GAME) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to game"); + + return false; + } + + case ScriptParser::TYPE_ITEM: + { + if(secondtype == ScriptParser::TYPE_ITEM) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to item"); + + return false; + } + + case ScriptParser::TYPE_ITEMCLASS: + { + if(secondtype == ScriptParser::TYPE_ITEMCLASS) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to itemdata"); + + return false; + } + + case ScriptParser::TYPE_NPC: + { + if(secondtype == ScriptParser::TYPE_NPC) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to npc"); + + return false; + } + + case ScriptParser::TYPE_LWPN: + { + if(secondtype == ScriptParser::TYPE_LWPN) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to lweapon"); + + return false; + } + + case ScriptParser::TYPE_EWPN: + { + if(secondtype == ScriptParser::TYPE_EWPN) + return true; + + if(toblame) + printErrorMsg(toblame, ILLEGALCAST, ScriptParser::printType(secondtype) + " to eweapon"); + + return false; + } + + default: + assert(false); + } + + return false; +} + +void TypeCheck::caseDefault(void *) +{ +} + +void TypeCheck::caseVarDecl(ASTVarDecl &, void *) +{ +} + +void TypeCheck::caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) +{ + SymbolTable * st = ((pair *)param)->first; + ASTExpr *init = host.getInitializer(); + init->execute(*this, param); + + if(failure) + return; + + int type = init->getType(); + int ltype = st->getVarType(&host); + + if(!standardCheck(ltype, type, &host)) + { + failure = true; + } +} + +void TypeCheck::caseArrayDecl(ASTArrayDecl &host, void *param) +{ + if(host.isRegister()) + { + ((ASTExpr *) host.getSize())->execute(*this, param); + + if(((ASTExpr *) host.getSize())->getType() != ScriptParser::TYPE_FLOAT) + { + printErrorMsg(&host, NONINTEGERARRAYSIZE, ""); + failure = true; + return; + } + } + + SymbolTable * st = ((pair*) param)->first; + int arraytype = st->getVarType(&host); + + if(host.getList() != NULL) + { + list l = host.getList()->getList(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + { + (*it)->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(arraytype, (*it)->getType(), &host)) + { + failure = true; + return; + } + } + } +} + +void TypeCheck::caseExprAnd(ASTExprAnd &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_BOOL, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_BOOL, host.getSecondOperand()->getType(), &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval == 0 || secondval == 0) + host.setIntValue(0); + else + host.setIntValue(1); + } +} + +void TypeCheck::caseExprOr(ASTExprOr &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_BOOL, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_BOOL, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval == 0 && secondval == 0) + host.setIntValue(0); + else + host.setIntValue(1); + } +} + +void TypeCheck::caseExprGT(ASTExprGT &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(), &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval > secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprGE(ASTExprGE &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval >= secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprLT(ASTExprLT &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval < secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprLE(ASTExprLE &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval <= secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprEQ(ASTExprEQ &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(host.getFirstOperand()->getType(), host.getSecondOperand()->getType(), + &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval == secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprNE(ASTExprNE &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(host.getFirstOperand()->getType(), host.getSecondOperand()->getType(), + &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(firstval != secondval) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprPlus(ASTExprPlus &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(firstval+secondval); + } +} + +void TypeCheck::caseExprMinus(ASTExprMinus &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(firstval-secondval); + } +} + +void TypeCheck::caseExprTimes(ASTExprTimes &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + double temp = ((double)secondval)/10000.0; + host.setIntValue((long)(firstval*temp)); + } +} + +void TypeCheck::caseExprDivide(ASTExprDivide &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(secondval == 0) + { + printErrorMsg(&host, DIVBYZERO); + failure = true; + return; + } + + host.setIntValue((firstval/secondval)*10000); + } +} + +void TypeCheck::caseExprBitOr(ASTExprBitOr &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(((firstval/10000)|(secondval/10000))*10000); + } +} +void TypeCheck::caseExprBitXor(ASTExprBitXor &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(((firstval/10000)^(secondval/10000))*10000); + } +} +void TypeCheck::caseExprBitAnd(ASTExprBitAnd &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(((firstval/10000)&(secondval/10000))*10000); + } +} +void TypeCheck::caseExprLShift(ASTExprLShift &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + if(host.getSecondOperand()->hasIntValue()) + { + if(host.getSecondOperand()->getIntValue()%10000) + { + printErrorMsg(&host, SHIFTNOTINT); + host.getSecondOperand()->setIntValue(10000*(host.getSecondOperand()->getIntValue()/10000)); + } + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + int secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(((firstval/10000)<<(secondval/10000))*10000); + } +} +void TypeCheck::caseExprRShift(ASTExprRShift &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + if(host.getSecondOperand()->hasIntValue()) + { + if(host.getSecondOperand()->getIntValue()%10000) + { + printErrorMsg(&host, SHIFTNOTINT); + host.getSecondOperand()->setIntValue(10000*(host.getSecondOperand()->getIntValue()/10000)); + } + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + int secondval = host.getSecondOperand()->getIntValue(); + host.setIntValue(((firstval/10000)>>(secondval/10000))*10000); + } +} +void TypeCheck::caseExprModulo(ASTExprModulo &host, void *param) +{ + host.getFirstOperand()->execute(*this, param); + host.getSecondOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getFirstOperand()->getType(), &host) + || !standardCheck(ScriptParser::TYPE_FLOAT, host.getSecondOperand()->getType(),&host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getFirstOperand()->hasIntValue() && host.getSecondOperand()->hasIntValue()) + { + long firstval = host.getFirstOperand()->getIntValue(); + long secondval = host.getSecondOperand()->getIntValue(); + + if(secondval == 0) + { + printErrorMsg(&host, DIVBYZERO); + failure = true; + return; + } + + host.setIntValue(firstval%secondval); + } +} +void TypeCheck::caseExprNot(ASTExprNot &host, void *param) +{ + host.getOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_BOOL, host.getOperand()->getType(), &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_BOOL); + + if(host.getOperand()->hasIntValue()) + { + long val = host.getOperand()->getIntValue(); + + if(val == 0) + host.setIntValue(1); + else + host.setIntValue(0); + } +} + +void TypeCheck::caseExprNegate(ASTExprNegate &host, void *param) +{ + host.getOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getOperand()->getType(), &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getOperand()->hasIntValue()) + { + long val = host.getOperand()->getIntValue(); + host.setIntValue(-val); + } +} +void TypeCheck::caseExprBitNot(ASTExprBitNot &host, void *param) +{ + host.getOperand()->execute(*this, param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getOperand()->getType(), &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); + + if(host.getOperand()->hasIntValue()) + { + long val = host.getOperand()->getIntValue(); + host.setIntValue((~(val/10000))*10000); + } +} +void TypeCheck::caseExprIncrement(ASTExprIncrement &host, void *param) +{ + pair *realp = (pair *)param; + int type; + GLVT p = GLVT(pair *>(this,realp),&type); + host.getOperand()->execute(*this, param); + + if(failure) + return; + + bool isexprdot; + IsDotExpr temp; + host.getOperand()->execute(temp, &isexprdot); + + if(!isexprdot) + { + int fid = realp->first->getID(host.getOperand()); + realp->first->putAST(&host, fid); + } + + GetLValType glvt; + host.getOperand()->execute(glvt, &p); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, *p.second, &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); +} +void TypeCheck::caseExprPreIncrement(ASTExprPreIncrement &host, void *param) +{ + pair *realp = (pair *)param; + int type; + GLVT p = GLVT(pair *>(this,realp),&type); + host.getOperand()->execute(*this, param); + + if(failure) + return; + + bool isexprdot; + IsDotExpr temp; + host.getOperand()->execute(temp, &isexprdot); + + if(!isexprdot) + { + int fid = realp->first->getID(host.getOperand()); + realp->first->putAST(&host, fid); + } + + GetLValType glvt; + host.getOperand()->execute(glvt, &p); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, *p.second, &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); +} +void TypeCheck::caseExprDecrement(ASTExprDecrement &host, void *param) +{ + pair *realp = (pair *)param; + int type; + GLVT p = GLVT(pair *>(this,realp),&type); + host.getOperand()->execute(*this, param); + + if(failure) + return; + + bool isexprdot; + IsDotExpr temp; + host.getOperand()->execute(temp, &isexprdot); + + if(!isexprdot) + { + int fid = realp->first->getID(host.getOperand()); + realp->first->putAST(&host, fid); + } + + GetLValType glvt; + host.getOperand()->execute(glvt, &p); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, *p.second, &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); +} +void TypeCheck::caseExprPreDecrement(ASTExprPreDecrement &host, void *param) +{ + pair *realp = (pair *)param; + int type; + GLVT p = GLVT(pair *>(this,realp),&type); + host.getOperand()->execute(*this, param); + + if(failure) + return; + + bool isexprdot; + IsDotExpr temp; + host.getOperand()->execute(temp, &isexprdot); + + if(!isexprdot) + { + int fid = realp->first->getID(host.getOperand()); + realp->first->putAST(&host, fid); + } + + GetLValType glvt; + host.getOperand()->execute(glvt, &p); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, *p.second, &host)) + { + failure = true; + return; + } + + host.setType(ScriptParser::TYPE_FLOAT); +} + +void TypeCheck::caseNumConstant(ASTNumConstant &host, void *) +{ + host.setType(ScriptParser::TYPE_FLOAT); + pair parts = host.getValue()->parseValue(); + pair val = ScriptParser::parseLong(parts); + + if(!val.second) + { + printErrorMsg(&host, CONSTTRUNC, host.getValue()->getValue()); + } + + host.setIntValue(val.first); +} + +void TypeCheck::caseFuncCall(ASTFuncCall &host, void *param) +{ + //yuck. Time to disambiguate these damn functions + //build the param types + list params = host.getParams(); + vector paramtypes; + vector possible; + bool isdotexpr; + IsDotExpr temp; + host.getName()->execute(temp, &isdotexpr); + + //if this is a simple function, we already have what we need + //otherwise we need the type of the thing being arrowed + if(!isdotexpr) + { + ASTExprArrow *lval = (ASTExprArrow *)host.getName(); + lval->getLVal()->execute(*this,param); + + if(failure) + return; + + int lvaltype = lval->getLVal()->getType(); + + if(!(lvaltype == ScriptParser::TYPE_FFC || lvaltype == ScriptParser::TYPE_LINK + || lvaltype == ScriptParser::TYPE_SCREEN || lvaltype == ScriptParser::TYPE_ITEM + || lvaltype == ScriptParser::TYPE_ITEMCLASS || lvaltype == ScriptParser::TYPE_GAME || lvaltype == ScriptParser::TYPE_NPC + || lvaltype == ScriptParser::TYPE_LWPN || lvaltype == ScriptParser::TYPE_EWPN)) + { + printErrorMsg(lval, ARROWNOTPOINTER); + failure = true; + return; + } + + //prepend that type to the function parameters, as that is implicitly passed + paramtypes.push_back(lvaltype); + } + + //now add the normal parameters + for(list::iterator it = params.begin(); it != params.end(); it++) + { + (*it)->execute(*this, param); + + if(failure) + return; + + paramtypes.push_back((*it)->getType()); + } + + SymbolTable *st = ((pair *)param)->first; + string paramstring = "("; + bool firsttype = true; + + for(vector::iterator it = paramtypes.begin(); it != paramtypes.end(); it++) + { + if(firsttype) + firsttype = false; + else + paramstring += ", "; + + paramstring += ScriptParser::printType(*it); + } + + paramstring += ")"; + + if(isdotexpr) + { + possible = st->getAmbiguousFuncs(&host); + + + vector > matchedfuncs; + + for(vector::iterator it = possible.begin(); it != possible.end(); it++) + { + vector stparams = st->getFuncParams(*it); + + //see if they match + if(stparams.size() != paramtypes.size()) + continue; + + bool matched = true; + int diffs = 0; + + for(unsigned int i=0; i(*it, diffs)); + } + } + + //now find the closest match *sigh* + vector bestmatch; + int bestdiffs = 10000; + + for(vector >::iterator it = matchedfuncs.begin(); it != matchedfuncs.end(); it++) + { + if((*it).second < bestdiffs) + { + bestdiffs = (*it).second; + bestmatch.clear(); + bestmatch.push_back((*it).first); + } + else if((*it).second == bestdiffs) + { + bestmatch.push_back((*it).first); + } + } + + string fullname; + + if(((ASTExprDot *)host.getName())->getNamespace() == "") + fullname = ((ASTExprDot*)host.getName())->getName(); + else + fullname = ((ASTExprDot *)host.getName())->getNamespace() + "." + ((ASTExprDot *)host.getName())->getName(); + + if(bestmatch.size() == 0) + { + printErrorMsg(&host, NOFUNCMATCH, fullname + paramstring); + failure = true; + return; + } + else if(bestmatch.size() > 1) + { + printErrorMsg(&host, TOOFUNCMATCH, fullname+paramstring); + failure = true; + return; + } + + //WHEW! + host.setType(st->getFuncType(bestmatch[0])); + st->putAST(&host, bestmatch[0]); + } + else + { + //still have to deal with the (%&# arrow functions + //luckily I will here assert that each type's functions MUST be unique + ASTExprArrow *name = (ASTExprArrow *)host.getName(); + int type = name->getLVal()->getType(); + pair > fidtype; + + switch(type) + { + case ScriptParser::TYPE_FFC: + fidtype = FFCSymbols::getInst().matchFunction(name->getName(),st); + break; + + case ScriptParser::TYPE_LINK: + fidtype = LinkSymbols::getInst().matchFunction(name->getName(),st); + break; + + case ScriptParser::TYPE_SCREEN: + fidtype = ScreenSymbols::getInst().matchFunction(name->getName(),st); + break; + + case ScriptParser::TYPE_GAME: + fidtype = GameSymbols::getInst().matchFunction(name->getName(),st); + break; + + case ScriptParser::TYPE_ITEM: + fidtype = ItemSymbols::getInst().matchFunction(name->getName(),st); + break; + + case ScriptParser::TYPE_ITEMCLASS: + fidtype = ItemclassSymbols::getInst().matchFunction(name->getName(), st); + break; + + case ScriptParser::TYPE_NPC: + fidtype = NPCSymbols::getInst().matchFunction(name->getName(), st); + break; + + case ScriptParser::TYPE_LWPN: + fidtype = LinkWeaponSymbols::getInst().matchFunction(name->getName(), st); + break; + + case ScriptParser::TYPE_EWPN: + fidtype = EnemyWeaponSymbols::getInst().matchFunction(name->getName(), st); + break; + + default: + assert(false); + } + + if(fidtype.first == -1) + { + failure = true; + printErrorMsg(&host, ARROWNOFUNC, name->getName()); + return; + } + + if(paramtypes.size() != fidtype.second.size()) + { + failure = true; + printErrorMsg(&host, NOFUNCMATCH, name->getName() + paramstring); + return; + } + + for(unsigned int i=0; igetName() + paramstring); + return; + } + } + + host.setType(st->getFuncType(fidtype.first)); + st->putAST(&host, fidtype.first); + } +} + + +void TypeCheck::caseBoolConstant(ASTBoolConstant &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + host.setType(ScriptParser::TYPE_BOOL); + host.setIntValue(host.getValue() ? 1 : 0); +} + +void TypeCheck::caseStmtAssign(ASTStmtAssign &host, void *param) +{ + pair *realp = (pair *)param; + //host.getLVal()->execute(*this, param); + host.getRVal()->execute(*this, param); + + if(failure) + return; + + int ltype; + GLVT p = GLVT(pair *>(this,realp), <ype); + GetLValType temp; + host.getLVal()->execute(temp, &p); + + if(failure) + return; + + int rtype = host.getRVal()->getType(); + + if(!standardCheck(ltype, rtype, &host)) + { + failure = true; + } +} + +void TypeCheck::caseExprDot(ASTExprDot &host, void *param) +{ + SymbolTable *st = ((pair *)param)->first; + + if(st->isConstant(host.getName())) + host.setType(ScriptParser::TYPE_FLOAT); + else + { + int type = st->getVarType(&host); + host.setType(type); + } +} + +void TypeCheck::caseExprArrow(ASTExprArrow &host, void *param) +{ + SymbolTable *st = ((pair *)param)->first; + //annoyingly enough I have to treat arrowed variables as function calls + //get the left-hand type + host.getLVal()->execute(*this,param); + + if(failure) + return; + + bool isIndexed = (host.getIndex() != NULL); + + if(isIndexed) + { + host.getIndex()->execute(*this,param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getIndex()->getType(), host.getIndex())) + { + failure = true; + return; + } + } + + int type = host.getLVal()->getType(); + pair > fidparam; + string name = "get" + host.getName(); + + if(isIndexed) + name += "[]"; + + switch(type) + { + case ScriptParser::TYPE_FFC: + { + fidparam = FFCSymbols::getInst().matchFunction(name,st); + break; + } + + case ScriptParser::TYPE_LINK: + { + fidparam = LinkSymbols::getInst().matchFunction(name,st); + break; + } + + case ScriptParser::TYPE_SCREEN: + { + fidparam = ScreenSymbols::getInst().matchFunction(name, st); + break; + } + + case ScriptParser::TYPE_GAME: + { + fidparam = GameSymbols::getInst().matchFunction(name, st); + break; + } + + case ScriptParser::TYPE_ITEM: + { + fidparam = ItemSymbols::getInst().matchFunction(name, st); + break; + } + + case ScriptParser::TYPE_ITEMCLASS: + { + fidparam = ItemclassSymbols::getInst().matchFunction(name, st); + break; + } + + case ScriptParser::TYPE_NPC: + { + fidparam = NPCSymbols::getInst().matchFunction(name,st); + break; + } + + case ScriptParser::TYPE_LWPN: + { + fidparam = LinkWeaponSymbols::getInst().matchFunction(name,st); + break; + } + + case ScriptParser::TYPE_EWPN: + { + fidparam = EnemyWeaponSymbols::getInst().matchFunction(name,st); + break; + } + + default: + failure = true; + printErrorMsg(&host, ARROWNOTPOINTER); + return; + } + + if(fidparam.first == -1 || (int)fidparam.second.size() != (isIndexed ? 2 : 1) || fidparam.second[0] != type) + { + failure = true; + printErrorMsg(&host, ARROWNOVAR, host.getName() + (isIndexed ? "[]" : "")); + return; + } + + st->putAST(&host, fidparam.first); + host.setType(st->getFuncType(fidparam.first)); +} + +void TypeCheck::caseExprArray(ASTExprArray &host, void *param) +{ + SymbolTable *st = ((pair *)param)->first; + + int type = st->getVarType(&host); + host.setType(type); + + if(host.getIndex()) + { + host.getIndex()->execute(*this,param); + + if(failure) + return; + + if(!standardCheck(ScriptParser::TYPE_FLOAT, host.getIndex()->getType(), host.getIndex())) + { + failure = true; + return; + } + } +} + +void TypeCheck::caseStmtFor(ASTStmtFor &host, void *param) +{ + RecursiveVisitor::caseStmtFor(host, param); + + if(failure) + return; + + int type = host.getTerminationCondition()->getType(); + + if(!standardCheck(ScriptParser::TYPE_BOOL, type, &host)) + { + failure = true; + return; + } +} + +void TypeCheck::caseStmtIf(ASTStmtIf &host, void *param) +{ + RecursiveVisitor::caseStmtIf(host, param); + + if(failure) + return; + + int type = host.getCondition()->getType(); + + if(!standardCheck(ScriptParser::TYPE_BOOL, type, &host)) + { + failure = true; + return; + } +} + +void TypeCheck::caseStmtWhile(ASTStmtWhile &host, void *param) +{ + RecursiveVisitor::caseStmtWhile(host, param); + + if(failure) + return; + + int type = host.getCond()->getType(); + + if(!standardCheck(ScriptParser::TYPE_BOOL, type, &host)) + { + failure = true; + return; + } +} + +void TypeCheck::caseStmtIfElse(ASTStmtIfElse &host, void *param) +{ + caseStmtIf(host, param); + host.getElseStmt()->execute(*this,param); +} + +void TypeCheck::caseStmtReturn(ASTStmtReturn &host, void *param) +{ + int rettype = ((pair *)param)->second; + + if(rettype != ScriptParser::TYPE_VOID) + { + printErrorMsg(&host, FUNCBADRETURN, ScriptParser::printType(rettype)); + failure = true; + } +} + +void TypeCheck::caseStmtReturnVal(ASTStmtReturnVal &host, void *param) +{ + host.getReturnValue()->execute(*this, param); + + if(failure) + return; + + int type = host.getReturnValue()->getType(); + int rettype = ((pair *)param)->second; + + if(!standardCheck(rettype, type, &host)) + { + failure = true; + } +} + diff --git a/src/parser/TypeChecker.h b/src/parser/TypeChecker.h new file mode 100644 index 0000000000..939c47b254 --- /dev/null +++ b/src/parser/TypeChecker.h @@ -0,0 +1,77 @@ +#ifndef TYPECHECKER_H +#define TYPECHECKER_H + +#include "UtilVisitors.h" + +class TypeCheck : public RecursiveVisitor +{ +public: + TypeCheck() : failure(false) {} + virtual void caseDefault(void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + virtual void caseExprAnd(ASTExprAnd &host, void *param); + virtual void caseExprOr(ASTExprOr &host, void *param); + virtual void caseExprGT(ASTExprGT &host, void *param); + virtual void caseExprGE(ASTExprGE &host, void *param); + virtual void caseExprLT(ASTExprLT &host, void *param); + virtual void caseExprLE(ASTExprLE &host, void *param); + virtual void caseExprEQ(ASTExprEQ &host, void *param); + virtual void caseExprNE(ASTExprNE &host, void *param); + virtual void caseExprPlus(ASTExprPlus &host, void *param); + virtual void caseExprMinus(ASTExprMinus &host, void *param); + virtual void caseExprTimes(ASTExprTimes &host, void *param); + virtual void caseExprDivide(ASTExprDivide &host, void *param); + virtual void caseExprNot(ASTExprNot &host, void *param); + virtual void caseExprNegate(ASTExprNegate &host, void *param); + virtual void caseNumConstant(ASTNumConstant &host, void *param); + virtual void caseFuncCall(ASTFuncCall &host, void *param); + virtual void caseBoolConstant(ASTBoolConstant &host, void *param); + virtual void caseStmtAssign(ASTStmtAssign &host, void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + virtual void caseStmtFor(ASTStmtFor &host, void *param); + virtual void caseStmtIf(ASTStmtIf &host, void *param); + virtual void caseStmtIfElse(ASTStmtIfElse &host, void *param); + virtual void caseStmtReturn(ASTStmtReturn &host, void *param); + virtual void caseStmtReturnVal(ASTStmtReturnVal &host, void *param); + virtual void caseStmtWhile(ASTStmtWhile &host, void *param); + virtual void caseExprBitOr(ASTExprBitOr &host, void *param); + virtual void caseExprBitXor(ASTExprBitXor &host, void *param); + virtual void caseExprBitAnd(ASTExprBitAnd &host, void *param); + virtual void caseExprLShift(ASTExprLShift &host, void *param); + virtual void caseExprRShift(ASTExprRShift &host, void *param); + virtual void caseExprModulo(ASTExprModulo &host, void *param); + virtual void caseExprBitNot(ASTExprBitNot &host, void *param); + virtual void caseExprIncrement(ASTExprIncrement &host, void *param); + virtual void caseExprPreIncrement(ASTExprPreIncrement &host, void *param); + virtual void caseExprDecrement(ASTExprDecrement &host, void *param); + virtual void caseExprPreDecrement(ASTExprPreDecrement &host, void *param); + bool isOK() + { + return !failure; + } + void fail() + { + failure = true; + } + friend class GetLValType; +private: + bool failure; + bool standardCheck(int firsttype, int secondtype, AST *toblame); +}; + +class GetLValType : public ASTVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); +}; + +#endif + diff --git a/src/parser/UtilVisitors.cpp b/src/parser/UtilVisitors.cpp new file mode 100644 index 0000000000..f033b1c5ff --- /dev/null +++ b/src/parser/UtilVisitors.cpp @@ -0,0 +1,934 @@ + +#include "../precompiled.h" //always first + +#include "UtilVisitors.h" +#include +#include "../zsyssimple.h" +#include "ParseError.h" + +void Clone::caseDefault(void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + //unreachable + assert(false); +} + +void Clone::caseProgram(ASTProgram &host, void *param) +{ + host.getDeclarations()->execute(*this,param); + result = new ASTProgram((ASTDeclList *)result, host.getLocation()); +} +void Clone::caseFloat(ASTFloat &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTFloat(host.getValue().c_str(),host.getType(),host.getLocation()); +} +void Clone::caseString(ASTString &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTString(host.getValue().c_str(),host.getLocation()); +} +void Clone::caseDeclList(ASTDeclList &host, void *param) +{ + ASTDeclList *dl = new ASTDeclList(host.getLocation()); + list decls = host.getDeclarations(); + list::reverse_iterator it; + + for(it = decls.rbegin(); it != decls.rend(); it++) + { + (*it)->execute(*this,param); + dl->addDeclaration((ASTDecl *)result); + } + + result = dl; +} +void Clone::caseImportDecl(ASTImportDecl &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTImportDecl(host.getFilename(),host.getLocation()); +} +void Clone::caseConstDecl(ASTConstDecl &host, void *param) +{ + host.getValue()->execute(*this,param); + result = new ASTConstDecl(host.getName(),(ASTFloat *)result,host.getLocation()); +} +void Clone::caseFuncDecl(ASTFuncDecl &host, void *param) +{ + ASTFuncDecl *af = new ASTFuncDecl(host.getLocation()); + host.getReturnType()->execute(*this,param); + ASTType *rettype = (ASTType *)result; + host.getBlock()->execute(*this,param); + ASTBlock *block = (ASTBlock *)result; + af->setName(host.getName()); + af->setBlock(block); + af->setReturnType(rettype); + list params = host.getParams(); + list::reverse_iterator it; + + for(it = params.rbegin(); it != params.rend(); it++) + { + (*it)->execute(*this,param); + af->addParam((ASTVarDecl *)result); + } + + result = af; +} +void Clone::caseTypeFloat(ASTTypeFloat &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeFloat(host.getLocation()); +} +void Clone::caseTypeBool(ASTTypeBool &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeBool(host.getLocation()); +} +void Clone::caseTypeVoid(ASTTypeVoid &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeVoid(host.getLocation()); +} +void Clone::caseTypeFFC(ASTTypeFFC &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeFFC(host.getLocation()); +} +void Clone::caseTypeGlobal(ASTTypeGlobal &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeGlobal(host.getLocation()); +} +void Clone::caseTypeItem(ASTTypeItem &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeItem(host.getLocation()); +} +void Clone::caseTypeItemclass(ASTTypeItemclass &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTTypeItemclass(host.getLocation()); +} +void Clone::caseTypeNPC(ASTTypeNPC &host, void *) +{ + result = new ASTTypeNPC(host.getLocation()); +} + +void Clone::caseTypeLWpn(ASTTypeLWpn &host, void *) +{ + result = new ASTTypeLWpn(host.getLocation()); +} + +void Clone::caseTypeEWpn(ASTTypeEWpn &host, void *) +{ + result = new ASTTypeEWpn(host.getLocation()); +} + +void Clone::caseVarDecl(ASTVarDecl &host, void *param) +{ + host.getType()->execute(*this,param); + ASTType *t = (ASTType *)result; + result = new ASTVarDecl(t,host.getName(), host.getLocation()); +} +void Clone::caseArrayDecl(ASTArrayDecl &host, void *param) +{ + ASTArrayList *l = NULL; + host.getType()->execute(*this,param); + ASTType *t = (ASTType *) result; + + if(host.getList()) + { + l = new ASTArrayList(host.getLocation()); + + for(list::iterator it = host.getList()->getList().begin(); it != host.getList()->getList().end(); it++) + { + (*it)->execute(*this,param); + l->addParam((ASTExpr *) result); + } + } + + AST *s; + + if(host.isRegister()) + { + ((ASTExpr *) host.getSize())->execute(*this, param); + s = (ASTExpr *) result; + } + else + { + ((ASTFloat *) host.getSize())->execute(*this, param); + s = (ASTFloat *) result; + } + + result = new ASTArrayDecl(t,host.getName(),s,host.isRegister(),l,host.getLocation()); +} + +void Clone::caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) +{ + host.getType()->execute(*this,param); + ASTType *t = (ASTType *)result; + host.getInitializer()->execute(*this,param); + ASTExpr *e = (ASTExpr *)result; + result = new ASTVarDeclInitializer(t,host.getName(),e, host.getLocation()); +} + +void Clone::caseExprAnd(ASTExprAnd &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprAnd *res = new ASTExprAnd(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprOr(ASTExprOr &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprOr *res = new ASTExprOr(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprGT(ASTExprGT &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprGT *res = new ASTExprGT(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprGE(ASTExprGE &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprGE *res = new ASTExprGE(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprLT(ASTExprLT &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprLT *res = new ASTExprLT(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprLE(ASTExprLE &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprLE *res = new ASTExprLE(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprEQ(ASTExprEQ &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprEQ *res = new ASTExprEQ(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprNE(ASTExprNE &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprNE *res = new ASTExprNE(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprPlus(ASTExprPlus &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprPlus *res = new ASTExprPlus(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprMinus(ASTExprMinus &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprMinus *res = new ASTExprMinus(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprTimes(ASTExprTimes &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprTimes *res = new ASTExprTimes(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprDivide(ASTExprDivide &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprDivide *res = new ASTExprDivide(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprBitOr(ASTExprBitOr &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprBitOr *res = new ASTExprBitOr(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprBitXor(ASTExprBitXor &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprBitXor *res = new ASTExprBitXor(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprBitAnd(ASTExprBitAnd &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprBitAnd *res = new ASTExprBitAnd(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprLShift(ASTExprLShift &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprLShift *res = new ASTExprLShift(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprRShift(ASTExprRShift &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprRShift *res = new ASTExprRShift(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprModulo(ASTExprModulo &host, void *param) +{ + host.getFirstOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + host.getSecondOperand()->execute(*this,param); + ASTExpr *s = (ASTExpr *)result; + ASTExprModulo *res = new ASTExprModulo(host.getLocation()); + res->setFirstOperand(f); + res->setSecondOperand(s); + result = res; +} +void Clone::caseExprNot(ASTExprNot &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprNot *res = new ASTExprNot(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprNegate(ASTExprNegate &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprNegate *res = new ASTExprNegate(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprBitNot(ASTExprBitNot &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprBitNot *res = new ASTExprBitNot(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprIncrement(ASTExprIncrement &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprIncrement *res = new ASTExprIncrement(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprPreIncrement(ASTExprPreIncrement &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprPreIncrement *res = new ASTExprPreIncrement(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprDecrement(ASTExprDecrement&host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprDecrement *res = new ASTExprDecrement(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseExprPreDecrement(ASTExprPreDecrement &host, void *param) +{ + host.getOperand()->execute(*this,param); + ASTExpr *f = (ASTExpr *)result; + ASTExprPreDecrement *res = new ASTExprPreDecrement(host.getLocation()); + res->setOperand(f); + result = res; +} +void Clone::caseNumConstant(ASTNumConstant &host, void *param) +{ + host.getValue()->execute(*this,param); + ASTFloat *f = (ASTFloat *)result; + result = new ASTNumConstant(f, host.getLocation()); +} +void Clone::caseFuncCall(ASTFuncCall &host, void *param) +{ + ASTFuncCall *fc = new ASTFuncCall(host.getLocation()); + host.getName()->execute(*this,param); + ASTExpr *name = (ASTExpr *)result; + fc->setName(name); + list params = host.getParams(); + list::reverse_iterator it; + + for(it = params.rbegin(); it != params.rend(); it++) + { + (*it)->execute(*this,param); + fc->addParam((ASTExpr *)result); + } + + result = fc; +} + +void Clone::caseBoolConstant(ASTBoolConstant &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTBoolConstant(host.getValue(),host.getLocation()); +} + +void Clone::caseBlock(ASTBlock &host, void *param) +{ + ASTBlock *b = new ASTBlock(host.getLocation()); + list stmts = host.getStatements(); + list::reverse_iterator it; + + for(it = stmts.rbegin(); it != stmts.rend(); it++) + { + (*it)->execute(*this,param); + b->addStatement((ASTStmt *)result); + } + + result = b; +} + +void Clone::caseStmtAssign(ASTStmtAssign &host, void *param) +{ + host.getLVal()->execute(*this,param); + ASTExpr *left = (ASTExpr *)result; + host.getRVal()->execute(*this,param); + ASTExpr *right = (ASTExpr *)result; + result = new ASTStmtAssign(left,right,host.getLocation()); +} + +void Clone::caseExprDot(ASTExprDot &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTExprDot(host.getNamespace(),host.getName(),host.getLocation()); +} + +void Clone::caseExprArrow(ASTExprArrow &host, void *param) +{ + host.getLVal()->execute(*this,param); + ASTExprArrow *arrow = new ASTExprArrow((ASTExpr *)result, host.getName(), host.getLocation()); + + if(host.getIndex()) + { + host.getIndex()->execute(*this,param); + arrow->setIndex((ASTExpr *)result); + } + + result = arrow; +} + +void Clone::caseExprArray(ASTExprArray &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + ASTExprArray *arr = new ASTExprArray(host.getNamespace(), host.getName(), host.getLocation()); + + if(host.getIndex()) + { + host.getIndex()->execute(*this,param); + arr->setIndex((ASTExpr *)result); + } + + result = arr; //new ASTExprArray(host.getNamespace(),host.getName(),host.getLocation()); +} + +void Clone::caseStmtFor(ASTStmtFor &host, void *param) +{ + host.getStmt()->execute(*this,param); + ASTBlock *block = (ASTBlock *)result; + host.getPrecondition()->execute(*this,param); + ASTStmt *prec = (ASTStmt *)result; + host.getTerminationCondition()->execute(*this,param); + ASTExpr *cond = (ASTExpr *)result; + host.getIncrement()->execute(*this,param); + ASTStmt *incr = (ASTStmt *)result; + result = new ASTStmtFor(prec,cond,incr,block,host.getLocation()); +} +void Clone::caseStmtIf(ASTStmtIf &host, void *param) +{ + host.getCondition()->execute(*this,param); + ASTExpr *cond = (ASTExpr *)result; + host.getStmt()->execute(*this,param); + result = new ASTStmtIf(cond, (ASTBlock *)result,host.getLocation()); +} +void Clone::caseStmtIfElse(ASTStmtIfElse &host, void *param) +{ + host.getCondition()->execute(*this,param); + ASTExpr *cond = (ASTExpr *)result; + host.getStmt()->execute(*this,param); + ASTBlock *block =(ASTBlock *)result; + host.getElseStmt()->execute(*this,param); + result = new ASTStmtIfElse(cond, block, (ASTBlock *)result,host.getLocation()); +} + +void Clone::caseStmtReturn(ASTStmtReturn &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTStmtReturn(host.getLocation()); +} + +void Clone::caseStmtReturnVal(ASTStmtReturnVal &host, void *param) +{ + host.getReturnValue()->execute(*this,param); + result = new ASTStmtReturnVal((ASTExpr *)result,host.getLocation()); +} + +void Clone::caseStmtEmpty(ASTStmtEmpty &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTStmtEmpty(host.getLocation()); +} + +void Clone::caseScript(ASTScript &host, void *param) +{ + host.getType()->execute(*this,param); + ASTType *type = (ASTType *)result; + host.getScriptBlock()->execute(*this,param); + result = new ASTScript(type, host.getName(), (ASTDeclList *)result, host.getLocation()); +} + +void Clone::caseStmtWhile(ASTStmtWhile &host, void *param) +{ + host.getCond()->execute(*this,param); + ASTExpr *cond = (ASTExpr *)result; + host.getStmt()->execute(*this,param); + result = new ASTStmtWhile(cond, (ASTStmt *)result, host.getLocation()); +} + +void Clone::caseStmtDo(ASTStmtDo &host, void *param) +{ + host.getCond()->execute(*this,param); + ASTExpr *cond = (ASTExpr *)result; + host.getStmt()->execute(*this,param); + result = new ASTStmtDo(cond, (ASTStmt *)result, host.getLocation()); +} + +void Clone::caseStmtBreak(ASTStmtBreak &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTStmtBreak(host.getLocation()); +} + +void Clone::caseStmtContinue(ASTStmtContinue &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + result = new ASTStmtContinue(host.getLocation()); +} +//////////////////////////////////////////////////////////////////////////////// +void GetImports::caseDefault(void *param) +{ + if(param != NULL) + *(bool *)param = false; +} + +void GetImports::caseImportDecl(ASTImportDecl &, void *param) +{ + if(param != NULL) + *(bool *)param = true; +} + +void GetImports::caseDeclList(ASTDeclList &host, void *) +{ + list &l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end();) + { + bool isimport; + (*it)->execute(*this, &isimport); + + if(isimport) + { + result.push_back((ASTImportDecl *)*it); + it=l.erase(it); + } + else + it++; + } +} + +void GetImports::caseProgram(ASTProgram &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + host.getDeclarations()->execute(*this,NULL); +} + +//////////////////////////////////////////////////////////////////////////////// +void GetConsts::caseDefault(void *param) +{ + if(param != NULL) + *(bool *)param = false; +} + +void GetConsts::caseConstDecl(ASTConstDecl &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + void *temp; + temp=&host; + + if(param != NULL) + *(bool *)param = true; +} + +void GetConsts::caseDeclList(ASTDeclList &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + list &l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end();) + { + bool isconst; + (*it)->execute(*this, &isconst); + + if(isconst) + { + result.push_back((ASTConstDecl *)*it); + it=l.erase(it); + } + else + it++; + } +} + +void GetConsts::caseProgram(ASTProgram &host, void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + host.getDeclarations()->execute(*this,NULL); +} + +void GetGlobalVars::caseDefault(void *param) +{ + if(param != NULL) + *(int *)param = 0; +} + +void GetGlobalVars::caseVarDecl(ASTVarDecl &, void *param) +{ + if(param != NULL) + *(int *)param = 1; +} + +void GetGlobalVars::caseVarDeclInitializer(ASTVarDeclInitializer &, void *param) +{ + if(param != NULL) + *(int *)param = 1; +} + +void GetGlobalVars::caseArrayDecl(ASTArrayDecl &, void *param) +{ + if(param != NULL) + *(int *)param = 2; +} + +void GetGlobalVars::caseProgram(ASTProgram &host, void *) +{ + host.getDeclarations()->execute(*this, NULL); +} + +void GetGlobalVars::caseDeclList(ASTDeclList &host, void *) +{ + list &l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end();) + { + int dectype; + (*it)->execute(*this, &dectype); + + if(dectype==1) + { + result.push_back((ASTVarDecl *)(*it)); + it=l.erase(it); + } + else if(dectype==2) + { + resultA.push_back((ASTArrayDecl *)(*it)); + it=l.erase(it); + } + else + it++; + } +} + +void GetGlobalFuncs::caseDefault(void *param) +{ + if(param != NULL) + *(bool *)param = false; +} + +void GetGlobalFuncs::caseFuncDecl(ASTFuncDecl &, void *param) +{ + if(param != NULL) + *(bool *)param = true; +} + +void GetGlobalFuncs::caseDeclList(ASTDeclList &host, void *) +{ + list &l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end();) + { + bool isfuncdecl; + (*it)->execute(*this, &isfuncdecl); + + if(isfuncdecl) + { + result.push_back((ASTFuncDecl *)*it); + it=l.erase(it); + } + else + it++; + } +} + +void GetGlobalFuncs::caseProgram(ASTProgram &host, void *) +{ + host.getDeclarations()->execute(*this,NULL); +} + +void GetScripts::caseDefault(void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + //there should be nothing left in here now + assert(false); +} + +void GetScripts::caseProgram(ASTProgram &host, void *param) +{ + host.getDeclarations()->execute(*this,param); +} + +void GetScripts::caseDeclList(ASTDeclList &host, void *param) +{ + list &l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end();) + { + (*it)->execute(*this, param); + result.push_back((ASTScript *)*it); + it=l.erase(it); + } +} + +void GetScripts::caseScript(ASTScript &host, void *param) +{ + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ +} + +void MergeASTs::caseDefault(void *param) +{ + //these are here to bypass compiler warnings about unused arguments + param=param; + + box_out("Something BAD BROKEN in the parser code!"); + box_eol(); + assert(false); +} + +void MergeASTs::caseProgram(ASTProgram &host, void *param) +{ + assert(param); + ASTProgram *other = (ASTProgram *)param; + list &decls = other->getDeclarations()->getDeclarations(); + + for(list::iterator it = decls.begin(); it != decls.end();) + { + host.getDeclarations()->addDeclaration((*it)); + it = decls.erase(it); + } + + delete other; +} + +void CheckForExtraneousImports::caseDefault(void *) +{ + +} + +void CheckForExtraneousImports::caseImportDecl(ASTImportDecl &host, void *) +{ + ok = false; + printErrorMsg(&host, IMPORTBADSCOPE); +} + +void ExtractType::caseDefault(void *) +{ + //unreachable + assert(false); +} + +void ExtractType::caseTypeBool(ASTTypeBool &, void *param) +{ + *(int *)param = ScriptParser::TYPE_BOOL; +} + +void ExtractType::caseTypeFloat(ASTTypeFloat &, void *param) +{ + *(int *)param = ScriptParser::TYPE_FLOAT; +} + +void ExtractType::caseTypeVoid(ASTTypeVoid &, void *param) +{ + *(int *)param = ScriptParser::TYPE_VOID; +} + +void ExtractType::caseTypeFFC(ASTTypeFFC &, void *param) +{ + *(int *)param = ScriptParser::TYPE_FFC; +} + +void ExtractType::caseTypeGlobal(ASTTypeGlobal &, void *param) +{ + *(int *)param = ScriptParser::TYPE_GLOBAL; +} + +void ExtractType::caseTypeItem(ASTTypeItem &, void *param) +{ + *(int *)param = ScriptParser::TYPE_ITEM; +} + +void ExtractType::caseTypeItemclass(ASTTypeItemclass &, void *param) +{ + *(int *)param = ScriptParser::TYPE_ITEMCLASS; +} + +void ExtractType::caseTypeNPC(ASTTypeNPC &, void *param) +{ + *(int *)param = ScriptParser::TYPE_NPC; +} + +void ExtractType::caseTypeLWpn(ASTTypeLWpn &, void *param) +{ + *(int *)param = ScriptParser::TYPE_LWPN; +} + +void ExtractType::caseTypeEWpn(ASTTypeEWpn &, void *param) +{ + *(int *)param = ScriptParser::TYPE_EWPN; +} + diff --git a/src/parser/UtilVisitors.h b/src/parser/UtilVisitors.h new file mode 100644 index 0000000000..b391f7b782 --- /dev/null +++ b/src/parser/UtilVisitors.h @@ -0,0 +1,517 @@ +#ifndef UTILVISITORS_H +#define UTILVISITORS_H + +#include "AST.h" + +class Clone : public ASTVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseFloat(ASTFloat &host, void *param); + virtual void caseString(ASTString &host, void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + virtual void caseImportDecl(ASTImportDecl &host, void *param); + virtual void caseConstDecl(ASTConstDecl &host, void *param); + virtual void caseFuncDecl(ASTFuncDecl &host, void *param); + virtual void caseTypeFloat(ASTTypeFloat &host, void *param); + virtual void caseTypeBool(ASTTypeBool &host, void *param); + virtual void caseTypeVoid(ASTTypeVoid &host, void *param); + virtual void caseTypeFFC(ASTTypeFFC &host, void *param); + virtual void caseTypeItem(ASTTypeItem &host, void *param); + virtual void caseTypeItemclass(ASTTypeItemclass &host, void *param); + virtual void caseTypeGlobal(ASTTypeGlobal &host, void *param); + virtual void caseTypeNPC(ASTTypeNPC &host, void *param); + virtual void caseTypeLWpn(ASTTypeLWpn &host, void *param); + virtual void caseTypeEWpn(ASTTypeEWpn &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param); + virtual void caseExprAnd(ASTExprAnd &host, void *param); + virtual void caseExprOr(ASTExprOr &host, void *param); + virtual void caseExprGT(ASTExprGT &host, void *param); + virtual void caseExprGE(ASTExprGE &host, void *param); + virtual void caseExprLT(ASTExprLT &host, void *param); + virtual void caseExprLE(ASTExprLE &host, void *param); + virtual void caseExprEQ(ASTExprEQ &host, void *param); + virtual void caseExprNE(ASTExprNE &host, void *param); + virtual void caseExprPlus(ASTExprPlus &host, void *param); + virtual void caseExprMinus(ASTExprMinus &host, void *param); + virtual void caseExprTimes(ASTExprTimes &host, void *param); + virtual void caseExprDivide(ASTExprDivide &host, void *param); + virtual void caseExprNot(ASTExprNot &host, void *param); + virtual void caseExprNegate(ASTExprNegate &host, void *param); + virtual void caseNumConstant(ASTNumConstant &host, void *param); + virtual void caseFuncCall(ASTFuncCall &host, void *param); + virtual void caseBoolConstant(ASTBoolConstant &host, void *param); + virtual void caseBlock(ASTBlock &host, void *param); + virtual void caseStmtAssign(ASTStmtAssign &host, void *param); + virtual void caseExprDot(ASTExprDot &host, void *param); + virtual void caseExprArrow(ASTExprArrow &host, void *param); + virtual void caseExprArray(ASTExprArray &host, void *param); + virtual void caseStmtFor(ASTStmtFor &host, void *param); + virtual void caseStmtIf(ASTStmtIf &host, void *param); + virtual void caseStmtIfElse(ASTStmtIfElse &host, void *param); + virtual void caseStmtReturn(ASTStmtReturn &host, void *param); + virtual void caseStmtReturnVal(ASTStmtReturnVal &host, void *param); + virtual void caseStmtEmpty(ASTStmtEmpty &host, void *param); + virtual void caseScript(ASTScript &host, void *param); + virtual void caseStmtWhile(ASTStmtWhile &host, void *param); + virtual void caseStmtDo(ASTStmtDo &host, void *param); + virtual void caseExprBitOr(ASTExprBitOr &host, void *param); + virtual void caseExprBitXor(ASTExprBitXor &host, void *param); + virtual void caseExprBitAnd(ASTExprBitAnd &host, void *param); + virtual void caseExprLShift(ASTExprLShift &host, void *param); + virtual void caseExprRShift(ASTExprRShift &host, void *param); + virtual void caseExprModulo(ASTExprModulo &host, void *param); + virtual void caseExprBitNot(ASTExprBitNot &host, void *param); + virtual void caseExprIncrement(ASTExprIncrement &host, void *param); + virtual void caseExprPreIncrement(ASTExprPreIncrement &host, void *param); + virtual void caseExprDecrement(ASTExprDecrement &host, void *param); + virtual void caseExprPreDecrement(ASTExprPreDecrement &host, void *param); + virtual void caseStmtBreak(ASTStmtBreak &host, void *param); + virtual void caseStmtContinue(ASTStmtContinue &host, void *param); + + AST *getResult() + { + return result; + } +private: + AST *result; +}; + +class RecursiveVisitor : public ASTVisitor +{ +public: + virtual void caseDefault(void *param) + { + param=param; /*these are here to bypass compiler warnings about unused arguments*/ + } + virtual void caseProgram(ASTProgram &host, void *param) + { + host.getDeclarations()->execute(*this,param); + } + virtual void caseDeclList(ASTDeclList &host, void *param) + { + list l = host.getDeclarations(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + { + (*it)->execute(*this,param); + } + } + virtual void caseFuncDecl(ASTFuncDecl &host, void *param) + { + host.getReturnType()->execute(*this,param); + list l = host.getParams(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + { + (*it)->execute(*this,param); + } + + host.getBlock()->execute(*this,param); + } + virtual void caseVarDecl(ASTVarDecl &host, void *param) + { + host.getType()->execute(*this,param); + } + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param) + { + host.getType()->execute(*this,param); + host.getInitializer()->execute(*this,param); + } + virtual void caseArrayDecl(ASTArrayDecl &host, void *param) + { + host.getType()->execute(*this,param); + + if(host.isRegister()) + ((ASTExpr *) host.getSize())->execute(*this, param); + + if(host.getList() != NULL) + { + for(list::iterator it = host.getList()->getList().begin(); it != host.getList()->getList().end(); it++) + { + (*it)->execute(*this,param); + } + } + } + virtual void caseExprAnd(ASTExprAnd &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprOr(ASTExprOr &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprGT(ASTExprGT &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprGE(ASTExprGE &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprLT(ASTExprLT &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprLE(ASTExprLE &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprEQ(ASTExprEQ &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprNE(ASTExprNE &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprPlus(ASTExprPlus &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprMinus(ASTExprMinus &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprTimes(ASTExprTimes &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprDivide(ASTExprDivide &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprBitOr(ASTExprBitOr &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprBitXor(ASTExprBitXor &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprBitAnd(ASTExprBitAnd &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprLShift(ASTExprLShift &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprRShift(ASTExprRShift &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprModulo(ASTExprModulo &host, void *param) + { + host.getFirstOperand()->execute(*this,param); + host.getSecondOperand()->execute(*this,param); + } + virtual void caseExprNot(ASTExprNot &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprBitNot(ASTExprBitNot &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprIncrement(ASTExprIncrement &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprPreIncrement(ASTExprPreIncrement &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprDecrement(ASTExprDecrement &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprPreDecrement(ASTExprPreDecrement &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprNegate(ASTExprNegate &host, void *param) + { + host.getOperand()->execute(*this,param); + } + virtual void caseExprArrow(ASTExprArrow &host, void*param) + { + host.getLVal()->execute(*this,param); + + if(host.getIndex()) + host.getIndex()->execute(*this,param); + } + virtual void caseExprArray(ASTExprArray &host, void*param) + { + if(host.getIndex()) host.getIndex()->execute(*this,param); + } + virtual void caseNumConstant(ASTNumConstant &host, void *param) + { + host.getValue()->execute(*this,param); + } + virtual void caseFuncCall(ASTFuncCall &host, void *param) + { + list l = host.getParams(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + { + (*it)->execute(*this,param); + } + } + virtual void caseBlock(ASTBlock &host, void *param) + { + list l = host.getStatements(); + + for(list::iterator it = l.begin(); it != l.end(); it++) + (*it)->execute(*this,param); + } + virtual void caseStmtAssign(ASTStmtAssign &host, void *param) + { + host.getLVal()->execute(*this,param); + host.getRVal()->execute(*this,param); + } + virtual void caseStmtFor(ASTStmtFor &host, void *param) + { + host.getPrecondition()->execute(*this,param); + host.getIncrement()->execute(*this,param); + host.getTerminationCondition()->execute(*this,param); + host.getStmt()->execute(*this,param); + } + virtual void caseStmtIf(ASTStmtIf &host, void *param) + { + host.getCondition()->execute(*this,param); + host.getStmt()->execute(*this,param); + } + virtual void caseStmtIfElse(ASTStmtIfElse &host, void *param) + { + host.getCondition()->execute(*this,param); + host.getStmt()->execute(*this,param); + host.getElseStmt()->execute(*this,param); + } + virtual void caseStmtReturnVal(ASTStmtReturnVal &host, void *param) + { + host.getReturnValue()->execute(*this,param); + } + virtual void caseScript(ASTScript &host, void *param) + { + host.getType()->execute(*this,param); + host.getScriptBlock()->execute(*this,param); + } + virtual void caseStmtWhile(ASTStmtWhile &host, void *param) + { + host.getCond()->execute(*this,param); + host.getStmt()->execute(*this,param); + } + virtual void caseStmtDo(ASTStmtDo &host, void *param) + { + host.getStmt()->execute(*this,param); + host.getCond()->execute(*this,param); + } +}; + +//removes all import declarations from a program +//call with param=NULL +//NOT responsible for freeing said imports +class GetImports : public ASTVisitor +{ +public: + GetImports() : result() {} + virtual void caseDefault(void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseImportDecl(ASTImportDecl &host, void *param); + vector &getResult() + { + return result; + } +private: + vector result; +}; + +class GetConsts : public ASTVisitor +{ +public: + GetConsts() : result() {} + virtual void caseDefault(void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseConstDecl(ASTConstDecl &host, void *param); + vector &getResult() + { + return result; + } +private: + vector result; +}; + +class GetGlobalFuncs : public ASTVisitor +{ +public: + GetGlobalFuncs() : result() {} + virtual void caseDefault(void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseFuncDecl(ASTFuncDecl &host, void *param); + vector getResult() + { + return result; + } +private: + vector result; +}; + +class GetGlobalVars : public ASTVisitor +{ +public: + GetGlobalVars() : result() {} + virtual void caseDefault(void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseVarDecl(ASTVarDecl &host, void *param); + virtual void caseVarDeclInitializer(ASTVarDeclInitializer &host, void *param); + virtual void caseArrayDecl(ASTArrayDecl &host, void *param); + vector getResult() + { + return result; + } + vector getResultA() + { + return resultA; + } +private: + vector result; + vector resultA; +}; + +class GetScripts : public ASTVisitor +{ +public: + GetScripts() : result() {} + virtual void caseDefault(void *param); + virtual void caseScript(ASTScript &host, void *param); + virtual void caseProgram(ASTProgram &host, void *param); + virtual void caseDeclList(ASTDeclList &host, void *param); + vector getResult() + { + return result; + } +private: + vector result; +}; + +//Merges one AST into another. Pass the AST that will be destroyed in the process +//as the param. +//The param AST gets completely consumed and deleted +class MergeASTs : public ASTVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseProgram(ASTProgram &host, void *param); +}; + +class CheckForExtraneousImports : public RecursiveVisitor +{ +public: + CheckForExtraneousImports() : ok(true) {} + bool isOK() + { + return ok; + } + virtual void caseDefault(void *param); + virtual void caseImportDecl(ASTImportDecl &host, void *param); +private: + bool ok; +}; + +class ExtractType : public ASTVisitor +{ +public: + virtual void caseDefault(void *param); + virtual void caseTypeVoid(ASTTypeVoid &host, void *param); + virtual void caseTypeFloat(ASTTypeFloat &host, void *param); + virtual void caseTypeBool(ASTTypeBool &host, void *param); + virtual void caseTypeFFC(ASTTypeFFC &host, void *param); + virtual void caseTypeItem(ASTTypeItem &host, void *param); + virtual void caseTypeItemclass(ASTTypeItemclass &host, void *param); + virtual void caseTypeGlobal(ASTTypeGlobal &host, void *param); + virtual void caseTypeNPC(ASTTypeNPC &host, void *param); + virtual void caseTypeLWpn(ASTTypeLWpn &host, void *param); + virtual void caseTypeEWpn(ASTTypeEWpn &host, void *param); +}; + +class IsDotExpr : public ASTVisitor +{ +public: + virtual void caseDefault(void *param) + { + *(bool *)param = false; + } + virtual void caseExprDot(ASTExprDot &, void *param) + { + *(bool *)param = true; + } +}; + +class IsArrayDecl : public ASTVisitor +{ +public: + virtual void caseDefault(void *param) + { + *(bool *)param = false; + } + virtual void caseArrayDecl(ASTArrayDecl &, void *param) + { + *(bool *)param = true; + } +}; + +class IsBlock : public ASTVisitor +{ +public: + virtual void caseDefault(void *param) + { + *(bool *)param = false; + } + virtual void caseBlock(ASTBlock &, void *param) + { + *(bool *)param = true; + } +}; + +class IsFuncDecl : public ASTVisitor +{ +public: + virtual void caseDefault(void *param) + { + param=param; /*these are here to bypass compiler warnings about unused arguments*/ *(bool *)param = false; + } + virtual void caseFuncDecl(ASTFuncDecl &host, void *param) + { + void *temp; + temp=&host; + param=param; /*these are here to bypass compiler warnings about unused arguments*/ *(bool *)param = true; + } +}; + +#endif + diff --git a/src/parser/bisontypes.h b/src/parser/bisontypes.h new file mode 100644 index 0000000000..bc9083ce47 --- /dev/null +++ b/src/parser/bisontypes.h @@ -0,0 +1,13 @@ +#ifndef BISONTYPES_H +#define BISONTYPES_H + +typedef struct YYLTYPE +{ + int first_line; + int last_line; + int first_column; + int last_column; +} YYLTYPE; + +#endif + diff --git a/src/parser/ffscript.lpp b/src/parser/ffscript.lpp new file mode 100644 index 0000000000..b2245e2e2c --- /dev/null +++ b/src/parser/ffscript.lpp @@ -0,0 +1,131 @@ +/* + use this file to generate lex.yy.c +command: flex -B -olex.yy.cpp ffscript.lpp +*/ + +%option yylineno +%option noyywrap +%option never-interactive +WS [ \t\n\r] + +%{ +#include +#include "AST.h" +#include "../zsyssimple.h" +#include "y.tab.hpp" +YYLTYPE noloc = {0,0,0,0}; +void doLines(); +%} + +%% + +script { doLines();return SCRIPT; } +float { doLines(); return FLOAT; } +int { doLines(); return FLOAT; } +for { doLines(); return FOR; } +bool { doLines();return BOOL; } +void { doLines();return VOID; } +if { doLines();return IF; } +else { doLines();return ELSE; } +return { doLines();return RETURN; } +import { doLines();return IMPORT; } +true { doLines();return TRUE; } +false { doLines();return FALSE; } +while {doLines(); return WHILE;} +ffc {doLines(); return FFC;} +itemdata {doLines(); return ITEMCLASS;} +item {doLines(); return ITEM;} +global {doLines(); return GLOBAL;} +break {doLines(); return BREAK;} +continue {doLines(); return CONTINUE;} +const {doLines(); return CONST;} +do {doLines(); return DO;} +npc {doLines(); return NPC;} +lweapon {doLines(); return LWEAPON;} +eweapon {doLines(); return EWEAPON;} + +\-\> { doLines(); return ARROW;} +\<\<= { doLines(); return LSHIFTASSIGN; } +\>\>= { doLines(); return RSHIFTASSIGN; } +\<\< { doLines(); return LSHIFT; } +\>\> { doLines(); return RSHIFT; } +\<= { doLines();return LE; } +\< { doLines();return LT; } +\>= { doLines();return GE; } +\> { doLines();return GT; } +== { doLines();return EQ; } +\!= { doLines();return NE; } +\= { doLines();return ASSIGN; } +\+= { doLines();return PLUSASSIGN; } +\-= { doLines();return MINUSASSIGN; } +\*= { doLines();return TIMESASSIGN; } +\/= { doLines();return DIVIDEASSIGN; } +\&\&= { doLines();return ANDASSIGN; } +\|\|= { doLines();return ORASSIGN; } +\&= { doLines();return BITANDASSIGN; } +\|= { doLines();return BITORASSIGN; } +\^= { doLines();return BITXORASSIGN; } +\%= { doLines();return MODULOASSIGN; } +\; { doLines();return SEMICOLON; } +\, { doLines();return COMMA; } +\[ { doLines();return LBRACKET; } +\] { doLines();return RBRACKET; } +\( { doLines();return LPAREN; } +\) { doLines();return RPAREN; } +\+\+ { doLines();return INCREMENT; } +\-\- { doLines();return DECREMENT; } +\. { doLines();return DOT; } +\+ { doLines();return PLUS; } +\- { doLines();return MINUS; } +\* { doLines();return TIMES; } +\/\/.* { ; } +\/ { doLines();return DIVIDE; } +\{ { doLines();return LBRACE; } +\} { doLines();return RBRACE; } +\&\& { doLines();return AND; } +\|\| { doLines();return OR; } +\& { doLines(); return BITAND; } +\| { doLines(); return BITOR; } +\~ { doLines(); return BITNOT; } +\^ { doLines(); return BITXOR; } +\! { doLines();return NOT; } +\% { doLines(); return MODULO; } + + +[_a-zA-Z]([_a-zA-Z]|[0-9])* { + doLines(); + yylval = new ASTString(yytext, yylloc); + return IDENTIFIER; + } + +([0-9]*\.?[0-9]+) { doLines();yylval = new ASTFloat(yytext, ASTFloat::TYPE_DECIMAL, yylloc); return NUMBER; } + +(0x[0-9a-fA-F]+) { doLines();yylval = new ASTFloat(yytext, ASTFloat::TYPE_HEX, yylloc); return NUMBER; } + +([0-1]+b) { doLines();yylval = new ASTFloat(yytext, ASTFloat::TYPE_BINARY, yylloc); return NUMBER; } + + +\"[^\"]+\" { doLines();yylval = new ASTString(yytext, yylloc); return QUOTEDSTRING; } + +\'[^\']?\' { doLines();yylval = new ASTString(yytext, yylloc); return SINGLECHAR; } + +{WS} { ; } + + +. { + char temp[512]; + sprintf(temp, "Scanner, line %d: lexical error '%s'.\n", yylineno, yytext); + box_out(temp); + box_eol(); + } +%% +void resetLexer(){ +YY_FLUSH_BUFFER; +yylineno=1; +} +void doLines() +{ +YYLTYPE rval = {yylineno, 0, yylineno, 0}; +yylloc = rval; +} + diff --git a/src/parser/ffscript.ypp b/src/parser/ffscript.ypp new file mode 100644 index 0000000000..765f57a060 --- /dev/null +++ b/src/parser/ffscript.ypp @@ -0,0 +1,616 @@ +/* + Parser for the scripting language compiler. Inteded for use with Flex and Bison; + use this file to generate y.tab.cpp + +command: bison -b y -v -d ffscript.ypp + +*/ + +/* declarations */ +%{ +#include +#include +#include +#include "AST.h" +#include "UtilVisitors.h" +#include "../zsyssimple.h" +#define YYINCLUDED_STDLIB_H +extern int yydebug; +extern int yylineno; +extern char* yytext; +extern int yylex(void); +extern FILE *yyin; +extern AST *resAST; +extern void resetLexer(); +void yyerror(const char* s); +string curfilename; +extern YYLTYPE noloc; + +#define SHORTCUT(x,d1,d3,dd,l1,l2) ASTExpr *lval = (ASTExpr *)d1; \ + Clone c; \ + lval->execute(c,NULL); \ + x *rhs = new x(l2); \ + rhs->setFirstOperand((ASTExpr *)c.getResult()); \ + rhs->setSecondOperand((ASTExpr *)d3); \ + dd = new ASTStmtAssign(lval, rhs, l1); +%} +%expect 1 +%error-verbose +%start Init + +%token SCRIPT +%token FLOAT +%token FOR +%token BOOL +%token VOID +%token IF +%token ELSE +%token RETURN +%token IMPORT +%token TRUE +%token FALSE +%token WHILE +%token FFC +%token ITEM +%token ITEMCLASS +%token GLOBAL +%token BREAK +%token CONTINUE +%token CONST +%token DO +%token NPC +%token LWEAPON +%token EWEAPON + +%token ASSIGN +%token SEMICOLON +%token COMMA +%token LBRACKET +%token RBRACKET +%token LPAREN +%token RPAREN +%token DOT +%token LBRACE +%token RBRACE +%token ARROW + +%token NUMBER +%token PLUSASSIGN +%token MINUSASSIGN +%token TIMESASSIGN +%token DIVIDEASSIGN +%token ANDASSIGN +%token ORASSIGN +%token BITANDASSIGN +%token BITORASSIGN +%token BITXORASSIGN +%token MODULOASSIGN +%token LSHIFTASSIGN +%token RSHIFTASSIGN +%token IDENTIFIER +%token QUOTEDSTRING +%token SINGLECHAR + +%left LSHIFT RSHIFT +%left BITAND BITOR BITXOR +%left AND OR +%left NOT BITNOT +%left INCREMENT DECREMENT +%left LE LT GE GT EQ NE +%left PLUS MINUS +%left TIMES DIVIDE +%left MODULO + + +%% + +Init : Prog {resAST = new ASTProgram((ASTDeclList *)$1, @1);} + ; + +Prog : Prog GlobalStmt {ASTDeclList *list = (ASTDeclList *)$1; + list->addDeclaration((ASTDecl *)$2); + $$ = list;} + | {$$ = new ASTDeclList(noloc);} + ; + +GlobalStmt : Script {$$ = $1;} + | Import {$$ = $1;} + | FuncDecl {$$ = $1;} + | ConstDecl {$$ = $1;} + | VarDecl SEMICOLON {$$ = $1;} + | VarDecl ASSIGN Expr SEMICOLON {ASTVarDecl *vd = (ASTVarDecl *)$1; + Clone c; + vd->getType()->execute(c,NULL); + $$ = new ASTVarDeclInitializer((ASTType *)c.getResult(), vd->getName(), (ASTExpr *)$3,@1); + delete vd;} + | ArrayDecl SEMICOLON {$$ = $1;} + ; + +ConstDecl : CONST FLOAT IDENTIFIER ASSIGN NUMBER SEMICOLON {ASTString *name = (ASTString *)$3; + ASTFloat *val = (ASTFloat *)$5; + $$ = new ASTConstDecl(name->getValue(), val,@1); + delete name;} + | CONST FLOAT IDENTIFIER ASSIGN MINUS NUMBER SEMICOLON {ASTString *name = (ASTString *)$3; + ASTFloat *val = (ASTFloat *)$6; + val->set_negative(true); + $$ = new ASTConstDecl(name->getValue(), val,@1); + delete name;} + +ArrayDecl : Type IDENTIFIER LBRACKET NUMBER RBRACKET { ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTExpr *size = (ASTExpr *)$4; + $$ = new ASTArrayDecl(type, name->getValue(), size, false, NULL, @1); + delete name;} + + | Type IDENTIFIER LBRACKET NUMBER RBRACKET ASSIGN LBRACE ArrayList RBRACE { ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTFloat *size = (ASTFloat *)$4; + ASTArrayList *list = (ASTArrayList *)$8; + $$ = new ASTArrayDecl(type, name->getValue(), size, false, list, @1); + delete name;} + | Type IDENTIFIER LBRACKET RBRACKET ASSIGN LBRACE ArrayList RBRACE { ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTArrayList *list = (ASTArrayList *)$7; + char val[15]; + sprintf(val, "%d", list->getList().size()); + ASTFloat *size = new ASTFloat(val, 0, @1); + $$ = new ASTArrayDecl(type, name->getValue(), size, false, list, @1); + delete name;} + + | Type IDENTIFIER LBRACKET NUMBER RBRACKET ASSIGN QUOTEDSTRING { ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTFloat *size = (ASTFloat *)$4; + ASTArrayList *list = new ASTArrayList(@1); + list->makeString(); + ASTString *string = (ASTString *)$7; + + for(unsigned int i=1; i < string->getValue().length()-1; i++) + list->addParam(new ASTNumConstant(new ASTFloat(long((string->getValue())[i]), 0, @1), @1)); + + list->addParam(new ASTNumConstant(new ASTFloat(0L, 0, @1), @1)); + $$ = new ASTArrayDecl(type, name->getValue(), size, false, list, @1); + delete name;} + + | Type IDENTIFIER LBRACKET RBRACKET ASSIGN QUOTEDSTRING { ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTArrayList *list = new ASTArrayList(@1); + list->makeString(); + ASTString *string = (ASTString *)$6; + ASTFloat *size = new ASTFloat(string->getValue().length()-1, 0, @1); + + for(unsigned int i=1; i < string->getValue().length()-1; i++) + list->addParam(new ASTNumConstant(new ASTFloat(long((string->getValue())[i]), 0, @1), @1)); + + list->addParam(new ASTNumConstant(new ASTFloat(0L, 0, @1), @1)); + $$ = new ASTArrayDecl(type, name->getValue(), size, false, list, @1); + delete name;} + ; + + + +ArrayList : ArrayList COMMA Expr { ASTArrayList *al = (ASTArrayList *)$1; + al->addParam((ASTExpr*)$3); + $$=al;} + | Expr { ASTArrayList *al = new ASTArrayList(@1); + al->addParam((ASTExpr *)$1); + $$=al;} + ; + +Script : ScriptType SCRIPT IDENTIFIER ScriptBlock {ASTType *type = (ASTType *)$1; + int scripttype; //Itemdata pointer instead of item pointer + ExtractType temp; + type->execute(temp, &scripttype); + if(scripttype == ScriptParser::TYPE_ITEM) + { + ASTType *t = type; //so we can keep the locationdata before deleting + type = new ASTTypeItemclass(type->getLocation()); + delete t; + } + ASTString *name = (ASTString *)$3; + ASTDeclList *sblock = (ASTDeclList *)$4; + $$ = new ASTScript(type, name->getValue(), sblock,@1); + delete name;} + ; + +ScriptType : Type {$$ = $1;} + | GLOBAL {$$ = new ASTTypeGlobal(@1);} + ; + +Import : IMPORT QUOTEDSTRING {ASTString *str = (ASTString *)$2; + $$ = new ASTImportDecl(str->getValue(),@1); + delete str;} + ; + +ScriptBlock : LBRACE ScriptStmtList RBRACE {$$ = $2;} + | LBRACE RBRACE {$$ = new ASTDeclList(@1);} + ; + +ScriptStmtList : ScriptStmt ScriptStmtList {ASTDeclList *dl = (ASTDeclList *)$2; + dl->addDeclaration((ASTDecl *)$1); + $$ = dl;} + | ScriptStmt { ASTDeclList *dl = new ASTDeclList(@1); + dl->addDeclaration((ASTDecl *)$1); + $$ = dl;} + ; + +ScriptStmt : VarDecl SEMICOLON {$$ = $1;} + | ArrayDecl SEMICOLON {$$ = $1;} + | VarDecl ASSIGN Expr SEMICOLON {ASTVarDecl *vd = (ASTVarDecl *)$1; + Clone c; + vd->getType()->execute(c,NULL); + $$ = new ASTVarDeclInitializer((ASTType *)c.getResult(), vd->getName(), (ASTExpr *)$3,@1); + delete vd;} + | FuncDecl {$$ = $1;} + ; + +VarDecl : Type IDENTIFIER {ASTType *type = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + $$ = new ASTVarDecl(type, name->getValue(),@1); + delete name;} + ; + +Type : FLOAT {$$ = new ASTTypeFloat(@1);} + | BOOL {$$ = new ASTTypeBool(@1);} + | VOID {$$ = new ASTTypeVoid(@1);} + | FFC {$$ = new ASTTypeFFC(@1);} + | ITEM {$$ = new ASTTypeItem(@1);} + | ITEMCLASS {$$ = new ASTTypeItemclass(@1);} + | NPC {$$ = new ASTTypeNPC(@1);} + | LWEAPON {$$ = new ASTTypeLWpn(@1);} + | EWEAPON {$$ = new ASTTypeEWpn(@1);} + ; + +FuncDecl : Type IDENTIFIER LPAREN ParamList RPAREN Block {ASTFuncDecl *fd = (ASTFuncDecl *)$4; + ASTType *rettype = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTBlock *block = (ASTBlock *)$6; + fd->setName(name->getValue()); + delete name; + fd->setReturnType(rettype); + fd->setBlock(block); + $$=fd;} + | Type IDENTIFIER LPAREN RPAREN Block {ASTFuncDecl *fd = new ASTFuncDecl(@1); + ASTType *rettype = (ASTType *)$1; + ASTString *name = (ASTString *)$2; + ASTBlock *block = (ASTBlock *)$5; + fd->setName(name->getValue()); + delete name; + fd->setReturnType(rettype); + fd->setBlock(block); + $$=fd;} + ; + +ParamList : VarDecl COMMA ParamList {ASTFuncDecl *fd = (ASTFuncDecl *)$3; + fd->addParam((ASTVarDecl *)$1); + $$=fd;} + | VarDecl {ASTFuncDecl *fd = new ASTFuncDecl(@1); + fd->addParam((ASTVarDecl *)$1); + $$=fd;} + ; + +Block : LBRACE StmtList RBRACE {$$=$2;} + | LBRACE RBRACE {$$ = new ASTBlock(@1);} + ; + +StmtList : StmtList Stmt {ASTBlock *block = (ASTBlock *)$1; + ASTStmt *stmt = (ASTStmt *)$2; + block->addStatement(stmt); + $$ = block;} + | Stmt {ASTBlock *block = new ASTBlock(@1); + ASTStmt *stmt = (ASTStmt *)$1; + block->addStatement(stmt); + $$ = block;} + ; + +Stmt : VarDecl SEMICOLON {$$ = $1;} + | ArrayDecl SEMICOLON {$$ = $1;} + | AssignStmt SEMICOLON {$$ = $1;} + | ShortcutAssignStmt SEMICOLON {$$=$1;} + | ForStmt {$$ = $1;} + | IfStmt {$$ = $1;} + | Block {$$ = $1;} + | ReturnStmt SEMICOLON {$$ = $1;} + | WhileStmt {$$ = $1;} + | DoStmt {$$ = $1;} + | SEMICOLON {$$ = new ASTStmtEmpty(@1);} + | Expr SEMICOLON {$$=$1;} + | BREAK SEMICOLON {$$ = new ASTStmtBreak(@1);} + | CONTINUE SEMICOLON {$$ = new ASTStmtContinue(@1);} + ; + +StmtNoSemi : VarDecl {$$ = $1;} + | ArrayDecl {$$ = $1;} + | AssignStmt {$$ = $1;} + | ShortcutAssignStmt {$$=$1;} + | ForStmt {$$ = $1;} + | IfStmt {$$ = $1;} + | Block {$$ = $1;} + | ReturnStmt {$$ = $1;} + | WhileStmt {$$ = $1;} + | DoStmt {$$ = $1;} + | {$$ = new ASTStmtEmpty(noloc);} + | Expr {$$=$1;} + | BREAK {$$ = new ASTStmtBreak(@1);} + | CONTINUE {$$ = new ASTStmtContinue(@1);} + ; + +ShortcutAssignStmt : DotExpr PLUSASSIGN Expr {SHORTCUT(ASTExprPlus,$1,$3,$$,@1,@2) } + | DotExpr MINUSASSIGN Expr {SHORTCUT(ASTExprMinus,$1,$3,$$,@1,@2) } + | DotExpr TIMESASSIGN Expr {SHORTCUT(ASTExprTimes,$1,$3,$$,@1,@2) } + | DotExpr DIVIDEASSIGN Expr {SHORTCUT(ASTExprDivide,$1,$3,$$,@1,@2) } + | DotExpr ANDASSIGN Expr {SHORTCUT(ASTExprAnd,$1,$3,$$,@1,@2) } + | DotExpr ORASSIGN Expr {SHORTCUT(ASTExprOr,$1,$3,$$,@1,@2) } + | DotExpr BITANDASSIGN Expr {SHORTCUT(ASTExprBitAnd,$1,$3,$$,@1,@2) } + | DotExpr BITORASSIGN Expr {SHORTCUT(ASTExprBitOr,$1,$3,$$,@1,@2) } + | DotExpr BITXORASSIGN Expr {SHORTCUT(ASTExprBitXor,$1,$3,$$,@1,@2) } + | DotExpr LSHIFTASSIGN Expr {SHORTCUT(ASTExprLShift,$1,$3,$$,@1,@2) } + | DotExpr RSHIFTASSIGN Expr {SHORTCUT(ASTExprRShift,$1,$3,$$,@1,@2) } + | DotExpr MODULOASSIGN Expr {SHORTCUT(ASTExprModulo,$1,$3,$$,@1,@2) } + ; + + +AssignStmt : LVal ASSIGN Expr {$$ = new ASTStmtAssign((ASTStmt *)$1, (ASTExpr *)$3,@1);} + ; + +LVal : VarDecl {$$ = $1;} + | DotExpr {$$ = $1;} + ; + +DotExpr : IDENTIFIER DOT IDENTIFIER {ASTString *lval = (ASTString *)$1; + ASTString *rval = (ASTString *)$3; + $$ = new ASTExprDot(lval->getValue(), rval->getValue(),@1); + delete lval; delete rval;} + | IDENTIFIER LBRACKET Expr RBRACKET { ASTString *name = (ASTString *)$1; + ASTExpr *num = (ASTExpr *)$3; + ASTExprArray *ar = new ASTExprArray("", name->getValue(), @1); + ar->setIndex(num); + $$ = ar; + delete name;} + | IDENTIFIER DOT IDENTIFIER LBRACKET Expr RBRACKET { ASTString *name = (ASTString *)$1; + ASTString *name2 = (ASTString *)$3; + ASTExpr *num = (ASTExpr *)$5; + ASTExprArray *ar = new ASTExprArray(name->getValue(), name2->getValue(), @1); + ar->setIndex(num); + $$ = ar; + delete name; + delete name2;} + | IDENTIFIER {ASTString *rval = (ASTString *)$1; + $$ = new ASTExprDot("", rval->getValue(),@1); + delete rval;} + | DotExpr ARROW IDENTIFIER {ASTExpr *id = (ASTExpr *)$1; + ASTString *rval = (ASTString *)$3; + $$ = new ASTExprArrow(id, rval->getValue(), @1); + delete rval;} + | DotExpr ARROW IDENTIFIER LBRACKET Expr RBRACKET {ASTExpr *id = (ASTExpr *)$1; + ASTString *rval = (ASTString *)$3; + ASTExpr *num = (ASTExpr *)$5; + ASTExprArrow *res = new ASTExprArrow(id, rval->getValue(), @1); + res->setIndex(num); + $$ = res;} + ; + +Expr : Expr OR Expr15 {ASTLogExpr *e = new ASTExprOr(@2); + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr15 {$$=$1;} + ; + +Expr15 : Expr15 AND Expr16 {ASTLogExpr *e = new ASTExprAnd(@2); + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr16 {$$=$1;} + ; + +Expr16 : Expr16 BITOR Expr17 {ASTBitExpr *e = new ASTExprBitOr(@2); + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr17 {$$=$1;} + ; + +Expr17 : Expr17 BITXOR Expr18 {ASTBitExpr *e = new ASTExprBitXor(@2); + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr18 {$$ = $1;} + ; + +Expr18 : Expr18 BITAND Expr2 {ASTBitExpr *e = new ASTExprBitAnd(@2); + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr2 {$$=$1;} + ; + +Expr2 : Expr2 RelOp Expr25 {ASTRelExpr *e = (ASTRelExpr *)$2; + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr25 {$$ = $1;} + ; + +Expr25 : Expr25 ShiftOp Expr3 {ASTShiftExpr *e = (ASTShiftExpr *)$2; + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr3 {$$=$1;} + ; + +ShiftOp : LSHIFT {$$ = new ASTExprLShift(@1);} + | RSHIFT {$$ = new ASTExprRShift(@1);} + ; + +RelOp : GT {$$ = new ASTExprGT(@1);} + | GE {$$ = new ASTExprGE(@1);} + | LT {$$ = new ASTExprLT(@1);} + | LE {$$ = new ASTExprLE(@1);} + | EQ {$$ = new ASTExprEQ(@1);} + | NE {$$ = new ASTExprNE(@1);} + ; + +Expr3 : Expr3 AddOp Expr4 {ASTAddExpr *e = (ASTAddExpr *)$2; + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr4 {$$ = $1;} + ; + +AddOp : PLUS {$$ = new ASTExprPlus(@1);} + | MINUS {$$ = new ASTExprMinus(@1);} + ; + +Expr4 : Expr4 MultOp Expr5 {ASTMultExpr *e = (ASTMultExpr *)$2; + ASTExpr *left = (ASTExpr *)$1; + ASTExpr *right = (ASTExpr *)$3; + e->setFirstOperand(left); + e->setSecondOperand(right); + $$=e;} + | Expr5 {$$=$1;} + ; + +MultOp : TIMES {$$ = new ASTExprTimes(@1);} + | DIVIDE {$$ = new ASTExprDivide(@1);} + | MODULO {$$ = new ASTExprModulo(@1);} + ; + +Expr5 : NOT Expr5 {ASTUnaryExpr *e = new ASTExprNot(@1); + ASTExpr *op = (ASTExpr *)$2; + e->setOperand(op); + $$=e;} + | MINUS Expr5 {ASTUnaryExpr *e = new ASTExprNegate(@1); + ASTExpr *op = (ASTExpr *)$2; + e->setOperand(op); + $$=e;} + | BITNOT Expr5 {ASTUnaryExpr *e = new ASTExprBitNot(@1); + ASTExpr *op = (ASTExpr *)$2; + e->setOperand(op); + $$=e;} + | Factor {$$=$1;} + ; + +Factor : LPAREN Expr RPAREN {$$=$2;} + | DotExpr {$$ = $1;} + | DotExpr INCREMENT {ASTUnaryExpr *e = new ASTExprIncrement(@2); + ASTExpr *op = (ASTExpr *)$1; + e->setOperand(op); + $$=e;} + | INCREMENT DotExpr {ASTUnaryExpr *e = new ASTExprPreIncrement(@1); + ASTExpr *op = (ASTExpr *)$2; + e->setOperand(op); + $$=e;} + | DotExpr DECREMENT {ASTUnaryExpr *e = new ASTExprDecrement(@2); + ASTExpr *op = (ASTExpr *)$1; + e->setOperand(op); + $$=e;} + | DECREMENT DotExpr {ASTUnaryExpr *e = new ASTExprPreDecrement(@1); + ASTExpr *op = (ASTExpr *)$2; + e->setOperand(op); + $$=e;} + | NUMBER {ASTFloat *val = (ASTFloat *)$1; + $$ = new ASTNumConstant(val,@1);} + | SINGLECHAR {ASTString *as = (ASTString *)$1; + char val[15]; + sprintf(val, "%d", as->getValue().at(1)); + $$ = new ASTNumConstant(new ASTFloat(val,0,@1),@1);} + | BoolConstant {$$ = $1;} + | FuncCall {$$=$1;} + ; + +BoolConstant : TRUE {$$ = new ASTBoolConstant(true,@1);} + | FALSE {$$ = new ASTBoolConstant(false,@1);} + ; + +FuncCall : DotExpr LPAREN ExprList RPAREN {ASTFuncCall *fc = (ASTFuncCall *)$3; + ASTExpr *name = (ASTExpr *)$1; + fc->setName(name); + $$=fc;} + | DotExpr LPAREN RPAREN {ASTFuncCall *fc = new ASTFuncCall(@1); + ASTExpr *name = (ASTExpr *)$1; + fc->setName(name); + $$=fc;} + ; + +ExprList : Expr COMMA ExprList {ASTFuncCall *fc = (ASTFuncCall *)$3; + ASTExpr *e = (ASTExpr *)$1; + fc->addParam(e); + $$ = fc;} + | Expr {ASTFuncCall *fc = new ASTFuncCall(@1); + ASTExpr *e = (ASTExpr *)$1; + fc->addParam(e); + $$ = fc;} + ; + +ForStmt : FOR LPAREN StmtNoSemi SEMICOLON Expr SEMICOLON StmtNoSemi RPAREN Stmt {ASTStmt *prec = (ASTStmt *)$3; + ASTExpr *term = (ASTExpr *)$5; + ASTStmt *incr = (ASTExpr *)$7; + ASTStmt *stmt = (ASTStmt *)$9; + $$ = new ASTStmtFor(prec,term,incr,stmt,@1);} + ; + +WhileStmt : WHILE LPAREN Expr RPAREN Stmt {ASTExpr *cond = (ASTExpr *)$3; + ASTStmt *stmt = (ASTStmt *)$5; + $$ = new ASTStmtWhile(cond,stmt,@1);} + +DoStmt : DO Stmt WHILE LPAREN Expr RPAREN {ASTExpr *cond = (ASTExpr *)$5; + ASTStmt *stmt = (ASTStmt *)$2; + $$ = new ASTStmtDo(cond,stmt,@1);} + +IfStmt : IF LPAREN Expr RPAREN Stmt {ASTExpr *cond = (ASTExpr *)$3; + ASTStmt *stmt = (ASTStmt *)$5; + $$ = new ASTStmtIf(cond,stmt,@1);} + | IF LPAREN Expr RPAREN Stmt ELSE Stmt {ASTExpr *cond = (ASTExpr *)$3; + ASTStmt *ifstmt = (ASTStmt *)$5; + ASTStmt *elsestmt = (ASTStmt *)$7; + $$ = new ASTStmtIfElse(cond,ifstmt,elsestmt,@1);} + ; + +ReturnStmt : RETURN Expr {$$ = new ASTStmtReturnVal((ASTExpr *)$2,@1);} + | RETURN {$$ = new ASTStmtReturn(@1);} + ; + +%% + +/* programs */ + +void yyerror(const char *s) { + char temp[512]; + sprintf(temp, "line %d: %s, on token %s", yylineno, s, yytext); + box_out(temp); + box_eol(); +} + +int go(const char *f) +{ +yyin = NULL; +resetLexer(); +yyin = fopen(f, "r"); +if(!yyin) +{ + box_out("Can't open input file"); + box_eol(); + return -1; +} + curfilename = string(f); + int result = yyparse(); + fclose(yyin); + return result; +} + diff --git a/src/parser/lex.yy.cpp b/src/parser/lex.yy.cpp new file mode 100644 index 0000000000..9eda0df68a --- /dev/null +++ b/src/parser/lex.yy.cpp @@ -0,0 +1,2206 @@ +#line 2 "lex.yy.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +//#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ +#pragma warn -rch +#pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state +{ +FILE *yy_input_file; + +char *yy_ch_buf; /* input buffer */ +char *yy_buf_pos; /* current position in input buffer */ + +/* Size of input buffer in bytes, not including room for EOB + * characters. + */ +yy_size_t yy_buf_size; + +/* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ +int yy_n_chars; + +/* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ +int yy_is_our_buffer; + +/* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ +int yy_is_interactive; + +/* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ +int yy_at_bol; + +/* Whether to try to fill the input buffer when we reach the + * end of it. + */ +int yy_fill_buffer; + +int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 +/* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 +}; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO((FILE *input_file)); + +void yy_switch_to_buffer YY_PROTO((YY_BUFFER_STATE new_buffer)); +void yy_load_buffer_state YY_PROTO((void)); +YY_BUFFER_STATE yy_create_buffer YY_PROTO((FILE *file, int size)); +void yy_delete_buffer YY_PROTO((YY_BUFFER_STATE b)); +void yy_init_buffer YY_PROTO((YY_BUFFER_STATE b, FILE *file)); +void yy_flush_buffer YY_PROTO((YY_BUFFER_STATE b)); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO((char *base, yy_size_t size)); +YY_BUFFER_STATE yy_scan_string YY_PROTO((yyconst char *yy_str)); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO((yyconst char *bytes, int len)); + +static void *yy_flex_alloc YY_PROTO((yy_size_t)); +static void *yy_flex_realloc YY_PROTO((void *, yy_size_t)); +static void yy_flex_free YY_PROTO((void *)); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define YY_USES_REJECT + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern int yylineno; +int yylineno = 1; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO((void)); +static yy_state_type yy_try_NUL_trans YY_PROTO((yy_state_type current_state)); +static int yy_get_next_buffer YY_PROTO((void)); +static void yy_fatal_error YY_PROTO((yyconst char msg[])); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 79 +#define YY_END_OF_BUFFER 80 +static yyconst short int yy_acclist[276] = +{ +0, +80, 78, 79, 77, 78, 79, 77, 79, 69, 78, +79, 78, 79, 70, 78, 79, 65, 78, 79, 78, +79, 51, 78, 79, 52, 78, 79, 58, 78, 79, +56, 78, 79, 48, 78, 79, 57, 78, 79, 55, +78, 79, 60, 78, 79, 72, 78, 79, 72, 78, +79, 72, 78, 79, 47, 78, 79, 31, 78, 79, +36, 78, 79, 33, 78, 79, 71, 78, 79, 49, +78, 79, 50, 78, 79, 68, 78, 79, 71, 78, +79, 71, 78, 79, 71, 78, 79, 71, 78, 79, +71, 78, 79, 71, 78, 79, 71, 78, 79, 71, + +78, 79, 71, 78, 79, 71, 78, 79, 71, 78, +79, 71, 78, 79, 71, 78, 79, 71, 78, 79, +61, 78, 79, 66, 78, 79, 62, 78, 79, 67, +78, 79, 35, 46, 63, 43, 76, 39, 53, 37, +54, 38, 25, 72, 59, 40, 72, 72, 74, 28, +30, 34, 32, 29, 71, 45, 71, 71, 71, 21, +71, 71, 71, 71, 71, 71, 71, 71, 7, 71, +71, 71, 71, 71, 71, 71, 71, 71, 71, 71, +44, 64, 75, 41, 59, 73, 26, 27, 71, 71, +71, 71, 71, 71, 14, 71, 71, 4, 71, 71, + +71, 3, 71, 71, 71, 22, 71, 71, 71, 71, +71, 71, 42, 5, 71, 71, 71, 71, 8, 71, +71, 71, 71, 71, 71, 16, 71, 71, 71, 71, +11, 71, 6, 71, 71, 18, 71, 20, 71, 71, +71, 12, 71, 2, 71, 71, 71, 71, 71, 71, +71, 13, 71, 71, 71, 17, 71, 10, 71, 71, +71, 9, 71, 1, 71, 71, 24, 71, 71, 23, +71, 19, 71, 15, 71 +} ; + +static yyconst short int yy_accept[174] = +{ +0, +1, 1, 1, 2, 4, 7, 9, 12, 14, 17, +20, 22, 25, 28, 31, 34, 37, 40, 43, 46, +49, 52, 55, 58, 61, 64, 67, 70, 73, 76, +79, 82, 85, 88, 91, 94, 97, 100, 103, 106, +109, 112, 115, 118, 121, 124, 127, 130, 133, 134, +134, 135, 136, 137, 137, 138, 139, 140, 141, 142, +143, 144, 145, 146, 147, 147, 148, 149, 150, 150, +151, 152, 153, 154, 155, 156, 157, 158, 159, 160, +162, 163, 164, 165, 166, 167, 168, 169, 171, 172, +173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + +183, 184, 185, 186, 187, 188, 189, 190, 191, 192, +193, 194, 195, 197, 198, 200, 201, 202, 204, 205, +206, 208, 209, 210, 211, 212, 213, 214, 216, 217, +218, 219, 221, 222, 223, 224, 225, 226, 228, 229, +230, 231, 233, 235, 236, 238, 240, 241, 242, 244, +246, 247, 248, 249, 250, 251, 252, 254, 255, 256, +258, 260, 261, 262, 264, 266, 267, 269, 270, 272, +274, 276, 276 +} ; + +static yyconst int yy_ec[256] = +{ +0, +1, 1, 1, 1, 1, 1, 1, 1, 2, 3, +1, 1, 2, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 2, 4, 5, 1, 1, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, +19, 19, 19, 19, 19, 19, 19, 1, 20, 21, +22, 23, 1, 1, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 1, 27, 28, 25, 1, 29, 30, 31, 32, + +33, 34, 35, 36, 37, 25, 38, 39, 40, 41, +42, 43, 25, 44, 45, 46, 47, 48, 49, 50, +25, 25, 51, 52, 53, 54, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1 +} ; + +static yyconst int yy_meta[55] = +{ +0, +1, 1, 2, 1, 3, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 4, 4, 4, 1, +1, 1, 1, 4, 5, 1, 1, 1, 4, 4, +4, 4, 4, 4, 5, 5, 5, 5, 5, 5, +5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +1, 1, 1, 1 +} ; + +static yyconst short int yy_base[178] = +{ +0, +0, 0, 217, 218, 218, 218, 194, 0, 193, 48, +206, 218, 218, 191, 44, 218, 45, 43, 41, 54, +59, 64, 218, 43, 190, 63, 0, 218, 218, 189, +46, 168, 167, 48, 64, 169, 61, 158, 163, 172, +173, 159, 160, 165, 218, 53, 218, 218, 218, 195, +218, 177, 218, 190, 218, 218, 218, 218, 218, 218, +218, 91, 0, 218, 94, 99, 104, 218, 0, 175, +218, 218, 218, 174, 0, 218, 153, 161, 152, 0, +147, 158, 151, 158, 146, 143, 144, 0, 142, 138, +150, 149, 150, 134, 135, 131, 140, 139, 218, 153, + +218, 218, 0, 0, 218, 218, 135, 144, 46, 139, +142, 125, 0, 140, 0, 138, 125, 0, 126, 136, +0, 117, 126, 129, 129, 121, 218, 0, 121, 112, +120, 0, 113, 122, 108, 124, 108, 119, 107, 105, +105, 0, 0, 114, 0, 0, 102, 90, 0, 0, +89, 81, 97, 83, 83, 74, 0, 68, 59, 0, +0, 53, 55, 0, 0, 61, 0, 51, 0, 0, +0, 218, 129, 134, 136, 141, 54 +} ; + +static yyconst short int yy_def[178] = +{ +0, +172, 1, 172, 172, 172, 172, 172, 173, 172, 172, +174, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 175, 172, 172, 172, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 172, 172, 172, 172, 172, 173, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 176, 172, 172, 172, 172, 172, 177, 172, +172, 172, 172, 172, 175, 172, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 172, 172, + +172, 172, 176, 177, 172, 172, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 172, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 175, 175, 175, 175, 175, 175, 175, 175, 175, +175, 0, 172, 172, 172, 172, 172 +} ; + +static yyconst short int yy_nxt[273] = +{ +0, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, +14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 27, 28, 29, 30, 27, 31, +32, 33, 34, 35, 36, 27, 37, 27, 38, 27, +39, 27, 27, 40, 41, 42, 27, 43, 44, 27, +45, 46, 47, 48, 52, 57, 63, 104, 59, 62, +62, 62, 64, 70, 71, 58, 60, 61, 65, 53, +66, 66, 67, 65, 99, 66, 66, 67, 65, 171, +67, 67, 67, 68, 73, 74, 81, 77, 68, 78, +130, 131, 83, 170, 88, 169, 82, 84, 168, 167, + +89, 90, 85, 69, 100, 86, 91, 62, 62, 62, +62, 62, 62, 65, 166, 66, 66, 67, 65, 165, +67, 67, 67, 164, 163, 162, 161, 160, 68, 50, +50, 159, 50, 50, 54, 54, 54, 54, 54, 75, +75, 103, 158, 103, 103, 103, 157, 156, 155, 154, +153, 152, 151, 150, 149, 148, 147, 146, 145, 144, +143, 142, 141, 140, 139, 138, 137, 136, 135, 134, +133, 132, 129, 128, 127, 126, 125, 124, 123, 122, +121, 120, 119, 118, 117, 116, 115, 114, 113, 112, +111, 110, 109, 108, 107, 106, 105, 55, 102, 101, + +98, 97, 96, 95, 94, 93, 92, 87, 80, 79, +76, 72, 56, 55, 51, 49, 172, 3, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172 +} ; + +static yyconst short int yy_chk[273] = +{ +0, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 10, 15, 19, 177, 17, 18, +18, 18, 19, 24, 24, 15, 17, 17, 20, 10, +20, 20, 20, 21, 46, 21, 21, 21, 22, 168, +22, 22, 22, 20, 26, 26, 34, 31, 21, 31, +109, 109, 35, 166, 37, 163, 34, 35, 162, 159, + +37, 37, 35, 20, 46, 35, 37, 62, 62, 62, +65, 65, 65, 66, 158, 66, 66, 66, 67, 156, +67, 67, 67, 155, 154, 153, 152, 151, 66, 173, +173, 148, 173, 173, 174, 174, 174, 174, 174, 175, +175, 176, 147, 176, 176, 176, 144, 141, 140, 139, +138, 137, 136, 135, 134, 133, 131, 130, 129, 126, +125, 124, 123, 122, 120, 119, 117, 116, 114, 112, +111, 110, 108, 107, 100, 98, 97, 96, 95, 94, +93, 92, 91, 90, 89, 87, 86, 85, 84, 83, +82, 81, 79, 78, 77, 74, 70, 54, 52, 50, + +44, 43, 42, 41, 40, 39, 38, 36, 33, 32, +30, 25, 14, 11, 9, 7, 3, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172, 172, 172, 172, 172, 172, 172, 172, 172, +172, 172 +} ; + +static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr; +static char *yy_full_match; +static int yy_lp; +#define REJECT \ +{ \ +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \ +yy_cp = yy_full_match; /* restore poss. backed-over text */ \ +++yy_lp; \ +goto find_rule; \ +} +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "ffscript.lpp" +#define INITIAL 0 +/* + use this file to generate lex.yy.c +command: flex -B -olex.yy.cpp fscript.lpp +*/ +#define YY_NEVER_INTERACTIVE 1 +#line 12 "ffscript.lpp" +#include +#include "AST.h" +#include "../zsyssimple.h" +#include "y.tab.hpp" +YYLTYPE noloc = {0,0,0,0}; +void doLines(); +#line 537 "lex.yy.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO((void)); +#else +extern int yywrap YY_PROTO((void)); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO((int c, char *buf_ptr)); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO((char *, yyconst char *, int)); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO((yyconst char *)); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO((void)); +#else +static int input YY_PROTO((void)); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO((int new_state)); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO((void)); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO((void)); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 20 "ffscript.lpp" + + +#line 691 "lex.yy.cpp" + + if(yy_init) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if(! yy_start) + yy_start = 1; /* first start state */ + + if(! yyin) + yyin = stdin; + + if(! yyout) + yyout = stdout; + + if(! yy_current_buffer) + yy_current_buffer = + yy_create_buffer(yyin, YY_BUF_SIZE); + + yy_load_buffer_state(); + } + + while(1) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; +yy_match: + + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + + while(yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int) yy_def[yy_current_state]; + + if(yy_current_state >= 173) + yy_c = yy_meta[(unsigned int) yy_c]; + } + + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + ++yy_cp; + } + while(yy_current_state != 172); + +yy_find_action: + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; +find_rule: /* we branch to this label when backing up */ + + if(0) + { + yy_flex_realloc(NULL,0); + yyunput(0,NULL); + goto find_rule; + } + + for(; ;) /* until we find what rule we matched */ + { + if(yy_lp && yy_lp < yy_accept[yy_current_state + 1]) + { + yy_act = yy_acclist[yy_lp]; + { + yy_full_match = yy_cp; + break; + } + } + + --yy_cp; + yy_current_state = *--yy_state_ptr; + yy_lp = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + if(yy_act != YY_END_OF_BUFFER) + { + int yyl; + + for(yyl = 0; yyl < yyleng; ++yyl) + if(yytext[yyl] == '\n') + ++yylineno; + } + +do_action: /* This label is used only to access EOF actions. */ + + + switch(yy_act) + { + /* beginning of action switch */ + case 1: + YY_RULE_SETUP +#line 22 "ffscript.lpp" + { doLines(); return SCRIPT; } + YY_BREAK + + case 2: + YY_RULE_SETUP +#line 23 "ffscript.lpp" + { doLines(); return FLOAT; } + YY_BREAK + + case 3: + YY_RULE_SETUP +#line 24 "ffscript.lpp" + { doLines(); return FLOAT; } + YY_BREAK + + case 4: + YY_RULE_SETUP +#line 25 "ffscript.lpp" + { doLines(); return FOR; } + YY_BREAK + + case 5: + YY_RULE_SETUP +#line 26 "ffscript.lpp" + { doLines(); return BOOL; } + YY_BREAK + + case 6: + YY_RULE_SETUP +#line 27 "ffscript.lpp" + { doLines(); return VOID; } + YY_BREAK + + case 7: + YY_RULE_SETUP +#line 28 "ffscript.lpp" + { doLines(); return IF; } + YY_BREAK + + case 8: + YY_RULE_SETUP +#line 29 "ffscript.lpp" + { doLines(); return ELSE; } + YY_BREAK + + case 9: + YY_RULE_SETUP +#line 30 "ffscript.lpp" + { doLines(); return RETURN; } + YY_BREAK + + case 10: + YY_RULE_SETUP +#line 31 "ffscript.lpp" + { doLines(); return IMPORT; } + YY_BREAK + + case 11: + YY_RULE_SETUP +#line 32 "ffscript.lpp" + { doLines(); return TRUE; } + YY_BREAK + + case 12: + YY_RULE_SETUP +#line 33 "ffscript.lpp" + { doLines(); return FALSE; } + YY_BREAK + + case 13: + YY_RULE_SETUP +#line 34 "ffscript.lpp" + {doLines(); return WHILE;} + YY_BREAK + + case 14: + YY_RULE_SETUP +#line 35 "ffscript.lpp" + {doLines(); return FFC;} + YY_BREAK + + case 15: + YY_RULE_SETUP +#line 36 "ffscript.lpp" + {doLines(); return ITEMCLASS;} + YY_BREAK + + case 16: + YY_RULE_SETUP +#line 37 "ffscript.lpp" + {doLines(); return ITEM;} + YY_BREAK + + case 17: + YY_RULE_SETUP +#line 38 "ffscript.lpp" + {doLines(); return GLOBAL;} + YY_BREAK + + case 18: + YY_RULE_SETUP +#line 39 "ffscript.lpp" + {doLines(); return BREAK;} + YY_BREAK + + case 19: + YY_RULE_SETUP +#line 40 "ffscript.lpp" + {doLines(); return CONTINUE;} + YY_BREAK + + case 20: + YY_RULE_SETUP +#line 41 "ffscript.lpp" + {doLines(); return CONST;} + YY_BREAK + + case 21: + YY_RULE_SETUP +#line 42 "ffscript.lpp" + {doLines(); return DO;} + YY_BREAK + + case 22: + YY_RULE_SETUP +#line 43 "ffscript.lpp" + {doLines(); return NPC;} + YY_BREAK + + case 23: + YY_RULE_SETUP +#line 44 "ffscript.lpp" + {doLines(); return LWEAPON;} + YY_BREAK + + case 24: + YY_RULE_SETUP +#line 45 "ffscript.lpp" + {doLines(); return EWEAPON;} + YY_BREAK + + case 25: + YY_RULE_SETUP +#line 47 "ffscript.lpp" + { doLines(); return ARROW;} + YY_BREAK + + case 26: + YY_RULE_SETUP +#line 48 "ffscript.lpp" + { doLines(); return LSHIFTASSIGN; } + YY_BREAK + + case 27: + YY_RULE_SETUP +#line 49 "ffscript.lpp" + { doLines(); return RSHIFTASSIGN; } + YY_BREAK + + case 28: + YY_RULE_SETUP +#line 50 "ffscript.lpp" + { doLines(); return LSHIFT; } + YY_BREAK + + case 29: + YY_RULE_SETUP +#line 51 "ffscript.lpp" + { doLines(); return RSHIFT; } + YY_BREAK + + case 30: + YY_RULE_SETUP +#line 52 "ffscript.lpp" + { doLines(); return LE; } + YY_BREAK + + case 31: + YY_RULE_SETUP +#line 53 "ffscript.lpp" + { doLines(); return LT; } + YY_BREAK + + case 32: + YY_RULE_SETUP +#line 54 "ffscript.lpp" + { doLines(); return GE; } + YY_BREAK + + case 33: + YY_RULE_SETUP +#line 55 "ffscript.lpp" + { doLines(); return GT; } + YY_BREAK + + case 34: + YY_RULE_SETUP +#line 56 "ffscript.lpp" + { doLines(); return EQ; } + YY_BREAK + + case 35: + YY_RULE_SETUP +#line 57 "ffscript.lpp" + { doLines(); return NE; } + YY_BREAK + + case 36: + YY_RULE_SETUP +#line 58 "ffscript.lpp" + { doLines(); return ASSIGN; } + YY_BREAK + + case 37: + YY_RULE_SETUP +#line 59 "ffscript.lpp" + { doLines(); return PLUSASSIGN; } + YY_BREAK + + case 38: + YY_RULE_SETUP +#line 60 "ffscript.lpp" + { doLines(); return MINUSASSIGN; } + YY_BREAK + + case 39: + YY_RULE_SETUP +#line 61 "ffscript.lpp" + { doLines(); return TIMESASSIGN; } + YY_BREAK + + case 40: + YY_RULE_SETUP +#line 62 "ffscript.lpp" + { doLines(); return DIVIDEASSIGN; } + YY_BREAK + + case 41: + YY_RULE_SETUP +#line 63 "ffscript.lpp" + { doLines(); return ANDASSIGN; } + YY_BREAK + + case 42: + YY_RULE_SETUP +#line 64 "ffscript.lpp" + { doLines(); return ORASSIGN; } + YY_BREAK + + case 43: + YY_RULE_SETUP +#line 65 "ffscript.lpp" + { doLines(); return BITANDASSIGN; } + YY_BREAK + + case 44: + YY_RULE_SETUP +#line 66 "ffscript.lpp" + { doLines(); return BITORASSIGN; } + YY_BREAK + + case 45: + YY_RULE_SETUP +#line 67 "ffscript.lpp" + { doLines(); return BITXORASSIGN; } + YY_BREAK + + case 46: + YY_RULE_SETUP +#line 68 "ffscript.lpp" + { doLines(); return MODULOASSIGN; } + YY_BREAK + + case 47: + YY_RULE_SETUP +#line 69 "ffscript.lpp" + { doLines(); return SEMICOLON; } + YY_BREAK + + case 48: + YY_RULE_SETUP +#line 70 "ffscript.lpp" + { doLines(); return COMMA; } + YY_BREAK + + case 49: + YY_RULE_SETUP +#line 71 "ffscript.lpp" + { doLines(); return LBRACKET; } + YY_BREAK + + case 50: + YY_RULE_SETUP +#line 72 "ffscript.lpp" + { doLines(); return RBRACKET; } + YY_BREAK + + case 51: + YY_RULE_SETUP +#line 73 "ffscript.lpp" + { doLines(); return LPAREN; } + YY_BREAK + + case 52: + YY_RULE_SETUP +#line 74 "ffscript.lpp" + { doLines(); return RPAREN; } + YY_BREAK + + case 53: + YY_RULE_SETUP +#line 75 "ffscript.lpp" + { doLines(); return INCREMENT; } + YY_BREAK + + case 54: + YY_RULE_SETUP +#line 76 "ffscript.lpp" + { doLines(); return DECREMENT; } + YY_BREAK + + case 55: + YY_RULE_SETUP +#line 77 "ffscript.lpp" + { doLines(); return DOT; } + YY_BREAK + + case 56: + YY_RULE_SETUP +#line 78 "ffscript.lpp" + { doLines(); return PLUS; } + YY_BREAK + + case 57: + YY_RULE_SETUP +#line 79 "ffscript.lpp" + { doLines(); return MINUS; } + YY_BREAK + + case 58: + YY_RULE_SETUP +#line 80 "ffscript.lpp" + { doLines(); return TIMES; } + YY_BREAK + + case 59: + YY_RULE_SETUP +#line 81 "ffscript.lpp" + { ; } + YY_BREAK + + case 60: + YY_RULE_SETUP +#line 82 "ffscript.lpp" + { doLines(); return DIVIDE; } + YY_BREAK + + case 61: + YY_RULE_SETUP +#line 83 "ffscript.lpp" + { doLines(); return LBRACE; } + YY_BREAK + + case 62: + YY_RULE_SETUP +#line 84 "ffscript.lpp" + { doLines(); return RBRACE; } + YY_BREAK + + case 63: + YY_RULE_SETUP +#line 85 "ffscript.lpp" + { doLines(); return AND; } + YY_BREAK + + case 64: + YY_RULE_SETUP +#line 86 "ffscript.lpp" + { doLines(); return OR; } + YY_BREAK + + case 65: + YY_RULE_SETUP +#line 87 "ffscript.lpp" + { doLines(); return BITAND; } + YY_BREAK + + case 66: + YY_RULE_SETUP +#line 88 "ffscript.lpp" + { doLines(); return BITOR; } + YY_BREAK + + case 67: + YY_RULE_SETUP +#line 89 "ffscript.lpp" + { doLines(); return BITNOT; } + YY_BREAK + + case 68: + YY_RULE_SETUP +#line 90 "ffscript.lpp" + { doLines(); return BITXOR; } + YY_BREAK + + case 69: + YY_RULE_SETUP +#line 91 "ffscript.lpp" + { doLines(); return NOT; } + YY_BREAK + + case 70: + YY_RULE_SETUP +#line 92 "ffscript.lpp" + { doLines(); return MODULO; } + YY_BREAK + + case 71: + YY_RULE_SETUP +#line 95 "ffscript.lpp" + { + doLines(); + yylval = new ASTString(yytext, yylloc); + return IDENTIFIER; + } + YY_BREAK + + case 72: + YY_RULE_SETUP +#line 101 "ffscript.lpp" + { doLines(); yylval = new ASTFloat(yytext, ASTFloat::TYPE_DECIMAL, yylloc); return NUMBER; } + YY_BREAK + + case 73: + YY_RULE_SETUP +#line 103 "ffscript.lpp" + { doLines(); yylval = new ASTFloat(yytext, ASTFloat::TYPE_HEX, yylloc); return NUMBER; } + YY_BREAK + + case 74: + YY_RULE_SETUP +#line 105 "ffscript.lpp" + { doLines(); yylval = new ASTFloat(yytext, ASTFloat::TYPE_BINARY, yylloc); return NUMBER; } + YY_BREAK + + case 75: + YY_RULE_SETUP +#line 108 "ffscript.lpp" + { doLines(); yylval = new ASTString(yytext, yylloc); return QUOTEDSTRING; } + YY_BREAK + + case 76: + YY_RULE_SETUP +#line 110 "ffscript.lpp" + { doLines(); yylval = new ASTString(yytext, yylloc); return SINGLECHAR; } + YY_BREAK + + case 77: + YY_RULE_SETUP +#line 112 "ffscript.lpp" + { ; } + YY_BREAK + + case 78: + YY_RULE_SETUP +#line 115 "ffscript.lpp" + { + char temp[512]; + sprintf(temp, "%s, line %d: lexical error '%s'.\n", curfilename.c_str(), yylineno, yytext); + box_out(temp); + box_eol(); + } + YY_BREAK + + case 79: + YY_RULE_SETUP +#line 121 "ffscript.lpp" + ECHO; + YY_BREAK +#line 1186 "lex.yy.cpp" + + case YY_STATE_EOF(INITIAL): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int)(yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if(yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if(yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars]) + { + /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans(yy_current_state); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if(yy_next_state) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch(yy_get_next_buffer()) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if(yywrap()) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if(! yy_did_buffer_switch_on_eof) + YY_NEW_FILE; + } + + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found"); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() +{ + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if(yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1]) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed"); + + if(yy_current_buffer->yy_fill_buffer == 0) + { + /* Don't try to fill the buffer, so this is an EOF. */ + if(yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int)(yy_c_buf_p - yytext_ptr) - 1; + + for(i = 0; i < number_to_move; ++i) + *(dest++) = *(source++); + + if(yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while(num_to_read <= 0) + { + /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( + "input buffer overflow, can't enlarge buffer because scanner uses REJECT"); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int)(yy_c_buf_p - b->yy_ch_buf); + + if(b->yy_is_our_buffer) + { + int new_size = b->yy_buf_size * 2; + + if(new_size <= 0) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc((void *) b->yy_ch_buf, + b->yy_buf_size + 2); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if(! b->yy_ch_buf) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow"); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if(num_to_read > YY_READ_BUF_SIZE) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT((&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if(yy_n_chars == 0) + { + if(number_to_move == YY_MORE_ADJ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; +} + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_state_ptr = yy_state_buf; + *yy_state_ptr++ = yy_current_state; + + for(yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + + while(yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int) yy_def[yy_current_state]; + + if(yy_current_state >= 173) + yy_c = yy_meta[(unsigned int) yy_c]; + } + + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + *yy_state_ptr++ = yy_current_state; + } + + return yy_current_state; +} + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans(yy_state_type yy_current_state) +#else +static yy_state_type yy_try_NUL_trans(yy_current_state) +yy_state_type yy_current_state; +#endif +{ + register int yy_is_jam; + + register YY_CHAR yy_c = 1; + + while(yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state) + { + yy_current_state = (int) yy_def[yy_current_state]; + + if(yy_current_state >= 173) + yy_c = yy_meta[(unsigned int) yy_c]; + } + + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 172); + + if(! yy_is_jam) + *yy_state_ptr++ = yy_current_state; + + return yy_is_jam ? 0 : yy_current_state; +} + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput(int c, register char *yy_bp) +#else +static void yyunput(c, yy_bp) +int c; +register char *yy_bp; +#endif +{ + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if(yy_cp < yy_current_buffer->yy_ch_buf + 2) + { + /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while(source > yy_current_buffer->yy_ch_buf) + *--dest = *--source; + + yy_cp += (int)(dest - source); + yy_bp += (int)(dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if(yy_cp < yy_current_buffer->yy_ch_buf + 2) + YY_FATAL_ERROR("flex scanner push-back overflow"); + } + + *--yy_cp = (char) c; + + if(c == '\n') + --yylineno; + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; +} +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif +{ + int c; + + *yy_c_buf_p = yy_hold_char; + + if(*yy_c_buf_p == YY_END_OF_BUFFER_CHAR) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if(yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars]) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { + /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch(yy_get_next_buffer()) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if(yywrap()) + return EOF; + + if(! yy_did_buffer_switch_on_eof) + YY_NEW_FILE; + +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + if(c == '\n') + ++yylineno; + + return c; +} + + +#ifdef YY_USE_PROTOS +void yyrestart(FILE *input_file) +#else +void yyrestart(input_file) +FILE *input_file; +#endif +{ + if(! yy_current_buffer) + yy_current_buffer = yy_create_buffer(yyin, YY_BUF_SIZE); + + yy_init_buffer(yy_current_buffer, input_file); + yy_load_buffer_state(); +} + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer) +#else +void yy_switch_to_buffer(new_buffer) +YY_BUFFER_STATE new_buffer; +#endif +{ + if(yy_current_buffer == new_buffer) + return; + + if(yy_current_buffer) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; +} + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state(void) +#else +void yy_load_buffer_state() +#endif +{ + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; +} + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer(FILE *file, int size) +#else +YY_BUFFER_STATE yy_create_buffer(file, size) +FILE *file; +int size; +#endif +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc(sizeof(struct yy_buffer_state)); + + if(! b) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc(b->yy_buf_size + 2); + + if(! b->yy_ch_buf) + YY_FATAL_ERROR("out of dynamic memory in yy_create_buffer()"); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b, file); + + return b; +} + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer(YY_BUFFER_STATE b) +#else +void yy_delete_buffer(b) +YY_BUFFER_STATE b; +#endif +{ + if(! b) + return; + + if(b == yy_current_buffer) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if(b->yy_is_our_buffer) + yy_flex_free((void *) b->yy_ch_buf); + + yy_flex_free((void *) b); +} + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO((int)); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer(YY_BUFFER_STATE b, FILE *file) +#else +void yy_init_buffer(b, file) +YY_BUFFER_STATE b; +FILE *file; +#endif + + +{ +yy_flush_buffer(b); + +b->yy_input_file = file; +b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE +b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE +b->yy_is_interactive = 0; +#else +b->yy_is_interactive = file ? (isatty(fileno(file)) > 0) : 0; +#endif +#endif +} + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer(YY_BUFFER_STATE b) +#else +void yy_flush_buffer(b) +YY_BUFFER_STATE b; +#endif + +{ +if(! b) + return; + +b->yy_n_chars = 0; + +/* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ +b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; +b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + +b->yy_buf_pos = &b->yy_ch_buf[0]; + +b->yy_at_bol = 1; +b->yy_buffer_status = YY_BUFFER_NEW; + +if(b == yy_current_buffer) + yy_load_buffer_state(); +} + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer(char *base, yy_size_t size) +#else +YY_BUFFER_STATE yy_scan_buffer(base, size) +char *base; +yy_size_t size; +#endif +{ +YY_BUFFER_STATE b; + +if(size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR) + /* They forgot to leave room for the EOB's. */ + return 0; + +b = (YY_BUFFER_STATE) yy_flex_alloc(sizeof(struct yy_buffer_state)); + +if(! b) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_buffer()"); + +b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ +b->yy_buf_pos = b->yy_ch_buf = base; +b->yy_is_our_buffer = 0; +b->yy_input_file = 0; +b->yy_n_chars = b->yy_buf_size; +b->yy_is_interactive = 0; +b->yy_at_bol = 1; +b->yy_fill_buffer = 0; +b->yy_buffer_status = YY_BUFFER_NEW; + +yy_switch_to_buffer(b); + +return b; +} +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string(yyconst char *yy_str) +#else +YY_BUFFER_STATE yy_scan_string(yy_str) +yyconst char *yy_str; +#endif +{ +int len; + +for(len = 0; yy_str[len]; ++len) + ; + +return yy_scan_bytes(yy_str, len); +} +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes(yyconst char *bytes, int len) +#else +YY_BUFFER_STATE yy_scan_bytes(bytes, len) +yyconst char *bytes; +int len; +#endif +{ +YY_BUFFER_STATE b; +char *buf; +yy_size_t n; +int i; + +/* Get memory for full buffer, including space for trailing EOB's. */ +n = len + 2; +buf = (char *) yy_flex_alloc(n); + +if(! buf) + YY_FATAL_ERROR("out of dynamic memory in yy_scan_bytes()"); + +for(i = 0; i < len; ++i) + buf[i] = bytes[i]; + +buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + +b = yy_scan_buffer(buf, n); + +if(! b) + YY_FATAL_ERROR("bad buffer in yy_scan_bytes()"); + +/* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ +b->yy_is_our_buffer = 1; + +return b; +} +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state(int new_state) +#else +static void yy_push_state(new_state) +int new_state; +#endif +{ +if(yy_start_stack_ptr >= yy_start_stack_depth) +{ + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof(int); + + if(! yy_start_stack) + yy_start_stack = (int *) yy_flex_alloc(new_size); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size); + + if(! yy_start_stack) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack"); +} + +yy_start_stack[yy_start_stack_ptr++] = YY_START; + +BEGIN(new_state); +} +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() +{ +if(--yy_start_stack_ptr < 0) + YY_FATAL_ERROR("start-condition stack underflow"); + +BEGIN(yy_start_stack[yy_start_stack_ptr]); +} +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() +{ +return yy_start_stack[yy_start_stack_ptr - 1]; +} +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error(yyconst char msg[]) +#else +static void yy_fatal_error(msg) +char msg[]; +#endif +{ +(void) fprintf(stderr, "%s\n", msg); +exit(YY_EXIT_FAILURE); +} + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy(char *s1, yyconst char *s2, int n) +#else +static void yy_flex_strncpy(s1, s2, n) +char *s1; +yyconst char *s2; +int n; +#endif +{ +register int i; + +for(i = 0; i < n; ++i) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen(yyconst char *s) +#else +static int yy_flex_strlen(s) +yyconst char *s; +#endif +{ +register int n; + +for(n = 0; s[n]; ++n) + ; + +return n; +} +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc(yy_size_t size) +#else +static void *yy_flex_alloc(size) +yy_size_t size; +#endif +{ +return (void *) malloc(size); +} + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc(void *ptr, yy_size_t size) +#else +static void *yy_flex_realloc(ptr, size) +void *ptr; +yy_size_t size; +#endif +{ +/* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ +return (void *) realloc((char *) ptr, size); +} + +#ifdef YY_USE_PROTOS +static void yy_flex_free(void *ptr) +#else +static void yy_flex_free(ptr) +void *ptr; +#endif +{ +free(ptr); +} + +#if YY_MAIN +int main() +{ +yylex(); +return 0; +} +#endif +#line 121 "ffscript.lpp" + +void resetLexer() +{ +YY_FLUSH_BUFFER; +yylineno=1; +} +void doLines() +{ +YYLTYPE rval = {yylineno, 0, yylineno, 0}; +yylloc = rval; +} + diff --git a/src/parser/lex.yy.cpp.fix b/src/parser/lex.yy.cpp.fix new file mode 100644 index 0000000000..30ae58b918 --- /dev/null +++ b/src/parser/lex.yy.cpp.fix @@ -0,0 +1,3 @@ +if(0) { yy_flex_realloc( NULL,0); yyunput(0,NULL); goto find_rule; } + + diff --git a/src/parser/unistd.h b/src/parser/unistd.h new file mode 100644 index 0000000000..a2ad792319 --- /dev/null +++ b/src/parser/unistd.h @@ -0,0 +1,37 @@ +#ifndef _MSC_VER +/* + * This file is part of the Mingw32 package. + * + * unistd.h maps (roughly) to io.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include +#include + +#define __UNISTD_GETOPT__ +#include "getopt.h" +#undef __UNISTD_GETOPT__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This is defined as a real library function to allow autoconf + to verify its existence. */ +int ftruncate(int, off_t); +/*__CRT_INLINE*/inline int ftruncate(int __fd, off_t __length) +{ + return _chsize(__fd, __length); +} + +#ifdef __cplusplus +} +#endif + +#endif /* _UNISTD_H */ + +#endif //_MSC_VER + diff --git a/src/parser/y.tab.cpp b/src/parser/y.tab.cpp new file mode 100644 index 0000000000..8d0b479efe --- /dev/null +++ b/src/parser/y.tab.cpp @@ -0,0 +1,3523 @@ +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 1 + + + +/* Copy the first part of user declarations. */ + +/* Line 189 of yacc.c */ +#line 10 "ffscript.ypp" + +#include "../precompiled.h" //always first + +#include +#include +#include +#include "AST.h" +#include "UtilVisitors.h" +#include "../zsyssimple.h" +#define YYINCLUDED_STDLIB_H +extern int yydebug; +extern int yylineno; +extern char* yytext; +extern int yylex(void); +extern FILE *yyin; +extern AST *resAST; +extern void resetLexer(); +void yyerror(const char* s); +string curfilename; +extern YYLTYPE noloc; + +#define SHORTCUT(x,d1,d3,dd,l1,l2) ASTExpr *lval = (ASTExpr *)d1; \ + Clone c; \ + lval->execute(c,NULL); \ + x *rhs = new x(l2); \ + rhs->setFirstOperand((ASTExpr *)c.getResult()); \ + rhs->setSecondOperand((ASTExpr *)d3); \ + dd = new ASTStmtAssign(lval, rhs, l1); + + +/* Line 189 of yacc.c */ +#line 102 "y.tab.cpp" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +/* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ +enum yytokentype +{ + SCRIPT = 258, + FLOAT = 259, + FOR = 260, + BOOL = 261, + VOID = 262, + IF = 263, + ELSE = 264, + RETURN = 265, + IMPORT = 266, + TRUE = 267, + FALSE = 268, + WHILE = 269, + FFC = 270, + ITEM = 271, + ITEMCLASS = 272, + GLOBAL = 273, + BREAK = 274, + CONTINUE = 275, + CONST = 276, + DO = 277, + NPC = 278, + LWEAPON = 279, + EWEAPON = 280, + ASSIGN = 281, + SEMICOLON = 282, + COMMA = 283, + LBRACKET = 284, + RBRACKET = 285, + LPAREN = 286, + RPAREN = 287, + DOT = 288, + LBRACE = 289, + RBRACE = 290, + ARROW = 291, + NUMBER = 292, + PLUSASSIGN = 293, + MINUSASSIGN = 294, + TIMESASSIGN = 295, + DIVIDEASSIGN = 296, + ANDASSIGN = 297, + ORASSIGN = 298, + BITANDASSIGN = 299, + BITORASSIGN = 300, + BITXORASSIGN = 301, + MODULOASSIGN = 302, + LSHIFTASSIGN = 303, + RSHIFTASSIGN = 304, + IDENTIFIER = 305, + QUOTEDSTRING = 306, + SINGLECHAR = 307, + RSHIFT = 308, + LSHIFT = 309, + BITXOR = 310, + BITOR = 311, + BITAND = 312, + OR = 313, + AND = 314, + BITNOT = 315, + NOT = 316, + DECREMENT = 317, + INCREMENT = 318, + NE = 319, + EQ = 320, + GT = 321, + GE = 322, + LT = 323, + LE = 324, + MINUS = 325, + PLUS = 326, + DIVIDE = 327, + TIMES = 328, + MODULO = 329 +}; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 264 of yacc.c */ +#line 231 "y.tab.cpp" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID(int yyi) +#else +static int +YYID(yyi) +int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC +/* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM +/* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc(YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free(void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \ + && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 549 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 75 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 48 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 157 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 270 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 329 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 8, 9, 11, 13, 15, 17, + 20, 25, 28, 35, 43, 49, 59, 68, 76, 83, + 87, 89, 94, 96, 98, 101, 105, 108, 111, 113, + 116, 119, 124, 126, 129, 131, 133, 135, 137, 139, + 141, 143, 145, 147, 154, 160, 164, 166, 170, 173, + 176, 178, 181, 184, 187, 190, 192, 194, 196, 199, + 201, 203, 205, 208, 211, 214, 216, 218, 220, 222, + 224, 226, 228, 230, 232, 234, 235, 237, 239, 241, + 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, + 285, 289, 293, 295, 297, 301, 306, 313, 315, 319, + 326, 330, 332, 336, 338, 342, 344, 348, 350, 354, + 356, 360, 362, 366, 368, 370, 372, 374, 376, 378, + 380, 382, 384, 388, 390, 392, 394, 398, 400, 402, + 404, 406, 409, 412, 415, 417, 421, 423, 426, 429, + 432, 435, 437, 439, 441, 443, 445, 447, 452, 456, + 460, 462, 472, 478, 485, 491, 499, 502 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 76, 0, -1, 77, -1, 77, 78, -1, -1, 82, + -1, 84, -1, 90, -1, 79, -1, 88, 27, -1, + 88, 26, 100, 27, -1, 80, 27, -1, 21, 4, + 50, 26, 37, 27, -1, 21, 4, 50, 26, 70, + 37, 27, -1, 89, 50, 29, 37, 30, -1, 89, + 50, 29, 37, 30, 26, 34, 81, 35, -1, 89, + 50, 29, 30, 26, 34, 81, 35, -1, 89, 50, + 29, 37, 30, 26, 51, -1, 89, 50, 29, 30, + 26, 51, -1, 81, 28, 100, -1, 100, -1, 83, + 3, 50, 85, -1, 89, -1, 18, -1, 11, 51, + -1, 34, 86, 35, -1, 34, 35, -1, 87, 86, + -1, 87, -1, 88, 27, -1, 80, 27, -1, 88, + 26, 100, 27, -1, 90, -1, 89, 50, -1, 4, + -1, 6, -1, 7, -1, 15, -1, 16, -1, 17, + -1, 23, -1, 24, -1, 25, -1, 89, 50, 31, + 91, 32, 92, -1, 89, 50, 31, 32, 92, -1, + 88, 28, 91, -1, 88, -1, 34, 93, 35, -1, + 34, 35, -1, 93, 94, -1, 94, -1, 88, 27, + -1, 80, 27, -1, 97, 27, -1, 96, 27, -1, + 118, -1, 121, -1, 92, -1, 122, 27, -1, 119, + -1, 120, -1, 27, -1, 100, 27, -1, 19, 27, + -1, 20, 27, -1, 88, -1, 80, -1, 97, -1, + 96, -1, 118, -1, 121, -1, 92, -1, 122, -1, + 119, -1, 120, -1, -1, 100, -1, 19, -1, 20, + -1, 99, 38, 100, -1, 99, 39, 100, -1, 99, + 40, 100, -1, 99, 41, 100, -1, 99, 42, 100, + -1, 99, 43, 100, -1, 99, 44, 100, -1, 99, + 45, 100, -1, 99, 46, 100, -1, 99, 48, 100, + -1, 99, 49, 100, -1, 99, 47, 100, -1, 98, + 26, 100, -1, 88, -1, 99, -1, 50, 33, 50, + -1, 50, 29, 100, 30, -1, 50, 33, 50, 29, + 100, 30, -1, 50, -1, 99, 36, 50, -1, 99, + 36, 50, 29, 100, 30, -1, 100, 58, 101, -1, + 101, -1, 101, 59, 102, -1, 102, -1, 102, 56, + 103, -1, 103, -1, 103, 55, 104, -1, 104, -1, + 104, 57, 105, -1, 105, -1, 105, 108, 106, -1, + 106, -1, 106, 107, 109, -1, 109, -1, 54, -1, + 53, -1, 66, -1, 67, -1, 68, -1, 69, -1, + 65, -1, 64, -1, 109, 110, 111, -1, 111, -1, + 71, -1, 70, -1, 111, 112, 113, -1, 113, -1, + 73, -1, 72, -1, 74, -1, 61, 113, -1, 70, + 113, -1, 60, 113, -1, 114, -1, 31, 100, 32, + -1, 99, -1, 99, 63, -1, 63, 99, -1, 99, + 62, -1, 62, 99, -1, 37, -1, 52, -1, 115, + -1, 116, -1, 12, -1, 13, -1, 99, 31, 117, + 32, -1, 99, 31, 32, -1, 100, 28, 117, -1, + 100, -1, 5, 31, 95, 27, 100, 27, 95, 32, + 94, -1, 14, 31, 100, 32, 94, -1, 22, 94, + 14, 31, 100, 32, -1, 8, 31, 100, 32, 94, + -1, 8, 31, 100, 32, 94, 9, 94, -1, 10, + 100, -1, 10, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 107, 107, 110, 113, 116, 117, 118, 119, 120, + 121, 126, 129, 133, 139, 145, 151, 160, 174, 191, + 194, 199, 215, 216, 219, 224, 225, 228, 231, 236, + 237, 238, 243, 246, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 263, 272, 283, 286, 291, 292, 295, + 299, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, 317, 318, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 337, + 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, + 348, 352, 355, 356, 359, 363, 369, 377, 380, 384, + 392, 398, 401, 407, 410, 416, 419, 425, 428, 434, + 437, 443, 446, 452, 455, 456, 459, 460, 461, 462, + 463, 464, 467, 473, 476, 477, 480, 486, 489, 490, + 491, 494, 498, 502, 506, 509, 510, 511, 515, 519, + 523, 527, 529, 533, 534, 537, 538, 541, 545, 551, + 555, 561, 568, 572, 576, 579, 585, 586 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "SCRIPT", "FLOAT", "FOR", "BOOL", "VOID", + "IF", "ELSE", "RETURN", "IMPORT", "TRUE", "FALSE", "WHILE", "FFC", + "ITEM", "ITEMCLASS", "GLOBAL", "BREAK", "CONTINUE", "CONST", "DO", "NPC", + "LWEAPON", "EWEAPON", "ASSIGN", "SEMICOLON", "COMMA", "LBRACKET", + "RBRACKET", "LPAREN", "RPAREN", "DOT", "LBRACE", "RBRACE", "ARROW", + "NUMBER", "PLUSASSIGN", "MINUSASSIGN", "TIMESASSIGN", "DIVIDEASSIGN", + "ANDASSIGN", "ORASSIGN", "BITANDASSIGN", "BITORASSIGN", "BITXORASSIGN", + "MODULOASSIGN", "LSHIFTASSIGN", "RSHIFTASSIGN", "IDENTIFIER", + "QUOTEDSTRING", "SINGLECHAR", "RSHIFT", "LSHIFT", "BITXOR", "BITOR", + "BITAND", "OR", "AND", "BITNOT", "NOT", "DECREMENT", "INCREMENT", "NE", + "EQ", "GT", "GE", "LT", "LE", "MINUS", "PLUS", "DIVIDE", "TIMES", + "MODULO", "$accept", "Init", "Prog", "GlobalStmt", "ConstDecl", + "ArrayDecl", "ArrayList", "Script", "ScriptType", "Import", + "ScriptBlock", "ScriptStmtList", "ScriptStmt", "VarDecl", "Type", + "FuncDecl", "ParamList", "Block", "StmtList", "Stmt", "StmtNoSemi", + "ShortcutAssignStmt", "AssignStmt", "LVal", "DotExpr", "Expr", "Expr15", + "Expr16", "Expr17", "Expr18", "Expr2", "Expr25", "ShiftOp", "RelOp", + "Expr3", "AddOp", "Expr4", "MultOp", "Expr5", "Factor", "BoolConstant", + "FuncCall", "ExprList", "ForStmt", "WhileStmt", "DoStmt", "IfStmt", + "ReturnStmt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 75, 76, 77, 77, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 80, 80, 80, 80, 80, 81, + 81, 82, 83, 83, 84, 85, 85, 86, 86, 87, + 87, 87, 87, 88, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 90, 90, 91, 91, 92, 92, 93, + 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 97, 98, 98, 99, 99, 99, 99, 99, 99, + 100, 100, 101, 101, 102, 102, 103, 103, 104, 104, + 105, 105, 106, 106, 107, 107, 108, 108, 108, 108, + 108, 108, 109, 109, 110, 110, 111, 111, 112, 112, + 112, 113, 113, 113, 113, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 115, 115, 116, 116, 117, + 117, 118, 119, 120, 121, 121, 122, 122 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 2, 0, 1, 1, 1, 1, 2, + 4, 2, 6, 7, 5, 9, 8, 7, 6, 3, + 1, 4, 1, 1, 2, 3, 2, 2, 1, 2, + 2, 4, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 6, 5, 3, 1, 3, 2, 2, + 1, 2, 2, 2, 2, 1, 1, 1, 2, 1, + 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 1, 1, 3, 4, 6, 1, 3, 6, + 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 1, 1, 3, 1, 1, 1, + 1, 2, 2, 2, 1, 3, 1, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 4, 3, 3, + 1, 9, 5, 6, 5, 7, 2, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 4, 0, 2, 1, 34, 35, 36, 0, 37, 38, + 39, 23, 0, 40, 41, 42, 3, 8, 0, 5, + 0, 6, 0, 22, 7, 24, 0, 11, 0, 0, + 9, 33, 0, 0, 145, 146, 0, 141, 97, 142, + 0, 0, 0, 0, 0, 136, 0, 101, 103, 105, + 107, 109, 111, 113, 123, 127, 134, 143, 144, 0, + 0, 0, 0, 21, 0, 0, 0, 133, 131, 140, + 138, 132, 0, 0, 139, 137, 10, 0, 0, 0, + 0, 0, 121, 120, 116, 117, 118, 119, 0, 115, + 114, 0, 125, 124, 0, 129, 128, 130, 0, 0, + 0, 0, 46, 0, 0, 0, 0, 26, 0, 0, + 28, 0, 0, 32, 135, 0, 94, 148, 150, 0, + 98, 100, 102, 104, 106, 108, 110, 112, 122, 126, + 0, 14, 0, 44, 0, 33, 0, 12, 0, 30, + 25, 27, 0, 29, 95, 0, 0, 147, 0, 0, + 18, 0, 0, 0, 157, 0, 0, 0, 0, 61, + 48, 0, 92, 0, 57, 0, 50, 0, 0, 0, + 136, 0, 55, 59, 60, 56, 0, 45, 43, 13, + 0, 0, 149, 0, 0, 20, 0, 17, 75, 0, + 156, 0, 63, 64, 0, 52, 51, 33, 47, 49, + 54, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 62, 58, 31, 96, 99, + 0, 16, 0, 77, 78, 66, 65, 71, 0, 68, + 67, 76, 69, 73, 74, 70, 72, 0, 0, 0, + 91, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 90, 88, 89, 19, 15, 0, 0, 0, 0, 0, + 154, 152, 0, 75, 0, 153, 0, 155, 0, 151 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 2, 16, 17, 161, 184, 19, 20, 21, + 63, 109, 110, 162, 163, 113, 104, 164, 165, 166, + 228, 167, 168, 169, 45, 171, 47, 48, 49, 50, + 51, 52, 91, 88, 53, 94, 54, 98, 55, 56, + 57, 58, 119, 172, 173, 174, 175, 176 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -182 +static const yytype_int16 yypact[] = +{ + -182, 33, 524, -182, -182, -182, -182, -4, -182, -182, + -182, -182, 18, -182, -182, -182, -182, -182, 30, -182, + 41, -182, 9, 31, -182, -182, 55, -182, 66, 177, + -182, 88, 94, 90, -182, -182, 177, -182, 64, -182, + 177, 177, 78, 78, 177, -10, -3, 83, 87, 95, + 96, 166, 73, -29, 22, -182, -182, -182, -182, -5, + 140, -20, 106, -182, 40, 177, 104, -182, -182, 122, + 122, -182, 17, 109, -182, -182, -182, 177, 177, 177, + 177, 177, -182, -182, -182, -182, -182, -182, 177, -182, + -182, 177, -182, -182, 177, -182, -182, -182, 177, 141, + 143, 137, 146, 125, 144, 151, 147, -182, 154, 148, + 145, 108, 31, -182, -182, -12, 156, -182, 12, 159, + 163, 83, 87, 95, 96, 166, 73, -29, 22, -182, + 11, 162, 259, -182, 145, -182, 137, -182, 179, -182, + -182, -182, 177, -182, -182, 177, 177, -182, 177, 177, + -182, 56, 176, 178, 177, 181, 183, 186, 381, -182, + -182, 188, 191, 169, -182, 320, -182, 193, 194, 196, + 475, 1, -182, -182, -182, -182, 198, -182, -182, -182, + 7, -7, -182, 13, 3, 168, 177, -182, 442, 177, + 168, 177, -182, -182, 222, -182, -182, 212, -182, -182, + -182, -182, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, -182, -182, -182, -182, -182, + 177, -182, 71, -182, -182, -182, 216, -182, 217, -182, + -182, 168, -182, -182, -182, -182, -182, 42, 43, 214, + 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, + 168, 168, 168, 168, -182, 177, 381, 381, 177, 10, + 234, -182, 44, 442, 381, -182, 218, -182, 381, -182 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -182, -182, -182, -182, -182, -1, 62, -182, -182, -182, + -182, 142, -182, -2, 4, 249, 119, -97, -182, -153, + -8, -181, -180, -182, -40, -9, 180, 182, 189, 190, + 175, 170, -182, -182, 197, -182, 165, -182, -25, -182, + -182, -182, 131, -179, -178, -177, -175, -174 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -94 +static const yytype_int16 yytable[] = +{ + 22, 18, 69, 70, 133, 194, 23, 229, 230, 232, + 233, 234, 199, 235, 236, 67, 68, 105, 144, 71, + 46, 72, 26, 218, 76, 99, 73, 64, 215, 34, + 35, 220, 100, 3, 217, 29, 30, 263, 221, 178, + 146, 92, 93, 219, 28, 149, 77, 25, 36, 117, + 106, 77, 74, 75, 37, 77, 115, 27, 102, 77, + 111, 108, 150, 118, 103, 77, 112, 38, 77, 39, + 77, 77, 114, 129, 256, 257, 265, 40, 41, 42, + 43, 31, 229, 230, 232, 233, 234, 44, 235, 236, + 186, 227, 170, 65, 95, 96, 97, 66, 77, 220, + 77, 77, 77, 260, 261, 32, 254, 187, 111, 108, + 4, 267, 5, 6, 112, 269, 33, 59, 170, 60, + 61, 8, 9, 10, 62, 170, 89, 90, 38, 13, + 14, 15, 102, 180, 142, 143, 181, 118, 103, 183, + 185, 107, 78, 79, 4, 190, 5, 6, 170, 4, + 80, 5, 6, 81, 116, 8, 9, 10, 73, 120, + 8, 9, 10, 13, 14, 15, 227, 130, 13, 14, + 15, 132, 101, 131, 134, 135, 136, 185, 137, 231, + 237, 139, 238, 140, 138, 145, 226, 225, 151, 34, + 35, 147, 148, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 179, 188, 36, 189, + 192, 253, 191, 193, 37, 195, 170, 170, 196, 197, + 200, 201, 202, 170, 170, 216, 77, 38, 170, 39, + 82, 83, 84, 85, 86, 87, 239, 40, 41, 42, + 43, 59, -92, 264, 255, 258, 259, 44, 222, 262, + 268, 24, 141, 177, 231, 266, 125, 121, 126, 128, + 122, 226, 225, 4, 152, 5, 6, 153, 123, 154, + 124, 34, 35, 155, 8, 9, 10, 182, 156, 157, + 0, 158, 13, 14, 15, 0, 159, 0, 127, 0, + 36, 0, 0, 132, 160, 0, 37, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, + 0, 39, 0, 0, 0, 0, 0, 0, 0, 40, + 41, 42, 43, 0, 4, 152, 5, 6, 153, 44, + 154, 0, 34, 35, 155, 8, 9, 10, 0, 156, + 157, 0, 158, 13, 14, 15, 0, 159, 0, 0, + 0, 36, 0, 0, 132, 198, 0, 37, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 38, 0, 39, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 0, 4, 152, 5, 6, 153, + 44, 154, 0, 34, 35, 155, 8, 9, 10, 0, + 156, 157, 0, 158, 13, 14, 15, 0, 159, 0, + 0, 0, 36, 0, 0, 132, 0, 0, 37, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 38, 0, 39, 0, 0, 0, 0, 0, 0, + 0, 40, 41, 42, 43, 0, 4, 152, 5, 6, + 153, 44, 154, 0, 34, 35, 155, 8, 9, 10, + 0, 223, 224, 0, 158, 13, 14, 15, 0, 0, + 0, 0, 0, 36, 0, 0, 132, 0, 0, 37, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 38, 0, 39, 0, 0, 0, 0, 0, + 0, -93, 40, 41, 42, 43, 72, 0, 0, 0, + 0, 73, 44, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 0, 0, 0, 4, 0, + 5, 6, 0, 0, 0, 7, 0, 74, 75, 8, + 9, 10, 11, 0, 0, 12, 0, 13, 14, 15 +}; + +static const yytype_int16 yycheck[] = +{ + 2, 2, 42, 43, 101, 158, 2, 188, 188, 188, + 188, 188, 165, 188, 188, 40, 41, 37, 30, 44, + 29, 31, 4, 30, 27, 30, 36, 36, 27, 12, + 13, 28, 37, 0, 27, 26, 27, 27, 35, 136, + 28, 70, 71, 30, 3, 34, 58, 51, 31, 32, + 70, 58, 62, 63, 37, 58, 65, 27, 60, 58, + 62, 62, 51, 72, 60, 58, 62, 50, 58, 52, + 58, 58, 32, 98, 32, 32, 32, 60, 61, 62, + 63, 50, 263, 263, 263, 263, 263, 70, 263, 263, + 34, 188, 132, 29, 72, 73, 74, 33, 58, 28, + 58, 58, 58, 256, 257, 50, 35, 51, 110, 110, + 4, 264, 6, 7, 110, 268, 50, 29, 158, 31, + 26, 15, 16, 17, 34, 165, 53, 54, 50, 23, + 24, 25, 134, 142, 26, 27, 145, 146, 134, 148, + 149, 35, 59, 56, 4, 154, 6, 7, 188, 4, + 55, 6, 7, 57, 50, 15, 16, 17, 36, 50, + 15, 16, 17, 23, 24, 25, 263, 26, 23, 24, + 25, 34, 32, 30, 28, 50, 32, 186, 27, 188, + 189, 27, 191, 35, 37, 29, 188, 188, 26, 12, + 13, 32, 29, 202, 203, 204, 205, 206, 207, 208, + 209, 210, 211, 212, 213, 214, 27, 31, 31, 31, + 27, 220, 31, 27, 37, 27, 256, 257, 27, 50, + 27, 27, 26, 263, 264, 27, 58, 50, 268, 52, + 64, 65, 66, 67, 68, 69, 14, 60, 61, 62, + 63, 29, 26, 9, 27, 31, 255, 70, 186, 258, + 32, 2, 110, 134, 263, 263, 81, 77, 88, 94, + 78, 263, 263, 4, 5, 6, 7, 8, 79, 10, + 80, 12, 13, 14, 15, 16, 17, 146, 19, 20, + -1, 22, 23, 24, 25, -1, 27, -1, 91, -1, + 31, -1, -1, 34, 35, -1, 37, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 50, + -1, 52, -1, -1, -1, -1, -1, -1, -1, 60, + 61, 62, 63, -1, 4, 5, 6, 7, 8, 70, + 10, -1, 12, 13, 14, 15, 16, 17, -1, 19, + 20, -1, 22, 23, 24, 25, -1, 27, -1, -1, + -1, 31, -1, -1, 34, 35, -1, 37, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 50, -1, 52, -1, -1, -1, -1, -1, -1, -1, + 60, 61, 62, 63, -1, 4, 5, 6, 7, 8, + 70, 10, -1, 12, 13, 14, 15, 16, 17, -1, + 19, 20, -1, 22, 23, 24, 25, -1, 27, -1, + -1, -1, 31, -1, -1, 34, -1, -1, 37, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 50, -1, 52, -1, -1, -1, -1, -1, -1, + -1, 60, 61, 62, 63, -1, 4, 5, 6, 7, + 8, 70, 10, -1, 12, 13, 14, 15, 16, 17, + -1, 19, 20, -1, 22, 23, 24, 25, -1, -1, + -1, -1, -1, 31, -1, -1, 34, -1, -1, 37, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 50, -1, 52, -1, -1, -1, -1, -1, + -1, 26, 60, 61, 62, 63, 31, -1, -1, -1, + -1, 36, 70, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, -1, -1, -1, 4, -1, + 6, 7, -1, -1, -1, 11, -1, 62, 63, 15, + 16, 17, 18, -1, -1, 21, -1, 23, 24, 25 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 76, 77, 0, 4, 6, 7, 11, 15, 16, + 17, 18, 21, 23, 24, 25, 78, 79, 80, 82, + 83, 84, 88, 89, 90, 51, 4, 27, 3, 26, + 27, 50, 50, 50, 12, 13, 31, 37, 50, 52, + 60, 61, 62, 63, 70, 99, 100, 101, 102, 103, + 104, 105, 106, 109, 111, 113, 114, 115, 116, 29, + 31, 26, 34, 85, 100, 29, 33, 113, 113, 99, + 99, 113, 31, 36, 62, 63, 27, 58, 59, 56, + 55, 57, 64, 65, 66, 67, 68, 69, 108, 53, + 54, 107, 70, 71, 110, 72, 73, 74, 112, 30, + 37, 32, 88, 89, 91, 37, 70, 35, 80, 86, + 87, 88, 89, 90, 32, 100, 50, 32, 100, 117, + 50, 101, 102, 103, 104, 105, 106, 109, 111, 113, + 26, 30, 34, 92, 28, 50, 32, 27, 37, 27, + 35, 86, 26, 27, 30, 29, 28, 32, 29, 34, + 51, 26, 5, 8, 10, 14, 19, 20, 22, 27, + 35, 80, 88, 89, 92, 93, 94, 96, 97, 98, + 99, 100, 118, 119, 120, 121, 122, 91, 92, 27, + 100, 100, 117, 100, 81, 100, 34, 51, 31, 31, + 100, 31, 27, 27, 94, 27, 27, 50, 35, 94, + 27, 27, 26, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 27, 27, 27, 30, 30, + 28, 35, 81, 19, 20, 80, 88, 92, 95, 96, + 97, 100, 118, 119, 120, 121, 122, 100, 100, 14, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 35, 27, 32, 32, 31, 100, + 94, 94, 100, 27, 9, 32, 95, 94, 32, 94 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print(FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +#else +static void +yy_symbol_value_print(yyoutput, yytype, yyvaluep, yylocationp) +FILE *yyoutput; +int yytype; +YYSTYPE const * const yyvaluep; +YYLTYPE const * const yylocationp; +#endif +{ + if(!yyvaluep) + return; + + YYUSE(yylocationp); +# ifdef YYPRINT + + if(yytype < YYNTOKENS) + YYPRINT(yyoutput, yytoknum[yytype], *yyvaluep); + +# else + YYUSE(yyoutput); +# endif + + switch(yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print(FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +#else +static void +yy_symbol_print(yyoutput, yytype, yyvaluep, yylocationp) +FILE *yyoutput; +int yytype; +YYSTYPE const * const yyvaluep; +YYLTYPE const * const yylocationp; +#endif +{ + if(yytype < YYNTOKENS) + YYFPRINTF(yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF(yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT(yyoutput, *yylocationp); + YYFPRINTF(yyoutput, ": "); + yy_symbol_value_print(yyoutput, yytype, yyvaluep, yylocationp); + YYFPRINTF(yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print(yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print(yybottom, yytop) +yytype_int16 *yybottom; +yytype_int16 *yytop; +#endif +{ + YYFPRINTF(stderr, "Stack now"); + + for(; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF(stderr, " %d", yybot); + } + + YYFPRINTF(stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print(YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) +#else +static void +yy_reduce_print(yyvsp, yylsp, yyrule) +YYSTYPE *yyvsp; +YYLTYPE *yylsp; +int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF(stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + + /* The symbols being reduced. */ + for(yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF(stderr, " $%d = ", yyi + 1); + yy_symbol_print(stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)])); + YYFPRINTF(stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, yylsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen(const char *yystr) +#else +static YYSIZE_T +yystrlen(yystr) +const char *yystr; +#endif +{ + YYSIZE_T yylen; + + for(yylen = 0; yystr[yylen]; yylen++) + continue; + + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy(char *yydest, const char *yysrc) +#else +static char * +yystpcpy(yydest, yysrc) +char *yydest; +const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr(char *yyres, const char *yystr) +{ + if(*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for(;;) + switch(*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if(*++yyp != '\\') + goto do_not_strip_quotes; + + /* Fall through. */ + default: + if(yyres) + yyres[yyn] = *yyp; + + yyn++; + break; + + case '"': + if(yyres) + yyres[yyn] = '\0'; + + return yyn; + } + +do_not_strip_quotes: + ; + } + + if(! yyres) + return yystrlen(yystr); + + return yystpcpy(yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error(char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if(!(YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE(yychar); + YYSIZE_T yysize0 = yytnamerr(0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy(yyformat, yyunexpected); + + for(yyx = yyxbegin; yyx < yyxend; ++yyx) + if(yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if(yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr(0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy(yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen(yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if(yysize_overflow) + return YYSIZE_MAXIMUM; + + if(yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + + while((*yyp = *yyf) != '\0') + { + if(*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr(yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct(const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +#else +static void +yydestruct(yymsg, yytype, yyvaluep, yylocationp) +const char *yymsg; +int yytype; +YYSTYPE *yyvaluep; +YYLTYPE *yylocationp; +#endif +{ + YYUSE(yyvaluep); + YYUSE(yylocationp); + + if(!yymsg) + yymsg = "Deleting"; + + YY_SYMBOL_PRINT(yymsg, yytype, yyvaluep, yylocationp); + + switch(yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse(void *YYPARSE_PARAM); +#else +int yyparse(); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse(void); +#else +int yyparse(); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Location data for the lookahead symbol. */ +YYLTYPE yylloc; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse(void *YYPARSE_PARAM) +#else +int +yyparse(YYPARSE_PARAM) +void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse(void) +#else +int +yyparse() + +#endif +#endif +{ + + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yyls = yylsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; + +#if YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 1; +#endif + + goto yysetstate; + + /*------------------------------------------------------------. + | yynewstate -- Push a new state, which is found in yystate. | + `------------------------------------------------------------*/ +yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + +yysetstate: + *yyssp = yystate; + + if(yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow(YY_("memory exhausted"), + &yyss1, yysize * sizeof(*yyssp), + &yyvs1, yysize * sizeof(*yyvsp), + &yyls1, yysize * sizeof(*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + + /* Extend the stack our own way. */ + if(YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + + yystacksize *= 2; + + if(YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC(YYSTACK_BYTES(yystacksize)); + + if(! yyptr) + goto yyexhaustedlab; + + YYSTACK_RELOCATE(yyss_alloc, yyss); + YYSTACK_RELOCATE(yyvs_alloc, yyvs); + YYSTACK_RELOCATE(yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + + if(yyss1 != yyssa) + YYSTACK_FREE(yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if(yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF((stderr, "Entering state %d\n", yystate)); + + if(yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + + /*-----------. + | yybackup. | + `-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + + if(yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if(yychar == YYEMPTY) + { + YYDPRINTF((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if(yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE(yychar); + YY_SYMBOL_PRINT("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + + if(yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + + yyn = yytable[yyn]; + + if(yyn <= 0) + { + if(yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if(yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + *++yylsp = yylloc; + goto yynewstate; + + + /*-----------------------------------------------------------. + | yydefault -- do the default action for the current state. | + `-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + + if(yyn == 0) + goto yyerrlab; + + goto yyreduce; + + + /*-----------------------------. + | yyreduce -- Do a reduction. | + `-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT(yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT(yyn); + + switch(yyn) + { + case 2: + + /* Line 1455 of yacc.c */ +#line 107 "ffscript.ypp" + {resAST = new ASTProgram((ASTDeclList *)(yyvsp[(1) - (1)]), (yylsp[(1) - (1)]));;} + break; + + case 3: + + /* Line 1455 of yacc.c */ +#line 110 "ffscript.ypp" + { + ASTDeclList *list = (ASTDeclList *)(yyvsp[(1) - (2)]); + list->addDeclaration((ASTDecl *)(yyvsp[(2) - (2)])); + (yyval) = list;; + } + break; + + case 4: + + /* Line 1455 of yacc.c */ +#line 113 "ffscript.ypp" + {(yyval) = new ASTDeclList(noloc);;} + break; + + case 5: + + /* Line 1455 of yacc.c */ +#line 116 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 6: + + /* Line 1455 of yacc.c */ +#line 117 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 7: + + /* Line 1455 of yacc.c */ +#line 118 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 8: + + /* Line 1455 of yacc.c */ +#line 119 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 9: + + /* Line 1455 of yacc.c */ +#line 120 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 10: + + /* Line 1455 of yacc.c */ +#line 121 "ffscript.ypp" + { + ASTVarDecl *vd = (ASTVarDecl *)(yyvsp[(1) - (4)]); + Clone c; + vd->getType()->execute(c,NULL); + (yyval) = new ASTVarDeclInitializer((ASTType *)c.getResult(), vd->getName(), (ASTExpr *)(yyvsp[(3) - (4)]),(yylsp[(1) - (4)])); + delete vd;; + } + break; + + case 11: + + /* Line 1455 of yacc.c */ +#line 126 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 12: + + /* Line 1455 of yacc.c */ +#line 129 "ffscript.ypp" + { + ASTString *name = (ASTString *)(yyvsp[(3) - (6)]); + ASTFloat *val = (ASTFloat *)(yyvsp[(5) - (6)]); + (yyval) = new ASTConstDecl(name->getValue(), val,(yylsp[(1) - (6)])); + delete name;; + } + break; + + case 13: + + /* Line 1455 of yacc.c */ +#line 133 "ffscript.ypp" + { + ASTString *name = (ASTString *)(yyvsp[(3) - (7)]); + ASTFloat *val = (ASTFloat *)(yyvsp[(6) - (7)]); + val->set_negative(true); + (yyval) = new ASTConstDecl(name->getValue(), val,(yylsp[(1) - (7)])); + delete name;; + } + break; + + case 14: + + /* Line 1455 of yacc.c */ +#line 139 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (5)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (5)]); + ASTExpr *size = (ASTExpr *)(yyvsp[(4) - (5)]); + (yyval) = new ASTArrayDecl(type, name->getValue(), size, false, NULL, (yylsp[(1) - (5)])); + delete name;; + } + break; + + case 15: + + /* Line 1455 of yacc.c */ +#line 145 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (9)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (9)]); + ASTFloat *size = (ASTFloat *)(yyvsp[(4) - (9)]); + ASTArrayList *list = (ASTArrayList *)(yyvsp[(8) - (9)]); + (yyval) = new ASTArrayDecl(type, name->getValue(), size, false, list, (yylsp[(1) - (9)])); + delete name;; + } + break; + + case 16: + + /* Line 1455 of yacc.c */ +#line 151 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (8)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (8)]); + ASTArrayList *list = (ASTArrayList *)(yyvsp[(7) - (8)]); + char val[15]; + sprintf(val, "%d", list->getList().size()); + ASTFloat *size = new ASTFloat(val, 0, (yylsp[(1) - (8)])); + (yyval) = new ASTArrayDecl(type, name->getValue(), size, false, list, (yylsp[(1) - (8)])); + delete name;; + } + break; + + case 17: + + /* Line 1455 of yacc.c */ +#line 160 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (7)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (7)]); + ASTFloat *size = (ASTFloat *)(yyvsp[(4) - (7)]); + ASTArrayList *list = new ASTArrayList((yylsp[(1) - (7)])); + list->makeString(); + ASTString *string = (ASTString *)(yyvsp[(7) - (7)]); + + for(unsigned int i=1; i < string->getValue().length()-1; i++) + list->addParam(new ASTNumConstant(new ASTFloat(long((string->getValue())[i]), 0, (yylsp[(1) - (7)])), (yylsp[(1) - (7)]))); + + list->addParam(new ASTNumConstant(new ASTFloat(0L, 0, (yylsp[(1) - (7)])), (yylsp[(1) - (7)]))); + (yyval) = new ASTArrayDecl(type, name->getValue(), size, false, list, (yylsp[(1) - (7)])); + delete name;; + } + break; + + case 18: + + /* Line 1455 of yacc.c */ +#line 174 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (6)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (6)]); + ASTArrayList *list = new ASTArrayList((yylsp[(1) - (6)])); + list->makeString(); + ASTString *string = (ASTString *)(yyvsp[(6) - (6)]); + ASTFloat *size = new ASTFloat(string->getValue().length()-1, 0, (yylsp[(1) - (6)])); + + for(unsigned int i=1; i < string->getValue().length()-1; i++) + list->addParam(new ASTNumConstant(new ASTFloat(long((string->getValue())[i]), 0, (yylsp[(1) - (6)])), (yylsp[(1) - (6)]))); + + list->addParam(new ASTNumConstant(new ASTFloat(0L, 0, (yylsp[(1) - (6)])), (yylsp[(1) - (6)]))); + (yyval) = new ASTArrayDecl(type, name->getValue(), size, false, list, (yylsp[(1) - (6)])); + delete name;; + } + break; + + case 19: + + /* Line 1455 of yacc.c */ +#line 191 "ffscript.ypp" + { + ASTArrayList *al = (ASTArrayList *)(yyvsp[(1) - (3)]); + al->addParam((ASTExpr*)(yyvsp[(3) - (3)])); + (yyval)=al;; + } + break; + + case 20: + + /* Line 1455 of yacc.c */ +#line 194 "ffscript.ypp" + { + ASTArrayList *al = new ASTArrayList((yylsp[(1) - (1)])); + al->addParam((ASTExpr *)(yyvsp[(1) - (1)])); + (yyval)=al;; + } + break; + + case 21: + + /* Line 1455 of yacc.c */ +#line 199 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (4)]); + int scripttype; //Itemdata pointer instead of item pointer + ExtractType temp; + type->execute(temp, &scripttype); + + if(scripttype == ScriptParser::TYPE_ITEM) + { + ASTType *t = type; //so we can keep the locationdata before deleting + type = new ASTTypeItemclass(type->getLocation()); + delete t; + } + + ASTString *name = (ASTString *)(yyvsp[(3) - (4)]); + ASTDeclList *sblock = (ASTDeclList *)(yyvsp[(4) - (4)]); + (yyval) = new ASTScript(type, name->getValue(), sblock,(yylsp[(1) - (4)])); + delete name;; + } + break; + + case 22: + + /* Line 1455 of yacc.c */ +#line 215 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 23: + + /* Line 1455 of yacc.c */ +#line 216 "ffscript.ypp" + {(yyval) = new ASTTypeGlobal((yylsp[(1) - (1)]));;} + break; + + case 24: + + /* Line 1455 of yacc.c */ +#line 219 "ffscript.ypp" + { + ASTString *str = (ASTString *)(yyvsp[(2) - (2)]); + (yyval) = new ASTImportDecl(str->getValue(),(yylsp[(1) - (2)])); + delete str;; + } + break; + + case 25: + + /* Line 1455 of yacc.c */ +#line 224 "ffscript.ypp" + {(yyval) = (yyvsp[(2) - (3)]);;} + break; + + case 26: + + /* Line 1455 of yacc.c */ +#line 225 "ffscript.ypp" + {(yyval) = new ASTDeclList((yylsp[(1) - (2)]));;} + break; + + case 27: + + /* Line 1455 of yacc.c */ +#line 228 "ffscript.ypp" + { + ASTDeclList *dl = (ASTDeclList *)(yyvsp[(2) - (2)]); + dl->addDeclaration((ASTDecl *)(yyvsp[(1) - (2)])); + (yyval) = dl;; + } + break; + + case 28: + + /* Line 1455 of yacc.c */ +#line 231 "ffscript.ypp" + { + ASTDeclList *dl = new ASTDeclList((yylsp[(1) - (1)])); + dl->addDeclaration((ASTDecl *)(yyvsp[(1) - (1)])); + (yyval) = dl;; + } + break; + + case 29: + + /* Line 1455 of yacc.c */ +#line 236 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 30: + + /* Line 1455 of yacc.c */ +#line 237 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 31: + + /* Line 1455 of yacc.c */ +#line 238 "ffscript.ypp" + { + ASTVarDecl *vd = (ASTVarDecl *)(yyvsp[(1) - (4)]); + Clone c; + vd->getType()->execute(c,NULL); + (yyval) = new ASTVarDeclInitializer((ASTType *)c.getResult(), vd->getName(), (ASTExpr *)(yyvsp[(3) - (4)]),(yylsp[(1) - (4)])); + delete vd;; + } + break; + + case 32: + + /* Line 1455 of yacc.c */ +#line 243 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 33: + + /* Line 1455 of yacc.c */ +#line 246 "ffscript.ypp" + { + ASTType *type = (ASTType *)(yyvsp[(1) - (2)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (2)]); + (yyval) = new ASTVarDecl(type, name->getValue(),(yylsp[(1) - (2)])); + delete name;; + } + break; + + case 34: + + /* Line 1455 of yacc.c */ +#line 252 "ffscript.ypp" + {(yyval) = new ASTTypeFloat((yylsp[(1) - (1)]));;} + break; + + case 35: + + /* Line 1455 of yacc.c */ +#line 253 "ffscript.ypp" + {(yyval) = new ASTTypeBool((yylsp[(1) - (1)]));;} + break; + + case 36: + + /* Line 1455 of yacc.c */ +#line 254 "ffscript.ypp" + {(yyval) = new ASTTypeVoid((yylsp[(1) - (1)]));;} + break; + + case 37: + + /* Line 1455 of yacc.c */ +#line 255 "ffscript.ypp" + {(yyval) = new ASTTypeFFC((yylsp[(1) - (1)]));;} + break; + + case 38: + + /* Line 1455 of yacc.c */ +#line 256 "ffscript.ypp" + {(yyval) = new ASTTypeItem((yylsp[(1) - (1)]));;} + break; + + case 39: + + /* Line 1455 of yacc.c */ +#line 257 "ffscript.ypp" + {(yyval) = new ASTTypeItemclass((yylsp[(1) - (1)]));;} + break; + + case 40: + + /* Line 1455 of yacc.c */ +#line 258 "ffscript.ypp" + {(yyval) = new ASTTypeNPC((yylsp[(1) - (1)]));;} + break; + + case 41: + + /* Line 1455 of yacc.c */ +#line 259 "ffscript.ypp" + {(yyval) = new ASTTypeLWpn((yylsp[(1) - (1)]));;} + break; + + case 42: + + /* Line 1455 of yacc.c */ +#line 260 "ffscript.ypp" + {(yyval) = new ASTTypeEWpn((yylsp[(1) - (1)]));;} + break; + + case 43: + + /* Line 1455 of yacc.c */ +#line 263 "ffscript.ypp" + { + ASTFuncDecl *fd = (ASTFuncDecl *)(yyvsp[(4) - (6)]); + ASTType *rettype = (ASTType *)(yyvsp[(1) - (6)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (6)]); + ASTBlock *block = (ASTBlock *)(yyvsp[(6) - (6)]); + fd->setName(name->getValue()); + delete name; + fd->setReturnType(rettype); + fd->setBlock(block); + (yyval)=fd;; + } + break; + + case 44: + + /* Line 1455 of yacc.c */ +#line 272 "ffscript.ypp" + { + ASTFuncDecl *fd = new ASTFuncDecl((yylsp[(1) - (5)])); + ASTType *rettype = (ASTType *)(yyvsp[(1) - (5)]); + ASTString *name = (ASTString *)(yyvsp[(2) - (5)]); + ASTBlock *block = (ASTBlock *)(yyvsp[(5) - (5)]); + fd->setName(name->getValue()); + delete name; + fd->setReturnType(rettype); + fd->setBlock(block); + (yyval)=fd;; + } + break; + + case 45: + + /* Line 1455 of yacc.c */ +#line 283 "ffscript.ypp" + { + ASTFuncDecl *fd = (ASTFuncDecl *)(yyvsp[(3) - (3)]); + fd->addParam((ASTVarDecl *)(yyvsp[(1) - (3)])); + (yyval)=fd;; + } + break; + + case 46: + + /* Line 1455 of yacc.c */ +#line 286 "ffscript.ypp" + { + ASTFuncDecl *fd = new ASTFuncDecl((yylsp[(1) - (1)])); + fd->addParam((ASTVarDecl *)(yyvsp[(1) - (1)])); + (yyval)=fd;; + } + break; + + case 47: + + /* Line 1455 of yacc.c */ +#line 291 "ffscript.ypp" + {(yyval)=(yyvsp[(2) - (3)]);;} + break; + + case 48: + + /* Line 1455 of yacc.c */ +#line 292 "ffscript.ypp" + {(yyval) = new ASTBlock((yylsp[(1) - (2)]));;} + break; + + case 49: + + /* Line 1455 of yacc.c */ +#line 295 "ffscript.ypp" + { + ASTBlock *block = (ASTBlock *)(yyvsp[(1) - (2)]); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(2) - (2)]); + block->addStatement(stmt); + (yyval) = block;; + } + break; + + case 50: + + /* Line 1455 of yacc.c */ +#line 299 "ffscript.ypp" + { + ASTBlock *block = new ASTBlock((yylsp[(1) - (1)])); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(1) - (1)]); + block->addStatement(stmt); + (yyval) = block;; + } + break; + + case 51: + + /* Line 1455 of yacc.c */ +#line 305 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 52: + + /* Line 1455 of yacc.c */ +#line 306 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 53: + + /* Line 1455 of yacc.c */ +#line 307 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 54: + + /* Line 1455 of yacc.c */ +#line 308 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (2)]);;} + break; + + case 55: + + /* Line 1455 of yacc.c */ +#line 309 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 56: + + /* Line 1455 of yacc.c */ +#line 310 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 57: + + /* Line 1455 of yacc.c */ +#line 311 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 58: + + /* Line 1455 of yacc.c */ +#line 312 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (2)]);;} + break; + + case 59: + + /* Line 1455 of yacc.c */ +#line 313 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 60: + + /* Line 1455 of yacc.c */ +#line 314 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 61: + + /* Line 1455 of yacc.c */ +#line 315 "ffscript.ypp" + {(yyval) = new ASTStmtEmpty((yylsp[(1) - (1)]));;} + break; + + case 62: + + /* Line 1455 of yacc.c */ +#line 316 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (2)]);;} + break; + + case 63: + + /* Line 1455 of yacc.c */ +#line 317 "ffscript.ypp" + {(yyval) = new ASTStmtBreak((yylsp[(1) - (2)]));;} + break; + + case 64: + + /* Line 1455 of yacc.c */ +#line 318 "ffscript.ypp" + {(yyval) = new ASTStmtContinue((yylsp[(1) - (2)]));;} + break; + + case 65: + + /* Line 1455 of yacc.c */ +#line 321 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 66: + + /* Line 1455 of yacc.c */ +#line 322 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 67: + + /* Line 1455 of yacc.c */ +#line 323 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 68: + + /* Line 1455 of yacc.c */ +#line 324 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 69: + + /* Line 1455 of yacc.c */ +#line 325 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 70: + + /* Line 1455 of yacc.c */ +#line 326 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 71: + + /* Line 1455 of yacc.c */ +#line 327 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 72: + + /* Line 1455 of yacc.c */ +#line 328 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 73: + + /* Line 1455 of yacc.c */ +#line 329 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 74: + + /* Line 1455 of yacc.c */ +#line 330 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 75: + + /* Line 1455 of yacc.c */ +#line 331 "ffscript.ypp" + {(yyval) = new ASTStmtEmpty(noloc);;} + break; + + case 76: + + /* Line 1455 of yacc.c */ +#line 332 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 77: + + /* Line 1455 of yacc.c */ +#line 333 "ffscript.ypp" + {(yyval) = new ASTStmtBreak((yylsp[(1) - (1)]));;} + break; + + case 78: + + /* Line 1455 of yacc.c */ +#line 334 "ffscript.ypp" + {(yyval) = new ASTStmtContinue((yylsp[(1) - (1)]));;} + break; + + case 79: + + /* Line 1455 of yacc.c */ +#line 337 "ffscript.ypp" + {SHORTCUT(ASTExprPlus,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 80: + + /* Line 1455 of yacc.c */ +#line 338 "ffscript.ypp" + {SHORTCUT(ASTExprMinus,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 81: + + /* Line 1455 of yacc.c */ +#line 339 "ffscript.ypp" + {SHORTCUT(ASTExprTimes,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 82: + + /* Line 1455 of yacc.c */ +#line 340 "ffscript.ypp" + {SHORTCUT(ASTExprDivide,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 83: + + /* Line 1455 of yacc.c */ +#line 341 "ffscript.ypp" + {SHORTCUT(ASTExprAnd,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 84: + + /* Line 1455 of yacc.c */ +#line 342 "ffscript.ypp" + {SHORTCUT(ASTExprOr,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 85: + + /* Line 1455 of yacc.c */ +#line 343 "ffscript.ypp" + {SHORTCUT(ASTExprBitAnd,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 86: + + /* Line 1455 of yacc.c */ +#line 344 "ffscript.ypp" + {SHORTCUT(ASTExprBitOr,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 87: + + /* Line 1455 of yacc.c */ +#line 345 "ffscript.ypp" + {SHORTCUT(ASTExprBitXor,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 88: + + /* Line 1455 of yacc.c */ +#line 346 "ffscript.ypp" + {SHORTCUT(ASTExprLShift,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 89: + + /* Line 1455 of yacc.c */ +#line 347 "ffscript.ypp" + {SHORTCUT(ASTExprRShift,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 90: + + /* Line 1455 of yacc.c */ +#line 348 "ffscript.ypp" + {SHORTCUT(ASTExprModulo,(yyvsp[(1) - (3)]),(yyvsp[(3) - (3)]),(yyval),(yylsp[(1) - (3)]),(yylsp[(2) - (3)])) ;} + break; + + case 91: + + /* Line 1455 of yacc.c */ +#line 352 "ffscript.ypp" + {(yyval) = new ASTStmtAssign((ASTStmt *)(yyvsp[(1) - (3)]), (ASTExpr *)(yyvsp[(3) - (3)]),(yylsp[(1) - (3)]));;} + break; + + case 92: + + /* Line 1455 of yacc.c */ +#line 355 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 93: + + /* Line 1455 of yacc.c */ +#line 356 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 94: + + /* Line 1455 of yacc.c */ +#line 359 "ffscript.ypp" + { + ASTString *lval = (ASTString *)(yyvsp[(1) - (3)]); + ASTString *rval = (ASTString *)(yyvsp[(3) - (3)]); + (yyval) = new ASTExprDot(lval->getValue(), rval->getValue(),(yylsp[(1) - (3)])); + delete lval; + delete rval;; + } + break; + + case 95: + + /* Line 1455 of yacc.c */ +#line 363 "ffscript.ypp" + { + ASTString *name = (ASTString *)(yyvsp[(1) - (4)]); + ASTExpr *num = (ASTExpr *)(yyvsp[(3) - (4)]); + ASTExprArray *ar = new ASTExprArray("", name->getValue(), (yylsp[(1) - (4)])); + ar->setIndex(num); + (yyval) = ar; + delete name;; + } + break; + + case 96: + + /* Line 1455 of yacc.c */ +#line 369 "ffscript.ypp" + { + ASTString *name = (ASTString *)(yyvsp[(1) - (6)]); + ASTString *name2 = (ASTString *)(yyvsp[(3) - (6)]); + ASTExpr *num = (ASTExpr *)(yyvsp[(5) - (6)]); + ASTExprArray *ar = new ASTExprArray(name->getValue(), name2->getValue(), (yylsp[(1) - (6)])); + ar->setIndex(num); + (yyval) = ar; + delete name; + delete name2;; + } + break; + + case 97: + + /* Line 1455 of yacc.c */ +#line 377 "ffscript.ypp" + { + ASTString *rval = (ASTString *)(yyvsp[(1) - (1)]); + (yyval) = new ASTExprDot("", rval->getValue(),(yylsp[(1) - (1)])); + delete rval;; + } + break; + + case 98: + + /* Line 1455 of yacc.c */ +#line 380 "ffscript.ypp" + { + ASTExpr *id = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTString *rval = (ASTString *)(yyvsp[(3) - (3)]); + (yyval) = new ASTExprArrow(id, rval->getValue(), (yylsp[(1) - (3)])); + delete rval;; + } + break; + + case 99: + + /* Line 1455 of yacc.c */ +#line 384 "ffscript.ypp" + { + ASTExpr *id = (ASTExpr *)(yyvsp[(1) - (6)]); + ASTString *rval = (ASTString *)(yyvsp[(3) - (6)]); + ASTExpr *num = (ASTExpr *)(yyvsp[(5) - (6)]); + ASTExprArrow *res = new ASTExprArrow(id, rval->getValue(), (yylsp[(1) - (6)])); + res->setIndex(num); + (yyval) = res;; + } + break; + + case 100: + + /* Line 1455 of yacc.c */ +#line 392 "ffscript.ypp" + { + ASTLogExpr *e = new ASTExprOr((yylsp[(2) - (3)])); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 101: + + /* Line 1455 of yacc.c */ +#line 398 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 102: + + /* Line 1455 of yacc.c */ +#line 401 "ffscript.ypp" + { + ASTLogExpr *e = new ASTExprAnd((yylsp[(2) - (3)])); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 103: + + /* Line 1455 of yacc.c */ +#line 407 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 104: + + /* Line 1455 of yacc.c */ +#line 410 "ffscript.ypp" + { + ASTBitExpr *e = new ASTExprBitOr((yylsp[(2) - (3)])); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 105: + + /* Line 1455 of yacc.c */ +#line 416 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 106: + + /* Line 1455 of yacc.c */ +#line 419 "ffscript.ypp" + { + ASTBitExpr *e = new ASTExprBitXor((yylsp[(2) - (3)])); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 107: + + /* Line 1455 of yacc.c */ +#line 425 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 108: + + /* Line 1455 of yacc.c */ +#line 428 "ffscript.ypp" + { + ASTBitExpr *e = new ASTExprBitAnd((yylsp[(2) - (3)])); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 109: + + /* Line 1455 of yacc.c */ +#line 434 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 110: + + /* Line 1455 of yacc.c */ +#line 437 "ffscript.ypp" + { + ASTRelExpr *e = (ASTRelExpr *)(yyvsp[(2) - (3)]); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 111: + + /* Line 1455 of yacc.c */ +#line 443 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 112: + + /* Line 1455 of yacc.c */ +#line 446 "ffscript.ypp" + { + ASTShiftExpr *e = (ASTShiftExpr *)(yyvsp[(2) - (3)]); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 113: + + /* Line 1455 of yacc.c */ +#line 452 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 114: + + /* Line 1455 of yacc.c */ +#line 455 "ffscript.ypp" + {(yyval) = new ASTExprLShift((yylsp[(1) - (1)]));;} + break; + + case 115: + + /* Line 1455 of yacc.c */ +#line 456 "ffscript.ypp" + {(yyval) = new ASTExprRShift((yylsp[(1) - (1)]));;} + break; + + case 116: + + /* Line 1455 of yacc.c */ +#line 459 "ffscript.ypp" + {(yyval) = new ASTExprGT((yylsp[(1) - (1)]));;} + break; + + case 117: + + /* Line 1455 of yacc.c */ +#line 460 "ffscript.ypp" + {(yyval) = new ASTExprGE((yylsp[(1) - (1)]));;} + break; + + case 118: + + /* Line 1455 of yacc.c */ +#line 461 "ffscript.ypp" + {(yyval) = new ASTExprLT((yylsp[(1) - (1)]));;} + break; + + case 119: + + /* Line 1455 of yacc.c */ +#line 462 "ffscript.ypp" + {(yyval) = new ASTExprLE((yylsp[(1) - (1)]));;} + break; + + case 120: + + /* Line 1455 of yacc.c */ +#line 463 "ffscript.ypp" + {(yyval) = new ASTExprEQ((yylsp[(1) - (1)]));;} + break; + + case 121: + + /* Line 1455 of yacc.c */ +#line 464 "ffscript.ypp" + {(yyval) = new ASTExprNE((yylsp[(1) - (1)]));;} + break; + + case 122: + + /* Line 1455 of yacc.c */ +#line 467 "ffscript.ypp" + { + ASTAddExpr *e = (ASTAddExpr *)(yyvsp[(2) - (3)]); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 123: + + /* Line 1455 of yacc.c */ +#line 473 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 124: + + /* Line 1455 of yacc.c */ +#line 476 "ffscript.ypp" + {(yyval) = new ASTExprPlus((yylsp[(1) - (1)]));;} + break; + + case 125: + + /* Line 1455 of yacc.c */ +#line 477 "ffscript.ypp" + {(yyval) = new ASTExprMinus((yylsp[(1) - (1)]));;} + break; + + case 126: + + /* Line 1455 of yacc.c */ +#line 480 "ffscript.ypp" + { + ASTMultExpr *e = (ASTMultExpr *)(yyvsp[(2) - (3)]); + ASTExpr *left = (ASTExpr *)(yyvsp[(1) - (3)]); + ASTExpr *right = (ASTExpr *)(yyvsp[(3) - (3)]); + e->setFirstOperand(left); + e->setSecondOperand(right); + (yyval)=e;; + } + break; + + case 127: + + /* Line 1455 of yacc.c */ +#line 486 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 128: + + /* Line 1455 of yacc.c */ +#line 489 "ffscript.ypp" + {(yyval) = new ASTExprTimes((yylsp[(1) - (1)]));;} + break; + + case 129: + + /* Line 1455 of yacc.c */ +#line 490 "ffscript.ypp" + {(yyval) = new ASTExprDivide((yylsp[(1) - (1)]));;} + break; + + case 130: + + /* Line 1455 of yacc.c */ +#line 491 "ffscript.ypp" + {(yyval) = new ASTExprModulo((yylsp[(1) - (1)]));;} + break; + + case 131: + + /* Line 1455 of yacc.c */ +#line 494 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprNot((yylsp[(1) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(2) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 132: + + /* Line 1455 of yacc.c */ +#line 498 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprNegate((yylsp[(1) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(2) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 133: + + /* Line 1455 of yacc.c */ +#line 502 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprBitNot((yylsp[(1) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(2) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 134: + + /* Line 1455 of yacc.c */ +#line 506 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 135: + + /* Line 1455 of yacc.c */ +#line 509 "ffscript.ypp" + {(yyval)=(yyvsp[(2) - (3)]);;} + break; + + case 136: + + /* Line 1455 of yacc.c */ +#line 510 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 137: + + /* Line 1455 of yacc.c */ +#line 511 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprIncrement((yylsp[(2) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(1) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 138: + + /* Line 1455 of yacc.c */ +#line 515 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprPreIncrement((yylsp[(1) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(2) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 139: + + /* Line 1455 of yacc.c */ +#line 519 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprDecrement((yylsp[(2) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(1) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 140: + + /* Line 1455 of yacc.c */ +#line 523 "ffscript.ypp" + { + ASTUnaryExpr *e = new ASTExprPreDecrement((yylsp[(1) - (2)])); + ASTExpr *op = (ASTExpr *)(yyvsp[(2) - (2)]); + e->setOperand(op); + (yyval)=e;; + } + break; + + case 141: + + /* Line 1455 of yacc.c */ +#line 527 "ffscript.ypp" + { + ASTFloat *val = (ASTFloat *)(yyvsp[(1) - (1)]); + (yyval) = new ASTNumConstant(val,(yylsp[(1) - (1)]));; + } + break; + + case 142: + + /* Line 1455 of yacc.c */ +#line 529 "ffscript.ypp" + { + ASTString *as = (ASTString *)(yyvsp[(1) - (1)]); + char val[15]; + sprintf(val, "%d", as->getValue().at(1)); + (yyval) = new ASTNumConstant(new ASTFloat(val,0,(yylsp[(1) - (1)])),(yylsp[(1) - (1)]));; + } + break; + + case 143: + + /* Line 1455 of yacc.c */ +#line 533 "ffscript.ypp" + {(yyval) = (yyvsp[(1) - (1)]);;} + break; + + case 144: + + /* Line 1455 of yacc.c */ +#line 534 "ffscript.ypp" + {(yyval)=(yyvsp[(1) - (1)]);;} + break; + + case 145: + + /* Line 1455 of yacc.c */ +#line 537 "ffscript.ypp" + {(yyval) = new ASTBoolConstant(true,(yylsp[(1) - (1)]));;} + break; + + case 146: + + /* Line 1455 of yacc.c */ +#line 538 "ffscript.ypp" + {(yyval) = new ASTBoolConstant(false,(yylsp[(1) - (1)]));;} + break; + + case 147: + + /* Line 1455 of yacc.c */ +#line 541 "ffscript.ypp" + { + ASTFuncCall *fc = (ASTFuncCall *)(yyvsp[(3) - (4)]); + ASTExpr *name = (ASTExpr *)(yyvsp[(1) - (4)]); + fc->setName(name); + (yyval)=fc;; + } + break; + + case 148: + + /* Line 1455 of yacc.c */ +#line 545 "ffscript.ypp" + { + ASTFuncCall *fc = new ASTFuncCall((yylsp[(1) - (3)])); + ASTExpr *name = (ASTExpr *)(yyvsp[(1) - (3)]); + fc->setName(name); + (yyval)=fc;; + } + break; + + case 149: + + /* Line 1455 of yacc.c */ +#line 551 "ffscript.ypp" + { + ASTFuncCall *fc = (ASTFuncCall *)(yyvsp[(3) - (3)]); + ASTExpr *e = (ASTExpr *)(yyvsp[(1) - (3)]); + fc->addParam(e); + (yyval) = fc;; + } + break; + + case 150: + + /* Line 1455 of yacc.c */ +#line 555 "ffscript.ypp" + { + ASTFuncCall *fc = new ASTFuncCall((yylsp[(1) - (1)])); + ASTExpr *e = (ASTExpr *)(yyvsp[(1) - (1)]); + fc->addParam(e); + (yyval) = fc;; + } + break; + + case 151: + + /* Line 1455 of yacc.c */ +#line 561 "ffscript.ypp" + { + ASTStmt *prec = (ASTStmt *)(yyvsp[(3) - (9)]); + ASTExpr *term = (ASTExpr *)(yyvsp[(5) - (9)]); + ASTStmt *incr = (ASTExpr *)(yyvsp[(7) - (9)]); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(9) - (9)]); + (yyval) = new ASTStmtFor(prec,term,incr,stmt,(yylsp[(1) - (9)]));; + } + break; + + case 152: + + /* Line 1455 of yacc.c */ +#line 568 "ffscript.ypp" + { + ASTExpr *cond = (ASTExpr *)(yyvsp[(3) - (5)]); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(5) - (5)]); + (yyval) = new ASTStmtWhile(cond,stmt,(yylsp[(1) - (5)]));; + } + break; + + case 153: + + /* Line 1455 of yacc.c */ +#line 572 "ffscript.ypp" + { + ASTExpr *cond = (ASTExpr *)(yyvsp[(5) - (6)]); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(2) - (6)]); + (yyval) = new ASTStmtDo(cond,stmt,(yylsp[(1) - (6)]));; + } + break; + + case 154: + + /* Line 1455 of yacc.c */ +#line 576 "ffscript.ypp" + { + ASTExpr *cond = (ASTExpr *)(yyvsp[(3) - (5)]); + ASTStmt *stmt = (ASTStmt *)(yyvsp[(5) - (5)]); + (yyval) = new ASTStmtIf(cond,stmt,(yylsp[(1) - (5)]));; + } + break; + + case 155: + + /* Line 1455 of yacc.c */ +#line 579 "ffscript.ypp" + { + ASTExpr *cond = (ASTExpr *)(yyvsp[(3) - (7)]); + ASTStmt *ifstmt = (ASTStmt *)(yyvsp[(5) - (7)]); + ASTStmt *elsestmt = (ASTStmt *)(yyvsp[(7) - (7)]); + (yyval) = new ASTStmtIfElse(cond,ifstmt,elsestmt,(yylsp[(1) - (7)]));; + } + break; + + case 156: + + /* Line 1455 of yacc.c */ +#line 585 "ffscript.ypp" + {(yyval) = new ASTStmtReturnVal((ASTExpr *)(yyvsp[(2) - (2)]),(yylsp[(1) - (2)]));;} + break; + + case 157: + + /* Line 1455 of yacc.c */ +#line 586 "ffscript.ypp" + {(yyval) = new ASTStmtReturn((yylsp[(1) - (1)]));;} + break; + + + + /* Line 1455 of yacc.c */ +#line 3102 "y.tab.cpp" + + default: + break; + } + + YY_SYMBOL_PRINT("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK(yylen); + yylen = 0; + YY_STACK_PRINT(yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + + if(0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + + /*------------------------------------. + | yyerrlab -- here on detecting error | + `------------------------------------*/ +yyerrlab: + + /* If not already recovering from an error, report this error. */ + if(!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror(YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error(0, yystate, yychar); + + if(yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + + if(!(yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + + if(yymsg != yymsgbuf) + YYSTACK_FREE(yymsg); + + yymsg = (char *) YYSTACK_ALLOC(yyalloc); + + if(yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if(0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error(yymsg, yystate, yychar); + yyerror(yymsg); + } + else + { + yyerror(YY_("syntax error")); + + if(yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + yyerror_range[0] = yylloc; + + if(yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if(yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if(yychar == YYEOF) + YYABORT; + } + else + { + yydestruct("Error: discarding", + yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + + /*---------------------------------------------------. + | yyerrorlab -- error raised explicitly by YYERROR. | + `---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if(/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[0] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK(yylen); + yylen = 0; + YY_STACK_PRINT(yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + + /*-------------------------------------------------------------. + | yyerrlab1 -- common code for both syntax error and YYERROR. | + `-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for(;;) + { + yyn = yypact[yystate]; + + if(yyn != YYPACT_NINF) + { + yyn += YYTERROR; + + if(0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + + if(0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if(yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct("Error: popping", + yystos[yystate], yyvsp, yylsp); + YYPOPSTACK(1); + yystate = *yyssp; + YY_STACK_PRINT(yyss, yyssp); + } + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT(yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + + /*-------------------------------------. + | yyacceptlab -- YYACCEPT comes here. | + `-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + + /*-----------------------------------. + | yyabortlab -- YYABORT comes here. | + `-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE + /*-------------------------------------------------. + | yyexhaustedlab -- memory exhaustion comes here. | + `-------------------------------------------------*/ +yyexhaustedlab: + yyerror(YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + + if(yychar != YYEMPTY) + yydestruct("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc); + + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK(yylen); + YY_STACK_PRINT(yyss, yyssp); + + while(yyssp != yyss) + { + yydestruct("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp); + YYPOPSTACK(1); + } + +#ifndef yyoverflow + + if(yyss != yyssa) + YYSTACK_FREE(yyss); + +#endif +#if YYERROR_VERBOSE + + if(yymsg != yymsgbuf) + YYSTACK_FREE(yymsg); + +#endif + /* Make sure YYID is used. */ + return YYID(yyresult); +} + + + +/* Line 1675 of yacc.c */ +#line 589 "ffscript.ypp" + + +/* programs */ + +void yyerror(const char *s) +{ + char temp[512]; + sprintf(temp, "line %d: %s, on token %s", yylineno, s, yytext); + box_out(temp); + box_eol(); +} + +int go(const char *f) +{ + yyin = NULL; + resetLexer(); + yyin = fopen(f, "r"); + + if(!yyin) + { + box_out("Can't open input file"); + box_eol(); + return -1; + } + + curfilename = string(f); + int result = yyparse(); + fclose(yyin); + return result; +} + + diff --git a/src/parser/y.tab.hpp b/src/parser/y.tab.hpp new file mode 100644 index 0000000000..961c74db61 --- /dev/null +++ b/src/parser/y.tab.hpp @@ -0,0 +1,142 @@ +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE +/* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ +enum yytokentype +{ + SCRIPT = 258, + FLOAT = 259, + FOR = 260, + BOOL = 261, + VOID = 262, + IF = 263, + ELSE = 264, + RETURN = 265, + IMPORT = 266, + TRUE = 267, + FALSE = 268, + WHILE = 269, + FFC = 270, + ITEM = 271, + ITEMCLASS = 272, + GLOBAL = 273, + BREAK = 274, + CONTINUE = 275, + CONST = 276, + DO = 277, + NPC = 278, + LWEAPON = 279, + EWEAPON = 280, + ASSIGN = 281, + SEMICOLON = 282, + COMMA = 283, + LBRACKET = 284, + RBRACKET = 285, + LPAREN = 286, + RPAREN = 287, + DOT = 288, + LBRACE = 289, + RBRACE = 290, + ARROW = 291, + NUMBER = 292, + PLUSASSIGN = 293, + MINUSASSIGN = 294, + TIMESASSIGN = 295, + DIVIDEASSIGN = 296, + ANDASSIGN = 297, + ORASSIGN = 298, + BITANDASSIGN = 299, + BITORASSIGN = 300, + BITXORASSIGN = 301, + MODULOASSIGN = 302, + LSHIFTASSIGN = 303, + RSHIFTASSIGN = 304, + IDENTIFIER = 305, + QUOTEDSTRING = 306, + SINGLECHAR = 307, + RSHIFT = 308, + LSHIFT = 309, + BITXOR = 310, + BITOR = 311, + BITAND = 312, + OR = 313, + AND = 314, + BITNOT = 315, + NOT = 316, + DECREMENT = 317, + INCREMENT = 318, + NE = 319, + EQ = 320, + GT = 321, + GE = 322, + LT = 323, + LE = 324, + MINUS = 325, + PLUS = 326, + DIVIDE = 327, + TIMES = 328, + MODULO = 329 +}; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + +extern YYSTYPE yylval; + +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +} YYLTYPE; +# define yyltype YYLTYPE /* obsolescent; will be withdrawn */ +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +extern YYLTYPE yylloc; + diff --git a/src/particles.cpp b/src/particles.cpp new file mode 100644 index 0000000000..85afe25679 --- /dev/null +++ b/src/particles.cpp @@ -0,0 +1,108 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +/**********************************/ +/********** Item Class **********/ +/**********************************/ + +#include "precompiled.h" //always first + +#include "particles.h" + +particle::~particle() +{ +} + +bool particle::animate(int index) +{ + //these are here to bypass compiler warnings about unused arguments + index=index; + return true; +} + +void particle::draw(BITMAP *dest) +{ + int tcs=cset; + tcs &= 15; + tcs <<= CSET_SHFT; + putpixel(dest, x, y+yofs, tcs+color); +} + +particle::particle(fix X,fix Y,int L,int CS,int C) : sprite() +{ + x=X; + y=Y; + layer=L; + cset=CS; + color=C; + yofs = 54; +} + + +pFaroresWindDust::pFaroresWindDust(fix X,fix Y,int L,int CS,int C, int T) : particle(X,Y,L,CS,C) +{ + initialized=false; + timer=T; +} + +bool pFaroresWindDust::animate(int index) +{ + index=index; + + if(!initialized) + { + os=step; + ot=timer; + initialized=true; + } + + step=os*(double)timer/(double)ot; + + if(timer>0) + { + --timer; + } + + move(step); + return (!timer); +} + +pTwilight::pTwilight(fix X,fix Y,int L,int CS,int C, int T) : particle(X,Y,L,CS,C) +{ + dir = up; + delay = T; +} + +bool pTwilight::animate(int index) +{ + index=index; + + if(delay>0) + { + delay--; + } + else + { + move(step); + } + + return (y<0)!=0; +} + + +/*** end of sprite.cc ***/ + diff --git a/src/particles.h b/src/particles.h new file mode 100644 index 0000000000..75dd87164e --- /dev/null +++ b/src/particles.h @@ -0,0 +1,56 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- + +#ifndef _PARTICLES_H_ +#define _PARTICLES_H_ + +#include "sprite.h" +#include "zdefs.h" + +class particle : public sprite +{ +public: + int layer, cset, color; + fix step; + particle(fix X,fix Y,int layer,int cset,int color); + virtual ~particle(); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; + +class pFaroresWindDust : public particle +{ +public: + fix os; + int ot; + int timer; + bool initialized; + pFaroresWindDust(fix X,fix Y,int layer,int cset,int color,int timer); + virtual bool animate(int index); +}; + +class pTwilight : public particle +{ +public: + int delay; + pTwilight(fix X,fix Y,int layer,int cset,int color, int delay); + virtual bool animate(int index); +}; + + + + +#endif +/*** end of sprite.cc ***/ + diff --git a/src/precompiled.cpp b/src/precompiled.cpp new file mode 100644 index 0000000000..444ea35a6a --- /dev/null +++ b/src/precompiled.cpp @@ -0,0 +1,4 @@ + + +#include "precompiled.h" + diff --git a/src/precompiled.h b/src/precompiled.h new file mode 100644 index 0000000000..d1669839b2 --- /dev/null +++ b/src/precompiled.h @@ -0,0 +1,37 @@ + +#pragma once + +#if defined(ZC_PCH) + +//globally remove extraneous bullshit +// + + +//allegro +#include "zc_alleg.h" + + +//c standard lib +#include +#include +#include +#include +#include +#include +#include + + +//c++ stl (these are already found in common headers) +#include +#include +#include +#include + + +//zc +#include "zc_malloc.h" + + + +#endif + diff --git a/src/qst.cpp b/src/qst.cpp new file mode 100644 index 0000000000..f1ca53ab6a --- /dev/null +++ b/src/qst.cpp @@ -0,0 +1,14239 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// qst.cc +// +// Code for loading '.qst' files in ZC and ZQuest. +// +//-------------------------------------------------------- + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include +#include +#include + +#include "encryption.h" +#include "mem_debug.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "colors.h" +#include "tiles.h" +#include "zsys.h" +#include "qst.h" +#include "zquest.h" +#include "defdata.h" +#include "subscr.h" +#include "font.h" +#include "zc_custom.h" +#include "sfx.h" +#include "md5.h" +#include "scoped_ptr.h" + + +#ifdef _MSC_VER + #define strncasecmp _strnicmp +#endif + +#ifndef _AL_MALLOC +#define _AL_MALLOC(a) _al_malloc(a) +#define _AL_FREE(a) _al_free(a) +#endif + +using std::string; +using std::pair; + +// extern bool debug; +extern int link_animation_speed; //lower is faster animation +extern std::vector TheMaps; +extern zcmap *ZCMaps; +extern MsgStr *MsgStrings; +extern DoorComboSet *DoorComboSets; +extern dmap *DMaps; +extern newcombo *combobuf; +extern byte *colordata; +//extern byte *tilebuf; +extern tiledata *newtilebuf; +extern byte *trashbuf; +extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; +extern comboclass *combo_class_buf; +extern guydata *guysbuf; +extern ZCHEATS zcheats; +extern zinitdata zinit; +extern char palnames[MAXLEVELS][17]; +extern int memrequested; +extern char *byte_conversion(int number, int format); +extern char *byte_conversion2(int number1, int number2, int format1, int format2); +string zScript; +std::map > ffcmap; +std::map > globalmap; +std::map > itemmap; + +bool combosread=false; +bool mapsread=false; +bool fixffcs=false; +bool fixpolsvoice=false; + +int memDBGwatch[8]= {0,0,0,0,0,0,0,0}; //So I can monitor memory crap + +//enum { qe_OK, qe_notfound, qe_invalid, qe_version, qe_obsolete, +// qe_missing, qe_internal, qe_pwd, qe_match, qe_minver }; + +extern combo_alias combo_aliases[MAXCOMBOALIASES]; +const char *qst_error[] = +{ + "OK","File not found","Invalid quest file", + "Version not supported","Obsolete version", + "Missing new data" , /* but let it pass in ZQuest */ + "Internal error occurred", "Invalid password", + "Doesn't match saved game", "New quest version; please restart game", + "Out of memory", "File Debug Mode" +}; + +//for legacy quests -DD +enum { ssiBOMB, ssiSWORD, ssiSHIELD, ssiCANDLE, ssiLETTER, ssiPOTION, ssiLETTERPOTION, ssiBOW, ssiARROW, ssiBOWANDARROW, ssiBAIT, ssiRING, ssiBRACELET, ssiMAP, + ssiCOMPASS, ssiBOSSKEY, ssiMAGICKEY, ssiBRANG, ssiWAND, ssiRAFT, ssiLADDER, ssiWHISTLE, ssiBOOK, ssiWALLET, ssiSBOMB, ssiHCPIECE, ssiAMULET, ssiFLIPPERS, + ssiHOOKSHOT, ssiLENS, ssiHAMMER, ssiBOOTS, ssiDINSFIRE, ssiFARORESWIND, ssiNAYRUSLOVE, ssiQUIVER, ssiBOMBBAG, ssiCBYRNA, ssiROCS, ssiHOVERBOOTS, + ssiSPINSCROLL, ssiCROSSSCROLL, ssiQUAKESCROLL, ssiWHISPRING, ssiCHARGERING, ssiPERILSCROLL, ssiWEALTHMEDAL, ssiHEARTRING, ssiMAGICRING, ssiSPINSCROLL2, + ssiQUAKESCROLL2, ssiAGONY, ssiSTOMPBOOTS, ssiWHIMSICALRING, ssiPERILRING, ssiMAX + }; + +static byte deprecated_rules[QUESTRULES_SIZE]; + + +void delete_combo_aliases() +{ + for(int j(0); j<256; j++) + { + if(combo_aliases[j].combos != NULL) + { + delete[] combo_aliases[j].combos; + combo_aliases[j].combos=NULL; + } + + if(combo_aliases[j].csets != NULL) + { + delete[] combo_aliases[j].csets; + combo_aliases[j].csets=NULL; + } + } + +} + + +char *VerStr(int version) +{ + static char ver_str[12]; + sprintf(ver_str,"v%d.%02X",version>>8,version&0xFF); + return ver_str; +} + +char *byte_conversion(int number, int format) +{ + static char num_str[40]; + + if(format==-1) //auto + { + format=1; //bytes + + if(number>1024) + { + format=2; //kilobytes + } + + if(number>1024*1024) + { + format=3; //megabytes + } + + if(number>1024*1024*1024) + { + format=4; //gigabytes (dude, what are you doing?) + } + } + + switch(format) + { + case 1: //bytes + sprintf(num_str,"%db",number); + break; + + case 2: //kilobytes + sprintf(num_str,"%.2fk",float(number)/1024); + break; + + case 3: //megabytes + sprintf(num_str,"%.2fM",float(number)/(1024*1024)); + break; + + case 4: //gigabytes + sprintf(num_str,"%.2fG",float(number)/(1024*1024*1024)); + break; + + default: + exit(1); + break; + } + + return num_str; +} + +char *byte_conversion2(int number1, int number2, int format1, int format2) +{ + static char num_str1[40]; + static char num_str2[40]; + static char num_str[80]; + + if(format1==-1) //auto + { + format1=1; //bytes + + if(number1>1024) + { + format1=2; //kilobytes + } + + if(number1>1024*1024) + { + format1=3; //megabytes + } + + if(number1>1024*1024*1024) + { + format1=4; //gigabytes (dude, what are you doing?) + } + } + + if(format2==-1) //auto + { + format2=1; //bytes + + if(number2>1024) + { + format2=2; //kilobytes + } + + if(number2>1024*1024) + { + format2=3; //megabytes + } + + if(number2>1024*1024*1024) + { + format2=4; //gigabytes (dude, what are you doing?) + } + } + + switch(format1) + { + case 1: //bytes + sprintf(num_str1,"%db",number1); + break; + + case 2: //kilobytes + sprintf(num_str1,"%.2fk",float(number1)/1024); + break; + + case 3: //megabytes + sprintf(num_str1,"%.2fM",float(number1)/(1024*1024)); + break; + + case 4: //gigabytes + sprintf(num_str1,"%.2fG",float(number1)/(1024*1024*1024)); + break; + + default: + exit(1); + break; + } + + switch(format2) + { + case 1: //bytes + sprintf(num_str2,"%db",number2); + break; + + case 2: //kilobytes + sprintf(num_str2,"%.2fk",float(number2)/1024); + break; + + case 3: //megabytes + sprintf(num_str2,"%.2fM",float(number2)/(1024*1024)); + break; + + case 4: //gigabytes + sprintf(num_str2,"%.2fG",float(number2)/(1024*1024*1024)); + break; + + default: + exit(1); + break; + } + + sprintf(num_str, "%s/%s", num_str1, num_str2); + return num_str; +} + +char *ordinal(int num) +{ + static const char *ending[4] = {"st","nd","rd","th"}; + static char ord_str[8]; + + char *end; + int t=(num%100)/10; + int n=num%10; + + if(n>=1 && n<4 && t!=1) + end = (char *)ending[n-1]; + else + end = (char *)ending[3]; + + sprintf(ord_str,"%d%s",num%10000,end); + return ord_str; +} + +int get_version_and_build(PACKFILE *f, word *version, word *build) +{ + int ret; + *version=0; + *build=0; + byte temp_map_count=map_count; + byte temp_midi_flags[MIDIFLAGS_SIZE]; + memcpy(temp_midi_flags, midi_flags, MIDIFLAGS_SIZE); + + zquestheader tempheader; + + if(!f) + { + return qe_invalid; + } + + ret=readheader(f, &tempheader, true); + + if(ret) + { + return ret; + } + + map_count=temp_map_count; + memcpy(midi_flags, temp_midi_flags, MIDIFLAGS_SIZE); + *version=tempheader.zelda_version; + *build=tempheader.build; + return 0; +} + + +bool find_section(PACKFILE *f, long section_id_requested) +{ + + if(!f) + { + return false; + } + + long section_id_read; + bool catchup=false; + word dummy; + byte tempbyte; + char tempbuf[65536]; + + + switch(section_id_requested) + { + case ID_RULES: + case ID_STRINGS: + case ID_MISC: + case ID_TILES: + case ID_COMBOS: + case ID_CSETS: + case ID_MAPS: + case ID_DMAPS: + case ID_DOORS: + case ID_ITEMS: + case ID_WEAPONS: + case ID_COLORS: + case ID_ICONS: + case ID_INITDATA: + case ID_GUYS: + case ID_MIDIS: + case ID_CHEATS: + break; + + default: + al_trace("Bad section requested!\n"); + return false; + break; + } + + dword section_size; + + //section id + if(!p_mgetl(§ion_id_read,f,true)) + { + return false; + } + + while(!pack_feof(f)) + { + switch(section_id_read) + { + case ID_RULES: + case ID_STRINGS: + case ID_MISC: + case ID_TILES: + case ID_COMBOS: + case ID_CSETS: + case ID_MAPS: + case ID_DMAPS: + case ID_DOORS: + case ID_ITEMS: + case ID_WEAPONS: + case ID_COLORS: + case ID_ICONS: + case ID_INITDATA: + case ID_GUYS: + case ID_MIDIS: + case ID_CHEATS: + catchup=false; + break; + + default: + break; + } + + + while(catchup) + { + //section id + section_id_read=(section_id_read<<8); + + if(!p_getc(&tempbyte,f,true)) + { + return false; + } + + section_id_read+=tempbyte; + } + + if(section_id_read==section_id_requested) + { + return true; + } + else + { + //section version info + if(!p_igetw(&dummy,f,true)) + { + return false; + } + + if(!p_igetw(&dummy,f,true)) + { + return false; + } + + //section size + if(!p_igetl(§ion_size,f,true)) + { + return false; + } + + //pack_fseek(f, section_size); + while(section_size>65535) + { + pfread(tempbuf,65535,f,true); + tempbuf[65535]=0; + section_size-=65535; + } + + if(section_size>0) + { + pfread(tempbuf,section_size,f,true); + tempbuf[section_size]=0; + } + } + + //section id + if(!p_mgetl(§ion_id_read,f,true)) + { + return false; + } + } + + return false; +} + + + + + +bool valid_zqt(PACKFILE *f) +{ + + //word tiles_used; + //word combos_used; + //open the file + //PACKFILE *f = pack_fopen(path, F_READ_PACKED); + if(!f) + return false; + + //for now, everything else is valid + return true; + + /*short version; + byte build; + + //read the version and make sure it worked + if(!p_igetw(&version,f,true)) + { + goto error; + } + + //read the build and make sure it worked + if(!p_getc(&build,f,true)) + goto error; + + //read the tile info and make sure it worked + if(!p_igetw(&tiles_used,f,true)) + { + goto error; + } + + for (int i=0; i1) //dungeon templates + { + for (int i=0; itemplatepath[0]==0) + { + filename=(char *)zc_malloc(23); + sprintf(filename, "qst.dat#NESQST_NEW_QST"); + } + else + { + filename=Header->templatepath; + } + + f=open_quest_file(&open_error, filename, deletefilename, true, true,false); + + if(Header->templatepath[0]==0) + { + zc_free(filename); + } + + if(!f) + { + return false; + } + + if(validate) + { + if(!valid_zqt(f)) + { + jwin_alert("Error","Invalid Quest Template",NULL,NULL,"O&K",NULL,'k',0,lfont); + pack_fclose(f); + + //setPackfilePassword(NULL); + if(deletefilename[0]) + { + delete_file(deletefilename); + } + + return false; + } + } + + return f; +} + +bool init_section(zquestheader *Header, long section_id, miscQdata *Misc, zctune *tunes, bool validate) +{ + combosread=false; + mapsread=false; + fixffcs=false; + + switch(section_id) + { + case ID_RULES: + case ID_STRINGS: + case ID_MISC: + case ID_TILES: + case ID_COMBOS: + case ID_CSETS: + case ID_MAPS: + case ID_DMAPS: + case ID_DOORS: + case ID_ITEMS: + case ID_WEAPONS: + case ID_COLORS: + case ID_ICONS: + case ID_INITDATA: + case ID_GUYS: + case ID_MIDIS: + case ID_CHEATS: + case ID_ITEMDROPSETS: + case ID_FAVORITES: + break; + + default: + return false; + break; + } + + int ret; + word version, build; + PACKFILE *f=NULL; + + char deletefilename[1024]; + deletefilename[0]=0; + + //why is this here? + /* + if(colordata==NULL) + return false; + */ + + //setPackfilePassword(datapwd); + f=open_quest_template(Header, deletefilename, validate); + + if(!f) //no file, nothing to delete + { +// setPackfilePassword(NULL); + return false; + } + + ret=get_version_and_build(f, &version, &build); + + if(ret||(version==0)) + { + pack_fclose(f); + + if(deletefilename[0]) + { + delete_file(deletefilename); + } + +// setPackfilePassword(NULL); + return false; + } + + if(!find_section(f, section_id)) + { + al_trace("Can't find section!\n"); + pack_fclose(f); + + if(deletefilename[0]) + { + delete_file(deletefilename); + } + + //setPackfilePassword(NULL); + return false; + } + + switch(section_id) + { + case ID_RULES: + //rules + ret=readrules(f, Header, true); + break; + + case ID_STRINGS: + //strings + ret=readstrings(f, Header, true); + break; + + case ID_MISC: + //misc data + ret=readmisc(f, Header, Misc, true); + break; + + case ID_TILES: + //tiles + ret=readtiles(f, newtilebuf, Header, version, build, 0, NEWMAXTILES, true, true); + break; + + case ID_COMBOS: + //combos + clear_combos(); + ret=readcombos(f, Header, version, build, 0, MAXCOMBOS, true); + combosread=true; + break; + + case ID_COMBOALIASES: + //combos + ret=readcomboaliases(f, Header, version, build, true); + break; + + case ID_CSETS: + //color data + ret=readcolordata(f, Misc, version, build, 0, newerpdTOTAL, true); + break; + + case ID_MAPS: + //maps + ret=readmaps(f, Header, true); + mapsread=true; + break; + + case ID_DMAPS: + //dmaps + ret=readdmaps(f, Header, version, build, 0, MAXDMAPS, true); + break; + + case ID_DOORS: + //door combo sets + ret=readdoorcombosets(f, Header, true); + break; + + case ID_ITEMS: + //items + ret=readitems(f, version, build, true); + break; + + case ID_WEAPONS: + //weapons + ret=readweapons(f, Header, true); + break; + + case ID_COLORS: + //misc. colors + ret=readmisccolors(f, Header, Misc, true); + break; + + case ID_ICONS: + //game icons + ret=readgameicons(f, Header, Misc, true); + break; + + case ID_INITDATA: + //initialization data + ret=readinitdata(f, Header, true); + break; + + case ID_GUYS: + //guys + ret=readguys(f, Header, true); + break; + + case ID_MIDIS: + //midis + ret=readtunes(f, Header, tunes, true); + break; + + case ID_CHEATS: + //cheat codes + ret=readcheatcodes(f, Header, true); + break; + + case ID_ITEMDROPSETS: + //item drop sets + // Why is this one commented out? + //ret=readitemdropsets(f, (int)version, (word)build, true); + break; + + case ID_FAVORITES: + // favorite combos and aliases + ret=readfavorites(f, version, build, true); + break; + + default: + ret=-1; + break; + } + + pack_fclose(f); + + if(deletefilename[0]) + { + delete_file(deletefilename); + } + + //setPackfilePassword(NULL); + if(!ret) + { + return true; + } + + return false; +} + +bool init_tiles(bool validate, zquestheader *Header) +{ + return init_section(Header, ID_TILES, NULL, NULL, validate); +} + +bool init_combos(bool validate, zquestheader *Header) +{ + return init_section(Header, ID_COMBOS, NULL, NULL, validate); +} + +bool init_colordata(bool validate, zquestheader *Header, miscQdata *Misc) +{ + return init_section(Header, ID_CSETS, Misc, NULL, validate); +} + +bool reset_items(bool validate, zquestheader *Header) +{ + bool ret = init_section(Header, ID_ITEMS, NULL, NULL, validate); + + //Ignore this, but don't remove it + /* + if (ret) + for(int i=0; icolors.blueframe_tile = 20044; + Misc->colors.blueframe_cset = 0; + Misc->colors.triforce_tile = 23461; + Misc->colors.triforce_cset = 1; + Misc->colors.triframe_tile = 18752; + Misc->colors.triframe_cset = 1; + Misc->colors.overworld_map_tile = 16990; + Misc->colors.overworld_map_cset = 2; + Misc->colors.HCpieces_tile = 21160; + Misc->colors.HCpieces_cset = 8; + Misc->colors.dungeon_map_tile = 19651; + Misc->colors.dungeon_map_cset = 8; + return true; +} + +bool reset_doorcombosets(bool validate, zquestheader *Header) +{ + return init_section(Header, ID_DOORS, NULL, NULL, validate); +} + +int get_qst_buffers() +{ + memrequested+=(sizeof(mapscr)*MAPSCRS); + Z_message("Allocating map buffer (%s)... ", byte_conversion2(sizeof(mapscr)*MAPSCRS,memrequested,-1, -1)); + TheMaps.resize(MAPSCRS); + + for(int i(0); itrack[c].len = 0; + m->track[c].data = NULL; + } + + p_mgetw(&divisions,f,true); + m->divisions=divisions; + + for(c=0; ctrack[c].len=len; + + if(m->track[c].len > 0) + { + m->track[c].data = (byte*)read_block(f, m->track[c].len, 0, true); + + if(!m->track[c].data) + { + destroy_midi(m); + return NULL; + } + } + } + + LOCK_DATA(m, sizeof(MIDI)); + + for(c=0; ctrack[c].data) + { + LOCK_DATA(m->track[c].data, m->track[c].len); + } + } + + return m; +} + +void clear_combo(int i) +{ + memset(combobuf+i,0,sizeof(newcombo)); +} + +void clear_combos() +{ + for(int tmpcounter=0; tmpcountertitle[0]=0; + m->loop=1; + m->volume=144; + m->start=0; + m->loop_start=-1; + m->loop_end=-1; + if(m->midi) + { + destroy_midi(m->midi); + } + m->midi=NULL; +} + + +void reset_midis(zcmidi_ *m) +{ + for(int i=0; i6; j++) + { + if((j!=2)&&(j!=3)) + { + tempdcs.doorcombo_l[dt_bomb][j]=TheMaps[map*MAPSCRS+scr].data[doortranslations_l[dt_bomb][j]]; + tempdcs.doorcset_l[dt_bomb][j]=TheMaps[map*MAPSCRS+scr].cset[doortranslations_l[dt_bomb][j]]; + } + } + + tempdcs.bombdoorcombo_l[0]=0; + tempdcs.bombdoorcset_l[0]=tdcmbcset(map,scr,115); + tempdcs.bombdoorcombo_l[1]=tdcmbdat(map,scr,115); + tempdcs.bombdoorcset_l[1]=tdcmbcset(map,scr,115); + tempdcs.bombdoorcombo_l[2]=0; + tempdcs.bombdoorcset_l[2]=tdcmbcset(map,scr,115); + tempdcs.walkthroughcombo[2]=tdcmbdat(map,scr,34); + tempdcs.walkthroughcset[2]=tdcmbdat(map,scr,34); + + //right + for(int i=0; i<9; i++) + { + for(int j=0; j<6; j++) + { + tempdcs.doorcombo_r[i][j]=tdcmbdat(map,scr,doortranslations_r[i][j]); + tempdcs.doorcset_r[i][j]=tdcmbcset(map,scr,doortranslations_r[i][j]); + } + } + + for(int j=0; j>6; j++) + { + if((j!=2)&&(j!=3)) + { + tempdcs.doorcombo_r[dt_bomb][j]=TheMaps[map*MAPSCRS+scr].data[doortranslations_r[dt_bomb][j]]; + tempdcs.doorcset_r[dt_bomb][j]=TheMaps[map*MAPSCRS+scr].cset[doortranslations_r[dt_bomb][j]]; + } + } + + tempdcs.bombdoorcombo_r[0]=0; + tempdcs.bombdoorcset_r[0]=tdcmbcset(map,scr,124); + tempdcs.bombdoorcombo_r[1]=tdcmbdat(map,scr,124); + tempdcs.bombdoorcset_r[1]=tdcmbcset(map,scr,124); + tempdcs.bombdoorcombo_r[2]=0; + tempdcs.bombdoorcset_r[2]=tdcmbcset(map,scr,124); + tempdcs.walkthroughcombo[3]=tdcmbdat(map,scr,34); + tempdcs.walkthroughcset[3]=tdcmbdat(map,scr,34); + + int k; + + for(k=0; k>15; + pwdkey = (pwdkey<<1)+t; + } + } + + memcpy(pwd,temp_pwd,30); +} + +bool check_questpwd(zquestheader *Header, char *pwd) +{ + cvs_MD5Context ctx; + unsigned char md5sum[16]; + + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)pwd, (unsigned)strlen(pwd)); + cvs_MD5Final(md5sum, &ctx); + + return (memcmp(Header->pwd_hash,md5sum,16)==0); + +} + + +int readheader(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + int dummy; + zquestheader tempheader; + memcpy(&tempheader, Header, sizeof(tempheader)); + char dummybuf[80]; + byte temp_map_count; + byte temp_midi_flags[MIDIFLAGS_SIZE]; + word version; + char temp_pwd[30], temp_pwd2[30]; + short temp_pwdkey; + cvs_MD5Context ctx; + memset(temp_midi_flags, 0, MIDIFLAGS_SIZE); + memset(&tempheader, 0, sizeof(tempheader)); + + if(!pfread(tempheader.id_str,sizeof(tempheader.id_str),f,true)) // first read old header + { + Z_message("Unable to read header string\n"); + return qe_invalid; + } + + // check header + if(strcmp(tempheader.id_str,QH_NEWIDSTR)) + { + if(strcmp(tempheader.id_str,QH_IDSTR)) + { + Z_message("Invalid header string: '%s' (was expecting '%s' or '%s')\n", tempheader.id_str, QH_IDSTR, QH_NEWIDSTR); + return qe_invalid; + } + } + + int templatepath_len=0; + + if(!strcmp(tempheader.id_str,QH_IDSTR)) //pre-1.93 version + { + byte padding; + + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&tempheader.zelda_version,f,true)) + { + return qe_invalid; + } + + if(tempheader.zelda_version > ZELDA_VERSION) + { + return qe_version; + } + + if(strcmp(tempheader.id_str,QH_IDSTR)) + { + return qe_invalid; + } + + if(bad_version(tempheader.zelda_version)) + { + return qe_obsolete; + } + + if(!p_igetw(&tempheader.internal,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.quest_number,f,true)) + { + return qe_invalid; + } + + if(!pfread(&quest_rules[0],2,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_map_count,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.old_str_count,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.data_flags[ZQ_TILES],f,true)) + { + return qe_invalid; + } + + if(!pfread(temp_midi_flags,4,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.data_flags[ZQ_CHEATS2],f,true)) + { + return qe_invalid; + } + + if(!pfread(dummybuf,14,f,true)) + { + return qe_invalid; + } + + if(!pfread(&quest_rules[2],2,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&dummybuf,f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.version,sizeof(tempheader.version),f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.title,sizeof(tempheader.title),f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.author,sizeof(tempheader.author),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_pwdkey,f,true)) + { + return qe_invalid; + } + + if(!pfread(temp_pwd,30,f,true)) + { + return qe_invalid; + } + + get_questpwd(temp_pwd, temp_pwdkey, temp_pwd2); + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)temp_pwd2, (unsigned)strlen(temp_pwd2)); + cvs_MD5Final(tempheader.pwd_hash, &ctx); + + if(tempheader.zelda_version < 0x177) // lacks new header stuff... + { + //memset(tempheader.minver,0,20); // char minver[9], byte build, byte foo[10] + // Not anymore... + memset(tempheader.minver,0,9); + tempheader.build=0; + tempheader.use_keyfile=0; + memset(tempheader.old_foo, 0, 9); + } + else + { + if(!pfread(tempheader.minver,sizeof(tempheader.minver),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.build,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.use_keyfile,f,true)) + { + return qe_invalid; + } + + if(!pfread(dummybuf,9,f,true)) + { + return qe_invalid; + } + } // starting at minver + + if(tempheader.zelda_version < 0x187) // lacks newer header stuff... + { + memset(&quest_rules[4],0,16); // word rules3..rules10 + } + else + { + if(!pfread(&quest_rules[4],16,f,true)) // read new header additions + { + return qe_invalid; // starting at rules3 + } + + if(tempheader.zelda_version <= 0x190) + { + set_bit(quest_rules,qr_MEANPLACEDTRAPS,0); + } + } + + if((tempheader.zelda_version < 0x192)|| + ((tempheader.zelda_version == 0x192)&&(tempheader.build<149))) + { + set_bit(quest_rules,qr_BRKNSHLDTILES,(get_bit(quest_rules,qr_BRKBLSHLDS_DEP))); + set_bit(deprecated_rules,qr_BRKBLSHLDS_DEP,1); + } + + if(tempheader.zelda_version >= 0x192) // lacks newer header stuff... + { + byte *mf=temp_midi_flags; + + if((tempheader.zelda_version == 0x192)&&(tempheader.build<178)) + { + mf=(byte*)dummybuf; + } + + if(!pfread(mf,32,f,true)) // read new header additions + { + return qe_invalid; // starting at foo2 + } + + if(!pfread(dummybuf,18,f,true)) // read new header additions + { + return qe_invalid; // starting at foo2 + } + } + + if((tempheader.zelda_version < 0x192)|| + ((tempheader.zelda_version == 0x192)&&(tempheader.build<145))) + { + memset(tempheader.templatepath,0,2048); + } + else + { + if(!pfread(tempheader.templatepath,280,f,true)) // read templatepath + { + return qe_invalid; + } + } + + if((tempheader.zelda_version < 0x192)|| + ((tempheader.zelda_version == 0x192)&&(tempheader.build<186))) + { + tempheader.use_keyfile=0; + } + } + else + { + //section id + if(!p_mgetl(&dummy,f,true)) + { + return qe_invalid; + } + + //section version info + if(!p_igetw(&version,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&tempheader.zelda_version,f,true)) + { + return qe_invalid; + } + + //do some quick checking... + if(tempheader.zelda_version > ZELDA_VERSION) + { + return qe_version; + } + + if(strcmp(tempheader.id_str,QH_NEWIDSTR)) + { + return qe_invalid; + } + + if(bad_version(tempheader.zelda_version)) + { + return qe_obsolete; + } + + if(!p_getc(&tempheader.build,f,true)) + { + return qe_invalid; + } + + if(version<3) + { + if(!pfread(temp_pwd,30,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_pwdkey,f,true)) + { + return qe_invalid; + } + + get_questpwd(temp_pwd, temp_pwdkey, temp_pwd2); + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)temp_pwd2, (unsigned)strlen(temp_pwd2)); + cvs_MD5Final(tempheader.pwd_hash, &ctx); + } + else + { + if(!pfread(tempheader.pwd_hash,sizeof(tempheader.pwd_hash),f,true)) + { + return qe_invalid; + } + } + + if(!p_igetw(&tempheader.internal,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.quest_number,f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.version,sizeof(tempheader.version),f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.minver,sizeof(tempheader.minver),f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.title,sizeof(tempheader.title),f,true)) + { + return qe_invalid; + } + + if(!pfread(tempheader.author,sizeof(tempheader.author),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.use_keyfile,f,true)) + { + return qe_invalid; + } + + /* + if(!pfread(tempheader.data_flags,sizeof(tempheader.data_flags),f,true)) + { + return qe_invalid; + } + */ + if(!p_getc(&tempheader.data_flags[ZQ_TILES],f,true)) + { + return qe_invalid; + } + + if(!pfread(&dummybuf,4,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempheader.data_flags[ZQ_CHEATS2],f,true)) + { + return qe_invalid; + } + + if(!pfread(dummybuf,14,f,true)) + { + return qe_invalid; + } + + templatepath_len=sizeof(tempheader.templatepath); + + if(version==1) + { + templatepath_len=280; + } + + if(!pfread(tempheader.templatepath,templatepath_len,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_map_count,f,true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(Header, &tempheader, sizeof(tempheader)); + map_count=temp_map_count; + memcpy(midi_flags, temp_midi_flags, MIDIFLAGS_SIZE); + } + + return 0; +} + +int readrules(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + int dummy; + zquestheader tempheader; + word s_version=0; + + memcpy(&tempheader, Header, sizeof(tempheader)); + + if(tempheader.zelda_version >= 0x193) + { + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!pfread(quest_rules,QUESTRULES_SIZE,f,true)) + { + return qe_invalid; + } + } + + //al_trace("Rules version %d\n", s_version); + + memcpy(deprecated_rules, quest_rules, QUESTRULES_SIZE); + + if(s_version<2) + { + set_bit(quest_rules,14,0); + set_bit(quest_rules,27,0); + set_bit(quest_rules,28,0); + set_bit(quest_rules,29,0); + set_bit(quest_rules,30,0); + set_bit(quest_rules,32,0); + set_bit(quest_rules,36,0); + set_bit(quest_rules,49,0); + set_bit(quest_rules,50,0); + set_bit(quest_rules,51,0); + set_bit(quest_rules,68,0); + set_bit(quest_rules,75,0); + set_bit(quest_rules,76,0); + set_bit(quest_rules,98,0); + set_bit(quest_rules,110,0); + set_bit(quest_rules,113,0); + set_bit(quest_rules,116,0); + set_bit(quest_rules,102,0); + set_bit(quest_rules,132,0); + } + + //Now, do any updates... + + if((tempheader.zelda_version < 0x211)||((tempheader.zelda_version == 0x211)&&(tempheader.build<18))) + { + set_bit(quest_rules, qr_SMOOTHVERTICALSCROLLING,1); + set_bit(quest_rules, qr_REPLACEOPENDOORS, 1); + set_bit(quest_rules, qr_OLDLENSORDER, 1); + set_bit(quest_rules, qr_NOFAIRYGUYFIRES, 1); + set_bit(quest_rules, qr_TRIGGERSREPEAT, 1); + } + + if((tempheader.zelda_version < 0x193)||((tempheader.zelda_version == 0x193)&&(tempheader.build<3))) + { + set_bit(quest_rules,qr_WALLFLIERS,1); + } + + if((tempheader.zelda_version < 0x193)||((tempheader.zelda_version == 0x193)&&(tempheader.build<4))) + { + set_bit(quest_rules,qr_NOBOMBPALFLASH,1); + } + + if((tempheader.zelda_version < 0x193)||((tempheader.zelda_version == 0x193)&&(tempheader.build<3))) + { + set_bit(quest_rules,qr_NOSCROLLCONTINUE,1); + } + + if(tempheader.zelda_version == 0x210) + { + set_bit(quest_rules, qr_NOSCROLLCONTINUE, get_bit(quest_rules, qr_CMBCYCLELAYERS)); + set_bit(quest_rules, qr_CMBCYCLELAYERS, 0); + } + + if(tempheader.zelda_version <= 0x210) + { + set_bit(quest_rules,qr_OLDSTYLEWARP,1); + } + + //might not be correct + if(tempheader.zelda_version < 0x210) + { + set_bit(deprecated_rules, qr_OLDTRIBBLES_DEP,1); + set_bit(quest_rules, qr_OLDHOOKSHOTGRAB,1); + } + + if(tempheader.zelda_version == 0x210) + { + set_bit(deprecated_rules, qr_OLDTRIBBLES_DEP, get_bit(quest_rules, qr_DMGCOMBOPRI)); + set_bit(quest_rules, qr_DMGCOMBOPRI, 0); + } + + if(tempheader.zelda_version < 0x211 || (tempheader.zelda_version == 0x211 && tempheader.build<15)) + { + set_bit(quest_rules, qr_OLDPICKUP,1); + } + + if(tempheader.zelda_version < 0x211 || (tempheader.zelda_version == 0x211 && tempheader.build < 18)) + { + set_bit(quest_rules,qr_NOSOLIDDAMAGECOMBOS, 1); + } + + if(tempheader.zelda_version < 0x250 || (tempheader.zelda_version == 0x250 && tempheader.build<29)) + { + // qr_OFFSETEWPNCOLLISIONFIX + // All 'official' quests need this disabled. + // All 2.10 and lower quests need this enabled to preseve compatability. + // All 2.11 - 2.5.1 quests should have it set also, due to a bug in about half of all the betas. + set_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX, 0); + } + + if(tempheader.zelda_version < 0x250) // version<0x250 checks for beta 18; build was set to 18 prematurely + { + set_bit(quest_rules,qr_HOOKSHOTDOWNBUG, 1); + } + + if(tempheader.zelda_version == 0x250 && tempheader.build == 24) // Annoying... + { + set_bit(quest_rules,qr_PEAHATCLOCKVULN, 1); + } + + if(tempheader.zelda_version < 0x250 || (tempheader.zelda_version == 0x250 && tempheader.build<28)) + { + set_bit(quest_rules, qr_OFFSCREENWEAPONS, 1); + } + + if(tempheader.zelda_version < 0x250 || (tempheader.zelda_version == 0x250 && tempheader.build<29)) + { + // qr_OFFSETEWPNCOLLISIONFIX + // All 'official' quests need this disabled. + // All 2.10 and lower quests need this enabled to preseve compatability. + // All 2.11 - 2.5.1 quests should have it set also, due to a bug in about half of all the betas. + set_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX, 0); + } + + if(s_version < 3) + { + set_bit(quest_rules, qr_HOLDNOSTOPMUSIC, 1); + set_bit(quest_rules, qr_CAVEEXITNOSTOPMUSIC, 1); + } + + if(s_version<4) + { + set_bit(quest_rules,10,0); + } + + if(s_version<5) + { + set_bit(quest_rules,27,0); + } + + if(s_version<6) + { + set_bit(quest_rules,46,0); + } + + if(s_version<7) // January 2008 + { + set_bit(quest_rules,qr_HEARTSREQUIREDFIX,0); + set_bit(quest_rules,qr_PUSHBLOCKCSETFIX,1); + } + + if(s_version<8) + { + set_bit(quest_rules, 12, 0); + } + else + { + set_bit(deprecated_rules, 12, 0); + } + + if(s_version<9) // October 2008 + { + set_bit(quest_rules,qr_NOROPE2FLASH_DEP,0); + set_bit(quest_rules,qr_NOBUBBLEFLASH_DEP,0); + set_bit(quest_rules,qr_GHINI2BLINK_DEP,0); + set_bit(quest_rules,qr_PHANTOMGHINI2_DEP,0); + } + + if(s_version<10) // December 2008 + { + set_bit(quest_rules,qr_NOCLOCKS_DEP,0); + set_bit(quest_rules, qr_ALLOW10RUPEEDROPS_DEP,0); + } + + if(s_version<11) // April 2009 + { + set_bit(quest_rules,qr_SLOWENEMYANIM_DEP,0); + } + + if(s_version<12) // December 2009 + { + set_bit(quest_rules,qr_BRKBLSHLDS_DEP,0); + set_bit(quest_rules, qr_OLDTRIBBLES_DEP,0); + } + + //if(tempheader.zelda_version < 0x250 || (tempheader.zelda_version == 0x250 && tempheader.build < 24)) + if(s_version < 13) + { + set_bit(quest_rules,qr_SHOPCHEAT, 1); + } + + if(keepdata==true) + { + memcpy(Header, &tempheader, sizeof(tempheader)); + } + + return 0; +} + +void init_msgstr(MsgStr *str) +{ + memset(str->s, 0, MSGSIZE+1); + str->nextstring=0; + str->tile=0; + str->cset=0; + str->trans=false; + str->font=font_zfont; + str->y=32; + str->sfx=18; + str->listpos=0; + str->x=24; + str->w=24*8; + str->h=3*8; + str->hspace=0; + str->vspace=0; + str->stringflags=0; +} + +void init_msgstrings(int start, int end) +{ + if(end <= start || end-start > msg_strings_size) + return; + + for(int i=start; izelda_version < 0x193) + { + byte tempbyte; + int strings_to_read=0; + + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<31))) + { + strings_to_read=128; + temp_msg_count=Header->old_str_count; + + // Some sort of string count corruption seems to be common in old quests + if(temp_msg_count>128) + { + temp_msg_count=128; + } + } + else if((Header->zelda_version == 0x192)&&(Header->build<140)) + { + strings_to_read=255; + temp_msg_count=Header->old_str_count; + } + else + { + if(!p_igetw(&temp_msg_count,f,true)) + { + return qe_invalid; + } + + strings_to_read=temp_msg_count; + + if(temp_msg_count >= msg_strings_size) + { + Z_message("Reallocating string buffer...\n"); + + if((MsgStrings=(MsgStr*)_al_sane_realloc(MsgStrings,sizeof(MsgStr)*MAXMSGS))==NULL) + return qe_nomem; + + memset(MsgStrings, 0, sizeof(MsgStr)*MAXMSGS); + msg_strings_size = MAXMSGS; + } + } + + //reset the message strings + if(keepdata) + { + init_msgstrings(0,msg_strings_size); + } + + for(int x=0; xzelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<148))) + { + tempMsgString.nextstring=tempbyte?x+1:0; + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + else + { + if(!p_igetw(&tempMsgString.nextstring,f,true)) + { + return qe_invalid; + } + + if(!pfread(temp_expansion,32,f,true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(&MsgStrings[x], &tempMsgString, sizeof(tempMsgString)); + } + } + } + else + { + int dummy_int; + word s_version; + word s_cversion; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //al_trace("Strings version %d\n", s_version); + //section size + if(!p_igetl(&dummy_int,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&temp_msg_count,f,true)) + { + return qe_invalid; + } + + if(temp_msg_count >= msg_strings_size) + { + Z_message("Reallocating string buffer...\n"); + + if((MsgStrings=(MsgStr*)_al_sane_realloc(MsgStrings,sizeof(MsgStr)*MAXMSGS))==NULL) + return qe_nomem; + + memset(MsgStrings, 0, sizeof(MsgStr)*MAXMSGS); + msg_strings_size = MAXMSGS; + } + + //reset the message strings + if(keepdata) + { + init_msgstrings(0,msg_strings_size); + } + + int string_length=(s_version<2)?73:145; + + for(int i=0; i3) + { + if(!p_igetw(&tempMsgString.listpos,f,true)) + { + return qe_invalid; + } + } + } + + if(keepdata==true) + { + memcpy(&MsgStrings[i], &tempMsgString, sizeof(tempMsgString)); + } + } + } + + if(keepdata==true) + { + msg_count=temp_msg_count; + } + + return 0; +} + +int readdoorcombosets(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<158))) + { + return 0; + } + + word temp_door_combo_set_count=0; + DoorComboSet tempDoorComboSet; + word dummy_word; + long dummy_long; + byte padding; + + if(keepdata==true) + { + for(int i=0; izelda_version > 0x192) + { + //section version info + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + //al_trace("Door combo sets version %d\n", dummy_word); + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy_long,f,true)) + { + return qe_invalid; + } + } + + //finally... section data + if(!p_igetw(&temp_door_combo_set_count,f,true)) + { + return qe_invalid; + } + + for(int i=0; izelda_version < 0x193) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + //up door + for(int j=0; j<9; j++) + { + for(int k=0; k<4; k++) + { + if(!p_igetw(&tempDoorComboSet.doorcombo_u[j][k],f,true)) + { + return qe_invalid; + } + } + } + + for(int j=0; j<9; j++) + { + for(int k=0; k<4; k++) + { + if(!p_getc(&tempDoorComboSet.doorcset_u[j][k],f,true)) + { + return qe_invalid; + } + } + } + + //down door + for(int j=0; j<9; j++) + { + for(int k=0; k<4; k++) + { + if(!p_igetw(&tempDoorComboSet.doorcombo_d[j][k],f,true)) + { + return qe_invalid; + } + } + } + + for(int j=0; j<9; j++) + { + for(int k=0; k<4; k++) + { + if(!p_getc(&tempDoorComboSet.doorcset_d[j][k],f,true)) + { + return qe_invalid; + } + } + } + + //left door + for(int j=0; j<9; j++) + { + for(int k=0; k<6; k++) + { + if(!p_igetw(&tempDoorComboSet.doorcombo_l[j][k],f,true)) + { + return qe_invalid; + } + } + } + + for(int j=0; j<9; j++) + { + for(int k=0; k<6; k++) + { + if(!p_getc(&tempDoorComboSet.doorcset_l[j][k],f,true)) + { + return qe_invalid; + } + } + } + + //right door + for(int j=0; j<9; j++) + { + for(int k=0; k<6; k++) + { + if(!p_igetw(&tempDoorComboSet.doorcombo_r[j][k],f,true)) + { + return qe_invalid; + } + } + } + + for(int j=0; j<9; j++) + { + for(int k=0; k<6; k++) + { + if(!p_getc(&tempDoorComboSet.doorcset_r[j][k],f,true)) + { + return qe_invalid; + } + } + } + + //up bomb rubble + for(int j=0; j<2; j++) + { + if(!p_igetw(&tempDoorComboSet.bombdoorcombo_u[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<2; j++) + { + if(!p_getc(&tempDoorComboSet.bombdoorcset_u[j],f,true)) + { + return qe_invalid; + } + } + + //down bomb rubble + for(int j=0; j<2; j++) + { + if(!p_igetw(&tempDoorComboSet.bombdoorcombo_d[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<2; j++) + { + if(!p_getc(&tempDoorComboSet.bombdoorcset_d[j],f,true)) + { + return qe_invalid; + } + } + + //left bomb rubble + for(int j=0; j<3; j++) + { + if(!p_igetw(&tempDoorComboSet.bombdoorcombo_l[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if(!p_getc(&tempDoorComboSet.bombdoorcset_l[j],f,true)) + { + return qe_invalid; + } + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + + } + + //right bomb rubble + for(int j=0; j<3; j++) + { + if(!p_igetw(&tempDoorComboSet.bombdoorcombo_r[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if(!p_getc(&tempDoorComboSet.bombdoorcset_r[j],f,true)) + { + return qe_invalid; + } + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + //walkthrough stuff + for(int j=0; j<4; j++) + { + if(!p_igetw(&tempDoorComboSet.walkthroughcombo[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<4; j++) + { + if(!p_getc(&tempDoorComboSet.walkthroughcset[j],f,true)) + { + return qe_invalid; + } + } + + //flags + for(int j=0; j<2; j++) + { + if(!p_getc(&tempDoorComboSet.flags[j],f,true)) + { + return qe_invalid; + } + } + + if(Header->zelda_version < 0x193) + { + if(!pfread(&tempDoorComboSet.expansion,sizeof(tempDoorComboSet.expansion),f,true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(&DoorComboSets[i], &tempDoorComboSet, sizeof(tempDoorComboSet)); + } + } + + if(keepdata==true) + { + door_combo_set_count=temp_door_combo_set_count; + } + + return 0; +} + +int count_dmaps() +{ + int i=MAXDMAPS-1; + bool found=false; + + while(i>=0 && !found) + { + if((DMaps[i].map!=0)||(DMaps[i].level!=0)||(DMaps[i].xoff!=0)|| + (DMaps[i].compass!=0)||(DMaps[i].color!=0)||(DMaps[i].midi!=0)|| + (DMaps[i].cont!=0)||(DMaps[i].type!=0)) + found=true; + + for(int j=0; j<8; j++) + { + if(DMaps[i].grid[j]!=0) + + found=true; + } + + if((DMaps[i].name[0]!=0)||(DMaps[i].title[0]!=0)|| + (DMaps[i].intro[0]!=0)||(DMaps[i].tmusic[0]!=0)) + found=true; + + if((DMaps[i].minimap_1_tile!=0)||(DMaps[i].minimap_2_tile!=0)|| + (DMaps[i].largemap_1_tile!=0)||(DMaps[i].largemap_2_tile!=0)|| + (DMaps[i].minimap_1_cset!=0)||(DMaps[i].minimap_2_cset!=0)|| + (DMaps[i].largemap_1_cset!=0)||(DMaps[i].largemap_2_cset!=0)) + found=true; + + if(!found) + { + i--; + } + } + + return i+1; +} + + +int count_shops(miscQdata *Misc) +{ + int i=255,j; + bool found=false; + + while(i>=0 && !found) + { + j=2; + + while(j>=0 && !found) + { + if((Misc->shop[i].hasitem[j]!=0)||(Misc->shop[i].price[j]!=0)) + { + found=true; + } + else + { + j--; + } + } + + if(Misc->shop[i].name[0]!=0) + { + found=true; + } + + if(!found) + { + i--; + } + } + + return i+1; +} + +int count_infos(miscQdata *Misc) +{ + int i=255,j; + bool found=false; + + while(i>=0 && !found) + { + j=2; + + while(j>=0 && !found) + { + if((Misc->info[i].str[j]!=0)||(Misc->info[i].price[j]!=0)) + { + found=true; + } + else + { + j--; + } + } + + if(Misc->info[i].name[0]!=0) + { + found=true; + } + + if(!found) + { + i--; + } + } + + return i+1; +} + +int count_warprings(miscQdata *Misc) +{ + int i=15,j; + bool found=false; + + while(i>=0 && !found) + { + j=7; + + while(j>=0 && !found) + { + if((Misc->warp[i].dmap[j]!=0)||(Misc->warp[i].scr[j]!=0)) + { + found=true; + } + else + { + j--; + } + } + + if(!found) + { + i--; + } + } + + return i+1; +} + +int count_palcycles(miscQdata *Misc) +{ + int i=255,j; + bool found=false; + + while(i>=0 && !found) + { + j=2; + + while(j>=0 && !found) + { + if(Misc->cycles[i][j].count!=0) + { + found=true; + } + else + { + j--; + } + } + + if(!found) + { + i--; + } + } + + return i+1; +} + +void clear_screen(mapscr *temp_scr) +{ + temp_scr->zero_memory(); + + for(int j=0; j<6; j++) + { + temp_scr->layeropacity[j]=255; + } +} + +int readdmaps(PACKFILE *f, zquestheader *Header, word, word, word start_dmap, word max_dmaps, bool keepdata) +{ + word dmapstoread=0; + dmap tempDMap; + + int dummy; + word s_version=0, s_cversion=0; + byte padding; + + if(keepdata==true) + { + for(int i=0; izelda_version > 0x192) + { + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("DMaps version %d\n", s_version); + + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&dmapstoread,f,true)) + { + return qe_invalid; + } + } + else + { + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<5))) + { + dmapstoread=32; + } + else if(s_version <= 4) + { + dmapstoread=OLDMAXDMAPS; + } + else + { + dmapstoread=MAXDMAPS; + } + } + + dmapstoread=zc_min(dmapstoread, max_dmaps); + dmapstoread=zc_min(dmapstoread, MAXDMAPS-start_dmap); + + for(int i=start_dmap; i 8) // February 2009 + { + if(!p_igetw(&tempDMap.color,f,true)) + { + return qe_invalid; + } + } + else + { + byte tempbyte; + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + tempDMap.color = (word)tempbyte; + } + + if(!p_getc(&tempDMap.midi,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.cont,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.type,f,keepdata)) + { + return qe_invalid; + } + + if((tempDMap.type & dmfTYPE) == dmOVERW && + (!Header || Header->zelda_version >= 0x210)) // Not sure exactly when this changed + tempDMap.xoff = 0; + + for(int j=0; j<8; j++) + { + if(!p_getc(&tempDMap.grid[j],f,keepdata)) + { + return qe_invalid; + } + } + + if(Header && ((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<41)))) + { + if(tempDMap.level>0&&tempDMap.level<10) + { + sprintf(tempDMap.title,"LEVEL-%d ", tempDMap.level); + } + + if(i==0 && Header->zelda_version <= 0x190) + { + tempDMap.cont-=tempDMap.xoff; + tempDMap.compass-=tempDMap.xoff; + } + + //forgotten -DD + if(tempDMap.level==0) + { + tempDMap.flags=dmfCAVES|dmf3STAIR|dmfWHIRLWIND|dmfGUYCAVES; + } + } + else + { + if(!pfread(&tempDMap.name,sizeof(DMaps[0].name),f,true)) + { + return qe_invalid; + } + + if(!pfread(&tempDMap.title,sizeof(DMaps[0].title),f,true)) + { + return qe_invalid; + } + + if(!pfread(&tempDMap.intro,sizeof(DMaps[0].intro),f,true)) + { + return qe_invalid; + } + + if(Header && ((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<152)))) + { + if(keepdata==true) + { + memcpy(&DMaps[i], &tempDMap, sizeof(tempDMap)); + } + + continue; + } + + if(Header && (Header->zelda_version < 0x193)) + { + if(!p_getc(&padding,f,keepdata)) + { + return qe_invalid; + } + } + + if(!p_igetw(&tempDMap.minimap_1_tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.minimap_1_cset,f,keepdata)) + { + return qe_invalid; + } + + if(Header && (Header->zelda_version < 0x193)) + { + if(!p_getc(&padding,f,keepdata)) + { + return qe_invalid; + } + } + + if(!p_igetw(&tempDMap.minimap_2_tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.minimap_2_cset,f,keepdata)) + { + return qe_invalid; + } + + if(Header && (Header->zelda_version < 0x193)) + { + if(!p_getc(&padding,f,keepdata)) + { + return qe_invalid; + } + } + + if(!p_igetw(&tempDMap.largemap_1_tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.largemap_1_cset,f,keepdata)) + { + return qe_invalid; + } + + if(Header && (Header->zelda_version < 0x193)) + { + + if(!p_getc(&padding,f,keepdata)) + { + return qe_invalid; + } + } + + if(!p_igetw(&tempDMap.largemap_2_tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.largemap_2_cset,f,keepdata)) + { + return qe_invalid; + } + + if(!pfread(&tempDMap.tmusic,sizeof(DMaps[0].tmusic),f,true)) + { + return qe_invalid; + } + } + + if(s_version>1) + { + if(!p_getc(&tempDMap.tmusictrack,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.active_subscreen,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&tempDMap.passive_subscreen,f,keepdata)) + { + return qe_invalid; + } + } + + if(s_version>2) + { + byte di[32]; + + if(!pfread(&di, 32, f, true)) return qe_invalid; + + for(int j=0; j= 6) + { + if(!p_igetl(&tempDMap.flags,f,keepdata)) + { + return qe_invalid; + } + } + else if(s_version>3) + { + char temp; + + if(!p_getc(&temp,f,keepdata)) + { + return qe_invalid; + } + + tempDMap.flags = temp; + } + else if(tempDMap.level==0 && ((Header->zelda_version < 0x211) || ((Header->zelda_version == 0x211) && (Header->build<18)))) + { + tempDMap.flags=dmfCAVES|dmf3STAIR|dmfWHIRLWIND|dmfGUYCAVES; + } + else + tempDMap.flags=0; + + if(s_version<7) + { + if(tempDMap.level==0 && get_bit(deprecated_rules,14)) + tempDMap.flags|= dmfVIEWMAP; + } + + if(s_version<8) + { + if(tempDMap.level==0 && (tempDMap.type&dmfTYPE)==dmDNGN) + { + tempDMap.type &= ~dmDNGN; + tempDMap.type |= dmCAVE; + } + else if((tempDMap.type&dmfTYPE)==dmCAVE) + { + tempDMap.flags |= dmfMINIMAPCOLORFIX; + } + } + + if(Header && ((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>=41))) + && (Header->zelda_version < 0x193)) + { + if(!p_getc(&padding,f,keepdata)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(&DMaps[i], &tempDMap, sizeof(tempDMap)); + } + } + + return 0; +} + +int readmisccolors(PACKFILE *f, zquestheader *Header, miscQdata *Misc, bool keepdata) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + miscQdata temp_misc; + word s_version=0, s_cversion=0; + int tempsize=0; + + memcpy(&temp_misc,Misc,sizeof(temp_misc)); + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Misc. colors version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + + //section size + if(!p_igetl(&tempsize,f,true)) + { + return qe_invalid; + } + + //finally... section data + readsize=0; + + if(!p_getc(&temp_misc.colors.text,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.caption,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.overw_bg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.dngn_bg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.dngn_fg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.cave_fg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.bs_dk,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.bs_goal,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.compass_lt,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.compass_dk,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.subscr_bg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.triframe_color,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.link_dot,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.bmap_bg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.bmap_fg,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.triforce_cset,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.triframe_cset,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.overworld_map_cset,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.dungeon_map_cset,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.blueframe_cset,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.triforce_tile,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.triframe_tile,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.overworld_map_tile,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.dungeon_map_tile,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.blueframe_tile,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_misc.colors.HCpieces_tile,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.HCpieces_cset,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_misc.colors.subscr_shadow,f,true)) + { + return qe_invalid; + } + + if(s_version < 2) + { + temp_misc.colors.msgtext = 0x01; + } + else + { + if(!p_getc(&temp_misc.colors.msgtext, f, true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(Misc, &temp_misc, sizeof(temp_misc)); + } + + return 0; +} + +int readgameicons(PACKFILE *f, zquestheader *, miscQdata *Misc, bool keepdata) +{ + miscQdata temp_misc; + word s_version=0, s_cversion=0; + byte icons; + int tempsize=0; + + memcpy(&temp_misc,Misc,sizeof(temp_misc)); + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Game icons version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + + //section size + if(!p_igetl(&tempsize,f,true)) + { + return qe_invalid; + } + + //finally... section data + readsize=0; + + icons=4; + + for(int i=0; izelda_version > 0x192) + { + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Misc. data version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + + //section size + if(!p_igetl(&tempsize,f,true)) + { + return qe_invalid; + } + } + + //finally... section data + readsize=0; + + //shops + if(Header->zelda_version > 0x192) + { + if(!p_igetw(&shops,f,true)) + { + return qe_invalid; + } + + } + + for(int i=0; i 6) + { + if(!pfread(temp_misc.shop[i].name,sizeof(temp_misc.shop[i].name),f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if(!p_getc(&temp_misc.shop[i].item[j],f,true)) + { + return qe_invalid; + } + + if(s_version < 4) + { + temp_misc.shop[i].hasitem[j] = (temp_misc.shop[i].item[j] == 0) ? 0 : 1; + } + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if(!p_igetw(&temp_misc.shop[i].price[j],f,true)) + { + return qe_invalid; + } + } + + if(s_version > 3) + { + for(int j=0; j<3; j++) + { + if(!p_getc(&temp_misc.shop[i].hasitem[j],f,true)) + return qe_invalid; + } + } + } + + //filter all the 0 items to the end (yeah, bubble sort; sue me) + for(int i=0; izelda_version > 0x192) + { + if(!p_igetw(&infos,f,true)) + { + return qe_invalid; + } + } + + for(int i=0; i 6) + { + if(!pfread(temp_misc.info[i].name,sizeof(temp_misc.info[i].name),f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<146))) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_misc.info[i].str[j]=tempbyte; + } + else + { + if(!p_igetw(&temp_misc.info[i].str[j],f,true)) + { + return qe_invalid; + } + } + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version == 0x192)&&(Header->build>145)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<3; j++) + { + if(!p_igetw(&temp_misc.info[i].price[j],f,true)) + { + return qe_invalid; + } + } + } + + //filter all the 0 strings to the end (yeah, bubble sort; sue me) + for(int i=0; i 5) + warprings++; + + if(Header->zelda_version > 0x192) + { + if(!p_igetw(&warprings,f,true)) + { + return qe_invalid; + } + } + + for(int i=0; i 5)?1:0); j++) + { + if(s_version <= 3) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_misc.warp[i].dmap[j]=(word)tempbyte; + } + else + { + if(!p_igetw(&temp_misc.warp[i].dmap[j],f,true)) + { + return qe_invalid; + } + } + } + + for(int j=0; j<8+((s_version > 5)?1:0); j++) + { + if(!p_getc(&temp_misc.warp[i].scr[j],f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&temp_misc.warp[i].size,f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + } + + //palette cycles + if(Header->zelda_version < 0x193) //in 1.93+, palette cycling is saved with the palettes + { + for(int i=0; i<256; i++) + { + for(int j=0; j<3; j++) + { + temp_misc.cycles[i][j].first=0; + temp_misc.cycles[i][j].count=0; + temp_misc.cycles[i][j].speed=0; + } + } + + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<73))) + { + palcycles=16; + } + + for(int i=0; izelda_version > 0x192) + { + if(!p_igetw(&windwarps,f,true)) + { + return qe_invalid; + } + } + + for(int i=0; izelda_version < 0x193) + { + for(int i=0; i<7; i++) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version == 0x192)&&(Header->build>145)) + { + for(int i=0; i<256; i++) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + } + + if(s_version>1) + { + if(!p_getc(&temp_misc.colors.subscr_shadow,f,true)) + { + return qe_invalid; + } + } + + //save game icons + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<73))) + { + icons=3; + } + + for(int i=0; izelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<30))) + { + if(keepdata==true) + { + memcpy(Misc, &temp_misc, sizeof(temp_misc)); + } + + return 0; + } + + //pond information + if(Header->zelda_version < 0x193) + { + if((Header->zelda_version == 0x192)&&(Header->build<146)) + { + pondsize=25; + } + + for(int i=0; izelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<146))) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_misc.endstring=tempbyte; + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + else + { + if(!p_igetw(&temp_misc.endstring,f,true)) + { + return qe_invalid; + } + } + + //expansion + if(Header->zelda_version < 0x193) + { + if((Header->zelda_version == 0x192)&&(Header->build<73)) + { + expansionsize=99*2; + } + + for(int i=0; i 0x192) + { + items_to_read=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Items version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&items_to_read,f,true)) + { + return qe_invalid; + } + } + + if(s_version>1) + { + for(int i=0; i1) + { + if(!p_getc(&tempitem.family,f,true)) + { + return qe_invalid; + } + + if(s_version < 16) + if(tempitem.family == 0xFF) + tempitem.family = itype_misc; + + if(!p_getc(&tempitem.fam_type,f,true)) + { + return qe_invalid; + } + + if(s_version>5) + { + if(!p_getc(&tempitem.power,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&tempitem.flags,f,true)) + { + return qe_invalid; + } + } + else + { + //tempitem.power = tempitem.fam_type; + char tempchar; + + if(!p_getc(&tempchar,f,true)) + { + return qe_invalid; + } + + tempitem.flags |= (tempchar ? ITEM_GAMEDATA : 0); + } + + if(!p_igetw(&tempitem.script,f,true)) + { + return qe_invalid; + } + + if(s_version<=3) + { + if(tempitem.script > NUMSCRIPTITEM) + { + tempitem.script = 0; + } + } + + if(!p_getc(&tempitem.count,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&tempitem.amount,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&tempitem.collect_script,f,true)) + { + return qe_invalid; + } + + if(s_version<=3) + { + if(tempitem.collect_script > NUMSCRIPTITEM) + { + tempitem.collect_script = 0; + } + } + + if(!p_igetw(&tempitem.setmax,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&tempitem.max,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.playsound,f,true)) + { + return qe_invalid; + } + + for(int j=0; j<8; j++) + { + if(!p_igetl(&tempitem.initiald[j],f,true)) + { + return qe_invalid; + } + } + + for(int j=0; j<2; j++) + { + if(!p_getc(&tempitem.initiala[j],f,true)) + { + return qe_invalid; + } + } + + if(s_version>4) + { + if(s_version>5) + { + if(!p_getc(&tempitem.wpn,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn2,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn3,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn4,f,true)) + { + return qe_invalid; + } + + if(s_version>=15) + { + if(!p_getc(&tempitem.wpn5,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn6,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn7,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn8,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn9,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempitem.wpn10,f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&tempitem.pickup_hearts,f,true)) + { + return qe_invalid; + } + + if(s_version<15) + { + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + tempitem.misc1=dummy_word; + + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + tempitem.misc2=dummy_word; + } + else + { + if(!p_igetl(&tempitem.misc1,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc2,f,true)) + { + return qe_invalid; + } + + // Version 24: shICE -> shSCRIPT; previously, all shields could block script weapons + if(s_version<24) + { + if(tempitem.family==itype_shield) + { + tempitem.misc1|=shSCRIPT; + } + } + } + + if(!p_getc(&tempitem.magic,f,true)) + { + return qe_invalid; + } + } + else + { + char tempchar; + + if(!p_getc(&tempchar,f,true)) + { + return qe_invalid; + } + + tempitem.flags |= (tempchar ? ITEM_EDIBLE : 0); + } + + // June 2007: more misc. attributes + if(s_version>=12) + { + if(s_version<15) + { + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + tempitem.misc3=dummy_word; + + if(!p_igetw(&dummy_word,f,true)) + { + return qe_invalid; + } + + tempitem.misc4=dummy_word; + } + else + { + if(!p_igetl(&tempitem.misc3,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc4,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc5,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc6,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc7,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc8,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc9,f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&tempitem.misc10,f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&tempitem.usesound,f,true)) + { + return qe_invalid; + } + } + } + } + else + { + tempitem.count=-1; + tempitem.family=itype_misc; + tempitem.flags=tempitem.wpn=tempitem.wpn2=tempitem.wpn3=tempitem.wpn3=tempitem.pickup_hearts=tempitem.misc1=tempitem.misc2=tempitem.usesound=0; + tempitem.playsound=WAV_SCALE; + reset_itembuf(&tempitem,i); + } + + if(keepdata==true) + { + memcpy(&itemsbuf[i], &tempitem, sizeof(itemdata)); + } + else if(zgpmode) + { + itemsbuf[i].tile=tempitem.tile; + itemsbuf[i].misc=tempitem.misc; + itemsbuf[i].csets=tempitem.csets; + itemsbuf[i].frames=tempitem.frames; + itemsbuf[i].speed=tempitem.speed; + itemsbuf[i].delay=tempitem.delay; + itemsbuf[i].ltm=tempitem.ltm; + } + } + + ////////////////////////////////////////////////////// + // Now do any updates because of new item additions + // (These can't be done above because items_to_read + // might be too low.) + ////////////////////////////////////////////////////// + if(keepdata==true) + { + for(int i=0; i4) + { + tempitem.flags|=ITEM_FLAG1; + } + } + + if(s_version < 18) // New Year's Eve 2007 + { + if(tempitem.family == itype_whistle) + tempitem.misc2 = 8; // Use the Whistle warp ring + else if(tempitem.family == itype_bait) + tempitem.misc1 = 768; // Frames until it goes + else if(tempitem.family == itype_triforcepiece) + { + if(tempitem.flags & ITEM_GAMEDATA) + { + tempitem.misc2 = 1; // Cutscene 1 + tempitem.flags |= ITEM_FLAG1; // Side Warp Out + } + } + } + + if(s_version < 19) // January 2008 + { + if(tempitem.family == itype_nayruslove) + { + tempitem.flags |= get_bit(deprecated_rules,qr_NOBOMBPALFLASH+1)?ITEM_FLAG3:0; + tempitem.flags |= get_bit(deprecated_rules,qr_NOBOMBPALFLASH+2)?ITEM_FLAG4:0; + } + } + + if(s_version < 20) // October 2008 + { + if(tempitem.family == itype_nayruslove) + { + tempitem.wpn6=wNAYRUSLOVE2A; + tempitem.wpn7=wNAYRUSLOVE2B; + tempitem.wpn8=wNAYRUSLOVES2A; + tempitem.wpn9=wNAYRUSLOVES2B; + tempitem.wpn5 = iwNayrusLoveShieldFront; + tempitem.wpn10 = iwNayrusLoveShieldBack; + } + } + + if(s_version < 21) // November 2008 + { + if(tempitem.flags & 0x0100) // ITEM_SLASH + { + tempitem.flags &= ~0x0100; + + if(tempitem.family == itype_sword || + tempitem.family == itype_wand || + tempitem.family == itype_candle || + tempitem.family == itype_cbyrna) + { + tempitem.flags |= ITEM_FLAG4; + } + } + } + + if(s_version < 22) // September 2009 + { + if(tempitem.family == itype_sbomb || tempitem.family == itype_bomb) + { + tempitem.misc3 = tempitem.power/2; + } + } + + if(s_version < 23) // March 2011 + { + if(tempitem.family == itype_dinsfire) + tempitem.wpn5 = wFIRE; + else if(tempitem.family == itype_book) + tempitem.wpn2 = wFIRE; + } + + // Version 25: Bomb bags were acting as though "super bombs also" was checked + // whether it was or not, and a lot of existing quests depended on the + // incorrect behavior. + if(s_version < 25) // January 2012 + { + if(tempitem.family == itype_bombbag) + tempitem.flags |= 16; + + if(tempitem.family == itype_dinsfire) + tempitem.flags |= ITEM_FLAG3; // Sideview gravity flag + } + + if(tempitem.fam_type==0) // Always do this + tempitem.fam_type=1; + + memcpy(&itemsbuf[i], &tempitem, sizeof(itemdata)); + + } + } + + return 0; +} + +void reset_itembuf(itemdata *item, int id) +{ + if(idtile; + byte miscs = item->misc, cset = item->csets, frames = item->frames, speed = item->speed, delay = item->delay; + long ltm = item->ltm; + + memcpy(item,&default_items[id],sizeof(itemdata)); + item->tile = tile; + item->misc = miscs; + item->csets = cset; + item->frames = frames; + item->speed = speed; + item->delay = delay; + item->ltm = ltm; + } +} + +void reset_itemname(int id) +{ + sprintf(item_string[id],"zz%03d",id); + + if(id < iLast) + strcpy(item_string[id],old_item_string[id]); +} + +int readweapons(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + word weapons_to_read=MAXWPNS; + int dummy; + byte padding; + wpndata tempweapon; + word s_version=0, s_cversion=0; + + + if(Header->zelda_version < 0x186) + { + weapons_to_read=64; + } + + if(Header->zelda_version < 0x185) + { + weapons_to_read=32; + } + + if(Header->zelda_version > 0x192) + { + weapons_to_read=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Weapons version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&weapons_to_read,f,true)) + { + return qe_invalid; + } + } + + if(s_version>2) + { + for(int i=0; izelda_version < 0x193) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + if(s_version < 6) + { + if(i==ewFIRETRAIL) + { + tempweapon.misc |= WF_BEHIND; + } + else + tempweapon.misc &= ~WF_BEHIND; + } + + if(keepdata==true) + { + memcpy(&wpnsbuf[i], &tempweapon, sizeof(tempweapon)); + } + } + + if(keepdata==true) + { + if(s_version<2) + { + wpnsbuf[wSBOOM]=wpnsbuf[wBOOM]; + } + + if(s_version<5) + { + wpnsbuf[iwQuarterHearts].tile=1; + wpnsbuf[iwQuarterHearts].csets=1; + } + + if(Header->zelda_version < 0x176) + { + wpnsbuf[iwSpawn] = *((wpndata*)(itemsbuf + iMisc1)); + wpnsbuf[iwDeath] = *((wpndata*)(itemsbuf + iMisc2)); + memset(&itemsbuf[iMisc1],0,sizeof(itemdata)); + memset(&itemsbuf[iMisc2],0,sizeof(itemdata)); + } + + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<129))) + { + wpnsbuf[wHSCHAIN_V] = wpnsbuf[wHSCHAIN_H]; + } + + if((Header->zelda_version < 0x210)) + { + wpnsbuf[wLSHEAD] = wpnsbuf[wHSHEAD]; + wpnsbuf[wLSCHAIN_H] = wpnsbuf[wHSCHAIN_H]; + wpnsbuf[wLSHANDLE] = wpnsbuf[wHSHANDLE]; + wpnsbuf[wLSCHAIN_V] = wpnsbuf[wHSCHAIN_V]; + } + } + + return 0; +} + +void init_guys(int guyversion) +{ + for(int i=0; i=0) + { + word tile, tile2; + byte flip, extend, dummy_byte; + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + walkspr[i][spr_tile]=(int)tile; + walkspr[i][spr_flip]=(int)flip; + walkspr[i][spr_extend]=(int)extend; + } + } + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + stabspr[i][spr_tile]=(int)tile; + stabspr[i][spr_flip]=(int)flip; + stabspr[i][spr_extend]=(int)extend; + } + } + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + slashspr[i][spr_tile]=(int)tile; + slashspr[i][spr_flip]=(int)flip; + slashspr[i][spr_extend]=(int)extend; + } + } + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + floatspr[i][spr_tile]=(int)tile; + floatspr[i][spr_flip]=(int)flip; + floatspr[i][spr_extend]=(int)extend; + } + } + + if(v_linksprites>1) + { + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + swimspr[i][spr_tile]=(int)tile; + swimspr[i][spr_flip]=(int)flip; + swimspr[i][spr_extend]=(int)extend; + } + } + } + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + divespr[i][spr_tile]=(int)tile; + divespr[i][spr_flip]=(int)flip; + divespr[i][spr_extend]=(int)extend; + } + } + + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + poundspr[i][spr_tile]=(int)tile; + poundspr[i][spr_flip]=(int)flip; + poundspr[i][spr_extend]=(int)extend; + } + } + + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + flip=0; + + if(v_linksprites>0) + { + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + castingspr[spr_tile]=(int)tile; + castingspr[spr_flip]=(int)flip; + castingspr[spr_extend]=(int)extend; + } + + if(v_linksprites>0) + { + for(int i=0; i<2; i++) + { + for(int j=0; j<2; j++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + holdspr[i][j][spr_tile]=(int)tile; + holdspr[i][j][spr_flip]=(int)flip; + holdspr[i][j][spr_extend]=(int)extend; + } + } + } + } + else + { + for(int i=0; i<2; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&tile2,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + holdspr[i][spr_hold1][spr_tile]=(int)tile; + holdspr[i][spr_hold1][spr_flip]=(int)flip; + holdspr[i][spr_hold1][spr_extend]=(int)extend; + holdspr[i][spr_hold2][spr_tile]=(int)tile2; + holdspr[i][spr_hold1][spr_flip]=(int)flip; + holdspr[i][spr_hold2][spr_extend]=(int)extend; + } + } + } + + if(v_linksprites>2) + { + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + jumpspr[i][spr_tile]=(int)tile; + jumpspr[i][spr_flip]=(int)flip; + jumpspr[i][spr_extend]=(int)extend; + } + } + } + + if(v_linksprites>3) + { + for(int i=0; i<4; i++) + { + if(!p_igetw(&tile,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&flip,f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&extend,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + chargespr[i][spr_tile]=(int)tile; + chargespr[i][spr_flip]=(int)flip; + chargespr[i][spr_extend]=(int)extend; + } + } + } + + if(v_linksprites>4) + { + if(!p_getc(&dummy_byte,f,keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + zinit.link_swim_speed=(byte)dummy_byte; + } + } + } + + return 0; +} + +int readlinksprites(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword dummy; + word s_version=0, s_cversion=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Link sprites version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + return readlinksprites2(f, s_version, dummy, keepdata); +} + +int readsubscreens(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + int dummy; + word s_version=0, s_cversion=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Subscreens version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + for(int i=0; i tempSubPtr(temp_sub); + + char tempname[64]; + + if(!pfread(tempname,64,f,true)) + { + return qe_invalid; + } + + if(s_version > 1) + { + if(!p_getc(&temp_ss,f,keepdata)) + { + return qe_invalid; + } + } + + if(s_version < 4) + { + unsigned char tmp=0; + + if(!p_getc(&tmp,f,true)) + { + return qe_invalid; + } + + numsub = (int)tmp; + } + else + { + word tmp; + + if(!p_igetw(&tmp, f, true)) + { + return qe_invalid; + } + + numsub = (int)tmp; + } + + int j; + + for(j=0; (jtype),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_sub->pos),f,keepdata)) + { + return qe_invalid; + } + + if(s_version < 5) + { + switch(temp_sub->pos) + { + case 0: + temp_sub->pos = sspUP | sspDOWN | sspSCROLLING; + break; + + case 1: + temp_sub->pos = sspUP; + break; + + case 2: + temp_sub->pos = sspDOWN; + break; + + default: + temp_sub->pos = 0; + } + } + + if(!p_igetw(&(temp_sub->x),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->y),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->w),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->h),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_sub->colortype1),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->color1),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_sub->colortype2),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->color2),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_sub->colortype3),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->color3),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d1),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d2),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d3),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d4),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d5),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d6),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d7),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d8),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d9),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetd(&(temp_sub->d10),f,keepdata)) + { + return qe_invalid; + } + + if(s_version < 2) + { + if(!p_igetl(&(temp_sub->speed),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_sub->delay),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_sub->frame),f,keepdata)) + { + return qe_invalid; + } + } + else + { + if(!p_getc(&(temp_sub->speed),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_sub->delay),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_sub->frame),f,keepdata)) + { + return qe_invalid; + } + } + + int temp_size=0; + + // bool deletets = false; + switch(temp_sub->type) + { + case ssoTEXT: + case ssoTEXTBOX: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMCLASSTEXT: + word temptempsize; + /*unsigned char temp1; + unsigned char temp2; + temp2 = 0; + if(!p_getc(&temp1,f,true)) + { + return qe_invalid; + } + if(temp1) + { + + if(!p_getc(&temp2,f,true)) + { + return qe_invalid; + } + }*/ + + if(!p_igetw(&temptempsize,f,true)) + { + return qe_invalid; + } + + //temptempsize = temp1 + (temp2 << 8); + temp_size = (int)temptempsize; + + //if(temp_sub->dp1!=NULL) delete[] temp_sub->dp1; + if(keepdata) + { + unsigned int char_length = temp_size+1; + temp_sub->dp1 = new char[char_length]; //memory not freed + + //deletets = true; //obsolete + } + + if(temp_size) + { + if(!pfread(temp_sub->dp1,temp_size+1,f,keepdata)) + { + return qe_invalid; + } + } + + break; + + case ssoLIFEMETER: + if(get_bit(deprecated_rules, 12) != 0) // qr_24HC + temp_sub->d3 = 1; + + if(!p_getc(&(temp_sub->dp1),f,keepdata)) + { + return qe_invalid; + } + + break; + + + case ssoCURRENTITEM: + + if(s_version < 6) + { + switch(temp_sub->d1) + { + case ssiBOMB: + temp_sub->d1 = itype_bomb; + break; + + case ssiSWORD: + temp_sub->d1 = itype_sword; + break; + + case ssiSHIELD: + temp_sub->d1 = itype_shield; + break; + + case ssiCANDLE: + temp_sub->d1 = itype_candle; + break; + + case ssiLETTER: + temp_sub->d1 = itype_letter; + break; + + case ssiPOTION: + temp_sub->d1 = itype_potion; + break; + + case ssiLETTERPOTION: + temp_sub->d1 = itype_letterpotion; + break; + + case ssiBOW: + temp_sub->d1 = itype_bow; + break; + + case ssiARROW: + temp_sub->d1 = itype_arrow; + break; + + case ssiBOWANDARROW: + temp_sub->d1 = itype_bowandarrow; + break; + + case ssiBAIT: + temp_sub->d1 = itype_bait; + break; + + case ssiRING: + temp_sub->d1 = itype_ring; + break; + + case ssiBRACELET: + temp_sub->d1 = itype_bracelet; + break; + + case ssiMAP: + temp_sub->d1 = itype_map; + break; + + case ssiCOMPASS: + temp_sub->d1 = itype_compass; + break; + + case ssiBOSSKEY: + temp_sub->d1 = itype_bosskey; + break; + + case ssiMAGICKEY: + temp_sub->d1 = itype_magickey; + break; + + case ssiBRANG: + temp_sub->d1 = itype_brang; + break; + + case ssiWAND: + temp_sub->d1 = itype_wand; + break; + + case ssiRAFT: + temp_sub->d1 = itype_raft; + break; + + case ssiLADDER: + temp_sub->d1 = itype_ladder; + break; + + case ssiWHISTLE: + temp_sub->d1 = itype_whistle; + break; + + case ssiBOOK: + temp_sub->d1 = itype_book; + break; + + case ssiWALLET: + temp_sub->d1 = itype_wallet; + break; + + case ssiSBOMB: + temp_sub->d1 = itype_sbomb; + break; + + case ssiHCPIECE: + temp_sub->d1 = itype_heartpiece; + break; + + case ssiAMULET: + temp_sub->d1 = itype_amulet; + break; + + case ssiFLIPPERS: + temp_sub->d1 = itype_flippers; + break; + + case ssiHOOKSHOT: + temp_sub->d1 = itype_hookshot; + break; + + case ssiLENS: + temp_sub->d1 = itype_lens; + break; + + case ssiHAMMER: + temp_sub->d1 = itype_hammer; + break; + + case ssiBOOTS: + temp_sub->d1 = itype_boots; + break; + + case ssiDINSFIRE: + temp_sub->d1 = itype_dinsfire; + break; + + case ssiFARORESWIND: + temp_sub->d1 = itype_faroreswind; + break; + + case ssiNAYRUSLOVE: + temp_sub->d1 = itype_nayruslove; + break; + + case ssiQUIVER: + temp_sub->d1 = itype_quiver; + break; + + case ssiBOMBBAG: + temp_sub->d1 = itype_bombbag; + break; + + case ssiCBYRNA: + temp_sub->d1 = itype_cbyrna; + break; + + case ssiROCS: + temp_sub->d1 = itype_rocs; + break; + + case ssiHOVERBOOTS: + temp_sub->d1 = itype_hoverboots; + break; + + case ssiSPINSCROLL: + temp_sub->d1 = itype_spinscroll; + break; + + case ssiCROSSSCROLL: + temp_sub->d1 = itype_crossscroll; + break; + + case ssiQUAKESCROLL: + temp_sub->d1 = itype_quakescroll; + break; + + case ssiWHISPRING: + temp_sub->d1 = itype_whispring; + break; + + case ssiCHARGERING: + temp_sub->d1 = itype_chargering; + break; + + case ssiPERILSCROLL: + temp_sub->d1 = itype_perilscroll; + break; + + case ssiWEALTHMEDAL: + temp_sub->d1 = itype_wealthmedal; + break; + + case ssiHEARTRING: + temp_sub->d1 = itype_heartring; + break; + + case ssiMAGICRING: + temp_sub->d1 = itype_magicring; + break; + + case ssiSPINSCROLL2: + temp_sub->d1 = itype_spinscroll2; + break; + + case ssiQUAKESCROLL2: + temp_sub->d1 = itype_quakescroll2; + break; + + case ssiAGONY: + temp_sub->d1 = itype_agony; + break; + + case ssiSTOMPBOOTS: + temp_sub->d1 = itype_stompboots; + break; + + case ssiWHIMSICALRING: + temp_sub->d1 = itype_whimsicalring; + break; + + case ssiPERILRING: + temp_sub->d1 = itype_perilring; + break; + + default: + temp_sub->d1 += itype_custom1 - ssiMAX; + } + } + + //fall-through + default: + if(!p_getc(&(temp_sub->dp1),f,keepdata)) + { + return qe_invalid; + } + + break; + } + + if(keepdata) + { + switch(temp_sub->type) + { + case ssoTEXT: + case ssoTEXTBOX: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMCLASSTEXT: + if(custom_subscreen[i].objects[j].dp1 != NULL) delete[](char *)custom_subscreen[i].objects[j].dp1; + + memcpy(&custom_subscreen[i].objects[j],temp_sub,sizeof(subscreen_object)); + custom_subscreen[i].objects[j].dp1 = NULL; + custom_subscreen[i].objects[j].dp1 = new char[temp_size+1]; + strcpy((char*)custom_subscreen[i].objects[j].dp1,(char*)temp_sub->dp1); + break; + + case ssoCOUNTER: + if(s_version<3) + { + temp_sub->d6=(temp_sub->d6?1:0)+(temp_sub->d8?2:0); + temp_sub->d8=0; + } + + default: + memcpy(&custom_subscreen[i].objects[j],temp_sub,sizeof(subscreen_object)); + break; + } + + strcpy(custom_subscreen[i].name, tempname); + custom_subscreen[i].ss_type = temp_ss; + } + } + + for(j=numsub; jobjects[i].type) + { + case ssoTEXT: + case ssoTEXTBOX: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMCLASSTEXT: + if(tempss->objects[i].dp1 != NULL) delete [](char *)tempss->objects[i].dp1; + + //fall through + default: + memset(&tempss->objects[i],0,sizeof(subscreen_object)); + break; + } + } +} + +void reset_subscreens() +{ + for(int i=0; i=ssdtMAX) + { + tempsubscreen=0; + } + + switch(tempsubscreen) + { + case ssdtOLD: + case ssdtNEWSUBSCR: + case ssdtREV2: + case ssdtBSZELDA: + case ssdtBSZELDAMODIFIED: + case ssdtBSZELDAENHANCED: + case ssdtBSZELDACOMPLETE: + { + tempsub = default_subscreen_active[tempsubscreen][0]; + int i; + + for(i=0; (i 1) + { + for(int i = 0; i < NUMSCRIPTITEM; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &itemscripts[i]); + + if(ret != 0) return qe_invalid; + } + + for(int i = 0; i < NUMSCRIPTGUYS; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &guyscripts[i]); + + if(ret != 0) return qe_invalid; + } + + for(int i = 0; i < NUMSCRIPTWEAPONS; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &wpnscripts[i]); + + if(ret != 0) return qe_invalid; + } + + for(int i = 0; i < NUMSCRIPTSCREEN; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &screenscripts[i]); + + if(ret != 0) return qe_invalid; + } + + if(s_version > 4) + { + for(int i = 0; i < NUMSCRIPTGLOBAL; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &globalscripts[i]); + + if(ret != 0) return qe_invalid; + } + } + else + { + for(int i = 0; i < NUMSCRIPTGLOBALOLD; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &globalscripts[i]); + + if(ret != 0) return qe_invalid; + } + + if(globalscripts[GLOBAL_SCRIPT_CONTINUE] != NULL) + delete [] globalscripts[GLOBAL_SCRIPT_CONTINUE]; + + globalscripts[GLOBAL_SCRIPT_CONTINUE] = new ffscript[1]; + globalscripts[GLOBAL_SCRIPT_CONTINUE][0].command = 0xFFFF; + } + + for(int i = 0; i < NUMSCRIPTLINK; i++) + { + ret = read_one_ffscript(f, Header, keepdata, i, s_version, s_cversion, &linkscripts[i]); + + if(ret != 0) return qe_invalid; + } + } + + if(s_version > 2) + { + long bufsize; + p_igetl(&bufsize, f, true); + char * buf = new char[bufsize+1]; + pfread(buf, bufsize, f, true); + buf[bufsize]=0; + + if(keepdata) + zScript = string(buf); + + delete[] buf; + word numffcbindings; + p_igetw(&numffcbindings, f, true); + + for(int i=0; i 3) + { + word numitembindings; + p_igetw(&numitembindings, f, true); + + for(int i=0; i=2) + { + if(!p_igetl(&num_commands,f,true)) + { + return qe_invalid; + } + } + + if(keepdata) + { + //FIXME: + if((*script) != NULL) //Surely we want to do this regardless of keepdata? + delete [](*script); + + (*script) = new ffscript[num_commands]; //memory leak + } + + for(int j=0; j>3]; +extern int sfxdat; +extern DATAFILE *sfxdata; +const char *old_sfx_string[Z35] = +{ + "Arrow", "Sword beam", "Bomb blast", "Boomerang", "Subscreen cursor", + "Shield is hit", "Item chime", "Roar (Dodongo, Gohma)", "Shutter", "Enemy dies", + "Enemy is hit", "Low hearts warning", "Fire", "Ganon's fanfare", "Boss is hit", "Hammer", + "Hookshot", "Message", "Link is hit", "Item fanfare", "Bomb placed", "Item pickup", + "Refill", "Roar (Aquamentus, Gleeok, Ganon)", "Item pickup 2", "Ocean ambience", + "Secret chime", "Link dies", "Stairs", "Sword", "Roar (Manhandla, Digdogger, Patra)", + "Wand magic", "Whistle", "Zelda's fanfare", "Charging weapon", "Charging weapon 2", + "Din's Fire", "Enemy falls from ceiling", "Farore's Wind", "Fireball", "Tall Grass slashed", + "Pound pounded", "Hover Boots", "Ice magic", "Jump", "Lens of Truth off", "Lens of Truth on", + "Nayru's Love shield", "Nayru's Love shield 2", "Push block", "Rock", "Spell rocket down", + "Spell rocket up", "Sword spin attack", "Splash", "Summon magic", "Sword tapping", + "Sword tapping (secret)", "Whistle whirlwind", "Cane of Byrna orbit" +}; +char *sfx_string[WAV_COUNT]; + +int readsfx(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + long dummy; + word s_version=0, s_cversion=0; + //int ret; + SAMPLE temp_sample; + temp_sample.loop_start=0; + temp_sample.loop_end=0; + temp_sample.param=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("SFX version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + /* HIGHLY UNORTHODOX UPDATING THING, by L + * This fixes quests made before revision 411 (such as the 'Lost Isle Build'), + * where the meaning of GOTOLESS changed. It also coincided with V_SFX + * changing from 1 to 2. + */ + if(s_version < 2 && keepdata) + set_bit(quest_rules,qr_GOTOLESSNOTEQUAL,1); + + /* End highly unorthodox updating thing */ + + int wavcount = WAV_COUNT; + + if(s_version < 6) + wavcount = 128; + + unsigned char tempflag[WAV_COUNT>>3]; + + if(s_version < 4) + { + memset(tempflag, 0xFF, WAV_COUNT>>3); + } + else + { + if(s_version < 6) + memset(tempflag, 0, WAV_COUNT>>3); + + for(int i=0; i<(wavcount>>3); i++) + { + p_getc(&tempflag[i], f, true); + } + + } + + if(keepdata) + memcpy(customsfxflag, tempflag, WAV_COUNT>>3); + + if(s_version>4) + { + for(int i=1; i=wavcount) + continue; + + char tempname[36]; + + if(!pfread(tempname, 36, f, keepdata)) + { + return qe_invalid; + } + + if(keepdata) + { + strcpy(sfx_string[i], tempname); + } + } + } + else + { + if(keepdata) + { + for(int i=1; i>3); + + int j=i; + + if(i>Z35) + { + i=Z35; + } + + SAMPLE *temp_sample = (SAMPLE *)sfxdata[i].dat; + + if(customsfxdata[j].data!=NULL) + { +// delete [] customsfxdata[j].data; + zc_free(customsfxdata[j].data); + } + +// customsfxdata[j].data = new byte[(temp_sample->bits==8?1:2)*temp_sample->len]; + customsfxdata[j].data = calloc((temp_sample->bits==8?1:2)*(temp_sample->stereo == 0 ? 1 : 2)*temp_sample->len,1); + customsfxdata[j].bits = temp_sample->bits; + customsfxdata[j].stereo = temp_sample->stereo; + customsfxdata[j].freq = temp_sample->freq; + customsfxdata[j].priority = temp_sample->priority; + customsfxdata[j].len = temp_sample->len; + customsfxdata[j].loop_start = temp_sample->loop_start; + customsfxdata[j].loop_end = temp_sample->loop_end; + customsfxdata[j].param = temp_sample->param; + memcpy(customsfxdata[j].data, (temp_sample->data), (temp_sample->bits==8?1:2)*(temp_sample->stereo==0 ? 1 : 2)*temp_sample->len); + i=j; + } +} + +extern char *guy_string[eMAXGUYS]; +extern const char *old_guy_string[OLDMAXGUYS]; + +int readguys(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + dword dummy; + word dummy2; + word guyversion=0; + + if(Header->zelda_version >= 0x193) + { + //section version info + if(!p_igetw(&guyversion,f,true)) + { + return qe_invalid; + } + + //al_trace("Guys version %d\n", guyversion); + if(!p_igetw(&dummy2,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + } + + if(guyversion > 3) + { + for(int i=0; i= OLDBETAMAXGUYS) + { + memset(tempname, 0, sizeof(char)*64); + sprintf(tempname, "e%03d", i); + strcpy(guy_string[i], tempname); + + continue; + } + + if(!pfread(tempname, 64, f, keepdata)) + { + return qe_invalid; + } + + // Don't retain names of uneditable enemy entries! + if(keepdata) + { + // for version upgrade to 2.5 + if(guyversion < 23 && i >= 177) + { + // some of the older builds have names such as 'zz123', + // (this order gets messed up with some eXXX and some zzXXX) + // so let's update to the newer naming convection. -Gleeok + char tmpbuf[64]; + memset(tmpbuf, 0, sizeof(char)*64); + sprintf(tmpbuf, "zz%03d", i); + + if(memcmp(tempname, tmpbuf, size_t(5)) == 0) + { + memset(tempname, 0, sizeof(char)*64); + sprintf(tempname, "e%03d", i); + } + } + + if(i >= OLDMAXGUYS || strlen(tempname)<1 || tempname[strlen(tempname)-1]!=' ') + { + strcpy(guy_string[i], tempname); + } + else + { + strcpy(guy_string[i],old_guy_string[i]); + } + } + } + } + else + { + if(keepdata) + { + for(int i=0; izelda_version < 0x211)||((Header->zelda_version == 0x211)&&(Header->build<7))) + { + if(get_bit(quest_rules,qr_NEWENEMYTILES)) + { + guysbuf[gGORIYA].tile=130; + guysbuf[gGORIYA].e_tile=130; + } + } + } + + if(Header->zelda_version < 0x193) + { + if(get_bit(deprecated_rules,46)) + { + guysbuf[eDODONGO].cset=14; + guysbuf[eDODONGO].bosspal=spDIG; + } + } + + // Not sure when this first changed, but it's necessary for 2.10, at least + if(Header->zelda_version <= 0x210) + { + guysbuf[eGLEEOK1F].misc6 = 16; + guysbuf[eGLEEOK2F].misc6 = 16; + guysbuf[eGLEEOK3F].misc6 = 16; + guysbuf[eGLEEOK4F].misc6 = 16; + + guysbuf[eWIZ1].misc4 = 1; + guysbuf[eBATROBE].misc4 = 1; + guysbuf[eSUMMONER].misc4 = 1; + guysbuf[eWWIZ].misc4 = 1; + } + + // The versions here may not be correct + // zelda_version>=0x211 handled at guyversion<24 + if(Header->zelda_version <= 0x190) + { + guysbuf[eCENT1].misc3 = 0; + guysbuf[eCENT2].misc3 = 0; + guysbuf[eMOLDORM].misc2 = 0; + } + else if(Header->zelda_version <= 0x210) + { + guysbuf[eCENT1].misc3 = 1; + guysbuf[eCENT2].misc3 = 1; + guysbuf[eMOLDORM].misc2 = 0; + } + + if(guyversion<=2) + { + return readlinksprites2(f, guyversion==2?0:-1, 0, keepdata); + } + + if(guyversion > 3) + { + guydata tempguy; + + for(int i=0; i= 256) + { + memset(&guysbuf[i], 0, sizeof(guydata)); + continue; + } + } + + memset(&tempguy, 0, sizeof(guydata)); + + if(!p_igetl(&(tempguy.flags),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.flags2),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.tile),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.width),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.height),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.s_tile),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.s_width),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.s_height),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.e_tile),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.e_width),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.e_height),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.hp),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.family),f,keepdata)) + { + return qe_invalid; + } + + if(guyversion < 9 && (i==eDKNUT1 || i==eDKNUT2 || i==eDKNUT3 || i==eDKNUT4 || i==eDKNUT5)) // Whoops, forgot about Darknuts... + { + if(get_bit(quest_rules,qr_NEWENEMYTILES)) + { + tempguy.s_tile=tempguy.e_tile+120; + tempguy.s_width=tempguy.e_width; + tempguy.s_height=tempguy.e_height; + } + else tempguy.s_tile=860; + } + + if(!p_igetw(&(tempguy.cset),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.anim),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.e_anim),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.frate),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.e_frate),f,keepdata)) + { + return qe_invalid; + } + + if(guyversion < 13) // April 2009 + { + if(get_bit(deprecated_rules, qr_SLOWENEMYANIM_DEP)) + { + tempguy.frate *= 2; + tempguy.e_frate *= 2; + } + } + + if(guyversion < 14) // May 1 2009 + { + if(tempguy.anim==a2FRMSLOW) + { + tempguy.anim=a2FRM; + tempguy.frate *= 2; + } + + if(tempguy.e_anim==a2FRMSLOW) + { + tempguy.e_anim=a2FRM; + tempguy.e_frate *= 2; + } + + if(tempguy.anim==aFLIPSLOW) + { + tempguy.anim=aFLIP; + tempguy.frate *= 2; + } + + if(tempguy.e_anim==aFLIPSLOW) + { + tempguy.e_anim=aFLIP; + tempguy.e_frate *= 2; + } + + if(tempguy.anim == aNEWDWALK) tempguy.anim = a4FRM4DIR; + + if(tempguy.e_anim == aNEWDWALK) tempguy.e_anim = a4FRM4DIR; + + if(tempguy.anim == aNEWPOLV || tempguy.anim == a4FRM3TRAP) + { + tempguy.anim=a4FRM4DIR; + tempguy.s_tile=(get_bit(quest_rules,qr_NEWENEMYTILES) ? tempguy.e_tile : tempguy.tile)+20; + } + + if(tempguy.e_anim == aNEWPOLV || tempguy.e_anim == a4FRM3TRAP) + { + tempguy.e_anim=a4FRM4DIR; + tempguy.s_tile=(get_bit(quest_rules,qr_NEWENEMYTILES) ? tempguy.e_tile : tempguy.tile)+20; + } + } + + if(!p_igetw(&(tempguy.dp),f,keepdata)) + { + return qe_invalid; + } + + //correction for guy fire + if(guyversion < 6) + { + if(i == gFIRE) + tempguy.dp = 2; + } + + if(!p_igetw(&(tempguy.wdp),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.weapon),f,keepdata)) + { + return qe_invalid; + } + + //correction for bosses using triple, "rising" fireballs + if(guyversion < 5) + { + if(i == eLAQUAM || i == eRAQUAM || i == eGOHMA1 || i == eGOHMA2 || + i == eGOHMA3 || i == eGOHMA4) + { + if(tempguy.weapon == ewFireball) + tempguy.weapon = ewFireball2; + } + } + + if(!p_igetw(&(tempguy.rate),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.hrate),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.step),f,keepdata)) + { + return qe_invalid; + } + + // HIGHLY UNORTHODOX UPDATING THING, part 2 + if(fixpolsvoice && tempguy.family==eePOLSV) + { + tempguy.step /= 2; + } + + if(!p_igetw(&(tempguy.homing),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.grumble),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.item_set),f,keepdata)) + { + return qe_invalid; + } + + if(guyversion>=22) // Version 22: Expand misc attributes to 32 bits + { + if(!p_igetl(&(tempguy.misc1),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc2),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc3),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc4),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc5),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc6),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc7),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc8),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc9),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc10),f,keepdata)) + { + return qe_invalid; + } + } + else + { + short tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc1=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc2=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc3=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc4=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc5=tempMisc; + + if(guyversion < 13) // April 2009 - a tiny Wizzrobe update + { + if(tempguy.family == eeWIZZ && !(tempguy.misc1)) + tempguy.misc5 = 74; + } + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc6=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc7=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc8=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc9=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc10=tempMisc; + } + + if(!p_igetw(&(tempguy.bgsfx),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.bosspal),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetw(&(tempguy.extend),f,keepdata)) + { + return qe_invalid; + } + + if(guyversion >= 16) // November 2009 - Super Enemy Editor + { + for(int j=0; j= 18) + { + if(!p_getc(&(tempguy.hitsfx),f,keepdata)) + { + return qe_invalid; + } + + if(!p_getc(&(tempguy.deadsfx),f,keepdata)) + { + return qe_invalid; + } + } + + if(guyversion >= 22) + { + if(!p_igetl(&(tempguy.misc11),f,keepdata)) + { + return qe_invalid; + } + + if(!p_igetl(&(tempguy.misc12),f,keepdata)) + { + return qe_invalid; + } + } + else if(guyversion >= 19) + { + short tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc11=tempMisc; + + if(!p_igetw(&tempMisc,f,keepdata)) + { + return qe_invalid; + } + + tempguy.misc12=tempMisc; + } + + //miscellaneous other corrections + //fix the mirror wizzrobe -DD + if(guyversion < 7) + { + if(i == eMWIZ) + { + tempguy.misc2 = 0; + tempguy.misc4 = 1; + } + } + + if(guyversion < 8) + { + if(i == eGLEEOK1 || i == eGLEEOK2 || i == eGLEEOK3 || i == eGLEEOK4 || i == eGLEEOK1F || i == eGLEEOK2F || i == eGLEEOK3F || i == eGLEEOK4F) + { + // Some of these are deliberately different to NewDefault/defdata.cpp, by the way. -L + tempguy.misc5 = 4; //neck length in segments + tempguy.misc6 = 8; //neck offset from first body tile + tempguy.misc7 = 40; //offset for each subsequent neck tile from the first neck tile + tempguy.misc8 = 168; //head offset from first body tile + tempguy.misc9 = 228; //flying head offset from first body tile + + if(i == eGLEEOK1F || i == eGLEEOK2F || i == eGLEEOK3F || i == eGLEEOK4F) + { + tempguy.misc6 += 10; //neck offset from first body tile + tempguy.misc8 -= 12; //head offset from first body tile + } + } + } + + if(guyversion < 10) // December 2007 - Dodongo CSet fix + { + if(get_bit(deprecated_rules,46) && tempguy.family==eeDONGO && tempguy.misc1==0) + tempguy.bosspal = spDIG; + } + + if(guyversion < 11) // December 2007 - Spinning Tile fix + { + if(tempguy.family==eeSPINTILE) + { + tempguy.flags |= guy_superman; + tempguy.item_set = 0; // Don't drop items + tempguy.step = 300; + } + } + + if(guyversion < 12) // October 2008 - Flashing Bubble, Rope 2, and Ghini 2 fix + { + if(get_bit(deprecated_rules, qr_NOROPE2FLASH_DEP)) + { + if(tempguy.family==eeROPE) + { + tempguy.flags2 &= ~guy_flashing; + } + } + + if(get_bit(deprecated_rules, qr_NOBUBBLEFLASH_DEP)) + { + if(tempguy.family==eeBUBBLE) + { + tempguy.flags2 &= ~guy_flashing; + } + } + + if((tempguy.family==eeGHINI)&&(tempguy.misc1)) + { + if(get_bit(deprecated_rules, qr_GHINI2BLINK_DEP)) + { + tempguy.flags2 |= guy_blinking; + } + + if(get_bit(deprecated_rules, qr_PHANTOMGHINI2_DEP)) + { + tempguy.flags2 |= guy_transparent; + } + } + } + + if(guyversion < 15) // July 2009 - Guy Fire and Fairy fix + { + if(i==gFIRE) + { + tempguy.e_anim = aFLIP; + tempguy.e_frate = 24; + } + + if(i==gFAIRY) + { + tempguy.e_anim = a2FRM; + tempguy.e_frate = 16; + } + } + + if(guyversion < 16) // November 2009 - Super Enemy Editor part 1 + { + if(i==0) Z_message("Updating guys to version 16...\n"); + + update_guy_1(&tempguy); + + if(i==eMPOLSV) + { + tempguy.defense[edefARROW] = edCHINK; + tempguy.defense[edefMAGIC] = ed1HKO; + tempguy.defense[edefREFMAGIC] = ed1HKO; + } + } + + if(guyversion < 17) // December 2009 + { + if(tempguy.family==eePROJECTILE) + { + tempguy.misc1 = 0; + } + } + + if(guyversion < 18) // January 2010 + { + bool boss = (tempguy.family == eeAQUA || tempguy.family==eeDONGO || tempguy.family == eeMANHAN || tempguy.family == eeGHOMA || tempguy.family==eeDIG + || tempguy.family == eeGLEEOK || tempguy.family==eePATRA || tempguy.family == eeGANON || tempguy.family==eeMOLD); + + tempguy.hitsfx = (boss && tempguy.family != eeMOLD && tempguy.family != eeDONGO && tempguy.family != eeDIG) ? WAV_GASP : 0; + tempguy.deadsfx = (boss && (tempguy.family != eeDIG || tempguy.misc10 == 0)) ? WAV_GASP : WAV_EDEAD; + + if(tempguy.family == eeAQUA) + for(int j=0; j=1) + { + tempguy.misc1++; + } + + tempguy.misc10 = 0; + } + + // Bomb Blast fix + if(tempguy.weapon==ewBomb && tempguy.family!=eeROPE && (tempguy.family!=eeWALK || tempguy.misc2 != e2tBOMBCHU)) + tempguy.weapon = ewLitBomb; + else if(tempguy.weapon==ewSBomb && tempguy.family!=eeROPE && (tempguy.family!=eeWALK || tempguy.misc2 != e2tBOMBCHU)) + tempguy.weapon = ewLitSBomb; + } + + if(guyversion < 21) // September 2011 + { + if(tempguy.family == eeKEESE || tempguy.family == eeKEESETRIB) + { + if(tempguy.family == eeKEESETRIB) + { + tempguy.family = eeKEESE; + tempguy.misc2 = e2tKEESETRIB; + tempguy.misc1 = 0; + } + + tempguy.rate = 2; + tempguy.hrate = 8; + tempguy.homing = 0; + tempguy.step= (tempguy.family == eeKEESE && tempguy.misc1 ? 100:62); + } + else if(tempguy.family == eePEAHAT || tempguy.family==eePATRA) + { + if(tempguy.family == eePEAHAT) + { + tempguy.rate = 4; + tempguy.step = 62; + } + else + tempguy.step = 25; + + tempguy.hrate = 8; + tempguy.homing = 0; + } + else if(tempguy.family == eeDIG || tempguy.family == eeMANHAN) + { + if(tempguy.family == eeMANHAN) + tempguy.step=50; + + tempguy.hrate = 16; + tempguy.homing = 0; + } + else if(tempguy.family == eeGLEEOK) + { + tempguy.rate = 2; + tempguy.homing = 0; + tempguy.hrate = 9; + tempguy.step=89; + } + else if(tempguy.family == eeGHINI) + { + tempguy.rate = 4; + tempguy.hrate = 12; + tempguy.step=62; + tempguy.homing = 0; + } + + // Bigdig random rate fix + if(tempguy.family==eeDIG && tempguy.misc10==1) + { + tempguy.rate = 2; + } + } + + if(guyversion < 24) // November 2012 + { + if(tempguy.family==eeLANM) + tempguy.misc3 = 1; + else if(tempguy.family==eeMOLD) + tempguy.misc2 = 0; + } + + if(keepdata) + { + guysbuf[i] = tempguy; + } + } + } + + return 0; +} + +void update_guy_1(guydata *tempguy) // November 2009 +{ + bool doesntcount = false; + tempguy->flags &= ~weak_arrow; // Formerly 'weak to arrow' which wasn't implemented + + switch(tempguy->family) + { + case 1: //eeWALK + switch(tempguy->misc10) + { + case 0: //Stalfos + if(tempguy->misc1==1) // Fires four projectiles at once + tempguy->misc1=4; + + break; + + case 1: //Darknut + goto darknuts; + break; + } + + tempguy->misc10 = 0; + break; + + case 2: //eeSHOOT + tempguy->family = eeWALK; + + switch(tempguy->misc10) + { + case 0: //Octorok + if(tempguy->misc1==1||tempguy->misc1==2) + { + tempguy->misc1=e1tFIREOCTO; + tempguy->misc2=e2tFIREOCTO; + } + else tempguy->misc1 = 0; + + tempguy->misc6=tempguy->misc4; + tempguy->misc4=tempguy->misc3; + tempguy->misc3=0; + break; + + case 1: // Moblin + tempguy->misc1 = 0; + break; + + case 2: //Lynel + tempguy->misc6=tempguy->misc1+1; + tempguy->misc1=0; + break; + + case 3: //Stalfos 2 + if(tempguy->misc1==1) // Fires four projectiles at once + tempguy->misc1=e1t4SHOTS; + else tempguy->misc1 = 0; + + break; + + case 4: //Darknut 5 +darknuts: + tempguy->defense[edefFIRE] = edIGNORE; + tempguy->defense[edefBRANG] = edSTUNORCHINK; + tempguy->defense[edefHOOKSHOT] = 0; + tempguy->defense[edefARROW] = tempguy->defense[edefBYRNA] = tempguy->defense[edefREFROCK] = + tempguy->defense[edefMAGIC] = tempguy->defense[edefSTOMP] = edCHINK; + + if(tempguy->misc1==1) + tempguy->misc1=2; + else if(tempguy->misc1==2) + { + tempguy->misc4=tempguy->misc3; + tempguy->misc3=tempguy->misc2; + tempguy->misc2=e2tSPLIT; + tempguy->misc1 = 0; + } + else tempguy->misc1 = 0; + + tempguy->flags |= inv_front; + + if(get_bit(deprecated_rules,qr_BRKBLSHLDS_DEP)) + tempguy->flags |= guy_bkshield; + + break; + } + + tempguy->misc10 = 0; + break; + + /* + case 9: //eeARMOS + tempguy->family = eeWALK; + break; + */ + case 11: //eeGEL + case 33: //eeGELTRIB + if(tempguy->family==33) + { + tempguy->misc4 = 1; + + if(get_bit(deprecated_rules, qr_OLDTRIBBLES_DEP)) //Old Tribbles + tempguy->misc3 = tempguy->misc2; + + tempguy->misc2 = e2tTRIBBLE; + } + else + { + tempguy->misc4 = 0; + tempguy->misc3 = 0; + tempguy->misc2 = 0; + } + + tempguy->family = eeWALK; + + if(tempguy->misc1) + { + tempguy->misc1=1; + tempguy->weapon = ewFireTrail; + } + + break; + + case 34: //eeZOLTRIB + case 12: //eeZOL + tempguy->misc4=tempguy->misc3; + tempguy->misc3=tempguy->misc2; + tempguy->family = eeWALK; + tempguy->misc2=e2tSPLITHIT; + + if(tempguy->misc1) + { + tempguy->misc1=1; + tempguy->weapon = ewFireTrail; + } + + break; + + case 13: //eeROPE + tempguy->family = eeWALK; + tempguy->misc9 = e9tROPE; + + if(tempguy->misc1) + { + tempguy->misc4 = tempguy->misc3; + tempguy->misc3 = tempguy->misc2; + tempguy->misc2 = e2tBOMBCHU; + } + + tempguy->misc1 = 0; + break; + + case 14: //eeGORIYA + tempguy->family = eeWALK; + + if(tempguy->misc1!=2) tempguy->misc1 = 0; + + break; + + case 17: //eeBUBBLE + tempguy->family = eeWALK; + tempguy->misc8 = tempguy->misc2; + tempguy->misc7 = tempguy->misc1 + 1; + tempguy->misc1 = tempguy->misc2 = 0; + + //fallthrogh + case eeTRAP: + case eeROCK: + doesntcount = true; + break; + + case 35: //eeVIRETRIB + case 18: //eeVIRE + tempguy->family = eeWALK; + tempguy->misc4=tempguy->misc3; + tempguy->misc3=tempguy->misc2; + tempguy->misc2=e2tSPLITHIT; + tempguy->misc9=e9tVIRE; + break; + + case 19: //eeLIKE + tempguy->family = eeWALK; + tempguy->misc7 = e7tEATITEMS; + tempguy->misc8=95; + break; + + case 20: //eePOLSV + tempguy->defense[edefBRANG] = edSTUNORCHINK; + tempguy->defense[edefBOMB] = tempguy->defense[edefSBOMB] = tempguy->defense[edefFIRE] = edIGNORE; + tempguy->defense[edefMAGIC] = tempguy->defense[edefBYRNA] = edCHINK; + tempguy->defense[edefARROW] = ed1HKO; + tempguy->defense[edefHOOKSHOT] = edSTUNONLY; + tempguy->family = eeWALK; + tempguy->misc9 = e9tPOLSVOICE; + tempguy->rate = 4; + tempguy->homing = 32; + tempguy->hrate = 10; + tempguy->grumble = 0; + break; + + case eeWIZZ: + if(tempguy->misc4) + { + for(int i=0; i < edefLAST; i++) + tempguy->defense[i] = (i != edefREFBEAM && i != edefREFMAGIC && i != edefQUAKE) ? edIGNORE : 0; + } + else + { + tempguy->defense[edefBRANG] = edSTUNORCHINK; + tempguy->defense[edefMAGIC] = edCHINK; + tempguy->defense[edefHOOKSHOT] = edSTUNONLY; + tempguy->defense[edefARROW] = tempguy->defense[edefFIRE] = + tempguy->defense[edefWAND] = tempguy->defense[edefBYRNA] = edIGNORE; + } + + break; + + case eePEAHAT: + tempguy->flags &= ~(guy_superman|guy_sbombonly); + + if(!(tempguy->flags & guy_bhit)) + tempguy->defense[edefBRANG] = edSTUNONLY; + + break; + + case eeLEV: + tempguy->defense[edefSTOMP] = edCHINK; + break; + } + + // Old flags + if(tempguy->flags & guy_superman) + { + for(int i = 0; i < edefLAST; i++) + if(!(i==edefSBOMB && (tempguy->flags & guy_sbombonly))) + tempguy->defense[i] = (i==edefBRANG && tempguy->defense[i] != edIGNORE + && tempguy->family != eeROCK && tempguy->family != eeTRAP + && tempguy->family != eePROJECTILE) ? edSTUNORIGNORE : edIGNORE; + } + + tempguy->flags &= ~(guy_superman|guy_sbombonly); + + if(doesntcount) + tempguy->flags |= (guy_doesntcount); +} + + +int readmapscreen(PACKFILE *f, zquestheader *Header, mapscr *temp_mapscr, zcmap *temp_map, word version) +{ + byte tempbyte, padding; + int extras, secretcombos; + + if(!p_getc(&(temp_mapscr->valid),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->guy),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<146))) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_mapscr->str=tempbyte; + } + else + { + if(!p_igetw(&(temp_mapscr->str),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->room),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->item),f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version < 0x211 || (Header->zelda_version == 0x211 && Header->build < 14)) + { + temp_mapscr->hasitem = (temp_mapscr->item != 0) ? 1 : 0; + } + else + { + if(!p_getc(&(temp_mapscr->hasitem),f,true)) + return qe_invalid; + } + + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<154))) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->tilewarptype[0]),f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->tilewarptype[i]),f,true)) + { + return qe_invalid; + } + } + } + else + { + temp_mapscr->tilewarptype[1]=0; + temp_mapscr->tilewarptype[2]=0; + temp_mapscr->tilewarptype[3]=0; + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>153))) + { + if(!p_igetw(&(temp_mapscr->door_combo_set),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->warpreturnx[0]),f,true)) + { + return qe_invalid; + } + + temp_mapscr->warpreturnx[1]=0; + temp_mapscr->warpreturnx[2]=0; + temp_mapscr->warpreturnx[3]=0; + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->warpreturnx[i]),f,true)) + { + return qe_invalid; + } + } + } + + if(!p_getc(&(temp_mapscr->warpreturny[0]),f,true)) + { + return qe_invalid; + } + + temp_mapscr->warpreturny[1]=0; + temp_mapscr->warpreturny[2]=0; + temp_mapscr->warpreturny[3]=0; + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->warpreturny[i]),f,true)) + { + return qe_invalid; + } + } + + if(version>=18) + { + if(!p_igetw(&temp_mapscr->warpreturnc,f,true)) + { + return qe_invalid; + } + } + else + { + byte temp; + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_mapscr->warpreturnc=temp<<8|temp; + } + } + + if(!p_getc(&(temp_mapscr->stairx),f,true)) + + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->stairy),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->itemx),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->itemy),f,true)) + { + return qe_invalid; + } + + if(version > 15) // February 2009 + { + if(!p_igetw(&(temp_mapscr->color),f,true)) + { + return qe_invalid; + } + } + else + { + if(!p_getc(& tempbyte,f,true)) + { + return qe_invalid; + } + + temp_mapscr->color = (word) tempbyte; + } + + if(!p_getc(&(temp_mapscr->enemyflags),f,true)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_getc(&(temp_mapscr->door[k]),f,true)) + { + return qe_invalid; + + } + } + + if(version <= 11) + { + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->tilewarpdmap[0]=(word)tempbyte; + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->tilewarpdmap[i]=(word)tempbyte; + } + } + else + { + temp_mapscr->tilewarpdmap[1]=0; + temp_mapscr->tilewarpdmap[2]=0; + temp_mapscr->tilewarpdmap[3]=0; + } + } + else + { + for(int i=0; i<4; i++) + { + if(!p_igetw(&(temp_mapscr->tilewarpdmap[i]),f,true)) + { + return qe_invalid; + } + } + } + + if(!p_getc(&(temp_mapscr->tilewarpscr[0]),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->tilewarpscr[i]),f,true)) + { + return qe_invalid; + } + } + } + else + { + temp_mapscr->tilewarpscr[1]=0; + temp_mapscr->tilewarpscr[2]=0; + temp_mapscr->tilewarpscr[3]=0; + } + + if(version >= 15) + { + if(!p_getc(&(temp_mapscr->tilewarpoverlayflags),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->tilewarpoverlayflags=0; + } + + if(!p_getc(&(temp_mapscr->exitdir),f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + } + + if((Header->zelda_version == 0x192)&&(Header->build>145)&&(Header->build<154)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + for(int k=0; k<10; k++) + { + /* + if (!temp_mapscr->enemy[k]) + { + continue; + } + */ + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<10))) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_mapscr->enemy[k]=tempbyte; + } + else + { + if(!p_igetw(&(temp_mapscr->enemy[k]),f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<108))) + { + //using enumerations here is dangerous + //very easy to break old quests -DD + if(temp_mapscr->enemy[k]>=57) //old eGOHMA1 + { + temp_mapscr->enemy[k]+=5; + } + else if(temp_mapscr->enemy[k]>=52) //old eGLEEOK2 + { + temp_mapscr->enemy[k]+=1; + } + } + + if(version < 9) + { + if(temp_mapscr->enemy[k]>0) + { + temp_mapscr->enemy[k]+=10; + } + } + } + + if(!p_getc(&(temp_mapscr->pattern),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->sidewarptype[0]),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->sidewarptype[i]),f,true)) + { + return qe_invalid; + } + } + } + else + { + temp_mapscr->sidewarptype[1]=0; + temp_mapscr->sidewarptype[2]=0; + temp_mapscr->sidewarptype[3]=0; + } + + if(version >= 15) + { + if(!p_getc(&(temp_mapscr->sidewarpoverlayflags),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->sidewarpoverlayflags=0; + } + + if(!p_getc(&(temp_mapscr->warparrivalx),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->warparrivaly),f,true)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_getc(&(temp_mapscr->path[k]),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->sidewarpscr[0]),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(temp_mapscr->sidewarpscr[i]),f,true)) + { + return qe_invalid; + } + } + } + else + { + temp_mapscr->sidewarpscr[1]=0; + temp_mapscr->sidewarpscr[2]=0; + temp_mapscr->sidewarpscr[3]=0; + } + + if(version <= 11) + { + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->sidewarpdmap[0]=(word)tempbyte; + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + for(int i=1; i<4; i++) + { + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->sidewarpdmap[i]=(word)tempbyte; + } + } + else + { + temp_mapscr->sidewarpdmap[1]=0; + temp_mapscr->sidewarpdmap[2]=0; + temp_mapscr->sidewarpdmap[3]=0; + } + } + else + { + for(int i=0; i<4; i++) + { + if(!p_igetw(&(temp_mapscr->sidewarpdmap[i]),f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + if(!p_getc(&(temp_mapscr->sidewarpindex),f,true)) + { + return qe_invalid; + } + } + else temp_mapscr->sidewarpindex = 0; + + if(!p_igetw(&(temp_mapscr->undercombo),f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version < 0x193) + { + if(!p_getc(&(temp_mapscr->old_cpage),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->undercset),f,true)) //recalculated for older quests + { + return qe_invalid; + } + + if(!p_igetw(&(temp_mapscr->catchall),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags2),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags3),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>1))) + //if (version>2) + { + if(!p_getc(&(temp_mapscr->flags4),f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>7))) + { + if(!p_getc(&(temp_mapscr->flags5),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_mapscr->noreset),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_mapscr->nocarry),f,true)) + { + return qe_invalid; + } + + if(temp_mapscr->flags5&32) + { + temp_mapscr->flags5 &= ~32; + temp_mapscr->noreset |= 48; + } + + if(version<8) + { + if(temp_mapscr->noreset&1) + { + temp_mapscr->noreset|=8192; + } + + if(temp_mapscr->nocarry&1) + { + temp_mapscr->nocarry|=8192; + temp_mapscr->nocarry&=~1; + } + } + } + else + { + temp_mapscr->flags5 = 0; + temp_mapscr->noreset = 0; + temp_mapscr->nocarry = 0; + } + + if((Header->zelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>9))) + { + if(!p_getc(&(temp_mapscr->flags6),f,true)) + { + return qe_invalid; + } + } + + if(version>5) + { + if(!p_getc(&(temp_mapscr->flags7),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags8),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags9),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->flags10),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->csensitive),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->csensitive=1; + } + + if(version<14) // August 2007: screen SFX added + { + if(temp_mapscr->flags&8) //fROAR + { + temp_mapscr->bosssfx= + (temp_mapscr->flags3&2) ? WAV_DODONGO : // fDODONGO + (temp_mapscr->flags2&32) ? WAV_VADER : // fVADER + WAV_ROAR; + } + + if(temp_mapscr->flags&128) //fSEA + { + temp_mapscr->oceansfx=WAV_SEA; + } + + if(!(temp_mapscr->flags3&64)) //fNOSECRETSOUND + { + temp_mapscr->secretsfx=WAV_SECRET; + } + + temp_mapscr->flags3 &= ~66; //64|2 + temp_mapscr->flags2 &= ~32; + temp_mapscr->flags &= ~136; // 128|8 + } + else + { + if(!p_getc(&(temp_mapscr->oceansfx),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->bosssfx),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->secretsfx),f,true)) + { + return qe_invalid; + } + } + + if(version<15) // October 2007: another SFX + { + temp_mapscr->holdupsfx=WAV_PICKUP; + } + else + { + if(!p_getc(&(temp_mapscr->holdupsfx),f,true)) + { + return qe_invalid; + } + } + + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>97))) + { + for(int k=0; k<6; k++) + { + if(!p_getc(&(temp_mapscr->layermap[k]),f,true)) + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&(temp_mapscr->layerscreen[k]),f,true)) + { + return qe_invalid; + } + } + } + else if((Header->zelda_version == 0x192)&&(Header->build>23)&&(Header->build<98)) + { + if(!p_getc(&(temp_mapscr->layermap[2]),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->layerscreen[2]),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->layermap[4]),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->layerscreen[4]),f,true)) + + { + return qe_invalid; + } + } + + if((Header->zelda_version == 0x192)&&(Header->build>149)) + { + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layerxsize + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layerxspeed + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layerxdelay + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layerysize + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layeryspeed + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_getc(&tempbyte,f,true)) //layerydelay + { + return qe_invalid; + } + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>149))) + { + for(int k=0; k<6; k++) + { + if(!p_getc(&(temp_mapscr->layeropacity[k]),f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>153))) + { + if((Header->zelda_version == 0x192)&&(Header->build>153)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + if(!p_igetw(&(temp_mapscr->timedwarptics),f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<24))) + { + extras=15; + } + else if(((Header->zelda_version == 0x192)&&(Header->build<98))) + { + extras=11; + } + else if((Header->zelda_version == 0x192)&&(Header->build<150)) + { + extras=32; + } + else if((Header->zelda_version == 0x192)&&(Header->build<154)) + { + extras=64; + } + else if(Header->zelda_version < 0x193) + { + extras=62; + } + else + + { + extras=0; + } + + for(int k=0; kzelda_version > 0x211)||((Header->zelda_version == 0x211)&&(Header->build>2))) + //if (version>3) + { + if(!p_getc(&(temp_mapscr->nextmap),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->nextscr),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->nextmap=0; + temp_mapscr->nextscr=0; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<137))) + { + secretcombos=20; + } + else if((Header->zelda_version == 0x192)&&(Header->build<154)) + { + secretcombos=256; + } + else + { + secretcombos=128; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<154))) + { + for(int k=0; ksecretcombo[k]=tempbyte; + } + } + } + else + { + for(int k=0; k<128; k++) + { + if(!p_igetw(&(temp_mapscr->secretcombo[k]),f,true)) + { + return qe_invalid; + } + + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>153))) + { + for(int k=0; k<128; k++) + { + if(!p_getc(&(temp_mapscr->secretcset[k]),f,true)) + { + return qe_invalid; + } + } + + for(int k=0; k<128; k++) + { + if(!p_getc(&(temp_mapscr->secretflag[k]),f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version == 0x192)&&(Header->build>97)&&(Header->build<154)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + const int _mapsSize = (temp_map->tileWidth*temp_map->tileHeight); + + temp_mapscr->data.resize(_mapsSize, 0); + temp_mapscr->sflag.resize(_mapsSize, 0); + temp_mapscr->cset.resize(_mapsSize, 0); + + for(int k=0; k<(temp_map->tileWidth*temp_map->tileHeight); k++) + { + if(!p_igetw(&(temp_mapscr->data[k]),f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version == 0x192)&&(Header->build>20)&&(Header->build<24)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>20))) + { + for(int k=0; k<(temp_map->tileWidth*temp_map->tileHeight); k++) + { + if(!p_getc(&(temp_mapscr->sflag[k]),f,true)) + { + return qe_invalid; + } + + if((Header->zelda_version == 0x192)&&(Header->build<24)) + { + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + } + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>97))) + { + for(int k=0; k<(temp_map->tileWidth*temp_map->tileHeight); k++) + { + + if(!p_getc(&(temp_mapscr->cset[k]),f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<154))) + { + temp_mapscr->undercset=(temp_mapscr->undercombo>>8)&7; + temp_mapscr->undercombo=(temp_mapscr->undercombo&0xFF)+(temp_mapscr->old_cpage<<8); + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<137))) + { + temp_mapscr->secretcombo[sSBOMB]=temp_mapscr->secretcombo[sBOMB]; + temp_mapscr->secretcombo[sRCANDLE]=temp_mapscr->secretcombo[sBCANDLE]; + temp_mapscr->secretcombo[sWANDFIRE]=temp_mapscr->secretcombo[sBCANDLE]; + temp_mapscr->secretcombo[sDINSFIRE]=temp_mapscr->secretcombo[sBCANDLE]; + temp_mapscr->secretcombo[sSARROW]=temp_mapscr->secretcombo[sARROW]; + temp_mapscr->secretcombo[sGARROW]=temp_mapscr->secretcombo[sARROW]; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<154))) + { + for(int k=0; k<(temp_map->tileWidth*temp_map->tileHeight); k++) + { + if((Header->zelda_version == 0x192)&&(Header->build>149)) + { + if((Header->zelda_version == 0x192)&&(Header->build!=153)) + { + temp_mapscr->cset[k]=((temp_mapscr->data[k]>>8)&7); + } + } + else + { + if((Header->zelda_version < 0x192)|| + ((Header->zelda_version == 0x192)&&(Header->build<21))) + { + temp_mapscr->sflag[k]=(temp_mapscr->data[k]>>11); + } + + temp_mapscr->cset[k]=((temp_mapscr->data[k]>>8)&7); + } + + temp_mapscr->data[k]=(temp_mapscr->data[k]&0xFF)+(temp_mapscr->old_cpage<<8); + } + } + + /*if(version>12) + { + if(!p_getc(&(temp_mapscr->scrWidth),f,true)) + { + return qe_invalid; + } + if(!p_getc(&(temp_mapscr->scrHeight),f,true)) + { + return qe_invalid; + } + }*/ + + if(version>4) + { + if(!p_igetw(&(temp_mapscr->screen_midi),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->screen_midi = -1; + } + + if(version>=17) + { + if(!p_getc(&(temp_mapscr->lens_layer),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->lens_layer = llNORMAL; + } + + if(version>6) + { + if(!p_igetl(&(temp_mapscr->ffcsUsed),f,true)) + { + return qe_invalid; + } + + int m; + float tempfloat; + + for(m=0; mffcsUsed>>m)&1) + { + if(!p_igetw(&(temp_mapscr->ffcs[m].data),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->ffcs[m].cset),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_mapscr->ffcs[m].delay),f,true)) + { + return qe_invalid; + } + + if(version < 9) + { + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].x=int(tempfloat*10000); + + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].y=int(tempfloat*10000); + + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].xVel=int(tempfloat*10000); + + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].yVel=int(tempfloat*10000); + + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].xAccel=int(tempfloat*10000); + + if(!p_igetf(&tempfloat,f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].yAccel=int(tempfloat*10000); + } + else + { + if(!p_igetl(&(temp_mapscr->ffcs[m].x),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].y),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].xVel),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].yVel),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].xAccel),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].yAccel),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(temp_mapscr->ffcs[m].link),f,true)) + { + return qe_invalid; + } + + if(version>7) + { + if(!p_getc(&(temp_mapscr->ffcs[m].width),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_mapscr->ffcs[m].height),f,true)) + { + return qe_invalid; + } + + if(!p_igetl(&(temp_mapscr->ffcs[m].flags),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->ffcs[m].width=15; + temp_mapscr->ffcs[m].height=15; + temp_mapscr->ffcs[m].flags=0; + } + + if(Header->zelda_version == 0x211 || (Header->zelda_version == 0x250 && Header->build<20)) + { + temp_mapscr->ffcs[m].flags|=ffIGNOREHOLDUP; + } + + if(version>9) + { + if(!p_igetw(&(temp_mapscr->ffcs[m].script),f,true)) + { + return qe_invalid; + } + } + else + { + temp_mapscr->ffcs[m].script=0; + } + + if(version>10) + { + for(int i=0; i<8; i++) + { + if(!p_igetl(&(temp_mapscr->ffcs[m].initd[i]),f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].inita[0]=tempbyte*10000; + + if(!p_getc(&(tempbyte),f,true)) + { + return qe_invalid; + } + + temp_mapscr->ffcs[m].inita[1]=tempbyte*10000; + } + else + { + temp_mapscr->ffcs[m].inita[0] = 10000; + temp_mapscr->ffcs[m].inita[1] = 10000; + } + + // Unnecessary? + temp_mapscr->ffcs[m].initialized = false; + + if(version <= 11) + { + fixffcs=true; + } + } + else + temp_mapscr->ffcs[m].clear(); + } + } + + //add in the new whistle flags + if(version<13) + { + if(temp_mapscr->flags & fWHISTLE) + { + temp_mapscr->flags7 |= (fWHISTLEPAL | fWHISTLEWATER); + } + } + + return 0; +} + + + +int readmaps(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + + int scr=0; + + word version=0; + dword dummy; + int screens_to_read; + + mapscr temp_mapscr; + zcmap temp_map; + word temp_map_count; + dword section_size; + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<137))) + { + screens_to_read=MAPSCRS192b136; + } + else + { + screens_to_read=MAPSCRS; + } + + if(Header->zelda_version > 0x192) + { + //section version info + if(!p_igetw(&version,f,true)) + { + return qe_invalid; + } + + //al_trace("Maps version %d\n", version); + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(§ion_size,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&temp_map_count,f,true)) + { + return 5; + } + } + else + { + temp_map_count=map_count; + } + + + if(keepdata==true) + { + const int _mapsSize = MAPSCRS*temp_map_count; + TheMaps.resize(_mapsSize); + + for(int i(0); i<_mapsSize; i++) + TheMaps[i].zero_memory(); + } + + if(keepdata==true) + { + memset(ZCMaps, 0, sizeof(zcmap)*MAXMAPS2); + } + + temp_mapscr.zero_memory(); + + for(int i=0; i12) + { + if(!p_getc(&(temp_map.tileWidth),f,true)) + { + return qe_invalid; + } + if(!p_getc(&(temp_map.tileHeight),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.subaWidth),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.subaHeight),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.subpWidth),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.subpHeight),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.scrResWidth),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.scrResHeight),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.viewWidth),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.viewHeight),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.viewX),f,true)) + { + return qe_invalid; + } + if(!p_igetw(&(temp_map.viewY),f,true)) + { + return qe_invalid; + } + if(!p_getc(&(temp_map.subaTrans),f,true)) + { + return qe_invalid; + } + if(!p_getc(&(temp_map.subpTrans),f,true)) + { + return qe_invalid; + } + } + else + {*/ + temp_map.scrResWidth = 256; + temp_map.scrResHeight = 224; + temp_map.tileWidth = 16; + temp_map.tileHeight = 11; + temp_map.viewWidth = 256; + temp_map.viewHeight = 176; + temp_map.viewX = 0; + temp_map.viewY = 64; + temp_map.subaWidth = 256; + temp_map.subaHeight = 168; + temp_map.subaTrans = false; + temp_map.subpWidth = 256; + temp_map.subpHeight = 56; + temp_map.subpTrans = false; + + //} + for(int j=0; jzelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<137))) + { + int index = (i*MAPSCRS+132); + +// delete_theMaps_data(index); + TheMaps[index]=TheMaps[index-1]; + + const int _mapsSize = (temp_map.tileWidth)*(temp_map.tileHeight); + + //err...what? @_@ + TheMaps[index].data.resize(_mapsSize, 0); + TheMaps[index].sflag.resize(_mapsSize, 0); + TheMaps[index].cset.resize(_mapsSize, 0); + + TheMaps[i*MAPSCRS+132].data = TheMaps[i*MAPSCRS+131].data; + TheMaps[i*MAPSCRS+132].sflag = TheMaps[i*MAPSCRS+131].sflag; + TheMaps[i*MAPSCRS+132].cset = TheMaps[i*MAPSCRS+131].cset; + + for(int j=133; jzelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<154))) + { + for(int j=0; j 0x192) + { + //section version info + if(!p_igetw(§ion_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Combos version %d\n", section_version); + if(!p_igetw(§ion_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + } + + if(version < 0x174) + { + combos_used=1024; + } + else if(version < 0x191) + { + combos_used=2048; + } + else + { + if(!p_igetw(&combos_used,f,true)) + { + return qe_invalid; + } + } + + //finally... section data + for(int i=0; i=3) + { + if(!p_getc(&temp_combo.flag,f,true)) + { + return qe_invalid; + } + } + + if(section_version>=4) + { + if(!p_getc(&temp_combo.skipanim,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_combo.nexttimer,f,true)) + { + return qe_invalid; + } + } + + if(section_version>=5) + { + if(!p_getc(&temp_combo.skipanimy,f,true)) + { + return qe_invalid; + } + } + + if(section_version>=6) + { + if(!p_getc(&temp_combo.animflags,f,true)) + { + return qe_invalid; + } + + if(section_version == 6) + temp_combo.animflags = temp_combo.animflags ? AF_FRESH : 0; + } + + if(version < 0x193) + { + for(int q=0; q<11; q++) + { + if(!p_getc(&dummy,f,true)) + { + return qe_invalid; + } + } + } + + //Goriya tiles were flipped around in 2.11 build 7. Compensate for the flip here. -DD + if((version < 0x211)||((version == 0x211)&&(build<7))) + { + if(!get_bit(quest_rules,qr_NEWENEMYTILES)) + { + switch(temp_combo.tile) + { + case 130: + temp_combo.tile = 132; + break; + + case 131: + temp_combo.tile = 133; + break; + + case 132: + temp_combo.tile = 130; + break; + + case 133: + temp_combo.tile = 131; + break; + } + } + } + + if(keepdata==true && i>=start_combo) + { + memcpy(&combobuf[i], &temp_combo, sizeof(temp_combo)); + } + } + + if(keepdata==true) + { + if((version < 0x192)|| ((version == 0x192)&&(build<185))) + { + for(int tmpcounter=0; tmpcounter 0x192) + { + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Color data version %d\n", s_version); + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + } + + //finally... section data + for(int i=0; i 0x192) + { + for(int i=0; i<256; i++) + { + for(int j=0; j<3; j++) + { + temp_misc.cycles[i][j].first=0; + temp_misc.cycles[i][j].count=0; + temp_misc.cycles[i][j].speed=0; + } + } + + if(!p_igetw(&palcycles,f,true)) + { + return qe_invalid; + } + + for(int i=0; idata_flags[ZQ_TILES]&&!from_init)) //keep for old quests + { + if(keepdata==true) + { + if(!init_tiles(true, Header)) + { + al_trace("Unable to initialize tiles\n"); + } + } + + delete[] temp_tile; + temp_tile=NULL; + return 0; + } + else + { + if(version > 0x192) + { + //section version info + if(!p_igetw(&dummy,f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + + if(!p_igetw(&dummy,f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + } + + if(version < 0x174) + { + tiles_used=TILES_PER_PAGE*4; + } //no expanded tile space + else if(version < 0x191) + { + tiles_used=OLDMAXTILES; + } + else + { + //finally... section data + + if(!p_igetw(&tiles_used,f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + } + + tiles_used=zc_min(tiles_used, max_tiles); + + tiles_used=zc_min(tiles_used, NEWMAXTILES-start_tile); + + for(word i=0; i0x211)||((version==0x211)&&(build>4))) + { + if(!p_getc(&format,f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + } + + if(!pfread(temp_tile,tilesize(format),f,true)) + { + delete[] temp_tile; + return qe_invalid; + } + + if(keepdata==true) + { + buf[start_tile+i].format=format; + + if(buf[start_tile+i].data) + { + zc_free(buf[start_tile+i].data); + buf[start_tile+i].data=NULL; + } + + buf[start_tile+i].data=(byte *)zc_malloc(tilesize(buf[start_tile+i].format)); + memcpy(buf[start_tile+i].data,temp_tile,tilesize(buf[start_tile+i].format)); + } + } + } + + if(keepdata==true) + { + for(int i=start_tile+tiles_used; izelda_version < 0x193) + { + // mf=Header->data_flags+ZQ_MIDIS2; + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<178))) + { + tunes_to_read=MAXCUSTOMMIDIS192b177; + } + else + { + tunes_to_read=MAXCUSTOMTUNES; + } + } + else + { + //section version info + if(!p_igetw(§ion_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Tunes version %d\n", section_version); + if(!p_igetw(&dummy2,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!pfread(midi_flags,sizeof(midi_flags),f,true)) + { + return qe_invalid; + } + + tunes_to_read=MAXCUSTOMTUNES; + } + + for(int i=0; izelda_version < 0x193) + { + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + } + + if(section_version >= 3) + { + if(!pfread(&temp.flags,sizeof(temp.flags),f,true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + tunes[i].copyfrom(temp); // memcpy(&midis[i], &temp_midi, sizeof(zcmidi_)); + } + + if(section_version < 2) //= 1 || (Header->zelda_version < 0x211) || (Header->zelda_version == 0x211 && Header->build < 18)) + { + // old format - a midi is a midi + if(((keepdata==true?tunes[i].data:temp.data)=read_midi(f, true))==NULL) + { + return qe_invalid; + } + + //yes you can do this. Isn't the ? operator awesome? :) + (keepdata ? tunes[i] : temp).format = MFORMAT_MIDI; + } + else + { + // 'midi' could be midi or nes, gb, ... music + if(!pfread(&(keepdata ? tunes[i] : temp).format,sizeof((keepdata ? tunes[i] : temp).format),f,true)) + { + return qe_invalid; + } + + zctune *ptr = (keepdata==true)?&(tunes[i]):&temp; + + switch(temp.format) + { + case MFORMAT_MIDI: + if((ptr->data=read_midi(f, true))==NULL) + { + return qe_invalid; + } + + break; + + default: + return qe_invalid; + break; + } + } + } + } + + return 0; +} + +int readcheatcodes(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + int dummy; + ZCHEATS tempzcheats; + char temp_use_cheats=1; + memset(&tempzcheats, 0, sizeof(tempzcheats)); + + if(Header->zelda_version > 0x192) + { + //section version info + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //al_trace("Cheats version %d\n", dummy); + if(!p_igetw(&dummy,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_getc(&temp_use_cheats,f,true)) + { + return qe_invalid; + } + } + + if(Header->data_flags[ZQ_CHEATS2]) + { + if(!p_igetl(&tempzcheats.flags,f,true)) + { + return qe_invalid; + } + + if(!pfread(&tempzcheats.codes, sizeof(tempzcheats.codes), f,true)) + { + return qe_invalid; + } + } + + if(keepdata==true) + { + memcpy(&zcheats, &tempzcheats, sizeof(tempzcheats)); + Header->data_flags[ZQ_CHEATS2]=temp_use_cheats; + } + + return 0; +} + +int readinitdata(PACKFILE *f, zquestheader *Header, bool keepdata) +{ + int dummy; + word s_version=0, s_cversion=0; + byte padding; + + zinitdata temp_zinit; + memset(&temp_zinit, 0, sizeof(zinitdata)); + + + // Legacy item properties (now integrated into itemdata) + byte sword_hearts[4]; + byte beam_hearts[4]; + byte beam_percent=0; + word beam_power[4]; + byte hookshot_length=99; + byte hookshot_links=100; + byte longshot_length=99; + byte longshot_links=100; + byte moving_fairy_hearts=3; + byte moving_fairy_heart_percent=0; + byte stationary_fairy_hearts=3; + byte stationary_fairy_heart_percent=0; + byte moving_fairy_magic=0; + byte moving_fairy_magic_percent=0; + byte stationary_fairy_magic=0; + byte stationary_fairy_magic_percent=0; + byte blue_potion_hearts=100; + byte blue_potion_heart_percent=1; + byte red_potion_hearts=100; + byte red_potion_heart_percent=1; + byte blue_potion_magic=100; + byte blue_potion_magic_percent=1; + byte red_potion_magic=100; + byte red_potion_magic_percent=1; + + temp_zinit.subscreen_style=get_bit(quest_rules,qr_COOLSCROLL)?1:0; + temp_zinit.max_rupees=255; + temp_zinit.max_keys=255; + temp_zinit.hcp_per_hc=4; + temp_zinit.bomb_ratio=4; + + for(int i=0; izelda_version > 0x192) + { + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Init data version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy,f,true)) + { + return qe_invalid; + } + } + + /* HIGHLY UNORTHODOX UPDATING THING, by L + * This fixes quests made before revision 277 (such as the 'Lost Isle Build'), + * where the speed of Pols Voice changed. It also coincided with V_INITDATA + * changing from 13 to 14. + */ + if(keepdata && s_version < 14) + fixpolsvoice=true; + + /* End highly unorthodox updating thing */ + + temp_zinit.ss_grid_x=8; + temp_zinit.ss_grid_y=8; + temp_zinit.ss_grid_xofs=0; + temp_zinit.ss_grid_yofs=0; + temp_zinit.ss_grid_color=8; + temp_zinit.ss_bbox_1_color=15; + temp_zinit.ss_bbox_2_color=7; + temp_zinit.ss_flags=0; + temp_zinit.gravity=16; + temp_zinit.terminalv=320; + temp_zinit.msg_speed=5; + temp_zinit.transition_type=0; + temp_zinit.jump_link_layer_threshold=255; + + if(s_version >= 15 && get_bit(deprecated_rules, 27)) // The short-lived rule, qr_JUMPLINKLAYER3 + temp_zinit.jump_link_layer_threshold=0; + + if(s_version >= 10) + { + char temp; + + //new-style items + for(int j=0; j<256; j++) + { + if(!p_getc(&temp,f,true)) + return qe_invalid; + + temp_zinit.items[j] = (temp != 0); + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>26))) + { + char temp; + + //finally... section data + if((Header->zelda_version > 0x192)|| + //new only + ((Header->zelda_version == 0x192)&&(Header->build>173))) + { + //OLD-style items... sigh + if(s_version < 10) + { + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iRaft]=(temp != 0); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iLadder]=(temp != 0); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iBook]=(temp != 0); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iMKey]=(temp!=0); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iFlippers]=(temp != 0); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iBoots]=(temp!=0); + } + } + + if(s_version < 10) + { + char tempring, tempsword, tempshield, tempwallet, tempbracelet, tempamulet, tempbow; + + if(!p_getc(&tempring,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempsword,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempshield,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempwallet,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempbracelet,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempamulet,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempbow,f,true)) + { + return qe_invalid; + } + + //old only + if((Header->zelda_version == 0x192)&&(Header->build<174)) + { + tempring=(tempring)?(1<<(tempring-1)):0; + tempsword=(tempsword)?(1<<(tempsword-1)):0; + tempshield=(tempshield)?(1<<(tempshield-1)):0; + tempwallet=(tempwallet)?(1<<(tempwallet-1)):0; + tempbracelet=(tempbracelet)?(1<<(tempbracelet-1)):0; + tempamulet=(tempamulet)?(1<<(tempamulet-1)):0; + tempbow=(tempbow)?(1<<(tempbow-1)):0; + } + + //rings start at level 2... wtf + //account for this -DD + tempring <<= 1; + addOldStyleFamily(&temp_zinit, itemsbuf, itype_ring, tempring); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_sword, tempsword); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_shield, tempshield); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_wallet, tempwallet); + //bracelet ALSO starts at level 2 :-( -DD + tempbracelet<<=1; + addOldStyleFamily(&temp_zinit, itemsbuf, itype_bracelet, tempbracelet); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_amulet, tempamulet); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_bow, tempbow); + + //new only + if((Header->zelda_version == 0x192)&&(Header->build>173)) + { + for(int q=0; q<32; q++) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + } + + char tempcandle, tempboomerang, temparrow, tempwhistle; + + if(!p_getc(&tempcandle,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&tempboomerang,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temparrow,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_potion, temp); + + if(!p_getc(&tempwhistle,f,true)) + { + return qe_invalid; + } + + //old only + if((Header->zelda_version == 0x192)&&(Header->build<174)) + { + tempcandle=(tempcandle)?(1<<(tempcandle-1)):0; + tempboomerang=(tempboomerang)?(1<<(tempboomerang-1)):0; + temparrow=(temparrow)?(1<<(temparrow-1)):0; + tempwhistle=(tempwhistle)?(1<<(tempwhistle-1)):0; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_candle, tempcandle); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_brang, tempboomerang); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_arrow, temparrow); + addOldStyleFamily(&temp_zinit, itemsbuf, itype_whistle, tempwhistle); + //What about the potion...? + + } + + //Oh sure, stick these IN THE MIDDLE OF THE ITEMS, just to make me want + //to jab out my eye... + if(!p_getc(&temp_zinit.bombs,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.super_bombs,f,true)) + { + return qe_invalid; + } + + //Back to more OLD item code + if(s_version < 10) + { + if((Header->zelda_version > 0x192)|| + //new only + ((Header->zelda_version == 0x192)&&(Header->build>173))) + { + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_wand, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_letter, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_lens, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_hookshot, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_bait, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_hammer, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_dinsfire, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_faroreswind, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_nayruslove, temp); + + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + if(Header->zelda_version == 0x192) + { + for(int q=0; q<32; q++) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + } + } + } + + //old only + if((Header->zelda_version == 0x192)&&(Header->build<174)) + { + byte equipment, items; //bit flags + + if(!p_getc(&equipment,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iRaft]=(get_bit(&equipment, idE_RAFT)!=0); + temp_zinit.items[iLadder]=(get_bit(&equipment, idE_LADDER)!=0); + temp_zinit.items[iBook]=(get_bit(&equipment, idE_BOOK)!=0); + temp_zinit.items[iMKey]=(get_bit(&equipment, idE_KEY)!=0); + temp_zinit.items[iFlippers]=(get_bit(&equipment, idE_FLIPPERS)!=0); + temp_zinit.items[iBoots]=(get_bit(&equipment, idE_BOOTS)!=0); + + + if(!p_getc(&items,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iWand]=(get_bit(&items, idI_WAND)!=0); + temp_zinit.items[iLetter]=(get_bit(&items, idI_LETTER)!=0); + temp_zinit.items[iLens]=(get_bit(&items, idI_LENS)!=0); + temp_zinit.items[iHookshot]=(get_bit(&items, idI_HOOKSHOT)!=0); + temp_zinit.items[iBait]=(get_bit(&items, idI_BAIT)!=0); + temp_zinit.items[iHammer]=(get_bit(&items, idI_HAMMER)!=0); + } + + if(!p_getc(&temp_zinit.hc,f,true)) + { + return qe_invalid; + } + + if(s_version < 14) + { + byte temphp; + + if(!p_getc(&temphp,f,true)) + { + return qe_invalid; + } + + temp_zinit.start_heart=temphp; + + if(!p_getc(&temphp,f,true)) + { + return qe_invalid; + } + + temp_zinit.cont_heart=temphp; + } + else + { + if(!p_igetw(&temp_zinit.start_heart,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.cont_heart,f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&temp_zinit.hcp,f,true)) + { + return qe_invalid; + } + + if(s_version >= 14) + { + if(!p_getc(&temp_zinit.hcp_per_hc,f,true)) + { + return qe_invalid; + } + + if(s_version<16) // July 2007 + { + if(get_bit(quest_rules,qr_BRANGPICKUP+1)) + temp_zinit.hcp_per_hc = 0xFF; + + //Dispose of legacy rule + set_bit(quest_rules,qr_BRANGPICKUP+1, 0); + } + } + + if(!p_getc(&temp_zinit.max_bombs,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.keys,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.rupies,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.triforce,f,true)) + { + return qe_invalid; + } + + if(s_version>12 || (Header->zelda_version == 0x211 && Header->build == 18)) + { + for(int i=0; i<64; i++) + { + if(!p_getc(&temp_zinit.map[i],f,true)) + { + return qe_invalid; + } + } + + for(int i=0; i<64; i++) + { + if(!p_getc(&temp_zinit.compass[i],f,true)) + { + return qe_invalid; + } + } + } + else + { + for(int i=0; i<32; i++) + { + if(!p_getc(&temp_zinit.map[i],f,true)) + { + return qe_invalid; + } + } + + for(int i=0; i<32; i++) + { + if(!p_getc(&temp_zinit.compass[i],f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version > 0x192)|| + //new only + ((Header->zelda_version == 0x192)&&(Header->build>173))) + { + if(s_version>12 || (Header->zelda_version == 0x211 && Header->build == 18)) + { + for(int i=0; i<64; i++) + { + if(!p_getc(&temp_zinit.boss_key[i],f,true)) + { + return qe_invalid; + } + } + } + else + { + for(int i=0; i<32; i++) + { + if(!p_getc(&temp_zinit.boss_key[i],f,true)) + { + return qe_invalid; + } + } + } + } + + for(int i=0; i<16; i++) + { + if(!p_getc(&temp_zinit.misc[i],f,true)) + { + return qe_invalid; + } + } + + if(s_version < 15) for(int i=0; i<4; i++) + { + if(!p_getc(&sword_hearts[i],f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&temp_zinit.last_map,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.last_screen,f,true)) + { + return qe_invalid; + } + + if(s_version < 14) + { + byte tempmp; + + if(!p_getc(&tempmp,f,true)) + { + return qe_invalid; + } + + temp_zinit.max_magic=tempmp; + + if(!p_getc(&tempmp,f,true)) + { + return qe_invalid; + } + + temp_zinit.magic=tempmp; + } + else + { + if(!p_igetw(&temp_zinit.max_magic,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.magic,f,true)) + { + return qe_invalid; + } + } + + if(s_version < 15) + { + if(s_version < 12) + { + temp_zinit.max_magic*=MAGICPERBLOCK; + temp_zinit.magic*=MAGICPERBLOCK; + } + + for(int i=0; i<4; i++) + { + if(!p_getc(&beam_hearts[i],f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&beam_percent,f,true)) + { + return qe_invalid; + } + } + else + { + if(!p_getc(&temp_zinit.bomb_ratio,f,true)) + { + return qe_invalid; + } + } + + if(s_version < 15) + { + byte tempbp; + + for(int i=0; i<4; i++) + { + if(!(s_version < 14 ? p_getc(&tempbp,f,true) : p_igetw(&tempbp,f,true))) + { + return qe_invalid; + } + + beam_power[i]=tempbp; + } + + if(!p_getc(&hookshot_links,f,true)) + { + return qe_invalid; + } + + if(s_version>6) + { + if(!p_getc(&hookshot_length,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&longshot_links,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&longshot_length,f,true)) + { + return qe_invalid; + } + } + } + + if(!p_getc(&temp_zinit.msg_more_x,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.msg_more_y,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.subscreen,f,true)) + { + return qe_invalid; + } + + //old only + if((Header->zelda_version == 0x192)&&(Header->build<174)) + { + for(int i=0; i<32; i++) + { + if(!p_getc(&temp_zinit.boss_key[i],f,true)) + { + return qe_invalid; + } + } + } + + if((Header->zelda_version > 0x192)||((Header->zelda_version == 0x192)&&(Header->build>173))) //new only + { + if(s_version <= 10) + { + byte tempbyte; + + if(!p_getc(&tempbyte,f,true)) + { + return qe_invalid; + } + + temp_zinit.start_dmap = (word)tempbyte; + } + else + { + if(!p_igetw(&temp_zinit.start_dmap,f,true)) + { + return qe_invalid; + } + } + + if(!p_getc(&temp_zinit.linkanimationstyle,f,true)) + { + return qe_invalid; + } + } + + if(s_version>1) + { + if(!p_getc(&temp_zinit.arrows,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.max_arrows,f,true)) + { + return qe_invalid; + } + } + + if(s_version>2) + { + if(s_version <= 10) + { + for(int i=0; i3) + { + if(!p_igetw(&temp_zinit.ss_grid_x,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_grid_y,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_grid_xofs,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_grid_yofs,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_grid_color,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_bbox_1_color,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_bbox_2_color,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.ss_flags,f,true)) + { + return qe_invalid; + } + + temp_zinit.ss_grid_x=zc_max(temp_zinit.ss_grid_x,1); + temp_zinit.ss_grid_y=zc_max(temp_zinit.ss_grid_y,1); + } + + if(s_version>4 && s_version<15) + { + if(!p_getc(&moving_fairy_hearts,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&moving_fairy_heart_percent,f,true)) + { + return qe_invalid; + } + } + + if(s_version>5 && s_version < 10) + { + if(!p_getc(&temp,f,true)) + { + return qe_invalid; + } + + addOldStyleFamily(&temp_zinit, itemsbuf, itype_quiver, temp); + } + + if(s_version>6 && s_version<15) + { + if(!p_getc(&stationary_fairy_hearts,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&stationary_fairy_heart_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&moving_fairy_magic,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&moving_fairy_magic_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&stationary_fairy_magic,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&stationary_fairy_magic_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&blue_potion_hearts,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&blue_potion_heart_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&red_potion_hearts,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&red_potion_heart_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&blue_potion_magic,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&blue_potion_magic_percent,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&red_potion_magic,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&red_potion_magic_percent,f,true)) + { + return qe_invalid; + } + } + + if(s_version>6) + { + if(!p_getc(&temp_zinit.subscreen_style,f,true)) + { + return qe_invalid; + } + } + + if(s_version>7) + { + if(!p_getc(&temp_zinit.usecustomsfx,f,true)) + { + return qe_invalid; + } + } + + if(s_version>8) + { + if(!p_igetw(&temp_zinit.max_rupees,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.max_keys,f,true)) + { + return qe_invalid; + } + } + + if(s_version>16) + { + if(!p_getc(&temp_zinit.gravity,f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&temp_zinit.terminalv,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.msg_speed,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.transition_type,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&temp_zinit.jump_link_layer_threshold,f,true)) + { + return qe_invalid; + } + } + + if(s_version>17) + { + if(!p_getc(&temp_zinit.msg_more_is_offset,f,true)) + { + return qe_invalid; + } + } + + //old only + if((Header->zelda_version == 0x192)&&(Header->build<174)) + { + byte items2; + + if(!p_getc(&items2,f,true)) + { + return qe_invalid; + } + + temp_zinit.items[iDinsFire]=(get_bit(&items2, idI_DFIRE)!=0); + temp_zinit.items[iFaroresWind]=(get_bit(&items2, idI_FWIND)!=0); + temp_zinit.items[iNayrusLove]=(get_bit(&items2, idI_NLOVE)!=0); + } + + if(Header->zelda_version < 0x193) + { + for(int q=0; q<96; q++) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + + //new only + if((Header->zelda_version == 0x192)&&(Header->build>173)) + { + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + + if(!p_getc(&padding,f,true)) + { + return qe_invalid; + } + } + } + } + + if((Header->zelda_version < 0x211)||((Header->zelda_version == 0x211)&&(Header->build<15))) + { + //temp_zinit.shield=i_smallshield; + int sshieldid = getItemID(itemsbuf, itype_shield, i_smallshield); + + if(sshieldid != -1) + temp_zinit.items[sshieldid] = true; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<27))) + { + temp_zinit.hc=3; + temp_zinit.start_heart=3; + temp_zinit.cont_heart=3; + temp_zinit.max_bombs=8; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<50))) + { + sword_hearts[0]=0; + sword_hearts[1]=5; + sword_hearts[2]=12; + sword_hearts[3]=21; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<51))) + { + temp_zinit.last_map=0; + temp_zinit.last_screen=0; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<68))) + { + temp_zinit.max_magic=0; + temp_zinit.magic=0; + set_bit(temp_zinit.misc,idM_DOUBLEMAGIC,0); + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<129))) + { + + for(int x=0; x<4; x++) + { + beam_hearts[x]=100; + } + + for(int i=0; izelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<168))) + { + //was new subscreen rule + temp_zinit.subscreen=get_bit(quest_rules,qr_FREEFORM)?1:0; + set_bit(quest_rules,qr_FREEFORM,0); + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<185))) + { + temp_zinit.start_dmap=0; + } + + if((Header->zelda_version < 0x192)||((Header->zelda_version == 0x192)&&(Header->build<186))) + { + temp_zinit.linkanimationstyle=get_bit(quest_rules,qr_BSZELDA)?1:0; + } + + if(s_version < 16 && get_bit(deprecated_rules, qr_COOLSCROLL+1)) + { + //addOldStyleFamily(&temp_zinit, itemsbuf, itype_wallet, 4); //is this needed? + temp_zinit.max_rupees=999; + temp_zinit.rupies=999; + } + + if(keepdata==true) + { + memcpy(&zinit, &temp_zinit, sizeof(zinitdata)); + + if(zinit.linkanimationstyle==las_zelda3slow) + { + link_animation_speed=2; + } + else + { + link_animation_speed=1; + } + } + + return 0; +} + +/* +void setupitemdropsets() +{ + for(int i=0; i 0x192) + { + item_drop_sets_to_read=0; + + //section version info + if(!p_igetw(&s_version,f,true)) + { + return qe_invalid; + } + + //al_trace("Item drop sets version %d\n", s_version); + if(!p_igetw(&s_cversion,f,true)) + { + return qe_invalid; + } + + //section size + if(!p_igetl(&dummy_dword,f,true)) + { + return qe_invalid; + } + + //finally... section data + if(!p_igetw(&item_drop_sets_to_read,f,true)) + { + return qe_invalid; + } + } + else + { + if(keepdata==true) + { + init_item_drop_sets(); + } + } + + if(s_version>=1) + { + for(int i=0; i("",""); + } + + globalmap[0] = pair("Slot 1: ~Init", "~Init"); + + for(int i=1; i("",""); + } + + //globalmap[3] = pair("Slot 4: ~Continue", "~Continue"); + for(int i=0; i("",""); + } + + reset_scripts(); + } + + zquestheader tempheader; + memset(&tempheader, 0, sizeof(zquestheader)); + + // oldquest flag is set when an unencrypted qst file is suspected. + bool oldquest = false; + int open_error=0; + char deletefilename[1024]; + PACKFILE *f=open_quest_file(&open_error, filename, deletefilename, compressed, encrypted, show_progress); + + if(!f) + return open_error; + + int ret=0; + + //header + box_out("Reading Header..."); + ret=readheader(f, &tempheader, true); + checkstatus(ret); + box_out("okay."); + box_eol(); + al_trace("Made in ZQuest %x Beta %d\n",tempheader.zelda_version, tempheader.build); + + if(tempheader.zelda_version>=0x193) + { + dword section_id; + + //section id + if(!p_mgetl(§ion_id,f,true)) + { + return qe_invalid; + } + + while(!pack_feof(f)) + { + switch(section_id) + { + case ID_RULES: + + //rules + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Rules..."); + ret=readrules(f, &tempheader, keepall&&!get_bit(skip_flags, skip_rules)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_STRINGS: + + //strings + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Strings..."); + ret=readstrings(f, &tempheader, keepall&&!get_bit(skip_flags, skip_strings)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_MISC: + + //misc data + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Misc. Data..."); + ret=readmisc(f, &tempheader, Misc, keepall&&!get_bit(skip_flags, skip_misc)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_TILES: + + //tiles + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Tiles..."); + ret=readtiles(f, newtilebuf, &tempheader, tempheader.zelda_version, tempheader.build, 0, NEWMAXTILES, false, keepall&&!get_bit(skip_flags, skip_tiles)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_COMBOS: + + //combos + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Combos..."); + ret=readcombos(f, &tempheader, tempheader.zelda_version, tempheader.build, 0, MAXCOMBOS, keepall&&!get_bit(skip_flags, skip_combos)); + combosread=true; + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_COMBOALIASES: + + //combo aliases + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Combo Aliases..."); + ret=readcomboaliases(f, &tempheader, tempheader.zelda_version, tempheader.build, keepall&&!get_bit(skip_flags, skip_comboaliases)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_CSETS: + + //color data + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Color Data..."); + ret=readcolordata(f, Misc, tempheader.zelda_version, tempheader.build, 0, newerpdTOTAL, keepall&&!get_bit(skip_flags, skip_csets)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_MAPS: + + //maps + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Maps..."); + ret=readmaps(f, &tempheader, keepall&&!get_bit(skip_flags, skip_maps)); + mapsread=true; + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_DMAPS: + + //dmaps + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading DMaps..."); + ret=readdmaps(f, &tempheader, tempheader.zelda_version, tempheader.build, 0, MAXDMAPS, keepall&&!get_bit(skip_flags, skip_dmaps)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_DOORS: + + //door combo sets + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Doors..."); + ret=readdoorcombosets(f, &tempheader, keepall&&!get_bit(skip_flags, skip_doors)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_ITEMS: + + //items + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Items..."); + ret=readitems(f, tempheader.zelda_version, tempheader.build, keepall&&!get_bit(skip_flags, skip_items)); + checkstatus(ret); + + box_out("okay."); + box_eol(); + break; + + case ID_WEAPONS: + + //weapons + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Weapons..."); + ret=readweapons(f, &tempheader, keepall&&!get_bit(skip_flags, skip_weapons)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_COLORS: + + //misc. colors + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Misc. Colors..."); + ret=readmisccolors(f, &tempheader, Misc, keepall&&!get_bit(skip_flags, skip_colors)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_ICONS: + + //game icons + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Game Icons..."); + ret=readgameicons(f, &tempheader, Misc, keepall&&!get_bit(skip_flags, skip_icons)); + checkstatus(ret); + box_out("okay."); + box_eol(); + break; + + case ID_INITDATA: + + //initialization data + if(catchup) + { + box_out("found."); + box_eol(); + catchup=false; + } + + box_out("Reading Init. Data..."); + ret=readinitdata(f, &tempheader, keepall&&!get_bit(skip_flags, skip_initdata)); + checkstatus(ret); + box_out("okay."); + box_eol(); + + if(keepall&&!get_bit(skip_flags, skip_subscreens)) + { + if(zinit.subscreen!=ssdtMAX) //not using custom subscreens + { + setupsubscreens(); + + for(int i=0; i. +// + +#include "questReport.h" + +#include +#include +#include + +#include "editbox.h" +#include "EditboxNew.h" +#include "gui.h" +#include "jwin.h" +#include "mem_debug.h" +#include "tiles.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "zsys.h" +#include "zq_class.h" +#include "zq_misc.h" +#include "zquest.h" + +extern int bie_cnt; +extern std::map > ffcmap; + +std::string quest_report_str; + +char *palname_spaced(int pal) +{ + static char buf[17]; + sprintf(buf,"%s",palnames[pal]); + + for(int i=strlen(buf); i<17; i+=1) + { + strcat(buf," "); + } + + return buf; +} + + +DIALOG integrity_report_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ +// { jwin_textbox_proc, 4, 2+21, 320-8, 240-6-21, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_win_proc, 0, 0, 320, 240, 0, vc(15), 0, D_EXIT, 0, 0, (void *) "Quest Report", NULL, NULL }, + { jwin_frame_proc, 4, 23, 320-8, (240-27)-24, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_editbox_proc, 6, 25, 320-8-4, (240-27)-24-4, 0, 0, 0, 0/*D_SELECTED*/, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *) close_dlg, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, (void *) onSnapshot, NULL, NULL }, + { jwin_button_proc, 64, 240-25, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 192, 240-25, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Save", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +void enlargeIntegrityReportDialog() +{ + integrity_report_dlg[0].w=800; + integrity_report_dlg[0].h=600; + integrity_report_dlg[1].w=800-8; + integrity_report_dlg[1].h=(600-27)-40; + integrity_report_dlg[2].w=800-8-4; + integrity_report_dlg[2].h=((600-27)-40)-4; + integrity_report_dlg[5].x=200-48; + integrity_report_dlg[5].y=600-38; + integrity_report_dlg[5].w=61*1.5; + integrity_report_dlg[5].h=21*1.5; + integrity_report_dlg[5].dp2 = lfont_l; + integrity_report_dlg[6].x=600-48; + integrity_report_dlg[6].y=600-38; + integrity_report_dlg[6].w=61*1.5; + integrity_report_dlg[6].h=21*1.5; + integrity_report_dlg[6].dp2 = lfont_l; +} + +void showQuestReport(int bg,int fg) +{ + integrity_report_dlg[0].dp2= lfont; + integrity_report_dlg[2].dp = new EditboxModel(quest_report_str, new EditboxWordWrapView(&integrity_report_dlg[2], is_large? sfont3 : sfont2, fg,bg,BasicEditboxView::HSTYLE_EOTEXT),true); + integrity_report_dlg[2].bg = bg; + int ret=zc_popup_dialog(integrity_report_dlg,2); + delete(EditboxModel*)(integrity_report_dlg[2].dp); + + if(ret==6) + { + if(!getname("Save Quest Report (.txt)","txt",NULL,datapath,false)) + return; + + if(exists(temppath)) + { + if(jwin_alert("Confirm Overwrite","File already exists.","Overwrite?",NULL,"Yes","No",'y','n',lfont)==2) + return; + } + + FILE *report = fopen(temppath,"w"); + + if(!report) + { + jwin_alert("Error","Unable to open file for writing!",NULL,NULL,"O&K",NULL,'k',0,lfont); + return; + } + + int written = (int)fwrite(quest_report_str.c_str(), sizeof(char), quest_report_str.size(), report); + + if(written != (int)quest_report_str.size()) + jwin_alert("Error","IO error while writing script to file!",NULL,NULL,"O&K",NULL,'k',0,lfont); + + fclose(report); + } +} + +void TileWarpsReport() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *warp_check; + warp_check=(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; itilewarpdmap[w]; + int ws=(DMaps[wdm].map*MAPSCRS+ts->tilewarpscr[w]+DMaps[wdm].xoff); + int cs=Map.getCurrMap()*MAPSCRS+Map.getCurrScr(); + + if(ws==cs) + { + warp_check[i]=1; + } + } + } + } + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(warp_check); +} + +void SideWarpsReport() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *warp_check; + warp_check=(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; isidewarpdmap[w]; + int ws=(DMaps[wdm].map*MAPSCRS+ts->sidewarpscr[w]+DMaps[wdm].xoff); + int cs=Map.getCurrMap()*MAPSCRS+Map.getCurrScr(); + + if(ws==cs) + { + warp_check[i]=1; + } + } + } + } + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(warp_check); +} + +void LayersReport() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *layer_check; + layer_check =(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; ilayerscreen[w]==Map.getCurrScr() && (ts->layermap[w]-1)==Map.getCurrMap()) + { + layer_check[i]=w+1; + } + } + } + } + + for(int m=0; mcolor), m+1, s, layer_check[i]); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(layer_check); +} + + +bool integrityBoolSpecialItem(mapscr *ts) +{ + return (ts->room==rSP_ITEM&&ts->catchall==0); +} + +void integrityCheckSpecialItem() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolEnemiesItem(mapscr *ts) +{ + if((ts->flags)&fITEM) + { + if(Map.getCurrScr() >= 0x80) return false; + + switch(ts->room) + { + case rZELDA: + return false; + + case rSP_ITEM: + case rMONEY: + case rGRUMBLE: + case rBOMBS: + case rARROWS: + case rSWINDLE: + case rMUPGRADE: + case rLEARNSLASH: + case rTAKEONE: + case rTRIFORCE: + if(ts->guy) return false; + } + + bool problem_found=true; + + for(int e=0; e<10; ++e) + { + if(ts->enemy[e]!=0) + { + problem_found=false; + break; + } + } + + return problem_found; + } + + return false; +} + +void integrityCheckEnemiesItem() +{ + mapscr *ts=NULL; + char buf[255]; + + bool problem_found=false; + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolEnemiesSecret(mapscr *ts) +{ + if((ts->flags2)&fCLEARSECRET) + { + if(Map.getCurrScr() >= 0x80) return false; + + switch(ts->room) + { + case rZELDA: + return false; + + case rSP_ITEM: + case rMONEY: + case rGRUMBLE: + case rBOMBS: + case rARROWS: + case rSWINDLE: + case rMUPGRADE: + case rLEARNSLASH: + case rTAKEONE: + case rTRIFORCE: + if(ts->guy) return false; + } + + bool problem_found=true; + + for(int e=0; e<10; ++e) + { + if(ts->enemy[e]!=0) + { + problem_found=false; + break; + } + } + + return problem_found; + } + + return false; +} + +void integrityCheckEnemiesSecret() +{ + mapscr *ts=NULL; + char buf[255]; + + bool problem_found=false; + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + +} + +void integrityCheckTileWarpDestSquare() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *warp_check; + mapscr *wscr; + warp_check=(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; itilewarpdmap[w]; + int ws=(DMaps[wdm].map*MAPSCRS+ts->tilewarpscr[w]+DMaps[wdm].xoff); + wscr=&TheMaps[ws]; + + if(ts->tilewarptype[w]!=wtPASS) + { + int wx, wy, retc = (ts->warpreturnc>>(w*2))&3; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + wx=wscr->warpreturnx[retc]; + wy=wscr->warpreturny[retc]; + } + else + { + wx=wscr->warparrivalx; + wy=wscr->warparrivaly; + } + + if(wx==0 && wy==0) + { + warp_check[ws]=m*MAPSCRS+s+1; + } + } + } + } + } + + for(int m=0; mcolor), m+1, s, ((warp_check[i]-1)/MAPSCRS)+1, (warp_check[i]-1)%MAPSCRS); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(warp_check); +} + +// does not check cycling combos +void integrityCheckTileWarpDest() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + bool warpa = false, warpb = false, warpc = false, warpd = false, warpr = false; + + for(int m=0; mvalid&mVALID)) + continue; + + warpa = warpb = warpc = warpd = warpr = false; + + for(int c=0; c<176+128; ++c) + { + // Checks both combos and secret combos. + int ctype = combobuf[(c>=176 ? ts->secretcombo[c-176] : ts->data[c])].type; + + switch(ctype) + { + case cCAVE: + case cPIT: + case cSTAIR: + case cCAVE2: + case cSWIMWARP: + case cDIVEWARP: + case cSWARPA: + if(ts->tilewarptype[0]==wtCAVE) + { + warpa = true; + } + + break; + + case cCAVEB: + case cPITB: + case cSTAIRB: + case cCAVE2B: + case cSWIMWARPB: + case cDIVEWARPB: + case cSWARPB: + if(ts->tilewarptype[1]==wtCAVE) + { + warpb = true; + } + + break; + + case cCAVEC: + case cPITC: + case cSTAIRC: + case cCAVE2C: + case cSWIMWARPC: + case cDIVEWARPC: + case cSWARPC: + if(ts->tilewarptype[2]==wtCAVE) + { + warpc = true; + } + + break; + + case cCAVED: + case cPITD: + case cSTAIRD: + case cCAVE2D: + case cSWIMWARPD: + case cDIVEWARPD: + case cSWARPD: + if(ts->tilewarptype[3]==wtCAVE) + { + warpd = true; + } + + break; + + case cSTAIRR: + case cPITR: + case cSWARPR: + if(ts->tilewarptype[0]==wtCAVE || ts->tilewarptype[1]==wtCAVE || + ts->tilewarptype[2]==wtCAVE || ts->tilewarptype[3]==wtCAVE) + { + warpr = true; + } + + break; + } + + } + + if(warpa || warpb || warpc || warpd || warpr) + { + if(!type_found) + { + quest_report_str+="The following screens have warp-type combos or warp-type secret combos, and their corresponding Tile Warp type is 'Cave/Item Cellar'. For some screens, this may not indicate a problem.\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X %s%s%s%s%s\n", palname_spaced(ts->color), m+1, s, warpa ? "[A] ":"", warpb ? "[B] ":"", + warpc ? "[C] ":"", warpd ? "[D] ":"", warpr ? "[Random]":""); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +void integrityCheckSideWarpDest() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + bool warpa = false, warpb = false, warpc = false, warpd = false, warpr = false, warpt = false; + + for(int m=0; mvalid&mVALID)) + continue; + + warpa = warpb = warpc = warpd = warpr = warpt = false; + + for(int c=0; c<176+128; ++c) + { + // Checks both combos and secret combos. + int ctype = combobuf[(c>=176 ? ts->secretcombo[c-176] : ts->data[c])].type; + + // Check Triforce items as well. + bool triforce = (itemsbuf[ts->item].family==itype_triforcepiece && itemsbuf[ts->item].flags & ITEM_FLAG1); + + if(ts->room==rSP_ITEM && !triforce) + { + triforce = (itemsbuf[ts->item].family==itype_triforcepiece && itemsbuf[ts->item].flags & ITEM_FLAG1); + } + + if(ctype==cAWARPA || triforce) + { + if(ts->sidewarptype[0]==wtCAVE) + { + (ctype==cAWARPA ? warpa : warpt) = true; + } + + break; + } + + if(ctype==cAWARPB) + { + if(ts->sidewarptype[1]==wtCAVE) + { + warpb = true; + } + + break; + } + + if(ctype==cAWARPC) + { + if(ts->sidewarptype[2]==wtCAVE) + { + warpc = true; + } + + break; + } + + if(ctype==cAWARPD) + { + if(ts->sidewarptype[3]==wtCAVE) + { + warpd = true; + } + + break; + } + + if(ctype==cAWARPR) + { + if(ts->sidewarptype[0]==wtCAVE || ts->sidewarptype[1]==wtCAVE || + ts->sidewarptype[2]==wtCAVE || ts->sidewarptype[3]==wtCAVE) + { + warpr = true; + } + + break; + } + + } + + if(warpa || warpb || warpc || warpd || warpr) + { + if(!type_found) + { + quest_report_str+="The following screens have Auto Side Warp combos, Auto Side Warp secret combos, or Triforce items that Side Warp Out when collected, but their corresponding Side Warp type is 'Cave/Item Cellar'. For some screens, this may not indicate a problem.\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X %s%s%s%s%s%s\n", palname_spaced(ts->color), m+1, s, warpa ? "[A] ":"", warpb ? "[B] ":"", + warpc ? "[C] ":"", warpd ? "[D] ":"", warpr ? "[Random]":"", warpt ? "[Triforce]" : ""); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + + +bool integrityBoolUnderCombo(mapscr *ts, int ctype) +{ + switch(ctype) + { + case cARMOS: + case cBUSH: + case cTALLGRASS: + case cFLOWERS: + case cSLASH: + case cSLASHITEM: + case cBUSHTOUCHY: + case cTALLGRASSTOUCHY: + case cFLOWERSTOUCHY: + case cSLASHTOUCHY: + case cSLASHITEMTOUCHY: + + // Not pushblocks - there could be a layer 1 combo. + if(ts->undercombo == 0) + { + return true; + } + } + + return false; +} + +// does not check cycling combos +void integrityCheckUnderCombo() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + bool case_found; + + for(int m=0; mvalid&mVALID)) + continue; + + case_found=false; + + for(int c=0; c<176+128; ++c) + { + // Checks both combos and secret combos. + if(integrityBoolUnderCombo(ts,combobuf[(c>=176 ? ts->secretcombo[c-176] : ts->data[c])].type)) + { + case_found = true; + break; + } + } + + if(case_found) + { + if(!type_found) + { + quest_report_str+="The following screens contain combo types or secret combos that are replaced with the Under Combo, but the Under Combo for that room is combo 0. In some cases, this may not indicate a problem. Also, this does not take cycling combos into account.\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X\n", palname_spaced(ts->color), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + + +bool integrityBoolSaveCombo(mapscr *ts, int ctype) +{ + switch(ctype) + { + case cSAVE: + case cSAVE2: + if((ts->flags4&fSAVEROOM) == 0 && (ts->flags4&fAUTOSAVE) == 0) + { + return true; + } + } + + return false; +} + +// Save Combo check +void integrityCheckSaveCombo() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + bool case_found; + + for(int m=0; mvalid&mVALID)) + continue; + + case_found=false; + + for(int c=0; c<176+128; ++c) + { + // Checks both combos and secret combos. + if(integrityBoolSaveCombo(ts,combobuf[(c>=176 ? ts->secretcombo[c-176] : ts->data[c])].type)) + { + case_found = true; + } + } + + for(int c=0; c< MAXFFCS; c++) + { + // Checks both combos and secret combos. + if(integrityBoolSaveCombo(ts,combobuf[ts->ffcs[c].data].type)) + case_found = true; + } + + if(case_found) + { + if(!type_found) + { + quest_report_str+="The following screens contain combo types, secret combos or freeform combos that are Save Points, but the screen does not have a 'Use As Save Screen' screen flag checked. In some cases, this may not indicate a problem.\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X\n", palname_spaced(ts->color), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + + +bool integrityBoolStringNoGuy(mapscr *ts) +{ + return (ts->str!=0&&ts->guy==0&&ts->room==0); +} + +void integrityCheckStringNoGuy() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolGuyNoString(mapscr *ts) +{ + return (ts->guy!=0&&ts->guy!=gFAIRY&&ts->room==0&&ts->str==0); +} + + +void integrityCheckGuyNoString() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolRoomNoGuy(mapscr *ts) +{ + switch(ts->room) + { + case rNONE: + case rSP_ITEM: + case r10RUPIES: + case rGANON: + case rZELDA: + break; + + case rINFO: + case rMONEY: + case rGAMBLE: + case rREPAIR: + case rRP_HC: + case rGRUMBLE: + case rTRIFORCE: + case rP_SHOP: + case rSHOP: + case rBOMBS: + case rSWINDLE: + case rWARP: + case rMUPGRADE: + case rLEARNSLASH: + case rARROWS: + case rTAKEONE: + default: + if(ts->guy==0&&ts->str!=0) + return true; + } + + return false; +} + +void integrityCheckRoomNoGuy() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolRoomNoString(mapscr *ts) +{ + switch(ts->room) + { + case rNONE: + case rSP_ITEM: + case r10RUPIES: + case rGANON: + case rZELDA: + break; + + case rINFO: + case rMONEY: + case rGAMBLE: + case rREPAIR: + case rRP_HC: + case rGRUMBLE: + case rTRIFORCE: + case rP_SHOP: + case rSHOP: + case rBOMBS: + case rSWINDLE: + case rWARP: + case rMUPGRADE: + case rLEARNSLASH: + case rARROWS: + case rTAKEONE: + default: + if(ts->str==0&&ts->guy!=0) + return true; + } + + return false; +} + +void integrityCheckRoomNoString() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + type_found=true; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +bool integrityBoolRoomNoGuyNoString(mapscr *ts) +{ + switch(ts->room) + { + case rNONE: + case rSP_ITEM: + case r10RUPIES: + case rGANON: + case rZELDA: + break; + + case rINFO: + case rMONEY: + case rGAMBLE: + case rREPAIR: + case rRP_HC: + case rGRUMBLE: + case rTRIFORCE: + case rP_SHOP: + case rSHOP: + case rBOMBS: + case rSWINDLE: + case rWARP: + case rMUPGRADE: + case rLEARNSLASH: + case rARROWS: + case rTAKEONE: + default: + if(ts->str==0&&ts->guy==0) return true; + } + + return false; +} + +void integrityCheckRoomNoGuyNoString() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mcolor), m+1, s); + quest_report_str+=buf; + type_found=true; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +void integrityCheckQuestNumber() +{ + if(header.quest_number!=0) + { + quest_report_str+="The quest number (in the Quest->Header menu) is not set to 0. This quest will not be playable unless this is changed!\n\n"; + } +} + +void integrityCheckItemWalkability() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mitem!=0&& + ((combobuf[ts->data[(ts->itemy &0xF0)+(ts->itemx >>4)]].walk!=0) || + (combobuf[ts->data[(ts->itemy &0xF0)+((ts->itemx+15)>>4)]].walk!=0) || + (combobuf[ts->data[((ts->itemy+15)&0xF0)+(ts->itemx >>4)]].walk!=0) || + (combobuf[ts->data[((ts->itemy+15)&0xF0)+((ts->itemx+15)>>4)]].walk!=0))) + { + if(!type_found) + { + quest_report_str+="The following screens have items whose item locations are set onto fully or partially unwalkable combos:\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X\n", palname_spaced(ts->color), m+1, s); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +void integrityCheckTileWarpDestSquareWalkability() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *warp_check; + mapscr *wscr; + warp_check=(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; itilewarpdmap[w]; + int ws=(DMaps[wdm].map*MAPSCRS+ts->tilewarpscr[w]+DMaps[wdm].xoff); + wscr=&TheMaps[ws]; + + if(ts->tilewarptype[w]!=wtPASS) + { + if(((combobuf[wscr->data[(wscr->warparrivaly &0xF0)+(wscr->warparrivalx >>4)]].walk&15)!=0) || + ((combobuf[wscr->data[(wscr->warparrivaly &0xF0)+((wscr->warparrivalx+15)>>4)]].walk&15)!=0) || + ((combobuf[wscr->data[((wscr->warparrivaly+15)&0xF0)+(wscr->warparrivalx >>4)]].walk&15)!=0) || + ((combobuf[wscr->data[((wscr->warparrivaly+15)&0xF0)+((wscr->warparrivalx+15)>>4)]].walk&15)!=0)) + { + warp_check[ws]=m*MAPSCRS+s+1; + } + } + } + } + } + + for(int m=0; mcolor), m+1, s, ((warp_check[i]-1)/MAPSCRS)+1, (warp_check[i]-1)%MAPSCRS); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(warp_check); +} + +void integrityCheckTileWarpDestScreenInvalid() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + int *warp_check; + mapscr *wscr; + warp_check=(int *)zc_malloc(Map.getMapCount()*MAPSCRS*sizeof(int)); + + for(int i=0; itilewarpdmap[w]; + int ws=(DMaps[wdm].map*MAPSCRS+ts->tilewarpscr[w]+DMaps[wdm].xoff); + wscr=&TheMaps[ws]; + + if(!(wscr->valid&mVALID)) + { + if(!type_found) + { + quest_report_str+="The following screens have tile warps to screens that are undefined/invalid:\n"; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X\n", palname_spaced(ts->color), m+1, s); + quest_report_str+=buf; + type_found=true; + } + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } + + zc_free(warp_check); +} + +int onIntegrityCheckSpecialItem() +{ + quest_report_str=""; + integrityCheckSpecialItem(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckEnemiesItem() +{ + quest_report_str=""; + integrityCheckEnemiesItem(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckEnemiesSecret() +{ + quest_report_str=""; + integrityCheckEnemiesSecret(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckTileWarpDestSquare() +{ + quest_report_str=""; + integrityCheckTileWarpDestSquare(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckStringNoGuy() +{ + quest_report_str=""; + integrityCheckStringNoGuy(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckGuyNoString() +{ + quest_report_str=""; + integrityCheckGuyNoString(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckRoomNoGuy() +{ + quest_report_str=""; + integrityCheckRoomNoGuy(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckRoomNoString() +{ + quest_report_str=""; + integrityCheckRoomNoString(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckRoomNoGuyNoString() +{ + quest_report_str=""; + integrityCheckRoomNoGuyNoString(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckQuestNumber() +{ + quest_report_str=""; + integrityCheckQuestNumber(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckItemWalkability() +{ + quest_report_str=""; + integrityCheckItemWalkability(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckTileWarpDestSquareWalkability() +{ + quest_report_str=""; + integrityCheckTileWarpDestSquareWalkability(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckTileWarpDestScreenInvalid() +{ + quest_report_str=""; + integrityCheckTileWarpDestScreenInvalid(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +void integrityCheckAllRooms() +{ + integrityCheckSpecialItem(); + integrityCheckEnemiesItem(); + integrityCheckEnemiesSecret(); + integrityCheckStringNoGuy(); + integrityCheckGuyNoString(); + integrityCheckRoomNoGuy(); + integrityCheckRoomNoString(); + integrityCheckRoomNoGuyNoString(); + integrityCheckItemWalkability(); + integrityCheckUnderCombo(); + integrityCheckSaveCombo(); +} + +void integrityCheckAllWarps() +{ + integrityCheckSideWarpDest(); + integrityCheckTileWarpDest(); + integrityCheckTileWarpDestSquare(); + integrityCheckTileWarpDestSquareWalkability(); + integrityCheckTileWarpDestScreenInvalid(); +} + +int onIntegrityCheckRooms() +{ + quest_report_str=""; + integrityCheckAllRooms(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckWarps() +{ + quest_report_str=""; + integrityCheckAllWarps(); + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onIntegrityCheckAll() +{ + quest_report_str=""; + // Quest Checks! + integrityCheckQuestNumber(); + // Other checks + integrityCheckAllRooms(); + integrityCheckAllWarps(); + + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +typedef struct item_location_node +{ + int map; + int screen; + int extra1; + int extra2; + int enemy; + int pal; + item_location_node* next; +} item_location_node; + +void itemLocationReport() +{ + mapscr *ts=NULL; + int sc=0; + int location_types=6; + char buf[255]; + + item_location_node **item_location_grid; + + item_location_grid = new item_location_node*[iMax]; + + for(int i=0; ihasitem) + { + //start at the room item in the item location grid + tempnode=&(item_location_grid[ts->item][0]); + //loop to the end of the list + int count=0; + + while(tempnode->next!=NULL) + { + ++count; + tempnode=tempnode->next; + } + + //make a new node + newnode=(item_location_node*)zc_malloc(sizeof(item_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->extra1=-1; + newnode->extra2=-1; + newnode->enemy=(ts->flags&fITEM ? -1 : (ts->enemyflags&efCARRYITEM) ? ts->enemy[0] : 0); + newnode->pal=ts->color; + newnode->next=NULL; + tempnode->next=newnode; + } + + if(ts->room==rSP_ITEM) + { + //start at the special item in the item location grid + tempnode=&(item_location_grid[ts->catchall][1]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(item_location_node*)zc_malloc(sizeof(item_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->extra1=-1; + newnode->extra2=-1; + newnode->enemy=-1; + newnode->pal=ts->color; + newnode->next=NULL; + tempnode->next=newnode; + } + + if(ts->room==rRP_HC) + { + //start at the hc/rp room item in the item location grid + tempnode=&(item_location_grid[iRPotion][2]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(item_location_node*)zc_malloc(sizeof(item_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->extra1=-1; + newnode->extra2=-1; + newnode->enemy=-1; + newnode->pal=ts->color; + newnode->next=NULL; + tempnode->next=newnode; + + tempnode=&(item_location_grid[iHeartC][2]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(item_location_node*)zc_malloc(sizeof(item_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->extra1=-1; + newnode->extra2=-1; + newnode->enemy=-1; + newnode->pal=ts->color; + newnode->next=NULL; + tempnode->next=newnode; + } + + + if(ts->room==rSHOP||ts->room==rP_SHOP||ts->room==rTAKEONE) + { + for(int si=0; si<3; ++si) + { + if(misc.shop[ts->catchall].item[si]>0) + { + //start at the special item in the item location grid + tempnode=&(item_location_grid[misc.shop[ts->catchall].item[si]][(ts->room==rSHOP?3:(ts->room==rP_SHOP?4:5))]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(item_location_node*)zc_malloc(sizeof(item_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->extra1=ts->catchall; + newnode->extra2=misc.shop[ts->catchall].price[si]; + newnode->enemy=-1; + newnode->pal=ts->color; + newnode->next=NULL; + tempnode->next=newnode; + } + } + } + } + } + + build_bii_list(false); + + //for each item + for(int i2=0; i2next!=NULL) + { + type_found=true; + + if(!item_found) + { + buf[0]=0; + sprintf(buf, "\n--- %s ---\n", item_string[i]); + quest_report_str+=buf; + } + + item_found=true; + + //loop through each item location for this item/type + do + { + tempnode=tempnode->next; + //add it to the list + buf[0]=0; + + switch(type) + { + case 1: + sprintf(buf, "%s %3d:%02X (special item)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen); + break; + + case 2: + sprintf(buf, "%s %3d:%02X (Heart Container / Red Potion room)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen); + break; + + case 3: + sprintf(buf, "%s %3d:%02X (shop %d @ %d rupees)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen, tempnode->extra1, tempnode->extra2); + break; + + case 4: + sprintf(buf, "%s %3d:%02X (potion shop %d @ %d rupees)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen, tempnode->extra1, tempnode->extra2); + break; + + case 5: + sprintf(buf, "%s %3d:%02X (take one item room)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen); + break; + + case 0: + default: + sprintf(buf, "%s %3d:%02X (room item%s%s)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen, + tempnode->enemy==-1 ? ", enemies -> item" : tempnode->enemy ? ", carried by " : "", + tempnode->enemy>0 ? guy_string[tempnode->enemy] : ""); + break; + } + + quest_report_str+=buf; + } + while(tempnode->next!=NULL); + } + } + } + + for(int i=0; inext; + + while(tempnode!=NULL) + { + tempnode2=tempnode->next; + zc_free(tempnode); + tempnode=tempnode2; + } + } + } + + //don't forget to zc_free this too -DD + delete[] item_location_grid[i]; + } + + if(!type_found) + { + buf[0]=0; + sprintf(buf, "None\n\n"); + quest_report_str+=buf; + } + else + { + quest_report_str += '\n'; + } + + //and this -DD + delete[] item_location_grid; +} + +int onItemLocationReport() +{ + quest_report_str=""; + itemLocationReport(); + + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +typedef struct enemy_location_node +{ + int map; + int screen; + int pal; + int list; + int eflag; + int comboflag; + int combotype; + int ganonscr; + enemy_location_node* next; +} enemy_location_node; + +void enemyLocationReport() +{ + mapscr *ts=NULL; + int sc=0; + char buf[255]; + + enemy_location_node *enemy_location_grid; + + enemy_location_grid = new enemy_location_node[MAXGUYS]; + + for(int i=0; ienemy[i]; + + if(!enemy) continue; + + enemytally[enemy]++; + } + + for(int i=0; inext!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(enemy_location_node*)zc_malloc(sizeof(enemy_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->pal=ts->color; + newnode->list=enemytally[i]; + newnode->eflag=0; + newnode->comboflag=0; + newnode->combotype=0; + newnode->ganonscr=0; + newnode->next=NULL; + tempnode->next=newnode; + } + } + } + + build_bie_list(false); + + for(int i2=1; i2next!=NULL) + { + type_found=true; + + if(!enemy_found) + { + buf[0]=0; + sprintf(buf, "\n--- %s ---\n", guy_string[i]); + quest_report_str+=buf; + } + + enemy_found=true; + + //loop through each location for this script + do + { + tempnode=tempnode->next; + //add it to the list + buf[0]=0; + sprintf(buf, "%s %3d:%02X (%d)\n", + palname_spaced(tempnode->pal), + tempnode->map, + tempnode->screen, + tempnode->list /* Possibly add more details later/never */); + quest_report_str+=buf; + } + while(tempnode->next!=NULL); + } + } + + for(int i=0; inext; + + while(tempnode!=NULL) + { + tempnode2=tempnode->next; + zc_free(tempnode); + tempnode=tempnode2; + } + } + } + + delete[] enemy_location_grid; + + if(!type_found) + { + buf[0]=0; + sprintf(buf, "None\n\n"); + quest_report_str+=buf; + } + else + { + quest_report_str += '\n'; + } +} + +int onEnemyLocationReport() +{ + quest_report_str=""; + enemyLocationReport(); + + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +typedef struct script_location_node +{ + int map; + int screen; + int pal; + long d[8]; + script_location_node* next; +} script_location_node; + +void scriptLocationReport() +{ + mapscr *ts=NULL; + int sc=0; + char buf[255]; + + script_location_node *script_location_grid; + + script_location_grid = new script_location_node[NUMSCRIPTFFC]; + + for(int i=0; iffcs[i].script; + + if(!script || !ts->ffcs[i].data) continue; + + tempnode=&(script_location_grid[script]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(script_location_node*)zc_malloc(sizeof(script_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->pal=ts->color; + + for(int j=0; j<8; ++j) + newnode->d[j] = ts->ffcs[i].initd[j]; + + newnode->next=NULL; + tempnode->next=newnode; + } + } + } + + for(int i=0; inext!=NULL) + { + type_found=true; + + if(!script_found) + { + buf[0]=0; + sprintf(buf, "\n--- %s ---\n", ffcmap[i-1].second.c_str()); + quest_report_str+=buf; + } + + script_found=true; + + //loop through each location for this script + do + { + tempnode=tempnode->next; + //add it to the list + buf[0]=0; + sprintf(buf, "%s %3d:%02X (Args: %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld)\n", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen, + tempnode->d[0]/10000,tempnode->d[1]/10000,tempnode->d[2]/10000,tempnode->d[3]/10000, + tempnode->d[4]/10000,tempnode->d[5]/10000,tempnode->d[6]/10000,tempnode->d[7]/10000); + quest_report_str+=buf; + } + while(tempnode->next!=NULL); + } + } + + for(int i=0; inext; + + while(tempnode!=NULL) + { + tempnode2=tempnode->next; + zc_free(tempnode); + tempnode=tempnode2; + } + } + } + + delete[] script_location_grid; + + if(!type_found) + { + buf[0]=0; + sprintf(buf, "None\n\n"); + quest_report_str+=buf; + } + else + { + quest_report_str += '\n'; + } +} + +int onScriptLocationReport() +{ + quest_report_str=""; + scriptLocationReport(); + + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +void ComboLocationReport() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + + for(int m=0; mvalid&mVALID)) + continue; + + int uses = 0; + int secretuses = 0; + int ffuses = 0; + bool undercombouses = false; + + for(int c=0; c<337; ++c) + { + // Checks both combos and secret combos. + if(c<176) + { + if(ts->data[c] == Combo) uses++; + } + else if(c<304) + { + if(ts->secretcombo[c-176] == Combo) secretuses++; + } + else if(c<336) + { + if(ts->ffcs[c-304].data == Combo && Combo > 0) ffuses++; + } + else if(ts->undercombo == Combo) undercombouses = true; + } + + if(uses > 0 || secretuses > 0 || ffuses > 0 || undercombouses) + { + if(!type_found) + { + buf[0]=0; + sprintf(buf, "The following screens use the currently selected combo (%d):\n", Combo); + quest_report_str+=buf; + type_found=true; + } + + buf[0]=0; + sprintf(buf, "%s %3d:%02X (%d use%s", palname_spaced(ts->color), m+1, s, uses, uses>1 ? "s" : ""); + quest_report_str+=buf; + + if(secretuses>0) + { + buf[0]=0; + sprintf(buf, ", %d secret%s", secretuses, secretuses>1 ? "s" : ""); + quest_report_str+=buf; + } + + if(ffuses>0) + { + buf[0]=0; + sprintf(buf, ", %d FFC%s", ffuses, ffuses>1 ? "s" : ""); + quest_report_str+=buf; + } + + buf[0]=0; + sprintf(buf, "%s)\n", undercombouses ? ", under combo" : ""); + quest_report_str+=buf; + } + } + } + + if(type_found) + { + quest_report_str += '\n'; + } +} + +int onComboLocationReport() +{ + quest_report_str=""; + ComboLocationReport(); + + restore_mouse(); + + if(quest_report_str!="") + showQuestReport(vc(15),vc(0)); + else + jwin_alert("Combo Locations", "No other screens use this combo.", NULL,NULL,"OK",NULL,13,27,lfont); + + return D_O_K; +} + +typedef struct combotype_location_node +{ + int map; + int screen; + int pal; + int uses; + int secretuses; + int ffuses; + bool undercombouses; + combotype_location_node* next; +} combotype_location_node; + +void ComboTypeLocationReport() +{ + mapscr *ts=NULL; + char buf[255]; + + bool type_found=false; + quest_report_str+="The following combo types appear in the quest at the following locations:\n"; + + combotype_location_node *combotype_location_grid; + combotype_location_grid = new combotype_location_node[MAXCOMBOTYPES]; + + for(int i=0; ivalid&mVALID)) + continue; + + int uses = 0; + int secretuses = 0; + int ffuses = 0; + bool undercombouses = false; + + for(int c=0; c<337; ++c) + { + // Checks both combos and secret combos. + if(c<176) + { + if(combobuf[ts->data[c]].type == Type) uses++; + } + else if(c<304) + { + if(combobuf[ts->secretcombo[c-176]].type == Type) secretuses++; + } + else if(c<336) + { + if(combobuf[ts->ffcs[c-304].data].type == Type) ffuses++; + } + else if(combobuf[ts->undercombo].type == Type) undercombouses = true; + } + + if(uses > 0 || secretuses > 0 || ffuses > 0 || undercombouses) + { + tempnode=&(combotype_location_grid[Type]); + + //loop to the end of the list + while(tempnode->next!=NULL) + { + tempnode=tempnode->next; + } + + //make a new node + newnode=(combotype_location_node*)zc_malloc(sizeof(combotype_location_node)); + //insert the map and screen data + newnode->map=m+1; + newnode->screen=s; + newnode->pal=ts->color; + newnode->uses=uses; + newnode->secretuses=secretuses; + newnode->ffuses=ffuses; + newnode->undercombouses=undercombouses; + newnode->next=NULL; + tempnode->next=newnode; + } + } + } + + for(int i=0; inext!=NULL) + { + type_found=true; + + if(!ctype_found) + { + buf[0]=0; + sprintf(buf, "\n--- %s ---\n", combo_class_buf[i].name); + quest_report_str+=buf; + } + + ctype_found=true; + + //loop through each location for this script + do + { + tempnode=tempnode->next; + //add it to the list + buf[0]=0; + sprintf(buf, "%s %3d:%02X (%d uses", palname_spaced(tempnode->pal), tempnode->map, tempnode->screen, tempnode->uses); + quest_report_str+=buf; + + if(tempnode->secretuses>0) + { + buf[0]=0; + sprintf(buf, ", %d secret%s", tempnode->secretuses, tempnode->secretuses > 1 ? "s" : ""); + quest_report_str+=buf; + } + + if(tempnode->ffuses>0) + { + buf[0]=0; + sprintf(buf, ", %d FFC%s", tempnode->ffuses, tempnode->ffuses > 1 ? "s" : ""); + quest_report_str+=buf; + } + + buf[0]=0; + sprintf(buf, "%s)\n", tempnode->undercombouses ? ", under combo" : ""); + quest_report_str+=buf; + } + while(tempnode->next!=NULL); + } + } + + for(int i=0; inext; + + while(tempnode!=NULL) + { + tempnode2=tempnode->next; + zc_free(tempnode); + tempnode=tempnode2; + } + } + } + + delete[] combotype_location_grid; + + if(!type_found) + { + buf[0]=0; + sprintf(buf, "None\n\n"); + quest_report_str+=buf; + } + else + { + quest_report_str += '\n'; + } +} + +int onComboTypeLocationReport() +{ + quest_report_str=""; + ComboTypeLocationReport(); + + restore_mouse(); + showQuestReport(vc(15),vc(0)); + return D_O_K; +} + +int onWhatWarpsReport() +{ + quest_report_str=""; + TileWarpsReport(); + SideWarpsReport(); + LayersReport(); + restore_mouse(); + + if(quest_report_str!="") + showQuestReport(vc(15),vc(0)); + else + jwin_alert("What Links Here", "No other screens warp to this screen", "or use this screen as a layer.",NULL,"OK",NULL,13,27,lfont); + + return D_O_K; +} diff --git a/src/questReport.h b/src/questReport.h new file mode 100644 index 0000000000..16156a2025 --- /dev/null +++ b/src/questReport.h @@ -0,0 +1,34 @@ +#ifndef QUESTREPORT_H +#define QUESTREPORT_H + +#include "zc_alleg.h" + +struct mapscr; + +void enlargeIntegrityReportDialog(); + +void showQuestReport(int bg,int fg); + +int onIntegrityCheckRooms(); +int onIntegrityCheckWarps(); +int onIntegrityCheckAll(); +int onItemLocationReport(); +int onEnemyLocationReport(); +int onScriptLocationReport(); +int onComboLocationReport(); +int onComboTypeLocationReport(); +int onWhatWarpsReport(); + +//Integrity booleans +bool integrityBoolSpecialItem(mapscr* ts); +bool integrityBoolEnemiesSecret(mapscr* ts); +bool integrityBoolEnemiesItem(mapscr* ts); +bool integrityBoolStringNoGuy(mapscr* ts); +bool integrityBoolGuyNoString(mapscr* ts); +bool integrityBoolRoomNoGuy(mapscr* ts); +bool integrityBoolRoomNoString(mapscr* ts); +bool integrityBoolRoomNoGuyNoString(mapscr* ts); +bool integrityBoolSaveCombo(mapscr* ts, int ctype); +bool integrityBoolUnderCombo(mapscr* ts, int ctype); + +#endif diff --git a/src/refInfo.cpp b/src/refInfo.cpp new file mode 100644 index 0000000000..feeacafd30 --- /dev/null +++ b/src/refInfo.cpp @@ -0,0 +1,23 @@ +#include "refInfo.h" +#include + +refInfo::refInfo() +{ + Clear(); +} + +void refInfo::Clear() +{ + pc=0; + sp=0; + scriptflag=0; + ffcref=0; + idata=0; + itemref=0; + guyref=0; + lwpn=0; + ewpn=0; + std::memset(d, 0, 8 * sizeof(long)); + a[0]=0; // Should these reset to 10000? + a[1]=0; +} diff --git a/src/refInfo.h b/src/refInfo.h new file mode 100644 index 0000000000..bbcdc97896 --- /dev/null +++ b/src/refInfo.h @@ -0,0 +1,24 @@ +#ifndef _ZC_REFINFO_H_ +#define _ZC_REFINFO_H_ + +#include "types.h" + +class refInfo +{ +public: + dword pc; //current command offset + + long d[8]; //d registers + long a[2]; //a regsisters (reference to another ffc on screen) + byte sp; //stack pointer for current script + dword scriptflag; //stores whether various operations were true/false etc. + + byte ffcref, idata; //current object pointers + dword itemref, guyref, lwpn, ewpn; + + + refInfo(); + void Clear(); +}; + +#endif diff --git a/src/rendertarget.h b/src/rendertarget.h new file mode 100644 index 0000000000..833856800d --- /dev/null +++ b/src/rendertarget.h @@ -0,0 +1,93 @@ +#ifndef _zscript_rendertarget_h_ +#define _zscript_rendertarget_h_ + +#include + + +#ifdef _MSC_VER +#ifndef _FORCE_INLINE +#define _FORCE_INLINE __forceinline +#endif +#else +#ifndef _FORCE_INLINE +#define _FORCE_INLINE inline +#endif +#endif + + + +class ZScriptDrawingRenderTarget +{ +public: + static const int MaxBuffers = 7; + + //These aren't allocated unless requested by the user, + //so we can handle sizes up to 512x512 with script drawing. + static const int BitmapWidth = 512; + static const int BitmapHeight = 512; + +protected: + BITMAP* _bitmap[ MaxBuffers ]; + int _current_target; + +public: + ZScriptDrawingRenderTarget() : _current_target(-1) + { + for(int i(0); i < MaxBuffers; ++i) + { + _bitmap[i] = 0; + } + } + + ~ZScriptDrawingRenderTarget() + { + for(int i(0); i < MaxBuffers; ++i) + { + if(_bitmap[i]) + destroy_bitmap(_bitmap[i]); + } + } + + _FORCE_INLINE void SetCurrentRenderTarget(int target) + { + _current_target = target; + } + + _FORCE_INLINE int GetCurrentRenderTarget() + { + return _current_target; + } + + _FORCE_INLINE BITMAP* GetTargetBitmap(int target) + { + if(target < 0 || target >= MaxBuffers) + return 0; + + if(!_bitmap[target]) + _bitmap[target] = create_bitmap_ex(8, BitmapWidth, BitmapHeight); + + return _bitmap[target]; + } + + BITMAP* GetBitmapPtr(int target) + { + if(target < 0 || target >= MaxBuffers) + return 0; + + return _bitmap[target]; + } + +private: + ZScriptDrawingRenderTarget(const ZScriptDrawingRenderTarget&); + ZScriptDrawingRenderTarget &operator =(const ZScriptDrawingRenderTarget&); +}; + +extern ZScriptDrawingRenderTarget* zscriptDrawingRenderTarget; + + + +//void do_primitives(BITMAP *targetBitmap, int type, mapscr *, int xoffset, int yoffset); + + +#endif + diff --git a/src/romview.cpp b/src/romview.cpp new file mode 100644 index 0000000000..c36072c716 --- /dev/null +++ b/src/romview.cpp @@ -0,0 +1,2344 @@ +/* + ROMview.cc + Version 3.5 + Last updated: 2/19/00 + + By Phantom Menace, Jan. 2000 + E-mail: jer@armageddongames.com + + This code is pretty simple except for the selection array "sel". + It stores the color set of each tile, one color set per byte, + but the number of tiles varies depending on the number of bitplanes. +*/ +#define ROMVIEW_SCALE + +#include +#include +#include +//#include + +//#ifndef _MSC_VER +//#include +//#endif + +#include "zc_alleg.h" + +#include +#include + +#include +#include + +#include "load_gif.h" +#include "save_gif.h" + +#include "jwin.h" +#include "jwinfsel.h" +#include "zsys.h" +#include "fontsdat.h" +#include "zdefs.h" +#include "zqscale.h" +#include "zc_malloc.h" + +//Yeah, not really zquest. +//Just here for scaling purposes. +bool is_zquest() +{ + return true; +} + +int tempmode=GFX_AUTODETECT_FULLSCREEN; +int palbmpx=0; +int palbmpy=0; +bool is_large=false; +int joystick_index=0; + +volatile int myvsync=0; +BITMAP *hw_screen; + +char *VerStr(int version) +{ + static char ver_str[12]; + sprintf(ver_str,"v%d.%02X",version>>8,version&0xFF); + return ver_str; +} + +int scale_arg; +int zq_scale; +byte disable_direct_updating=0; +char temppath[2048]; +bool close_button_quit=false; +void hit_close_button() +{ + close_button_quit=true; + return; +} + +FONT *pfont; +FONT *lfont; +FONT *lfont_l; +FONT *sfont3; +BITMAP *tmp_scr, *scr_buf; +int scrx=0; +int scry=0; +DATAFILE *fontsdata=NULL; +char fontsdat_sig[52]; +int zq_screen_w=320; +int zq_screen_h=240; + +void go() +{ + scare_mouse(); + blit(screen,tmp_scr,scrx,scry,0,0,screen->w,screen->h); + unscare_mouse(); +} + +void comeback() +{ + scare_mouse(); + blit(tmp_scr,screen,0,0,scrx,scry,screen->w,screen->h); + unscare_mouse(); +} + + +// Just a way to save a little executable size... +// (Ordering: I prefer VESA over ModeX) +//BEGIN_COLOR_DEPTH_LIST +// COLOR_DEPTH_8 +//END_COLOR_DEPTH_LIST + + +#define zc_min(a,b) ((a)<(b)?(a):(b)) +#define PANE 28 // number of rows on the screen at a time +// rows in the window "pane" + + +typedef unsigned char byte; +typedef unsigned short word; + + +const char *VERSION = "ROMView v4.1"; +const int EXTLEN = 32; +const int STA_PAL = 0x5907; +const int ZST_PAL = 0x618; + + +PALETTE pal[4]; +BITMAP *palbmp; +byte *sel=NULL, *rombuf=NULL; +char *helpbuf=NULL; +int savew=128,saveh=0; +int bp=4,nes=0,cset=15; +int black,white,gray,dkgray,ltgray,blue; +int selsize=0,selcnt=0; +int currpal=0; +int ofs=0, fofs=0; // offset, fine-tuning offset +long fsize=0; // romfile size +long helpsize=0; // helpbuf size +bool single=false; // selection mode +bool locked=false; +bool prompt = true; // auto setup + + +enum { PARTIAL=1, FULL, AUTOMENU }; +int redraw = FULL; + +char romfile[260] = "", palfile[260] = ""; + +char rom_ext[EXTLEN] = " "; + +const char *zst_desc = "ZSNES save states"; +const char *sta_desc = "NESticle save states"; +const char *zst_ext = "zst;zs1;zs2;zs3;zs4;zs5;zs6;zs7;zs8;zs9"; +const char *sta_ext = "sta;st1;st2;st3;st4;st5;st6;st7;zt8;st9"; + + +EXT_LIST rom_ext_list[] = +{ + { (char *)"SNES ROMs", (char *)"smc;swc;fig" }, + { (char *)zst_desc, (char *)zst_ext }, + { (char *)"NES ROMs", (char *)"nes" }, + { (char *)sta_desc, (char *)sta_ext }, + { (char *)"User defined", (char *)rom_ext }, + { (char *)"All files", NULL }, + { NULL, NULL } +}; + + +EXT_LIST pal_ext_list[] = +{ + { (char *)"Image files", (char *)"bmp;pcx;gif;jpg;png" }, + { (char *)zst_desc, (char *)zst_ext }, + { (char *)sta_desc, (char *)sta_ext }, + { NULL, NULL } +}; + + + +void redraw_screen(int type); +void setup_colors(); + + +void byebye() +{ + printf("%s, Phantom Menace, www.armageddongames.com\n", VERSION); +} + + + +/* puttile_SNES() + * + * Puts an 8x8 tile using "bp" number of bitplanes (1,2,4,8) + * in the color set "cs". + * + * See the SNES documentation at zophar.net for more info on + * the SNES tile format. + */ +void puttile_SNES(BITMAP *dest,int x,int y,byte *src,int cs) +{ + byte buf[64]; + + for(int l=0; l<8; l++) + { + int bx = l<<3; + byte b = src[(bp&1)?l:l<<1]; + + for(int i=7; i>=0; i--) + { + buf[bx+i] = (b&1)+(cs<<4); + b>>=1; + } + } + + src++; + + for(int p=1; p=0; i--) + { + buf[bx+i] |= (b&1)<>=1; + } + } + + if(p&1) + src+=15; + else + src++; + } + + byte *si = buf; + + for(int j=0; j<8; j++) + for(int i=0; i<8; i++) + putpixel(dest,x+i,y+j,*(si++)); +} + + + +/* puttile_NES() + * + * Puts an 8x8 tile in NES format using color set "cs". + * + * See the NES documentation at zophar.net for more info on + * the NES tile format. + */ +void puttile_NES(BITMAP *dest,int x,int y,byte *src,int cs) +{ + byte buf[64]; + + for(int l=0; l<8; l++) + { + int bx = l<<3; + byte b = *src; + src++; + + for(int i=7; i>=0; i--) + { + buf[bx+i] = (b&1)+(cs<<4); + b>>=1; + } + } + + for(int l=0; l<8; l++) + { + int bx = l<<3; + byte b = *src; + src++; + + for(int i=7; i>=0; i--) + { + buf[bx+i] |= (b&1)<<1; + b>>=1; + } + } + + byte *si = buf; + + for(int j=0; j<8; j++) + for(int i=0; i<8; i++) + putpixel(dest,x+i,y+j,*(si++)); +} + +bool sel_row_is_uniform(int offset) +{ + byte val=sel[offset]; + + for(int i=1; i<16; i++) + if(sel[offset+i]!=val) + return false; + + return true; +} + + +void draw_pane(byte *buf,byte *s,int px, int py) +{ + // This draws a screen's worth of tiles stored in "buf" + // using the selection info in "s". + + int bx = ((ofs/128)/bp)*16; + + if(fsize) + { + for(int y=0; y<208; y+=8) + { + if(*s) + { + for(int x=0; x<128; x+=8) + { + if(nes) + puttile_NES(scr_buf,x+4,y+py+2,buf,s[x>>3]>>4); + else + puttile_SNES(scr_buf,x+4,y+py+2,buf,s[x>>3]>>4); + + buf += bp<<3; + } + } + else + { + for(int x=0; x<128; x+=8) + { + if(nes) + puttile_NES(scr_buf,x+px+2,y+py+2,buf,cset); + else + puttile_SNES(scr_buf,x+px+2,y+py+2,buf,cset); + + buf += bp<<3; + } + } + + s+=16; + } + } + else + { + rectfill(scr_buf,px+2,py+2,px+129,py+209,black); + } + + jwin_draw_frame(scr_buf,px,py,132, 212, FR_DEEP); + + rectfill(scr_buf,134+px,py+2,139+px,209+py,black); + jwin_draw_frame(scr_buf,132+px,py,10, 212, FR_DEEP); + + //locked colors + for(int i=0; i>1) + py+2; + + if(!sel[bx+i]) + { + textprintf_ex(scr_buf,font,135+px,y,white,-1," "); + } + else + { + if(sel_row_is_uniform(bx+i)) + { + textprintf_ex(scr_buf,font,135+px,y,white,-1,"%X",sel[bx+i]>>4); + } + else + { + textprintf_ex(scr_buf,font,135+py,y,white,-1,"<"); + } + } + } + +} + + +void set_sel_row(int offset, byte val) +{ + for(int i=0; i<16; i++) + sel[offset+i]=val; +} + + +void calc_selcnt() +{ + selcnt=0; + + for(int i=0; i>3)]>>4); + else + puttile_SNES(bmp,x+xofs,y,buf,sel[i+(x>>3)]>>4); + + buf += bp<<3; + } + + y+=8; + + if(y>=saveh) + { + xofs+=128; + y=0; + } + } + } + + return bmp; +} + + + +RGB _RGB(int r,int g,int b) +{ + RGB x; + x.r = r; + x.g = g; + x.b = b; + return x; +} + + +RGB invRGB(RGB c) +{ + RGB x; + x.r = 63-c.r; + x.g = 63-c.g; + x.b = 63-c.b; + return x; +} + + +inline int pal_sum(RGB p) +{ + return p.r + p.g + p.b; +} + +int pal_abs(RGB p,RGB q) +{ + return abs(p.r-q.r) + abs(p.g-q.g) + abs(p.b-q.b); +} + + +void get_bw(RGB *p) +{ + // This locates black, white and gray colors in the palette "p". + // The color indices are stored globally. + + /* + RGB DkGray = {20,20,20, 0}; + RGB Gray = {32,32,32, 0}; + RGB LtGray = {48,48,48, 0}; + RGB Blue = { 0, 0,32, 0}; + + // don't use color 0 + black=white=gray=dkgray=ltgray=blue=1; + + for(int i=1; i<256; i++) + { + if(pal_sum(p[i])pal_sum(p[white])) + white=i; + if(pal_abs(p[i],Gray) < pal_abs(p[gray],Gray)) + gray=i; + if(pal_abs(p[i],DkGray) < pal_abs(p[dkgray],DkGray)) + dkgray=i; + if(pal_abs(p[i],LtGray) < pal_abs(p[ltgray],LtGray)) + ltgray=i; + if(pal_abs(p[i],Blue) < pal_abs(p[blue],Blue)) + blue=i; + } + */ + black= bestfit_color(p, 0, 0, 0); + white= bestfit_color(p, 63, 63, 63); + dkgray=bestfit_color(p, 20, 20, 20); + gray= bestfit_color(p, 32, 32, 32); + ltgray=bestfit_color(p, 48, 48, 48); + blue= bestfit_color(p, 0, 0, 32); +} + +/* +byte mouse_data[16*16] = +{ + 1,1,0,0,0,0,0,0,0,0, + 1,2,1,0,0,0,0,0,0,0, + 1,2,2,1,0,0,0,0,0,0, + 1,2,2,2,1,0,0,0,0,0, + 1,2,2,2,2,1,0,0,0,0, + 1,2,2,2,2,2,1,0,0,0, + 1,2,2,2,2,2,2,1,0,0, + 1,2,2,2,2,2,2,2,1,0, + 1,2,2,2,2,2,2,2,2,1, + 1,2,2,2,2,2,1,1,1,1, + 1,2,2,1,2,2,1,0,0,0, + 1,2,1,0,1,2,2,1,0,0, + 1,1,0,0,1,2,2,1,0,0, + 0,0,0,0,0,1,2,2,1,0, + 0,0,0,0,0,1,2,2,1,0, + 0,0,0,0,0,0,1,1,1,0 +}; +*/ + +byte mouse_data[16*16] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,3,2,1,0,0,0,0,0,0,0,0,0,0,0, + 0,2,4,3,2,1,0,0,0,0,0,0,0,0,0,0, + 0,2,4,3,3,2,1,0,0,0,0,0,0,0,0,0, + 0,2,4,4,3,3,2,1,0,0,0,0,0,0,0,0, + 0,2,4,4,3,3,3,2,1,0,0,0,0,0,0,0, + 0,2,4,4,4,3,3,3,2,1,0,0,0,0,0,0, + 0,2,4,4,4,3,3,3,3,2,1,0,0,0,0,0, + 0,2,4,4,4,4,3,3,3,1,1,1,0,0,0,0, + 0,2,4,4,3,3,1,1,1,0,0,0,0,0,0,0, + 0,2,3,3,1,1,0,0,0,0,0,0,0,0,0,0, + 0,2,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; + + +DIALOG help_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { d_textbox_proc, 0, 0, 319, 239, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *)close_dlg, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +void do_help() +{ + help_dlg[0].dp = helpbuf; + help_dlg[0].fg = ltgray; + help_dlg[0].bg = black; + help_dlg[0].dp2 = lfont; + + popup_dialog(help_dlg,0); +} + + + +long readfile(const char *path,void *buf,int count) +{ + FILE *f=fopen(path,"rb"); + + if(!f) + return 0; + + long r=fread(buf,1,count,f); + fclose(f); + return r; +} + + + +void setup_palettes() +{ + for(int i=0; i<256; i++) + pal[1][i] = pal[2][i] = pal[0][i]; + + for(int i=0; i<256; i+=16) + pal[1][i] = black_palette[0]; + + for(int i=0; i<256; i++) + pal[3][i] = invRGB(pal[0][i]); + + for(int i=0; i<256; i+=16) + pal[2][i] = pal[3][i]; +} + + + +RGB nes_palette[] = +{ + {31,31,31, 0}, // 0 + { 0, 0,63, 0}, // 1 + { 0, 0,47, 0}, // 2 + {17,10,47, 0}, // 3 + {37, 0,33, 0}, // 4 + {42, 0, 8, 0}, // 5 + {42, 4, 0, 0}, // 6 + {34, 5, 0, 0}, // 7 + {20,12, 0, 0}, // 8 + { 0,30, 0, 0}, // 9 + { 0,26, 0, 0}, // 10 + { 0,22, 0, 0}, // 11 + { 0,16,22, 0}, // 12 + { 0, 0, 0, 0}, // 13 + { 0, 0, 0, 0}, // 14 + { 0, 0, 0, 0}, // 15 + {47,47,47, 0}, // 16 + { 0,30,62, 0}, // 17 + { 0,22,62, 0}, // 18 + {26,17,63, 0}, // 19 + {54, 0,51, 0}, // 20 + {57, 0,22, 0}, // 21 + {62,14, 0, 0}, // 22 + {57,23, 4, 0}, // 23 + {43,31, 0, 0}, // 24 + { 0,46, 0, 0}, // 25 + { 0,42, 0, 0}, // 26 + { 0,42,17, 0}, // 27 + { 0,34,34, 0}, // 28 + { 0, 0, 0, 0}, // 29 + { 0, 0, 0, 0}, // 30 + { 0, 0,32, 0}, // 31 + {62,62,62, 0}, // 32 + {15,47,63, 0}, // 33 + {26,34,63, 0}, // 34 + {38,30,62, 0}, // 35 + {62,30,62, 0}, // 36 + {62,22,38, 0}, // 37 + {62,30,22, 0}, // 38 + {63,40,17, 0}, // 39 + {62,46, 0, 0}, // 40 + {46,62, 6, 0}, // 41 + {22,54,21, 0}, // 42 + {22,62,38, 0}, // 43 + { 0,58,54, 0}, // 44 + {30,30,30, 0}, // 45 + { 0, 0, 0, 0}, // 46 + {16,16,16, 0}, // 47 + {63,63,63, 0}, // 48 + {41,57,63, 0}, // 49 + {46,46,62, 0}, // 50 + {54,46,62, 0}, // 51 + {62,46,62, 0}, // 52 + {62,41,48, 0}, // 53 + {60,52,44, 0}, // 54 + {63,56,42, 0}, // 55 + {62,54,30, 0}, // 56 + {54,62,30, 0}, // 57 + {46,62,46, 0}, // 58 + {46,62,54, 0}, // 59 + { 0,63,63, 0}, // 60 + {62,54,62, 0}, // 61 + { 0,54,50, 0}, // 62 + {31,63,63, 0} // 63 +}; + + + +void load_sta_pal(byte *si) +{ +// pal[0] = black_palette; + memcpy(pal[0], black_palette, sizeof(PALETTE)); + RGB *di = pal[0]; + + for(int i=0; i<32; i++) + { + *di = *(di+128) = nes_palette[(*si)&63]; + si++; + di++; + + if((i&3)==3) + di+=12; + } + + pal[0][15] = nes_palette[0x30]; + pal[0][14] = nes_palette[0x10]; + pal[0][13] = nes_palette[0x00]; + pal[0][12] = nes_palette[0x2F]; + pal[0][11] = nes_palette[0x1F]; + + if(palbmp) + { + zc_free(palbmp); + palbmp = NULL; + } + + setup_palettes(); + currpal = cset = 0; + redraw=FULL; + setup_colors(); +} + + + +void load_zst_pal(byte *src) +{ + word *si = (word*)src; + RGB *di = pal[0]; + + for(int i=0; i<256; i++) + { + *di = _RGB((((*si)<<1)&0x3f),(((*si)>>4)&0x3e),(((*si)>>9)&0x3e)); + si++; + di++; + } + + if(palbmp) + { + zc_free(palbmp); + palbmp = NULL; + } + + setup_palettes(); + currpal = cset = 0; + redraw=FULL; + setup_colors(); +} + + + +void load_rom(char *path) +{ + if(!path) + return; + + long size = file_size_ex_password(path,""); + + if(size==0) + { + jwin_alert("Load error",path,"not found",NULL,"OK",NULL,13,27,lfont); + return; + } + + fsize = size; + + if(rombuf) + zc_free(rombuf); + + if(sel) + zc_free(sel); + + // make sel big enough for one byte per tile in 1-bitplane mode + // then a row of 16 tiles takes 128 bytes + selsize = (fsize>>7)<<4; + rombuf = (byte*)zc_malloc(fsize); + sel = (byte*)zc_malloc(selsize); + + if(!sel || !rombuf) + { + jwin_alert("Load error","Out of memory",NULL,NULL,"OK",NULL,13,27,lfont); + fsize = selsize = 0; + return; + } + + for(int i=0; i0) fofs--; + + redraw=PARTIAL; + return D_O_K; +} +int onIncOfs() +{ + fofs++; + redraw=PARTIAL; + return D_O_K; +} + +int onUp() +{ + ofs -= 8*16*bp; + redraw=PARTIAL; + return D_O_K; +} +int onDown() +{ + ofs += 8*16*bp; + redraw=PARTIAL; + return D_O_K; +} +int onLeft() +{ + fofs -= 8*bp; + + if(fofs<0) fofs=0; + + redraw=PARTIAL; + return D_O_K; +} +int onRight() +{ + fofs += 8*bp; + redraw=PARTIAL; + return D_O_K; +} +int onPgUp() +{ + ofs -= 8*PANE*16*bp; + redraw=PARTIAL; + return D_O_K; +} +int onPgDn() +{ + ofs += 8*PANE*16*bp; + redraw=PARTIAL; + return D_O_K; +} +int onHome() +{ + ofs = 0; + redraw=PARTIAL; + return D_O_K; +} +int onEnd() +{ + ofs = fsize; + redraw=PARTIAL; + return D_O_K; +} + +int onMode() +{ + single = !single; + redraw=PARTIAL; + return D_O_K; +} + + +int onWidth() +{ + if(savew==512) + savew=128; + else + savew<<=1; + + redraw=PARTIAL; + return D_O_K; +} + + +int onPalette() +{ + currpal++; + currpal&=3; + setup_colors(); + redraw=FULL; + return D_O_K; +} + + + + +void do_save(bool saveas) +{ + static int fnum=1; + + struct al_ffblk fb; + BITMAP *bmp; + char fname[260]; + + if(selcnt==0) + { + jwin_alert("Save Error","Nothing is selected",NULL,NULL,"OK",NULL,13,27,lfont); + return; + } + + // create the image + bmp = create_save_bitmap(); + + if(!bmp) + { + jwin_alert("Save Error","Out of memory",NULL,NULL,"OK",NULL,13,27,lfont); + return; + } + + // find next default file name + sprintf(fname,"rombmp%02d.bmp",fnum); + + while(fnum<99 && !al_findfirst(fname, &fb, FA_ALL)) + { + sprintf(fname,"rombmp%02d.bmp",++fnum); + } + + + // save as ? + if(saveas) + { + int ret = jwin_file_select_ex("Save Image File (bmp,pcx)", fname, "bmp;pcx", 2048, -1, -1, lfont); + redraw_screen(FULL); + + if(ret==0) + goto clean_up; + + if(!al_findfirst(fname, &fb, FA_ALL)) + { + if(jwin_alert("Confirm Overwrite",fname,"already exists.","Overwrite it?","&Yes","&No",'y','n',lfont)==2) + goto clean_up; + } + } + + // write the file + if(save_bitmap(fname,bmp,pal[currpal])==0) + jwin_alert("ROMview","Saved as:",fname,NULL,"OK",NULL,13,27,lfont); + else + jwin_alert("Save Error","Error saving:",fname,NULL,"OK",NULL,13,27,lfont); + +clean_up: + destroy_bitmap(bmp); +} + + + +int onSave() +{ + do_save(false); + return D_O_K; +} + + +int onSaveAs() +{ + do_save(true); + return D_O_K; +} + + +int onPreview() +{ + BITMAP *bmp,*buf; + int px=0,py=0; + double scale=1.0; + bool done=false, refresh=true; + + if(selcnt==0) + { + jwin_alert("Preview Error","Nothing is selected",NULL,NULL,"OK",NULL,13,27,lfont); + return D_O_K; + } + + // create the image + bmp = create_save_bitmap(); + + if(!bmp) + { + jwin_alert("Preview Error","Out of memory",NULL,NULL,"OK",NULL,13,27,lfont); + return D_O_K; + } + + // use double buffering if possible + buf = create_bitmap_ex(8, 320,240); + + scare_mouse(); + + while(!done) + { + if(refresh) + { + // use double buffering if possible + BITMAP *b = (buf!=NULL) ? buf : screen; + + if(buf==NULL) + vsync(); + + clear_to_color(b,black); + stretch_blit(bmp,b,0,0,bmp->w,bmp->h, + int(320+(px-bmp->w)*scale)/2,int(240+(py-bmp->h)*scale)/2, + int(bmp->w*scale),int(bmp->h*scale)); + + //text_mode(black); + textprintf_ex(b,font,0,232,white,-1,"%dx%d %.0f%%",bmp->w,bmp->h,scale*100); + + if(buf) + { + vsync(); + blit(buf,screen,0,0,0,0,320,240); + } + + refresh=false; + } + + int speed = 5; + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + speed = 25; + + if(key[KEY_UP]) + { + py+=speed; + refresh=true; + } + + if(key[KEY_DOWN]) + { + py-=speed; + refresh=true; + } + + if(key[KEY_LEFT]) + { + px+=speed; + refresh=true; + } + + if(key[KEY_RIGHT]) + { + px-=speed; + refresh=true; + } + + if(keypressed() && !refresh) + { + refresh=true; + + switch(readkey()>>8) + { + case KEY_ESC: + done=true; + break; + + case KEY_PGUP: + if(scale>0.1) scale*=0.95; + + break; + + case KEY_PGDN: + if(scale<5.0) scale/=0.95; + + break; + + case KEY_TILDE: + scale=0.5; + break; + + case KEY_1: + scale=1.0; + break; + + case KEY_2: + scale=2.0; + break; + + case KEY_3: + scale=3.0; + break; + + case KEY_4: + scale=4.0; + break; + + case KEY_5: + scale=5.0; + break; + + case KEY_C: + px=py=0; + break; + + case KEY_Z: + px = bmp->w - int(320 / scale); + py = bmp->h - int(240 / scale); + break; + + default: + refresh=false; + } + } + } // while(!done) + + destroy_bitmap(bmp); + destroy_bitmap(buf); + rectfill(screen,0,0,319,15,black); + unscare_mouse(); + redraw_screen(FULL); + return D_REDRAW; +} + + + + +int onSelectAll() +{ + if(fsize && jwin_alert("Confirm Select","Select entire ROM?",NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + locked=true; + + for(int i=0; i", onSelectPane, NULL, 0, NULL }, + { (char *)"Select &All\ta", onSelectAll, NULL, 0, NULL }, + { (char *)"&Clear All\tc", onClearAll, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +MENU bp_menu[] = +{ + { (char *)"&1\t1", onBP1, NULL, 0, NULL }, + { (char *)"&2\t2", onBP2, NULL, 0, NULL }, + { (char *)"&4\t4", onBP4, NULL, 0, NULL }, + { (char *)"&8\t8", onBP8, NULL, 0, NULL }, + { (char *)"&NES\tn", onBPNES, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +MENU misc_menu[] = +{ + { (char *)"&About...", onAbout, NULL, 0, NULL }, + { (char *)"&Help\tF1", onHelp, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Palette\tp", onPalette, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +MENU main_menu[] = +{ + { (char *)"&File", NULL, file_menu, 0, NULL }, + { (char *)"&Ripper", NULL, rip_menu, 0, NULL }, + { (char *)"&Selection", NULL, sel_menu, 0, NULL }, + { (char *)"&BP", NULL, bp_menu, 0, NULL }, + { (char *)"&Misc", NULL, misc_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + + +DIALOG main_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, -2, -2, 324, 244, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_menu_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)main_menu, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *)onExit, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, (void *)onHelp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F3, (void *)onLoadROM, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F4, (void *)onLoadPal, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_1, (void *)onBP1, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_2, (void *)onBP2, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_4, (void *)onBP4, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_8, (void *)onBP8, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_N, (void *)onBPNES, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_UP, (void *)onUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DOWN, (void *)onDown, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGUP, (void *)onPgUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGDN, (void *)onPgDn, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_HOME, (void *)onHome, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_END, (void *)onEnd, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_LEFT, (void *)onLeft, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, (void *)onRight, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_MINUS_PAD, (void *)onDecCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PLUS_PAD, (void *)onIncCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_P, (void *)onPalette, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_A, (void *)onSelectAll, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_C, (void *)onClearAll, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_SPACE, (void *)onSelectPane, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_S, (void *)onSave, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_W, (void *)onWidth, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_V, (void *)onPreview, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_Z, (void *)onDecOfs, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_X, (void *)onIncOfs, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_M, (void *)onMode, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_EQUALS, (void *)onDecCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_MINUS, (void *)onIncCSet, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + +void setup_colors() +{ + static BITMAP *mouse = NULL; + + set_palette(pal[currpal]); + get_bw(pal[currpal]); + gui_bg_color = black; + gui_fg_color = white; + gui_mg_color = ltgray; + set_dialog_color(main_dlg, gui_fg_color, gui_bg_color); + + jwin_colors[jcSELFG] = + jwin_colors[jcLIGHT] = + jwin_colors[jcTITLEFG] = + jwin_colors[jcTEXTBG] = white; + + jwin_colors[jcMEDLT] = ltgray; + + jwin_colors[jcBOX] = ltgray; + + jwin_colors[jcMEDDARK] = gray; + + jwin_colors[jcBOXFG] = + jwin_colors[jcTEXTFG] = black; + + jwin_colors[jcDARK] = dkgray; + + jwin_colors[jcTITLEL] = + jwin_colors[jcTITLER] = + jwin_colors[jcSELBG] = blue; + + jwin_set_colors(jwin_colors); + + if(!mouse) + mouse = create_bitmap_ex(8, 16,16); + + if(mouse) + { + int si=0; + + for(int y=0; y<16; y++) + for(int x=0; x<16; x++) + { + int c=mouse_data[si++]; + + switch(c) + { + case 1: + c=dkgray; + break; + + case 2: + c=gray; + break; + + case 3: + c=ltgray; + break; + + case 4: + c=white; + break; + } + + putpixel(mouse,x,y,c); + } + + set_mouse_sprite(mouse); + } + + show_mouse(screen); +} + + +void redraw_screen(int type) +{ + int bx = ((ofs/128)/bp)*16; + calc_saveh(); + + scare_mouse(); + clear_to_color(scr_buf, ltgray); + + //rom contents + textout_ex(scr_buf,font,"Tiles",2+66,24-8,black,-1); + draw_pane(rombuf+ofs+fofs,sel+bx,2,26); + + if(type==FULL) + { + //palette source image + rectfill(scr_buf,148,76,315,235,black); + + if(palbmp) + { + blit(palbmp,scr_buf,palbmpx,palbmpy,148,76,168,160); + } + + jwin_draw_frame(scr_buf,146,74,172, 164, FR_DEEP); + + //palette + for(int i=0; i<256; i++) + { + int x = ((i&15)*3)+160+88; + int y = ((i>>4)*3)+76-74; + rectfill(scr_buf,x,y+16,x+2,y+2+16,i); + } + + //palette rectangles + jwin_draw_frame(scr_buf,159+87,0+16,52, 52, FR_DEEP); + jwin_draw_frame(scr_buf,159+87+52,0+16,7, 52, FR_DEEP); + //rect(scr_buf,159+88,75-74,230+88,140-74,white); + //rect(scr_buf,224+88,76-74,225+88,139-74,white); + } + + //line above info box + //hline(scr_buf,144,16,319,black); + //info box contents + textprintf_ex(scr_buf,font,146,17,black,-1,"bit planes: %d %s ",bp,locked?"locked":" "); + textprintf_ex(scr_buf,font,146,25,black,-1,"row offset: %06Xh ",ofs); + textprintf_ex(scr_buf,font,146,33,black,-1,"tuning offset: %03Xh ",fofs); + textprintf_ex(scr_buf,font,146,41,black,-1,"bitmap size: %dx%d ",savew,saveh); + textprintf_ex(scr_buf,font,146,49,black,-1,"bitmap size: %d KB ",(saveh*savew)>>10); + textprintf_ex(scr_buf,font,146,57,black,-1,"selection: %s ",single?"single":"row "); + textprintf_ex(scr_buf,font,146,65,black,-1,"color set: %X",cset); + textprintf_ex(scr_buf,font,215,65,black,-1,"pal: %d ",currpal); + + //rom contents/locked color divider + //rectfill(scr_buf,128,16,131,239,black); + //locked color/info box divider + //rectfill(scr_buf,140,16,143,239,black); + //cset indicator background + rectfill(scr_buf,226+88-14,76-74+16,229+88-14-1,139-74,black); + //cset indicator + rectfill(scr_buf,226+88-14,76-74+(cset*3)+16,229+88-14-1,79-74+(cset*3)-1+16,white); + + blit(scr_buf, screen, 0, 16, 0, 16, zq_screen_w, zq_screen_h-16); + unscare_mouse(); + + redraw=0; +} + + + +int log2(const int x) +{ + int log = 0; + int a = 1; + + while(x > a) + { + a <<= 1; + log++; + } + + return log; +} + +int main(int argc, char **argv) +{ + + /* + // Initialize SDL + if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { + fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); + return(1); + } + */ + allegro_init(); + install_timer(); + install_keyboard(); + install_mouse(); + + three_finger_flag=false; + register_bitmap_file_type("GIF", load_gif, save_gif); + jpgalleg_init(); + loadpng_init(); + + set_config_file("ag.cfg"); + tmp_scr=create_bitmap_ex(8, 320, 240); + scr_buf=create_bitmap_ex(8, 320, 240); + memset(temppath, 0, 2048); + + gui_mouse_focus = 0; + + set_color_depth(8); + set_close_button_callback((void (*)()) hit_close_button); + +#ifndef ALLEGRO_DOS + zq_scale = get_config_int("romview","scale",1); + scale_arg = used_switch(argc,argv,"-scale"); + scale_arg = false; // What!? + +#ifdef _WIN32 + // This seems to fix some problems on Windows 7 + disable_direct_updating = (byte) get_config_int("graphics","disable_direct_updating",1); +#endif + + if(scale_arg && (argc>(scale_arg+1))) + { + scale_arg = atoi(argv[scale_arg+1]); + + if(scale_arg == 0) + { + scale_arg = 1; + } + + zq_scale=scale_arg; + } + else + { + scale_arg = zq_scale; + } + + // Ho hum...Romview has some problems so just disable scaling altogether...for now. -Gleeok + //zqwin_set_scale(scale_arg); + zqwin_set_scale(0,false); +#endif + + if(used_switch(argc,argv,"-fullscreen")) + { + tempmode = GFX_AUTODETECT_FULLSCREEN; + } + else if(used_switch(argc,argv,"-windowed")) + { + tempmode=GFX_AUTODETECT_WINDOWED; + } + + if(tempmode==GFX_AUTODETECT_FULLSCREEN) + { +#ifdef ALLEGRO_MACOSX + scale_arg=2; +#else + + if(scale_arg>2) + { + scale_arg=1; + } + +#endif + zqwin_set_scale(scale_arg); + } + + /* No -fullscreen while debugging */ +#if defined _MSC_VER && defined _DEBUG + tempmode=GFX_AUTODETECT_WINDOWED; +#endif + + if(set_gfx_mode(tempmode,320,240,0,0) != 0) + { + allegro_exit(); + byebye(); + printf("Error setting video mode: %s\n", allegro_error); + return 2; + } + + resolve_password(datapwd); + //setPackfilePassword(datapwd); + packfile_password(datapwd); + + sprintf(fontsdat_sig,"Fonts.Dat %s Build %d",VerStr(FONTSDAT_VERSION), FONTSDAT_BUILD); + + Z_message("Fonts.Dat..."); + + if((fontsdata=load_datafile("fonts.dat"))==NULL) + { + Z_error("failed"); + } + + if(strncmp((char*)fontsdata[0].dat,fontsdat_sig,23)) + { + unload_datafile(fontsdata); + Z_error("\nIncompatible version of fonts.dat.\nPlease upgrade to %s Build %d",VerStr(FONTSDAT_VERSION), FONTSDAT_BUILD); + } + + Z_message("OK\n"); + + //setPackfilePassword(NULL); + packfile_password(""); + //const char *passwd = ""; + + font = (FONT*)fontsdata[FONT_GUI_PROP].dat; + pfont = (FONT*)fontsdata[FONT_8xPROP_THIN].dat; + lfont = (FONT*)fontsdata[FONT_LARGEPROP].dat; + + load_rom((argc>1 && argv[1][0]!='-') ? argv[1] : NULL); + load_pal((argc>2 && argv[2][0]!='-') ? argv[2] : NULL); + + + helpsize = file_size_ex_password("romview.txt",""); + + if(helpsize==0) + { + helpbuf=NULL; + } + else + { + helpbuf=(char*)zc_malloc(helpsize+1); + + if(!helpbuf) + helpsize=0; + else + { + if(readfile("romview.txt",helpbuf,helpsize)!=helpsize) + helpsize=0; + else + helpbuf[helpsize]=0; + } + } + + + redraw_screen(FULL); + redraw = FULL; // to update menu + + misc_menu[1].flags = (helpsize==0) ? D_DISABLED : 0; + auto_menu[0].flags = prompt ? 0 : D_SELECTED; + auto_menu[1].flags = prompt ? D_SELECTED : 0; + + DIALOG_PLAYER *player = init_dialog(main_dlg,-1); + + while(update_dialog(player)) + { + if(redraw==AUTOMENU) + { + auto_menu[0].flags = prompt ? 0 : D_SELECTED; + auto_menu[1].flags = prompt ? D_SELECTED : 0; + redraw = 0; + } + else if(redraw) + { + int maxofs = (fsize - 128*PANE*bp) & (0xFFFFFF80 << (log2(bp))); + + if(ofs > maxofs) + ofs = maxofs; + + if(ofs < 0) + ofs = 0; + + calc_selcnt(); + + // update menu flags + if(fsize) + { + sel_menu[0].flags = single ? D_SELECTED : 0; + bp_menu[0].flags = ((bp==1) ? D_SELECTED : 0) + (locked ? D_DISABLED : 0); + bp_menu[1].flags = ((bp==2)&&(!nes) ? D_SELECTED : 0) + (locked ? D_DISABLED : 0); + bp_menu[2].flags = ((bp==4) ? D_SELECTED : 0) + (locked ? D_DISABLED : 0); + bp_menu[3].flags = ((bp==8) ? D_SELECTED : 0) + (locked ? D_DISABLED : 0); + bp_menu[4].flags = ((bp==2)&&(nes) ? D_SELECTED : 0) + (locked ? D_DISABLED : 0); + + rip_menu[1].flags = + rip_menu[3].flags = + rip_menu[4].flags = (selcnt==0) ? D_DISABLED : 0; + } + + // redraw screen + + if(redraw==FULL) + { + main_menu[1].flags = + main_menu[2].flags = + main_menu[3].flags = (fsize==0) ? D_DISABLED : 0; +// rectfill(screen,0,0,319,15,black); + broadcast_dialog_message(MSG_DRAW,0); + } + + redraw_screen(FULL); + + // wait for mouse button release + // and eat key presses in the mean time + while(gui_mouse_b()) + clear_keybuf(); + } + + if(mouse_in_rect(2,26,142,208)) + { + //rom contents + if((gui_mouse_b()&1) && fsize) + { + locked=true; + int bx = ((ofs/128)/bp)*16; + int di = ((gui_mouse_y()-26)/8)*16; + + if(sel[bx+di]==0 || !single) + set_sel_row(bx+di,16*cset+1); + + if(single) + { + int x = zc_min(gui_mouse_x()/8,15); + sel[bx+di+x] = 16*cset+1; + } + + redraw=PARTIAL; + calc_selcnt(); + } + else if(gui_mouse_b()&2) + { + int bx = ((ofs/128)/bp)*16; + int di = ((gui_mouse_y()-26)/8)*16; + set_sel_row(bx+di,0); + redraw=PARTIAL; + calc_selcnt(); + } + else if(gui_mouse_z()) + { + if(mouse_z>0) + { + switch(((key[KEY_ZC_LCONTROL]||key[KEY_ZC_RCONTROL])?2:0)+((key[KEY_LSHIFT]||key[KEY_RSHIFT])?1:0)) + { + case 3: //control, shift + onLeft(); + break; + + case 2: //control + onDecOfs(); + break; + + case 1: //shift + onPgUp(); + break; + + case 0: //nothing + default: + onUp(); + break; + } + } + else + { + switch(((key[KEY_ZC_LCONTROL]||key[KEY_ZC_RCONTROL])?2:0)+((key[KEY_LSHIFT]||key[KEY_RSHIFT])?1:0)) + { + case 3: //control, shift + onRight(); + break; + + case 2: //control + onIncOfs(); + break; + + case 1: //shift + onPgDn(); + break; + + case 0: //nothing + default: + onDown(); + break; + } + } + + position_mouse_z(0); + } + } + else if(mouse_in_rect(246,18,59,48)) + { + //palette + if(gui_mouse_b()&1) + { + while(gui_mouse_b()&1) + { + int new_cset = zc_min(zc_max(0, (gui_mouse_y()-18)/3),15); + + if(cset != new_cset) + { + cset = new_cset; + scare_mouse(); + redraw_screen(FULL); + unscare_mouse(); + } + } + } + else if(gui_mouse_z()) + { + if(mouse_z>0) + { + scare_mouse(); + cset=(cset+15)%16; + redraw_screen(FULL); + unscare_mouse(); + } + else + { + scare_mouse(); + cset=(cset+1)%16; + redraw_screen(FULL); + unscare_mouse(); + } + + position_mouse_z(0); + } + } + else if(mouse_in_rect(148,76,168,160)) + { + // palette source image + if(palbmp) + { + if(gui_mouse_b()&1) + { + int sx=palbmpx+gui_mouse_x(); + int sy=palbmpy+gui_mouse_y(); + + while(gui_mouse_b()&1) + { + int newpalbmpx = zc_min(zc_max(0,sx-gui_mouse_x()),zc_max(palbmp->w-168,0)); + int newpalbmpy = zc_min(zc_max(0,sy-gui_mouse_y()),zc_max(palbmp->h-160,0)); + + if(palbmpx != newpalbmpx || palbmpy != newpalbmpy) + { + palbmpx = newpalbmpx; + palbmpy = newpalbmpy; + scare_mouse(); + redraw_screen(FULL); + unscare_mouse(); + } + } + } + } + } + + if(close_button_quit) + { + close_button_quit=false; + + if(onExit()==D_CLOSE) + { + break; + } + } + } // while(update_dialog(player)) + + shutdown_dialog(player); + + zc_free(rombuf); + zc_free(sel); + destroy_bitmap(tmp_scr); + destroy_bitmap(scr_buf); + allegro_exit(); + byebye(); + + return 0; +} +END_OF_MAIN() + +// these are here so that copy_dialog won't choke when compiling romview +int d_alltriggerbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_comboa_radio_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_comboabutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssdn_btn_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssdn_btn2_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssdn_btn3_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssdn_btn4_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_sslt_btn_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_sslt_btn2_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_sslt_btn3_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_sslt_btn4_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssrt_btn_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssrt_btn2_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssrt_btn3_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssrt_btn4_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssup_btn_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssup_btn2_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssup_btn3_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_ssup_btn4_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_tri_edit_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_triggerbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int dcs_auto_button_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_jbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_kbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_listen_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_savemidi_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_dummy_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_timer_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + d=d; + msg=msg; + + return D_O_K; +} + +void large_dialog(DIALOG *d) +{ + d=d; +} + +/* That's all folks */ + + diff --git a/src/room.cpp b/src/room.cpp new file mode 100644 index 0000000000..f842d9a9a0 --- /dev/null +++ b/src/room.cpp @@ -0,0 +1,584 @@ +#include "room.h" + +#include "gamedata.h" +#include "guys.h" +#include "items.h" +#include "link.h" +#include "sound.h" +#include "maps.h" +#include "messageManager.h" +#include "zc_sys.h" +#include "zelda.h" +#include +#include +#include + +extern LinkClass Link; +extern MessageManager messageMgr; +extern sprite_list items; +RoomItems roomItems; + +item* createItem(int id) +{ + item* i=new item(id); + items.add(i); + return i; +} + +RoomItems::RoomItems(): + //items{ 0, 0, 0 }, + //prices{ 0, 0, 0 }, + numItems(0), + pricesVisible(true), + showSignedPrices(false), + rupeeMarker(0) +{ + items[0] = items[1] = items[2] = 0; + prices[0] = prices[1] = prices[2] = 0; +} + +void RoomItems::initialize() +{ + numItems=0; + pricesVisible=true; + showSignedPrices=false; + if(rupeeMarker) + { + rupeeMarker->markForDeletion(); + rupeeMarker=0; + } +} + +void RoomItems::addItem(item* it, int price) +{ + items[numItems]=it; + prices[numItems]=price; + numItems++; + + it->y=get_bit(quest_rules, qr_NOITEMOFFSET) ? 88 : 89; // Is that right? + + // It's a little silly to redo the positions each time, but whatever... + if(numItems==1) + it->x=120; + else if(numItems==2) + { + items[0]->x=88; + items[1]->x=152; + } + else // Better be 3 + { + items[0]->x=88; + items[1]->x=120; + items[2]->x=152; + } +} + +void RoomItems::drawPrices(BITMAP* target, int offset) +{ + if(!pricesVisible) + return; + + for(int i=0; i0) + priceStr='+'; + else if(prices[i]<0) + priceStr='-'; + } + + char numBuf[6]; + sprintf(numBuf, "%d", static_cast(std::abs(prices[i]))); + priceStr+=numBuf; + + int priceX=items[i]->x; + switch(priceStr.length()) + { + case 1: + priceX+=8; + break; + + case 3: + case 4: + priceX-=8; + break; + + case 5: + case 6: + priceX-=16; + break; + } + + textout_ex(target, zfont, priceStr.c_str(), priceX, 112+offset, 1, -1); + + if(rupeeMarker) + textout_ex(target, zfont, "X", 64, 112+offset, 1, -1); + } +} + +void RoomItems::clear() +{ + numItems=0; + pricesVisible=false; + if(rupeeMarker) + { + rupeeMarker->markForDeletion(); + rupeeMarker=0; + } +} + +void RoomItems::setPricesVisible(bool val, bool showRupee) +{ + pricesVisible=val; + if(showRupee && !rupeeMarker) + { + rupeeMarker=createItem(iRupy); + rupeeMarker->x=48; + rupeeMarker->y=108; // Should this check the item offset rule? + rupeeMarker->setPickupFlags(ipDUMMY); + } + else if(!showRupee && rupeeMarker) + { + rupeeMarker->markForDeletion(); + rupeeMarker=0; + } +} + +namespace +{ + +void clearRoomItems() +{ + roomItems.clear(); +} + +void buyShopItem(item* it, int price) +{ + // We've already checked that Link has enough money + + if(!current_item_power(itype_wallet)) // Infinite money? + game->change_drupy(-price); + + // Leave the rupee behind. It'll disappear when fadeclk hits 0. + // Which is another thing that ought to be changed... + roomItems.setPricesVisible(false, true); + + for(int i=0; i<3; i++) + { + item* it2=roomItems.getItem(i); + if(!it2) + break; + else if(it2==it) + continue; + it2->setPickupFlags(ipDUMMY|ipFADE); + //it2->onGetDummyMoney.clear(); + } +} + +void buyInfo(int infoMsg, int price) +{ + if(game->get_spendable_rupies()change_drupy(-price); + + roomItems.setPricesVisible(false); + messageMgr.showMessage(infoMsg); + + for(int i=0; i<3; i++) + { + item* it=roomItems.getItem(i); + if(!it) + break; + it->setPickupFlags(ipDUMMY); + //it->onGetDummyMoney.clear(); + } +} + +void getSecretMoney(item* it, int amount) +{ + it->pickup=ipDUMMY; + roomItems.setPricesVisible(true, false); + setmapflag(); + if(!current_item_power(itype_wallet)) + game->change_drupy(amount); +} + +// There's probably a simpler way to handle this... +const int gambleResults[24][3]={ + { 20, -10, -10 }, { 20, -10, -10 }, { 20, -40, -10}, { 20, -10, -40}, + { 50, -10, -10 }, { 50, -10, -10 }, { 50, -40, -10}, { 50, -10, -40}, + { -10, 20, -10 }, { -10, 20, -10 }, { -40, 20, -10}, { -10, 20, -40}, + { -10, 50, -10 }, { -10, 50, -10 }, { -40, 50, -10}, { -10, 50, -40}, + { -10, -10, 20 }, { -10, -10, 20 }, { -10, -40, 20}, { -40, -10, 20}, + { -10, -10, 50 }, { -10, -10, 50 }, { -10, -40, 50}, { -40, -10, 50} +}; + +void gamble(int index) +{ + if(game->get_spendable_rupies()<10 && + !current_item_power(itype_wallet)) + return; + + const int* results=gambleResults[rand()%24]; + for(int i=0; i<3; i++) + roomItems.setPrice(i, results[i]); + + game->change_drupy(results[index]); + + for(int i=0; i<3; i++) + { + item* it=roomItems.getItem(i); + if(!it) + break; + it->setPickupFlags(ipDUMMY); + //it->onGetDummyMoney.clear(); + } +} + +void moreBombsOrArrows(item* it, int price, bool arrows) +{ + if(game->get_spendable_rupies()change_drupy(-price); + setmapflag(); + + if(arrows) + { + game->change_maxarrows(10); + game->set_arrows(game->get_maxarrows()); + } + else // Bombs + { + game->change_maxbombs(4); + game->set_bombs(game->get_maxbombs()); + { + int div=zinit.bomb_ratio; + if(div>0) + game->change_maxcounter(4/div, 6); + } + + //also give Link an actual Bomb item + for(int i=0; ipickup=ipDUMMY|ipFADE; + fadeclk=66; + messageMgr.clear(true); + roomItems.setPricesVisible(false); + verifyBothWeapons(); +} + +void leaveMoneyOrLife(item* it, int price) +{ + if(it->id==iRupy) + { + if(game->get_spendable_rupies()change_drupy(-price); + } + else + { + if(game->get_maxlife()<=HP_PER_HEART) + return; + + game->set_life(zc_max(game->get_life()-HP_PER_HEART, 0)); + game->set_maxlife(zc_max(game->get_maxlife()-HP_PER_HEART, HP_PER_HEART)); + } + + for(int i=0; i<3; i++) + { + item* it2=roomItems.getItem(i); + if(!it2) + break; + it2->setPickupFlags(ipDUMMY|ipFADE); + //it2->onGetDummyMoney.clear(); + } + + roomItems.setPricesVisible(false); + messageMgr.clear(true); + fadeclk=66; + setmapflag(); +} + +// Adjust for wealth medals. Price should be positive. +int adjustPrice(int price) +{ + if(price==0) + return 0; + + int medalID=current_item_id(itype_wealthmedal); + + if(medalID>=0) + { + if((itemsbuf[medalID].flags&ITEM_FLAG1)!=0) // Percent + price=((price*itemsbuf[medalID].misc1)/100); + else + price-=itemsbuf[medalID].misc1; + } + + return price; +} + +void learnSlash() +{ + game->set_canslash(1); + sfx(WAV_SCALE); +} + +void getHalfMagic() +{ + if(game->get_magicdrainrate()) // ??? + game->set_magicdrainrate(1); + sfx(WAV_SCALE); +} + +void dummyShopItems() +{ + for(int i=0; i<3; i++) + { + item* it=roomItems.getItem(i); + if(it) + it->pickup&=~ipDUMMY; + } +} + +void payForDoorRepair(int amount) +{ + game->change_drupy(amount); +} + +} // End namespace + + + +void setUpRoom(const mapscr& screen) +{ + int repairCharge; + int message=screen.str; + item* theItem; + + switch(screen.room) + { + case rSP_ITEM: + roomItems.initialize(); + roomItems.setPricesVisible(false); + + theItem=createItem(screen.catchall); + theItem->setPickupFlags(ipONETIME2|ipHOLDUP|ipCHECK|ipSPECIAL); + theItem->onPickUp=clearRoomItems; + roomItems.addItem(theItem); + + break; + + case rINFO: + { + const infotype& info=QMisc.info[screen.catchall]; + roomItems.initialize(); + roomItems.setPricesVisible(true); + roomItems.setSignedPrices(true); + + for(int i=0; i<3; i++) + { + // The number of items isn't stored anywhere; + // we just check if the message is non-zero. + if(info.str[i]==0) + break; // continue? + + int msg=info.str[i]; + int price=adjustPrice(info.price[i]); + + theItem=createItem(iRupy); + theItem->setPickupFlags(ipMONEY|ipDUMMY); + //theItem->onGetDummyMoney=fastdelegate::bind(buyInfo, msg, price); + theItem->onGetDummyMoney= (void*)buyInfo; + roomItems.addItem(theItem, -price); + } + + break; + } + + case rMONEY: + { + roomItems.initialize(); + roomItems.setPricesVisible(false); + + int amount=screen.catchall; + theItem=createItem(iRupy); + theItem->setPickupFlags(ipONETIME|ipDUMMY|ipMONEY); + //theItem->onGetDummyMoney=fastdelegate::bind(getSecretMoney, theItem, amount); + theItem->onGetDummyMoney=(void*)getSecretMoney; + roomItems.addItem(theItem, amount); + + break; + } + + case rGAMBLE: + roomItems.initialize(); + roomItems.setPricesVisible(true); + roomItems.setSignedPrices(true); + + for(int i=0; i<3; i++) + { + theItem=createItem(iRupy); + theItem->setPickupFlags(ipMONEY|ipDUMMY); + //theItem->onGetDummyMoney=fastdelegate::bind(gamble, i); + theItem->onGetDummyMoney=(void*)(gamble); + roomItems.addItem(theItem, -10); + } + + break; + + case rRP_HC: + roomItems.initialize(); + roomItems.setPricesVisible(false); + theItem=createItem(iRPotion); + theItem->setPickupFlags(ipONETIME2|ipHOLDUP|ipFADE); + roomItems.addItem(theItem); + theItem=createItem(iHeartC); + theItem->setPickupFlags(ipONETIME2|ipHOLDUP|ipFADE); + roomItems.addItem(theItem); + break; + + case rP_SHOP: + if(current_item(itype_letter)setPickupFlags(flags); + theItem->setPrice(price); // There's got to be a better way... + // theItem->onPickUp=fastdelegate::bind(buyShopItem, theItem, price); + theItem->onPickUp=(void*)(buyShopItem); + roomItems.addItem(theItem, price); + } + + break; + } + + case rBOMBS: + case rARROWS: + { + roomItems.initialize(); + roomItems.setPricesVisible(true, false); + roomItems.setSignedPrices(true); + + int price=adjustPrice(screen.catchall); + bool arrows=(screen.room==rARROWS); // Select arrows or bombs + theItem=createItem(iRupy); + theItem->setPickupFlags(ipDUMMY|ipMONEY); + //theItem->onGetDummyMoney=fastdelegate::bind(moreBombsOrArrows, theItem, price, arrows); + theItem->onGetDummyMoney=(void*)(moreBombsOrArrows); + roomItems.addItem(theItem, -price); + + break; + } + + case rSWINDLE: + { + roomItems.initialize(); + roomItems.setPricesVisible(true, false); + roomItems.setSignedPrices(true); + + int price=screen.catchall; + theItem=createItem(iHeartC); + theItem->setPickupFlags(ipDUMMY|ipMONEY); + // theItem->onGetDummyMoney=fastdelegate::bind(leaveMoneyOrLife, theItem, price); + theItem->onGetDummyMoney=(void*)(leaveMoneyOrLife); + roomItems.addItem(theItem, -1); + theItem=createItem(iRupy); + theItem->setPickupFlags(ipDUMMY|ipMONEY); + // theItem->onGetDummyMoney=fastdelegate::bind(leaveMoneyOrLife, theItem, price); + theItem->onGetDummyMoney=(void*)(leaveMoneyOrLife); + roomItems.addItem(theItem, -price); + + break; + } + + case rREPAIR: + repairCharge=-screen.catchall; + setmapflag(); + break; + + // These are mostly handled later + case rMUPGRADE: + case rLEARNSLASH: + setmapflag(); + break; + } + + if(message!=0) + { + messageMgr.showMessage(message); + + // These should activate even if the player quits mid-message. + // Currently, they work when F6->Continue is used, but not F6->Save. + // None of them work with blank messages. That should probably change, + // but it was the same in 2.50... + switch(screen.room) + { + case rLEARNSLASH: + messageMgr.setMessageEndCallback(learnSlash); + break; + + case rMUPGRADE: + messageMgr.setMessageEndCallback(getHalfMagic); + break; + + case rREPAIR: + __debugbreak(); + //messageMgr.setMessageEndCallback(fastdelegate::bind(payForDoorRepair, repairCharge)); + break; + + case rP_SHOP: + messageMgr.setMessageEndCallback(dummyShopItems); + break; + } + + } + else // No message + Link.unfreeze(); +} diff --git a/src/room.h b/src/room.h new file mode 100644 index 0000000000..fb83bd156d --- /dev/null +++ b/src/room.h @@ -0,0 +1,53 @@ +#ifndef _ZC_ROOM_H_ +#define _ZC_ROOM_H_ + +#define NOMINMAX //stupid windows headers.. + +struct BITMAP; +class item; +struct mapscr; + +class RoomItems +{ +public: + RoomItems(); + void initialize(); + void addItem(item* it, int price=0); + void drawPrices(BITMAP* target, int offset); + void clear(); + inline void setPrice(int index, int newPrice) + { + prices[index]=newPrice; + } + + inline void setSignedPrices(bool val) + { + showSignedPrices=val; + } + + void setPricesVisible(bool val, bool showRupee); + + inline void setPricesVisible(bool val) + { + setPricesVisible(val, val); + } + + inline item* getItem(int index) + { + return (index /* For all those memory debugging fans ;-) */ +#endif +#include "zc_alleg.h" +#include "save_gif.h" +#include "zc_malloc.h" + +typedef struct +{ + short base; + unsigned char new_str; +} LZW_STRING; + +typedef struct +{ + int pos; + int bit_pos; + unsigned char data[255]; +} BUFFER; + +void clear_speed_buffer(short *speed_buffer); +void dump_buffer(BUFFER *b, PACKFILE *f); +void output(BUFFER *b, int bit_size, int code, PACKFILE *f); + +void clear_speed_buffer(short *speed_buffer) +{ +//#if defined(ALLEGRO_MACOSX) || defined(_MSC_VER) + //OSX doesn't like the assembly below. *shrug* + //this is basically the same as memset(speed_buffer,-1,256*4096*2) + //but is filling speed_buffer 4 bytes at a time instead of 1. + int b=(256*4096/2); + long *a=(long*)speed_buffer; + + while(--b>=0) + { + *a=-1; + a++; + } + + /* + #else + // clear speed buffer to -1 + __asm__("0:\n" + "movl %%ecx, (%%eax)\n" + "addl %%edx, %%eax\n" + "decl %%ebx\n" + "jne 0b\n" + : + : "a" (speed_buffer), "b" (256 * 4096 / 2), "c" (-1), "d" (4) + : "memory"); + #endif + */ +} + +void dump_buffer(BUFFER *b, PACKFILE *f) +{ + int size; + + size = b->pos; + + if(b->bit_pos != 0) + size ++; + + pack_putc(size, f); + pack_fwrite(b->data, size, f); +} + +void output(BUFFER *b, int bit_size, int code, PACKFILE *f) +{ + int shift; + + /* pack the code into the buffer */ + shift = b->bit_pos; + + for(;;) + { + if(shift >= 0) + { + if(b->bit_pos != 0) + b->data[b->pos] = (unsigned char)((code << shift) | b->data[b->pos]); + else + b->data[b->pos] = (unsigned char)(code << shift); + } + else + { + if(b->bit_pos != 0) + b->data[b->pos] = (unsigned char)((code >> -shift) | b->data[b->pos]); + else + b->data[b->pos] = (unsigned char)(code >> -shift); + } + + if(bit_size + shift > 7) + { + b->bit_pos = 0; + b->pos ++; + shift -= 8; + + if(b->pos == 255) + { + dump_buffer(b, f); + b->pos = 0; + b->bit_pos = 0; + } + + if(bit_size + shift <= 0) + break; + } + else + { + b->bit_pos = bit_size + shift; + break; + } + } +} + +int save_gif(const char *filename, BITMAP *bmp, const RGB *pal) +{ + PACKFILE *f; + int i, bpp, bit_size; + LZW_STRING string_table[4096]; + int prefix; + int input_pos = 0; + int c; /* current character */ + int empty_str; + BUFFER buffer; + short *speed_buffer; + + f = pack_fopen_password(filename, F_WRITE,""); + + if(!f) + return errno; + + pack_mputl(0x47494638, f); /* GIF8 */ + pack_mputw(0x3761, f); /* 7a */ + pack_iputw(bmp->w, f); /* width */ + pack_iputw(bmp->h, f); /* height */ + pack_putc(215, f); /* packed fields */ + pack_putc(0, f); /* background colour */ + pack_putc(0, f); /* pixel aspect ratio */ + + /* global colour table */ + for(i = 0; i < 256; i ++) + { + pack_putc(pal[i].r << 2, f); + pack_putc(pal[i].g << 2, f); + pack_putc(pal[i].b << 2, f); + } + + pack_putc(0x2c, f); /* image separator */ + pack_iputw(0, f); /* x offset */ + pack_iputw(0, f); /* y offset */ + pack_iputw(bmp->w, f); /* width */ + pack_iputw(bmp->h, f); /* height */ + pack_putc(0, f); /* packed fields */ + + /* Image data starts here */ + bpp = 8; + pack_putc(bpp, f); /* initial code size */ + + /* initialize string table */ + for(i = 0; i < 1 << bpp; i ++) + { + string_table[i].base = -1; + string_table[i].new_str = i; + } + + for(; i < (1 << bpp) + 2; i ++) + { + string_table[i].base = -1; + // string_table[i].new_str = -1; + string_table[i].new_str = 255; + } + + empty_str = (1 << bpp) + 2; + + prefix = -1; + + bit_size = bpp + 1; + + buffer.pos = 0; + buffer.bit_pos = 0; + + output(&buffer, bit_size, 1 << bpp, f); /* clear code */ + + speed_buffer = (short*)zc_malloc(256 * 4096 * 2); + clear_speed_buffer(speed_buffer); + + for(;;) + { + if((c = getpixel(bmp, input_pos % bmp->w, input_pos / bmp->w)) == EOF) + { + output(&buffer, bit_size, prefix, f); + output(&buffer, bit_size, (1 << bpp) + 1, f); /* end of information */ + dump_buffer(&buffer, f); + pack_putc(0, f); /* no more data blocks */ + break; + } + + input_pos ++; + + if(prefix == -1) + i = c; + else + i = speed_buffer[prefix * 256 + c]; + + if(i != -1) + { + prefix = i; + } + else + { + /* add prefix + c to string table */ + string_table[empty_str].base = prefix; + string_table[empty_str].new_str = c; + + /*if(prefix < 512) */ + speed_buffer[prefix * 256 + c] = empty_str; + + empty_str ++; + + /* output code for prefix */ + output(&buffer, bit_size, prefix, f); + + if(empty_str == (1 << bit_size) + 1) + bit_size ++; + + /* make sure string table doesn't overflow */ + if(empty_str == 4095) + { + output(&buffer, bit_size, 1 << bpp, f); /* clear code */ + empty_str = (1 << bpp) + 2; + bit_size = bpp + 1; + + clear_speed_buffer(speed_buffer); + } + + /* set prefix to c */ + prefix = c; + } + } + + zc_free(speed_buffer); + + pack_putc(0x3b, f); /* trailer (end of gif) */ + pack_fclose(f); + return errno; +} + diff --git a/src/save_gif.h b/src/save_gif.h new file mode 100644 index 0000000000..345ada090d --- /dev/null +++ b/src/save_gif.h @@ -0,0 +1,15 @@ +#ifndef SAVE_GIF_H +#define SAVE_GIF_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +int save_gif(const char *filename, BITMAP *bmp, const RGB *pal); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/src/scoped_ptr.h b/src/scoped_ptr.h new file mode 100644 index 0000000000..5b50751d38 --- /dev/null +++ b/src/scoped_ptr.h @@ -0,0 +1,190 @@ +////////////////////////////////////// +// Fast Container Library +// MIT License +////////////////////////////////////// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include // for size_t + +template +struct scoped_ptr_deleter +{ + typedef T value_type; + void operator()( const T* p ) const { delete p; } +}; + + +template +struct scoped_array_ptr_deleter +{ + typedef T value_type; + void operator()( const T* p ) const { delete [] p; } +}; + + + +// scoped_ptr + +template < class T, class Deleter = scoped_ptr_deleter > +class scoped_ptr +{ +public: + typedef T element_type; + typedef scoped_ptr this_type; + typedef Deleter deleter_type; + + explicit scoped_ptr( T* p = 0 ) + : _ptr(p) + { + } + + ~scoped_ptr() + { + delete_ptr(); + } + + operator bool() const { return _ptr != 0; } + bool operator!() const { return _ptr == 0; } + + T& operator*() const { return *_ptr; } + T* operator->() const { return _ptr; } + T* get() const { return _ptr; } + + void reset( T* p = 0 ) + { + if( p != _ptr ) + { + delete_ptr(); + _ptr = p; + } + } + + void swap( scoped_ptr& x ) + { + T* tmp = _ptr; + _ptr = x._ptr; + x._ptr = tmp; + } + + void delete_ptr() const + { + Deleter deleter; + deleter(_ptr); + } + +protected: + scoped_ptr( const scoped_ptr& ); + scoped_ptr& operator=( const scoped_ptr& ); + scoped_ptr& operator=( T* p ); + + T* _ptr; +}; + + + +template inline + void swap( scoped_ptr& a, scoped_ptr& b ) + { + a.swap(b); + } + +template + bool operator <(const scoped_ptr& a, const scoped_ptr& b) + { + return (a.get() < b.get()); + } + + + + +// scoped_array_ptr + +template < class T, class Deleter = scoped_array_ptr_deleter > +class scoped_array_ptr +{ +public: + typedef T element_type; + typedef scoped_array_ptr this_type; + typedef Deleter deleter_type; + + explicit scoped_array_ptr( T* p = 0 ) + : _ptr(p) + { + } + + ~scoped_array_ptr() + { + delete_ptr(); + } + + operator bool() const { return _ptr != 0; } + bool operator!() const { return _ptr == 0; } + + T& operator*() const { return *_ptr; } + T* operator->() const { return _ptr; } + T* get() const { return _ptr; } + + T& operator[]( size_t i ) const { return _ptr[i]; } + + void reset( T* p = 0 ) + { + if( p != _ptr ) + { + delete_ptr(); + _ptr = p; + } + } + + void swap( scoped_array_ptr& x ) + { + T* tmp = _ptr; + _ptr = x._ptr; + x._ptr = tmp; + } + + void delete_ptr() const + { + Deleter deleter; + deleter(_ptr); + } + +protected: + scoped_array_ptr( const scoped_array_ptr& ); + scoped_array_ptr& operator=( const scoped_array_ptr& ); + scoped_array_ptr& operator=( T* p ); + + T* _ptr; +}; + + + +template inline + void swap( scoped_array_ptr& a, scoped_array_ptr& b ) + { + a.swap(b); + } + +template + bool operator <( const scoped_array_ptr& a, const scoped_array_ptr& b ) + { + return (a.get() < b.get()); + } + + diff --git a/src/screenFreezeState.cpp b/src/screenFreezeState.cpp new file mode 100644 index 0000000000..2ef6f9bab6 --- /dev/null +++ b/src/screenFreezeState.cpp @@ -0,0 +1,70 @@ +#include "screenFreezeState.h" +#include "maps.h" +#include "messageManager.h" +#include "tiles.h" +#include "zdefs.h" +#include "zelda.h" + + +ScreenFreezeState::ScreenFreezeState(const MessageManager& mm): + messageMgr(mm), + messageFreeze(false) // The rest will be reset in update() +{ +} + +void ScreenFreezeState::update() +{ + if(get_bit(quest_rules,qr_MSGFREEZE)!=0) + messageFreeze = messageMgr.messageIsActive(); + freezeFFCCombo = false; + freezeNonFFCCombo = false; + + for(int i=0; i<32; i++) + { + if(combobuf[tmpscr->ffcs[i].getCombo()].type==cSCREENFREEZE) + freezeNonFFCCombo=true; + if(combobuf[tmpscr->ffcs[i].getCombo()].type==cSCREENFREEZEFF) + freezeFFCCombo=true; + } + + if(!(freezeNonFFCCombo && freezeFFCCombo)) + { + for(int i=0; i<176; i++) + { + if(combobuf[tmpscr->data[i]].type == cSCREENFREEZE) + freezeNonFFCCombo=true; + if(combobuf[tmpscr->data[i]].type == cSCREENFREEZEFF) + freezeFFCCombo=true; + } + } +} + +bool ScreenFreezeState::scriptDrawingFrozen() const +{ + return messageFreeze; +} + +bool ScreenFreezeState::ffcsFrozen() const +{ + return messageFreeze || freezeFFCCombo; +} + +bool ScreenFreezeState::globalScriptFrozen() const +{ + return messageFreeze; +} + +bool ScreenFreezeState::entitiesFrozen() const +{ + return messageFreeze || freezeNonFFCCombo; +} + +bool ScreenFreezeState::itemRefillsFrozen() const +{ + return messageFreeze; +} + +bool ScreenFreezeState::guysAndFiresFrozen() const +{ + return freezeNonFFCCombo; +} diff --git a/src/screenFreezeState.h b/src/screenFreezeState.h new file mode 100644 index 0000000000..3c56dd92ad --- /dev/null +++ b/src/screenFreezeState.h @@ -0,0 +1,29 @@ +#ifndef _ZC_SCREENFREEZESTATE_H_ +#define _ZC_SCREENFREEZESTATE_H_ + +class MessageManager; + +// Not sure if this warrants its own class. +// It might be merged into something else later. +class ScreenFreezeState +{ +public: + ScreenFreezeState(const MessageManager& messageMgr); + void update(); + + bool scriptDrawingFrozen() const; + bool ffcsFrozen() const; + bool globalScriptFrozen() const; + bool entitiesFrozen() const; + bool itemRefillsFrozen() const; + + // This one sucks. Even if messages freeze everything, guys and fires + // still update. Gotta do something better here. + bool guysAndFiresFrozen() const; + +private: + const MessageManager& messageMgr; + bool messageFreeze, freezeFFCCombo, freezeNonFFCCombo; +}; + +#endif diff --git a/src/screenWipe.cpp b/src/screenWipe.cpp new file mode 100644 index 0000000000..593978b717 --- /dev/null +++ b/src/screenWipe.cpp @@ -0,0 +1,883 @@ +#include "screenWipe.h" +#include "zc_alleg.h" +#include "zelda.h" + +static int chooseWipeShape(); +static void drawScreenWipe(BITMAP* dest, int x, int y, int a, int max_a); + +enum { bos_circle=0, bos_oval, bos_triangle, bos_smas }; + +static int black_opening_count=0; +static int black_opening_x,black_opening_y; +static int black_opening_shape; + +static const qword trianglelines[16]= +{ + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, +}; + +static word screen_triangles[28][32]; + +// the ULL suffixes are to prevent this warning: +// warning: integer constant is too large for "long" type +static const qword triangles[4][16][8]= //[direction][value][line] +{ + { + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL, + 0xFD00000000000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFD000000000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFD0000000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFD00000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFD000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFD0000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFD00ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + } + }, + { + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL, + 0x0000000000000000ULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL, + 0x00000000000000FDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL, + 0x000000000000FDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x0000000000FDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x00000000FDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x000000FDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + } + }, + { + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL + }, + { + 0x0000000000000000ULL, + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL + }, + { + 0xFD00000000000000ULL, + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFD000000000000ULL, + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFD0000000000ULL, + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFD00000000ULL, + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFD000000ULL, + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFD0000ULL, + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFD00ULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + } + }, + { + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL + }, + { + 0x0000000000000000ULL, + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL + }, + { + 0x0000000000000000ULL, + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL + }, + { + 0x00000000000000FDULL, + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x000000000000FDFDULL, + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x0000000000FDFDFDULL, + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x00000000FDFDFDFDULL, + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x000000FDFDFDFDFDULL, + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x0000FDFDFDFDFDFDULL, + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0x00FDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + }, + { + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL, + 0xFDFDFDFDFDFDFDFDULL + } + } +}; + + +void beginScreenWipeOut(int x, int y) +{ + black_opening_shape=chooseWipeShape(); + + int w=256, h=224; + int blockrows=28, blockcolumns=32; + int xoffset=(x-(w/2))/8, yoffset=(y-(h/2))/8; + + for(int blockrow=0; blockrow0) //shape is closing + { + drawScreenWipe(framebuf,black_opening_x,black_opening_y,black_opening_count,66); + + if(advance) + black_opening_count--; + } +} + +bool screenWipeIsActive() +{ + return black_opening_count!=0; +} + +void abortScreenWipe() +{ + black_opening_count=0; +} + +static int chooseWipeShape() +{ + // First, count how many bits are set + int numBits=0; + int bitCounter; + + for(int i=0; i<4; i++) + { + if(COOLSCROLL&(1<line[(blockrow*8+linerow)]); + + for(int blockcolumn=0; blockcolumn<32; ++blockcolumn) //40 + { + *triangleline=triangles[(screen_triangles[blockrow][blockcolumn]&0xC000)>>14] + [zc_min(zc_max((((31+distance)*(max_a-a)/max_a)+((screen_triangles[blockrow][blockcolumn]&0x0FFF)-0x0100)-(15+distance)),0),15)] + [linerow]; + ++triangleline; + } + } + } +} + +static void drawCircleWipe(BITMAP* dest, int x, int y, int a, int max_a) +{ + int w=256, h=224; + double new_w=(w/2)+abs(w/2-x); + double new_h=(h/2)+abs(h/2-y); + int r=int(sqrt((new_w*new_w)+(new_h*new_h))*a/max_a); + circlefill(tmp_scr,x,y,r,0); +} + +static void drawScreenWipe(BITMAP* dest, int x, int y, int a, int max_a) +{ + clear_to_color(tmp_scr, BLACK); + int w=256, h=224; + + switch(black_opening_shape) + { + case bos_oval: + drawOvalWipe(dest, x, y, a, max_a); + break; + + case bos_triangle: + drawTriangleWipe(dest, x, y, a, max_a); + break; + + case bos_smas: + drawSMASWipe(dest, x, y, a, max_a); + break; + + case bos_circle: + default: + drawCircleWipe(dest, x, y, a, max_a); + break; + } + + masked_blit(tmp_scr, dest, 0, 0, 0, 0, 320, 240); +} diff --git a/src/screenWipe.h b/src/screenWipe.h new file mode 100644 index 0000000000..ecf60c542d --- /dev/null +++ b/src/screenWipe.h @@ -0,0 +1,21 @@ +#ifndef _ZC_SCREENWIPE_H_ +#define _ZC_SCREENWIPE_H_ + +struct BITMAP; + +/// Begin wipe in from black. +void beginScreenWipeIn(int centerX, int centerY); + +/// Begin wipe out to black. +void beginScreenWipeOut(int centerX, int centerY); + +/// Cancel any active screen wipe. +void abortScreenWipe(); + +/// Returns true if a screen wipe is in progress. +bool screenWipeIsActive(); + +/// Updates the active screen wipe. +void updateScreenWipe(bool advance); + +#endif diff --git a/src/script_drawing.cpp b/src/script_drawing.cpp new file mode 100644 index 0000000000..7ad3f4b097 --- /dev/null +++ b/src/script_drawing.cpp @@ -0,0 +1,2265 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + + +#include "precompiled.h" //always first + +#include +#include "script_drawing.h" +#include "rendertarget.h" +#include "maps.h" +#include "tiles.h" +#include "zelda.h" +#include "ffscript.h" +#include + + +template inline +fixed degrees_to_fixed(T d) +{ + return ftofix(DegtoFix(d)); +} +template inline +fixed radians_to_fixed(T d) +{ + return ftofix(RadtoFix(d)); +} + +BITMAP* ScriptDrawingBitmapPool::_parent_bmp = 0; + + + + +FONT *get_zc_font(int index) +{ + //return getfont(index); + switch(index) + { + default: + return zfont; + + case font_z3font: + return z3font; + + case font_z3smallfont: + return z3smallfont; + + case font_deffont: + return deffont; + + case font_lfont: + return lfont; + + case font_lfont_l: + return lfont_l; + + case font_pfont: + return pfont; + + case font_mfont: + return mfont; + + case font_ztfont: + return ztfont; + + case font_sfont: + return sfont; + + case font_sfont2: + return sfont2; + + case font_spfont: + return spfont; + + case font_ssfont1: + return ssfont1; + + case font_ssfont2: + return ssfont2; + + case font_ssfont3: + return ssfont3; + + case font_ssfont4: + return ssfont4; + + case font_gblafont: + return gblafont; + + case font_goronfont: + return goronfont; + + case font_zoranfont: + return zoranfont; + + case font_hylian1font: + return hylian1font; + + case font_hylian2font: + return hylian2font; + + case font_hylian3font: + return hylian3font; + + case font_hylian4font: + return hylian4font; + + case font_gboraclefont: + return gboraclefont; + + case font_gboraclepfont: + return gboraclepfont; + + case font_dsphantomfont: + return dsphantomfont; + + case font_dsphantompfont: + return dsphantompfont; + } +} + + +class TileHelper +{ +public: + + static void OldPutTile(BITMAP* _Dest, int tile, int x, int y, int w, int h, int color, int flip, byte skiprows=0) + { + // Past the end of the tile page? + if(skiprows>0 && tile%TILES_PER_ROW+w>=TILES_PER_ROW) + { + byte w2=(tile+w)%TILES_PER_ROW; + OldPutTile(_Dest, tile, x, y, w-w2, h, color, flip); + OldPutTile(_Dest, tile+(w-w2)+(skiprows*TILES_PER_ROW), x+16*(w-w2), y, w2, h, color, flip); + return; + } + + switch(flip) + { + case 1: + for(int j=0; j=0; k--) + oldputtile16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+j*16, color, flip); + + break; + + case 2: + for(int j=h-1; j>=0; j--) + for(int k=0; k=0; j--) + for(int k=w-1; k>=0; k--) + oldputtile16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+((h-1)-j)*16, color, flip); + + break; + + case 0: + default: + for(int j=0; j0 && tile%TILES_PER_ROW+w>=TILES_PER_ROW) + { + byte w2=(tile+w)%TILES_PER_ROW; + OverTile(_Dest, tile, x, y, w-w2, h, color, flip); + OverTile(_Dest, tile+(w-w2)+(skiprows*TILES_PER_ROW), x+16*(w-w2), y, w2, h, color, flip); + return; + } + + switch(flip) + { + case 1: + for(int j=0; j=0; k--) + overtile16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+j*16, color, flip); + + break; + + case 2: + for(int j=h-1; j>=0; j--) + for(int k=0; k=0; j--) + for(int k=w-1; k>=0; k--) + overtile16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+((h-1)-j)*16, color, flip); + + break; + + default: + for(int j=0; j0 && tile%TILES_PER_ROW+w>=TILES_PER_ROW) + { + byte w2=(tile+w)%TILES_PER_ROW; + OverTileTranslucent(_Dest, tile, x, y, w-w2, h, color, flip, opacity); + OverTileTranslucent(_Dest, tile+(w-w2)+(skiprows*TILES_PER_ROW), x+16*(w-w2), y, w2, h, color, flip, opacity); + return; + } + + switch(flip) + { + case 1: + for(int j=0; j=0; k--) + overtiletranslucent16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+j*16, color, flip, opacity); + + break; + + case 2: + for(int j=h-1; j>=0; j--) + for(int k=0; k=0; j--) + for(int k=w-1; k>=0; k--) + overtiletranslucent16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+((h-1)-j)*16, color, flip, opacity); + + break; + + default: + for(int j=0; j0 && tile%TILES_PER_ROW+w>=TILES_PER_ROW) + { + byte w2=(tile+w)%TILES_PER_ROW; + PutTileTranslucent(_Dest, tile, x, y, w-w2, h, color, flip, opacity); + PutTileTranslucent(_Dest, tile+(w-w2)+(skiprows*TILES_PER_ROW), x+16*(w-w2), y, w2, h, color, flip, opacity); + return; + } + + switch(flip) + { + case 1: + for(int j=0; j=0; k--) + puttiletranslucent16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+j*16, color, flip, opacity); + + break; + + case 2: + for(int j=h-1; j>=0; j--) + for(int k=0; k=0; j--) + for(int k=w-1; k>=0; k--) + puttiletranslucent16(_Dest, tile+(j*TILES_PER_ROW)+k, x+((w-1)-k)*16, y+((h-1)-j)*16, color, flip, opacity); + + break; + + default: + for(int j=0; jx2) + { + zc_swap(x1,x2); + } + + if(y1>y2) + { + zc_swap(y1,y2); + } + + if(sdci[7] != 10000) + { + int w=x2-x1+1; + int h=y2-y1+1; + int w2=(w*sdci[7])/10000; + int h2=(h*sdci[7])/10000; + x1=x1-((w2-w)/2); + x2=x2+((w2-w)/2); + y1=y1-((h2-h)/2); + y2=y2+((h2-h)/2); + } + + int color=sdci[6]/10000; + + if(sdci[12]/10000<=127) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + if(sdci[10]==0) //no rotation + { + if(sdci[11]) //filled + { + rectfill(bmp, x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset, color); + } + else //outline + { + rect(bmp, x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset, color); + } + } + else //rotate + { + int xy[16]; + int rx=sdci[8]/10000; + int ry=sdci[9]/10000; + fixed ra1=itofix(sdci[10]%10000)/10000; + fixed ra2=itofix(sdci[10]/10000); + fixed ra=ra1+ra2; + ra = (ra/360)*256; + + fixed fcosa = fixcos(ra); + fixed fsina = fixsin(ra); + + xy[ 0]=xoffset+rx + fixtoi((fcosa * (x1 - rx) - fsina * (y1 - ry))); //x1 + xy[ 1]=yoffset+ry + fixtoi((fsina * (x1 - rx) + fcosa * (y1 - ry))); //y1 + xy[ 2]=xoffset+rx + fixtoi((fcosa * (x2 - rx) - fsina * (y1 - ry))); //x2 + xy[ 3]=yoffset+ry + fixtoi((fsina * (x2 - rx) + fcosa * (y1 - ry))); //y1 + xy[ 4]=xoffset+rx + fixtoi((fcosa * (x2 - rx) - fsina * (y2 - ry))); //x2 + xy[ 5]=yoffset+ry + fixtoi((fsina * (x2 - rx) + fcosa * (y2 - ry))); //y2 + xy[ 6]=xoffset+rx + fixtoi((fcosa * (x1 - rx) - fsina * (y2 - ry))); //x1 + xy[ 7]=yoffset+ry + fixtoi((fsina * (x1 - rx) + fcosa * (y2 - ry))); //y2 + xy[ 8]=xoffset+rx + fixtoi((fcosa * (x1 - rx) - fsina * (y1 - ry + 1))); //x1 + xy[ 9]=yoffset+ry + fixtoi((fsina * (x1 - rx) + fcosa * (y1 - ry + 1))); //y1 + xy[10]=xoffset+rx + fixtoi((fcosa * (x2 - rx - 1) - fsina * (y1 - ry))); //x2 + xy[11]=yoffset+ry + fixtoi((fsina * (x2 - rx - 1) + fcosa * (y1 - ry))); //y1 + xy[12]=xoffset+rx + fixtoi((fcosa * (x2 - rx) - fsina * (y2 - ry - 1))); //x2 + xy[13]=yoffset+ry + fixtoi((fsina * (x2 - rx) + fcosa * (y2 - ry - 1))); //y2 + xy[14]=xoffset+rx + fixtoi((fcosa * (x1 - rx + 1) - fsina * (y2 - ry))); //x1 + xy[15]=yoffset+ry + fixtoi((fsina * (x1 - rx + 1) + fcosa * (y2 - ry))); //y2 + + if(sdci[11]) //filled + { + polygon(bmp, 4, xy, color); + } + else //outline + { + line(bmp, xy[0], xy[1], xy[10], xy[11], color); + line(bmp, xy[2], xy[3], xy[12], xy[13], color); + line(bmp, xy[4], xy[5], xy[14], xy[15], color); + line(bmp, xy[6], xy[7], xy[ 8], xy[ 9], color); + } + } + + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + + +void do_circler(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=radius + //sdci[5]=color + //sdci[6]=scale factor + //sdci[7]=rotation anchor x + //sdci[8]=rotation anchor y + //sdci[9]=rotation angle + //sdci[10]=fill + //sdci[11]=opacity + if(sdci[6]==0) //scale + { + return; + } + + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + qword r=sdci[4]; + + if(sdci[6] != 10000) + { + r*=sdci[6]; + r/=10000; + } + + r/=10000; + int color=sdci[5]/10000; + + if(sdci[11]/10000<=127) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + if(sdci[9]!=0&&(sdci[2]!=sdci[7]||sdci[3]!=sdci[8])) //rotation + { + int xy[2]; + int rx=sdci[7]/10000; + int ry=sdci[8]/10000; + fixed ra1=itofix(sdci[9]%10000)/10000; + fixed ra2=itofix(sdci[9]/10000); + fixed ra=ra1+ra2; + ra = (ra/360)*256; + + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + x1=xy[0]; + y1=xy[1]; + } + + if(sdci[10]) //filled + { + circlefill(bmp, x1+xoffset, y1+yoffset, r, color); + } + else //outline + { + circle(bmp, x1+xoffset, y1+yoffset, r, color); + } + + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + +void do_arcr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=radius + //sdci[5]=start angle + //sdci[6]=end angle + //sdci[7]=color + //sdci[8]=scale factor + //sdci[9]=rotation anchor x + //sdci[10]=rotation anchor y + //sdci[11]=rotation angle + //sdci[12]=closed + //sdci[13]=fill + //sdci[14]=opacity + + if(sdci[8]==0) //scale + { + return; + } + + int cx=sdci[2]/10000; + int cy=sdci[3]/10000; + qword r=sdci[4]; + + if(sdci[8] != 10000) + { + r*=sdci[8]; + r/=10000; + } + + r/=10000; + + int color=sdci[7]/10000; + + fixed ra1=itofix(sdci[11]%10000)/10000; + fixed ra2=itofix(sdci[11]/10000); + fixed ra=ra1+ra2; + ra = (ra/360)*256; + + + fixed a1=itofix(sdci[5]%10000)/10000; + fixed a2=itofix(sdci[5]/10000); + fixed sa=a1+a2; + sa = (sa/360)*256; + + a1=itofix(sdci[6]%10000)/10000; + a2=itofix(sdci[6]/10000); + fixed ea=a1+a2; + ea = (ea/360)*256; + + if(sdci[11]!=0) //rotation + { + int rx=sdci[9]/10000; + int ry=sdci[10]/10000; + + cx=rx + fixtoi((fixcos(ra) * (cx - rx) - fixsin(ra) * (cy - ry))); //x1 + cy=ry + fixtoi((fixsin(ra) * (cx - rx) + fixcos(ra) * (cy - ry))); //y1 + ea-=ra; + sa-=ra; + } + + int fx=cx+fixtoi(fixcos(-(ea+sa)/2)*r/2); + int fy=cy+fixtoi(fixsin(-(ea+sa)/2)*r/2); + + if(sdci[12]) //closed + { + if(sdci[13]) //filled + { + clear_bitmap(prim_bmp); + arc(prim_bmp, cx+xoffset, cy+yoffset, sa, ea, int(r), color); + line(prim_bmp, cx+xoffset, cy+yoffset, cx+xoffset+fixtoi(fixcos(-sa)*r), cy+yoffset+fixtoi(fixsin(-sa)*r), color); + line(prim_bmp, cx+xoffset, cy+yoffset, cx+xoffset+fixtoi(fixcos(-ea)*r), cy+yoffset+fixtoi(fixsin(-ea)*r), color); + floodfill(prim_bmp, zc_max(0,fx)+xoffset, zc_max(0,fy)+yoffset, color); + + if(sdci[14]/10000<=127) //translucent + { + draw_trans_sprite(bmp, prim_bmp, 0,0); + } + else + { + draw_sprite(bmp, prim_bmp, 0,0); + } + } + else + { + arc(bmp, cx+xoffset, cy+yoffset, sa, ea, int(r), color); + line(bmp, cx+xoffset, cy+yoffset, cx+xoffset+fixtoi(fixcos(-sa)*r), cy+yoffset+fixtoi(fixsin(-sa)*r), color); + line(bmp, cx+xoffset, cy+yoffset, cx+xoffset+fixtoi(fixcos(-ea)*r), cy+yoffset+fixtoi(fixsin(-ea)*r), color); + } + } + else + { + if(sdci[14]/10000<=127) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + arc(bmp, cx+xoffset, cy+yoffset, sa, ea, int(r), color); + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + } +} + + +void do_ellipser(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=radiusx + //sdci[5]=radiusy + //sdci[6]=color + //sdci[7]=scale factor + //sdci[8]=rotation anchor x + //sdci[9]=rotation anchor y + //sdci[10]=rotation angle + //sdci[11]=fill + //sdci[12]=opacity + + if(sdci[7]==0) //scale + { + return; + } + + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + int radx=sdci[4]/10000; + radx*=sdci[7]/10000; + int rady=sdci[5]/10000; + rady*=sdci[7]/10000; + int color=sdci[6]/10000; + float rotation = sdci[10]/10000; + + int rx=sdci[8]/10000; + int ry=sdci[9]/10000; + fixed ra1=itofix(sdci[10]%10000)/10000; + fixed ra2=itofix(sdci[10]/10000); + fixed ra=ra1+ra2; + ra = (ra/360)*256; + + int xy[2]; + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + x1=xy[0]; + y1=xy[1]; + + if(radx<1||rady<1||radx>255||rady>255) return; + + BITMAP* bitty = script_drawing_commands.AquireSubBitmap(radx*2+1, rady*2+1); + + if(sdci[11]) //filled + { + + if(sdci[12]/10000<128) //translucent + { + clear_bitmap(prim_bmp); + ellipsefill(bitty, radx, rady, radx, rady, color==0?255:color); + rotate_sprite(prim_bmp, bitty, x1+xoffset-radx,y1+yoffset-rady, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, 0, 0); + } + else // no opacity + { + ellipsefill(bitty, radx, rady, radx, rady, color==0?255:color); + rotate_sprite(bmp, bitty, x1+xoffset-radx,y1+yoffset-rady, degrees_to_fixed(rotation)); + } + } + else //not filled + { + if(sdci[12]/10000<128) //translucent + { + clear_bitmap(prim_bmp); + ellipse(bitty, radx, rady, radx, rady, color==0?255:color); + rotate_sprite(prim_bmp, bitty, x1+xoffset-radx,y1+yoffset-rady, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, 0, 0); + } + else // no opacity + { + ellipse(bitty, radx, rady, radx, rady, color==0?255:color); + rotate_sprite(bmp, bitty, x1+xoffset-radx,y1+yoffset-rady, degrees_to_fixed(rotation)); + } + } + + // Since 0 is the transparent color, the stuff above will fail if the ellipse color is also 0. + // Instead, it uses color 255 and replaces it afterward. That'll also screw up color 255 around + // the ellipse, but it shouldn't be used anyway. + if(color==0) + { + int x; + int y; + + // This is very slow, so check the smallest possible square + int endx=zc_min(bmp->w-1, x1+zc_max(radx, rady)); + int endy=zc_min(bmp->h-1, y1+zc_max(radx, rady)); + + for(int y=zc_max(0, y1-zc_max(radx, rady)); y<=endy; y++) + for(int x=zc_max(0, x1-zc_max(radx, rady)); x<=endx; x++) + if(getpixel(bmp, x, y)==255) + putpixel(bmp, x, y, 0); + } + + script_drawing_commands.ReleaseSubBitmap(bitty); +} + + +void do_liner(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=x2 + //sdci[5]=y2 + //sdci[6]=color + //sdci[7]=scale factor + //sdci[8]=rotation anchor x + //sdci[9]=rotation anchor y + //sdci[10]=rotation angle + //sdci[11]=opacity + if(sdci[7]==0) //scale + { + return; + } + + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + int x2=sdci[4]/10000; + int y2=sdci[5]/10000; + + if(sdci[7] != 10000) + { + int w=x2-x1+1; + int h=y2-y1+1; + int w2=int(w*((double)sdci[7]/10000.0)); + int h2=int(h*((double)sdci[7]/10000.0)); + x1=x1-((w2-w)/2); + x2=x2+((w2-w)/2); + y1=y1-((h2-h)/2); + y2=y2+((h2-h)/2); + } + + int color=sdci[6]/10000; + + if(sdci[11]/10000<=127) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + if(sdci[10]!=0) //rotation + { + int xy[4]; + int rx=sdci[8]/10000; + int ry=sdci[9]/10000; + fixed ra1=itofix(sdci[10]%10000)/10000; + fixed ra2=itofix(sdci[10]/10000); + fixed ra=ra1+ra2; + + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + xy[ 2]=rx + fixtoi((fixcos(ra) * (x2 - rx) - fixsin(ra) * (y2 - ry))); //x2 + xy[ 3]=ry + fixtoi((fixsin(ra) * (x2 - rx) + fixcos(ra) * (y2 - ry))); //y2 + x1=xy[0]; + y1=xy[1]; + x2=xy[2]; + y2=xy[3]; + } + + line(bmp, x1+xoffset, y1+yoffset, x2+xoffset, y2+yoffset, color); + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + +void do_spliner(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + /* layer, x1, y1, x2, y2, x3, y3, x4, y4, color, opacity */ + + int points[8] = { xoffset + (sdci[2]/10000), yoffset + (sdci[3]/10000), + xoffset + (sdci[4]/10000), yoffset + (sdci[5]/10000), + xoffset + (sdci[6]/10000), yoffset + (sdci[7]/10000), + xoffset + (sdci[8]/10000), yoffset + (sdci[9]/10000) + }; + + if(sdci[11]/10000 < 128) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + spline(bmp, points, sdci[10]/10000); + + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + +void do_putpixelr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=color + //sdci[5]=rotation anchor x + //sdci[6]=rotation anchor y + //sdci[7]=rotation angle + //sdci[8]=opacity + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + int color=sdci[4]/10000; + + if(sdci[8]/10000<=127) //translucent + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + if(sdci[7]!=0) //rotation + { + int xy[2]; + int rx=sdci[5]/10000; + int ry=sdci[6]/10000; + fixed ra1=itofix(sdci[7]%10000)/10000; + fixed ra2=itofix(sdci[7]/10000); + fixed ra=ra1+ra2; + + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + x1=xy[0]; + y1=xy[1]; + } + + putpixel(bmp, x1+xoffset, y1+yoffset, color); + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + +void do_drawtiler(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=tile + //sdci[5]=tile width + //sdci[6]=tile height + //sdci[7]=color (cset) + //sdci[8]=scale x + //sdci[9]=scale y + //sdci[10]=rotation anchor x + //sdci[11]=rotation anchor y + //sdci[12]=rotation angle + //sdci[13]=flip + //sdci[14]=transparency + //sdci[15]=opacity + + int w = sdci[5]/10000; + int h = sdci[6]/10000; + + if(w < 1 || h < 1 || h > 20 || w > 20) + { + return; + } + + int xscale=sdci[8]/10000; + int yscale=sdci[9]/10000; + int rx = sdci[10]/10000; + int ry = sdci[11]/10000; + float rotation=sdci[12]/10000; + int flip=(sdci[13]/10000)&3; + bool transparency=sdci[14]!=0; + int opacity=sdci[15]/10000; + int color=sdci[7]/10000; + + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + + //don't scale if it's not safe to do so + bool canscale = true; + + if(xscale==0||yscale==0) + { + return; + } + + if(xscale<0||yscale<0) + canscale = false; //default size + + if((xscale>0 && yscale>0) || rotation) //scaled or rotated + { + BITMAP* pbitty = script_drawing_commands.AquireSubBitmap(w*16, h*16); + + if(transparency) //transparency + { + TileHelper::OverTile(pbitty, (sdci[4]/10000), 0, 0, w, h, color, flip); + } + else //no transparency + { + TileHelper::OldPutTile(pbitty, (sdci[4]/10000), 0, 0, w, h, color, flip); + } + + if(rotation != 0) + { + //low negative values indicate no anchor-point rotation + if(rx>-777||ry>-777) + { + int xy[2]; + fixed ra1=itofix(sdci[12]%10000)/10000; + fixed ra2=itofix(sdci[12]/10000); + fixed ra=ra1+ra2; + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + x1=xy[0]; + y1=xy[1]; + } + + if(canscale) //scale first + { + //damnit all, .. fixme. + BITMAP* tempbit = create_bitmap_ex(8, xscale>512?512:xscale, yscale>512?512:yscale); + clear_bitmap(tempbit); + + stretch_sprite(tempbit, pbitty, 0, 0, xscale, yscale); + + if(opacity < 128) + { + clear_bitmap(prim_bmp); + rotate_sprite(prim_bmp, tempbit, 0, 0, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + rotate_sprite(bmp, tempbit, x1+xoffset, y1+yoffset, degrees_to_fixed(rotation)); + } + + destroy_bitmap(tempbit); + } + else //no scale + { + if(opacity < 128) + { + clear_bitmap(prim_bmp); + rotate_sprite(prim_bmp, pbitty, 0, 0, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + rotate_sprite(bmp, pbitty, x1+xoffset, y1+yoffset, degrees_to_fixed(rotation)); + } + } + } + else //scale only + { + if(canscale) + { + if(opacity<128) + { + clear_bitmap(prim_bmp); + stretch_sprite(prim_bmp, pbitty, 0, 0, xscale, yscale); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + stretch_sprite(bmp, pbitty, x1+xoffset, y1+yoffset, xscale, yscale); + } + } + else //error -do not scale + { + if(opacity<128) + { + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + draw_sprite(bmp, pbitty, x1+xoffset, y1+yoffset); + } + } + } + + script_drawing_commands.ReleaseSubBitmap(pbitty); + + } + else // no scale or rotation + { + if(transparency) + { + if(opacity<=127) + TileHelper::OverTileTranslucent(bmp, (sdci[4]/10000), xoffset+x1, yoffset+y1, w, h, color, flip, opacity); + else + TileHelper::OverTile(bmp, (sdci[4]/10000), xoffset+x1, yoffset+y1, w, h, color, flip); + } + else + { + if(opacity<=127) + TileHelper::PutTileTranslucent(bmp, (sdci[4]/10000), xoffset+x1, yoffset+y1, w, h, color, flip, opacity); + else + TileHelper::OldPutTile(bmp, (sdci[4]/10000), xoffset+x1, yoffset+y1, w, h, color, flip); + } + } +} + + +void do_drawcombor(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=combo + //sdci[5]=tile width + //sdci[6]=tile height + //sdci[7]=color (cset) + //sdci[8]=scale x + //sdci[9]=scale y + //sdci[10]=rotation anchor x + //sdci[11]=rotation anchor y + //sdci[12]=rotation angle + //sdci[13]=frame + //sdci[14]=flip + //sdci[15]=transparency + //sdci[16]=opacity + + int w = sdci[5]/10000; + int h = sdci[6]/10000; + + if(w<1||h<1||h>20||w>20) + { + return; + } + + int xscale=sdci[8]/10000; + int yscale=sdci[9]/10000; + int rx = sdci[10]/10000; //these work now + int ry = sdci[11]/10000; //these work now + float rotation=sdci[12]/10000; + + bool transparency=sdci[15]!=0; + int opacity=sdci[16]/10000; + int color=sdci[7]/10000; + int x1=sdci[2]/10000; + int y1=sdci[3]/10000; + + const newcombo & c = combobuf[(sdci[4]/10000)]; + int tiletodraw = combo_tile(c, x1, y1); + int flip = ((sdci[14]/10000) & 3) ^ c.flip; + int skiprows=combobuf[(sdci[4]/10000)].skipanimy; + + + //don't scale if it's not safe to do so + bool canscale = true; + + if(xscale==0||yscale==0) + { + return; + } + + if(xscale<0||yscale<0) + canscale = false; //default size + + if((xscale>0 && yscale>0) || rotation) //scaled or rotated + { + BITMAP* pbitty = script_drawing_commands.AquireSubBitmap(w*16, h*16); //-pbitty in the hisouse. :D + + if(transparency) + { + TileHelper::OverTile(pbitty, tiletodraw, 0, 0, w, h, color, flip, skiprows); + } + else //no transparency + { + TileHelper::OldPutTile(pbitty, tiletodraw, 0, 0, w, h, color, flip, skiprows); + } + + if(rotation != 0) // rotate + { + //fixed point sucks ;0 + if(rx>-777||ry>-777) //set the rotation anchor and rotate around that + { + int xy[2]; + fixed ra1=itofix(sdci[12]%10000)/10000; + fixed ra2=itofix(sdci[12]/10000); + fixed ra=ra1+ra2; + xy[ 0]=rx + fixtoi((fixcos(ra) * (x1 - rx) - fixsin(ra) * (y1 - ry))); //x1 + xy[ 1]=ry + fixtoi((fixsin(ra) * (x1 - rx) + fixcos(ra) * (y1 - ry))); //y1 + x1=xy[0]; + y1=xy[1]; + } + + if(canscale) //scale first + { + BITMAP* tempbit = create_bitmap_ex(8, xscale>512?512:xscale, yscale>512?512:yscale); + clear_bitmap(tempbit); + + stretch_sprite(tempbit, pbitty, 0, 0, xscale, yscale); + + if(opacity < 128) + { + clear_bitmap(prim_bmp); + rotate_sprite(prim_bmp, tempbit, 0, 0, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + rotate_sprite(bmp, tempbit, x1+xoffset, y1+yoffset, degrees_to_fixed(rotation)); + } + + destroy_bitmap(tempbit); + } + else //no scale + { + if(opacity < 128) + { + clear_bitmap(prim_bmp); + rotate_sprite(prim_bmp, pbitty, 0, 0, degrees_to_fixed(rotation)); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + rotate_sprite(bmp, pbitty, x1+xoffset, y1+yoffset, degrees_to_fixed(rotation)); + } + } + } + else //scale only + { + if(canscale) + { + if(opacity<128) + { + clear_bitmap(prim_bmp); + stretch_sprite(prim_bmp, pbitty, 0, 0, xscale, yscale); + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + stretch_sprite(bmp, pbitty, x1+xoffset, y1+yoffset, xscale, yscale); + } + } + else //error -do not scale + { + if(opacity<128) + { + draw_trans_sprite(bmp, prim_bmp, x1+xoffset, y1+yoffset); + } + else + { + draw_sprite(bmp, pbitty, x1+xoffset, y1+yoffset); + } + } + } + + script_drawing_commands.ReleaseSubBitmap(pbitty); //rap sucks + } + else // no scale or rotation + { + if(transparency) + { + if(opacity<=127) + TileHelper::OverTileTranslucent(bmp, tiletodraw, xoffset+x1, yoffset+y1, w, h, color, flip, opacity, skiprows); + else + TileHelper::OverTile(bmp, tiletodraw, xoffset+x1, yoffset+y1, w, h, color, flip, skiprows); + } + else + { + if(opacity<=127) + TileHelper::PutTileTranslucent(bmp, tiletodraw, xoffset+x1, yoffset+y1, w, h, color, flip, opacity, skiprows); + else + TileHelper::OldPutTile(bmp, tiletodraw, xoffset+x1, yoffset+y1, w, h, color, flip, skiprows); + } + } +} + + +void do_fasttiler(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + /* layer, x, y, tile, color opacity */ + + int opacity = sdci[6]/10000; + + if(opacity < 128) + overtiletranslucent16(bmp, sdci[4]/10000, xoffset+(sdci[2]/10000), yoffset+(sdci[3]/10000), sdci[5]/10000, 0, opacity); + else + overtile16(bmp, sdci[4]/10000, xoffset+(sdci[2]/10000), yoffset+(sdci[3]/10000), sdci[5]/10000, 0); +} + + +void do_fastcombor(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + /* layer, x, y, tile, color opacity */ + + int opacity = sdci[6] / 10000; + int x1 = sdci[2] / 10000; + int y1 = sdci[3] / 10000; + int index = sdci[4]/10000; + + //if( index >= MAXCOMBOS ) return; //bleh. + const newcombo & c = combobuf[index]; + + if(opacity < 128) + overtiletranslucent16(bmp, combo_tile(c, x1, y1), xoffset+x1, yoffset+y1, sdci[5]/10000, (int)c.flip, opacity); + else + overtile16(bmp, combo_tile(c, x1, y1), xoffset+x1, yoffset+y1, sdci[5]/10000, (int)c.flip); +} + + + +void do_drawcharr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=font + //sdci[5]=color + //sdci[6]=bg color + //sdci[7]=strech x (width) + //sdci[8]=stretch y (height) + //sdci[9]=char + //sdci[10]=opacity + + int x=sdci[2]/10000; + int y=sdci[3]/10000; + int font_index=sdci[4]/10000; + int color=sdci[5]/10000; + int bg_color=sdci[6]/10000; //-1 = transparent + int w=sdci[7]/10000; + int h=sdci[8]/10000; + char glyph=char(sdci[9]/10000); + int opacity=sdci[10]/10000; + + //safe check + if(bg_color < -1) bg_color = -1; + + if(w>512) w=512; //w=vbound(w,0,512); + + if(h>512) h=512; //h=vbound(h,0,512); + + //undone + if(w>0&&h>0)//stretch the character + { + BITMAP *pbmp = script_drawing_commands.GetSmallTextureBitmap(1,1); + + if(opacity < 128) + { + if(w>128||h>128) + { + clear_bitmap(prim_bmp); + + textprintf_ex(pbmp, get_zc_font(font_index), 0, 0, color, bg_color, "%c", glyph); + stretch_sprite(prim_bmp, pbmp, 0, 0, w, h); + draw_trans_sprite(bmp, prim_bmp, x+xoffset, y+yoffset); + } + else //this is faster + { + BITMAP *pbmp2 = script_drawing_commands.AquireSubBitmap(w,h); + + textprintf_ex(pbmp, get_zc_font(font_index), 0, 0, color, bg_color, "%c", glyph); + stretch_sprite(pbmp2, pbmp, 0, 0, w, h); + draw_trans_sprite(bmp, pbmp2, x+xoffset, y+yoffset); + + script_drawing_commands.ReleaseSubBitmap(pbmp2); + } + } + else // no opacity + { + textprintf_ex(pbmp, get_zc_font(font_index), 0, 0, color, bg_color, "%c", glyph); + stretch_sprite(bmp, pbmp, x+xoffset, y+yoffset, w, h); + } + + } + else //no stretch + { + if(opacity < 128) + { + BITMAP *pbmp = create_sub_bitmap(prim_bmp,0,0,16,16); + clear_bitmap(pbmp); + + textprintf_ex(pbmp, get_zc_font(font_index), 0, 0, color, bg_color, "%c", glyph); + draw_trans_sprite(bmp, pbmp, x+xoffset, y+yoffset); + + destroy_bitmap(pbmp); + } + else // no opacity + { + textprintf_ex(bmp, get_zc_font(font_index), x+xoffset, y+yoffset, color, bg_color, "%c", glyph); + } + } +} + + +void do_drawintr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=font + //sdci[5]=color + //sdci[6]=bg color + //sdci[7]=strech x (width) + //sdci[8]=stretch y (height) + //sdci[9]=integer + //sdci[10]=num decimal places + //sdci[11]=opacity + + int x=sdci[2]/10000; + int y=sdci[3]/10000; + int font_index=sdci[4]/10000; + int color=sdci[5]/10000; + int bg_color=sdci[6]/10000; //-1 = transparent + int w=sdci[7]/10000; + int h=sdci[8]/10000; + float number=static_cast(sdci[9])/10000.0f; + int decplace=sdci[10]/10000; + int opacity=sdci[11]/10000; + + //safe check + if(bg_color < -1) bg_color = -1; + + if(w>512) w=512; //w=vbound(w,0,512); + + if(h>512) h=512; //h=vbound(h,0,512); + + char numbuf[15]; + + switch(decplace) + { + default: + case 0: + sprintf(numbuf,"%d",int(number)); + break; + + case 1: + sprintf(numbuf,"%.01f",number); + break; + + case 2: + sprintf(numbuf,"%.02f",number); + break; + + case 3: + sprintf(numbuf,"%.03f",number); + break; + + case 4: + sprintf(numbuf,"%.04f",number); + break; + } + + if(w>0&&h>0)//stretch + { + BITMAP *pbmp = script_drawing_commands.GetSmallTextureBitmap(1,1); + + if(opacity < 128) + { + if(w>128||h>128) + { + clear_bitmap(prim_bmp); + + textout_ex(pbmp, get_zc_font(font_index), numbuf, 0, 0, color, bg_color); + stretch_sprite(prim_bmp, pbmp, 0, 0, w, h); + draw_trans_sprite(bmp, prim_bmp, x+xoffset, y+yoffset); + } + else + { + BITMAP *pbmp2 = create_sub_bitmap(prim_bmp,0,0,w,h); + clear_bitmap(pbmp2); + + textout_ex(pbmp, get_zc_font(font_index), numbuf, 0, 0, color, bg_color); + stretch_sprite(pbmp2, pbmp, 0, 0, w, h); + draw_trans_sprite(bmp, pbmp2, x+xoffset, y+yoffset); + + destroy_bitmap(pbmp2); + } + } + else // no opacity + { + textout_ex(pbmp, get_zc_font(font_index), numbuf, 0, 0, color, bg_color); + stretch_sprite(bmp, pbmp, x+xoffset, y+yoffset, w, h); + } + + } + else //no stretch + { + if(opacity < 128) + { + BITMAP *pbmp = create_sub_bitmap(prim_bmp,0,0,16,16); + clear_bitmap(pbmp); + + textout_ex(pbmp, get_zc_font(font_index), numbuf, 0, 0, color, bg_color); + draw_trans_sprite(bmp, pbmp, x+xoffset, y+yoffset); + + destroy_bitmap(pbmp); + } + else // no opacity + { + textout_ex(bmp, get_zc_font(font_index), numbuf, x+xoffset, y+yoffset, color, bg_color); + } + } +} + + +void do_drawstringr(BITMAP *bmp, int i, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x + //sdci[3]=y + //sdci[4]=font + //sdci[5]=color + //sdci[6]=bg color + //sdci[7]=format_option + //sdci[8]=opacity + //sdci[9]=char + + std::string* str = (std::string*)script_drawing_commands[i].GetPtr(); + + if(!str) + { + al_trace("String pointer is null! Internal error. \n"); + return; + } + + int x=sdci[2]/10000; + int y=sdci[3]/10000; + int font_index=sdci[4]/10000; + int color=sdci[5]/10000; + int bg_color=sdci[6]/10000; //-1 = transparent + int format_type=sdci[7]/10000; + int opacity=sdci[9]/10000; + //sdci[8] not needed :) + + //safe check + if(bg_color < -1) bg_color = -1; + + if(opacity < 128) + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + + if(format_type == 2) // right-sided text + { + textout_right_ex(bmp, get_zc_font(font_index), str->c_str(), x+xoffset, y+yoffset, color, bg_color); + } + else if(format_type == 1) // centered text + { + textout_centre_ex(bmp, get_zc_font(font_index), str->c_str(), x+xoffset, y+yoffset, color, bg_color); + } + else // standard left-sided text + { + textout_ex(bmp, get_zc_font(font_index), str->c_str(), x+xoffset, y+yoffset, color, bg_color); + } + + if(opacity < 128) + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); +} + + +void do_drawquadr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x1 + //sdci[3]=y1 + //sdci[4]=x2 + //sdci[5]=y2 + //sdci[6]=x3 + //sdci[7]=y3 + //sdci[8]=x4 + //sdci[9]=y4 + //sdci[10]=width + //sdci[11]=height + //sdci[12]=cset + //sdci[13]=flip + //sdci[14]=tile/combo + //sdci[15]=polytype + + int x1 = sdci[2]/10000; + int y1 = sdci[3]/10000; + int x2 = sdci[4]/10000; + int y2 = sdci[5]/10000; + int x3 = sdci[6]/10000; + int y3 = sdci[7]/10000; + int x4 = sdci[8]/10000; + int y4 = sdci[9]/10000; + int w = sdci[10]/10000; + int h = sdci[11]/10000; + int color = sdci[12]/10000; + int flip=(sdci[13]/10000)&3; + int tile = sdci[14]/10000; + int polytype = sdci[15]/10000; + + //todo: finish palette shading + /* + POLYTYPE_FLAT + POLYTYPE_GCOL + POLYTYPE_GRGB + POLYTYPE_ATEX + POLYTYPE_PTEX + POLYTYPE_ATEX_MASK + POLYTYPE_PTEX_MASK + POLYTYPE_ATEX_LIT + POLYTYPE_PTEX_LIT + POLYTYPE_ATEX_MASK_LIT + POLYTYPE_PTEX_MASK_LIT + POLYTYPE_ATEX_TRANS + POLYTYPE_PTEX_TRANS + POLYTYPE_ATEX_MASK_TRANS + POLYTYPE_PTEX_MASK_TRANS + */ + polytype = vbound(polytype, 0, 14); + + if(((w-1) & w) != 0 || ((h-1) & h) != 0) + { + Z_message("Quad() : PO2 error with %i, %i.", w, h); + return; //non power of two error + } + + int tex_width = w*16; + int tex_height = h*16; + + bool mustDestroyBmp = false; + BITMAP *tex = script_drawing_commands.GetSmallTextureBitmap(w,h); + + if(!tex) + { + mustDestroyBmp = true; + tex = create_bitmap_ex(8, tex_width, tex_height); + clear_bitmap(tex); + } + + int col[4]; + /* + if( color < 0 ) + { + col[0]=draw_container.color_buffer[0]; + col[1]=draw_container.color_buffer[1]; + col[2]=draw_container.color_buffer[2]; + col[3]=draw_container.color_buffer[3]; + } + else */ + { + col[0]=col[1]=col[2]=col[3]=color; + } + + if(tile > 0) // TILE + { + TileHelper::OverTile(tex, tile, 0, 0, w, h, color, flip); + } + else // COMBO + { + const newcombo & c = combobuf[ vbound(abs(tile), 0, 0xffff) ]; + const int tiletodraw = combo_tile(c, x1, y1); + flip = flip ^ c.flip; + + TileHelper::OldPutTile(tex, tiletodraw, 0, 0, w, h, color, flip); + } + + V3D_f V1 = { static_cast(x1+xoffset), static_cast(y1+yoffset), 0, 0, 0, col[0] }; + V3D_f V2 = { static_cast(x2+xoffset), static_cast(y2+yoffset), 0, 0, static_cast(tex_height), col[1] }; + V3D_f V3 = { static_cast(x3+xoffset), static_cast(y3+yoffset), 0, static_cast(tex_width), static_cast(tex_height), col[2] }; + V3D_f V4 = { static_cast(x4+xoffset), static_cast(y4+yoffset), 0, static_cast(tex_width), 0, col[3] }; + + quad3d_f(bmp, polytype, tex, &V1, &V2, &V3, &V4); + + if(mustDestroyBmp) + destroy_bitmap(tex); + +} + + +void do_drawtriangler(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=x1 + //sdci[3]=y1 + //sdci[4]=x2 + //sdci[5]=y2 + //sdci[6]=x3 + //sdci[7]=y3 + //sdci[8]=width + //sdci[9]=height + //sdci[10]=cset + //sdci[11]=flip + //sdci[12]=tile/combo + //sdci[13]=polytype + + int x1 = sdci[2]/10000; + int y1 = sdci[3]/10000; + int x2 = sdci[4]/10000; + int y2 = sdci[5]/10000; + int x3 = sdci[6]/10000; + int y3 = sdci[7]/10000; + int w = sdci[8]/10000; + int h = sdci[9]/10000; + int color = sdci[10]/10000; + int flip=(sdci[11]/10000)&3; + int tile = sdci[12]/10000; + int polytype = sdci[13]/10000; + + polytype = vbound(polytype, 0, 14); + + if(((w-1) & w) != 0 || ((h-1) & h) != 0) return; //non power of two error + + int tex_width = w*16; + int tex_height = h*16; + + bool mustDestroyBmp = false; + BITMAP *tex = script_drawing_commands.GetSmallTextureBitmap(w,h); + + if(!tex) + { + mustDestroyBmp = true; + tex = create_bitmap_ex(8, tex_width, tex_height); + clear_bitmap(tex); + } + + int col[3]; + /* + if( color < 0 ) + { + col[0]=draw_container.color_buffer[0]; + col[1]=draw_container.color_buffer[1]; + col[2]=draw_container.color_buffer[2]; + } + else */ + { + col[0]=col[1]=col[2]=color; + } + + if(tile > 0) // TILE + { + TileHelper::OverTile(tex, tile, 0, 0, w, h, color, flip); + } + else // COMBO + { + const newcombo & c = combobuf[ vbound(abs(tile), 0, 0xffff) ]; + const int tiletodraw = combo_tile(c, x1, y1); + flip = flip ^ c.flip; + + TileHelper::OldPutTile(tex, tiletodraw, 0, 0, w, h, color, flip); + } + + V3D_f V1 = { static_cast(x1+xoffset), static_cast(y1+yoffset), 0, 0, 0, col[0] }; + V3D_f V2 = { static_cast(x2+xoffset), static_cast(y2+yoffset), 0, 0, static_cast(tex_height), col[1] }; + V3D_f V3 = { static_cast(x3+xoffset), static_cast(y3+yoffset), 0, static_cast(tex_width), static_cast(tex_height), col[2] }; + + + triangle3d_f(bmp, polytype, tex, &V1, &V2, &V3); + + if(mustDestroyBmp) + destroy_bitmap(tex); +} + + +void do_drawbitmapr(BITMAP *bmp, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=bitmap + //sdci[3]=sourcex + //sdci[4]=sourcey + //sdci[5]=sourcew + //sdci[6]=sourceh + //sdci[7]=destx + //sdci[8]=desty + //sdci[9]=destw + //sdci[10]=desth + //sdci[11]=rotation + //sdci[12]=mask + + int bitmapIndex = sdci[2]/10000; + int sx = sdci[3]/10000; + int sy = sdci[4]/10000; + int sw = sdci[5]/10000; + int sh = sdci[6]/10000; + int dx = sdci[7]/10000; + int dy = sdci[8]/10000; + int dw = sdci[9]/10000; + int dh = sdci[10]/10000; + float rot = sdci[11]/10000; + bool masked = (sdci[12] != 0); + + //bugfix + sx = vbound(sx, 0, 512); + sy = vbound(sy, 0, 512); + sw = vbound(sw, 0, 512 - sx); //keep the w/h within range as well + sh = vbound(sh, 0, 512 - sy); + + + if(sx >= ZScriptDrawingRenderTarget::BitmapWidth || sy >= ZScriptDrawingRenderTarget::BitmapHeight) + return; + + bool stretched = (sw != dw || sh != dh); + + BITMAP *sourceBitmap = zscriptDrawingRenderTarget->GetBitmapPtr(bitmapIndex); + + if(!sourceBitmap) + { + Z_message("Warning: Screen->DrawBitmap(%d) contains invalid data or is not initialized.\n", bitmapIndex); + Z_message("[Note* Deferred drawing or layering order possibly not set right.]\n"); + return; + } + + BITMAP* subBmp = 0; + + if(rot != 0) + { + subBmp = script_drawing_commands.AquireSubBitmap(dw, dh); + + if(!subBmp) + { + } + } + + + dx = dx + xoffset; + dy = dy + yoffset; + + if(stretched) + { + if(masked) + { + if(rot != 0) + { + masked_stretch_blit(sourceBitmap, subBmp, sx, sy, sw, sh, 0, 0, dw, dh); + rotate_sprite(bmp, subBmp, dx, dy, degrees_to_fixed(rot)); + } + else + masked_stretch_blit(sourceBitmap, bmp, sx, sy, sw, sh, dx, dy, dw, dh); + } + else + { + if(rot != 0) + { + stretch_blit(sourceBitmap, subBmp, sx, sy, sw, sh, 0, 0, dw, dh); + rotate_sprite(bmp, subBmp, dx, dy, degrees_to_fixed(rot)); + } + else + stretch_blit(sourceBitmap, bmp, sx, sy, sw, sh, dx, dy, dw, dh); + } + } + else + { + if(masked) + { + if(rot != 0) + { + masked_blit(sourceBitmap, subBmp, sx, sy, 0, 0, dw, dh); + rotate_sprite(bmp, subBmp, dx, dy, degrees_to_fixed(rot)); + } + else + masked_blit(sourceBitmap, bmp, sx, sy, dx, dy, dw, dh); + } + else + { + if(rot != 0) + { + blit(sourceBitmap, subBmp, sx, sy, 0, 0, dw, dh); + rotate_sprite(bmp, subBmp, dx, dy, degrees_to_fixed(rot)); + } + else + blit(sourceBitmap, bmp, sx, sy, dx, dy, dw, dh); + } + } + + //cleanup + if(subBmp) + { + script_drawing_commands.ReleaseSubBitmap(subBmp); + } +} + + +void do_drawquad3dr(BITMAP *bmp, int i, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=pos[12] + //sdci[3]=uv[8] + //sdci[4]=color[4] + //sdci[5]=size[2] + //sdci[6]=flip + //sdci[7]=tile/combo + //sdci[8]=polytype + + std::vector* v_ptr = (std::vector*)script_drawing_commands[i].GetPtr(); + + if(!v_ptr) + { + al_trace("Quad3d: Vector pointer is null! Internal error. \n"); + return; + } + + std::vector &v = *v_ptr; + + if(v.empty()) + return; + + long* pos = &v[0]; + long* uv = &v[12]; + long* col = &v[20]; + long* size = &v[24]; + + int w = size[0]; //magic numerical constants... yuck. + int h = size[1]; + int flip = (sdci[6]/10000)&3; + int tile = sdci[7]/10000; + int polytype = sdci[8]/10000; + + polytype = vbound(polytype, 0, 14); + + if(((w-1) & w) != 0 || ((h-1) & h) != 0) return; //non power of two error + + int tex_width = w*16; + int tex_height = h*16; + + bool mustDestroyBmp = false; + BITMAP *tex = script_drawing_commands.GetSmallTextureBitmap(w,h); + + if(!tex) + { + mustDestroyBmp = true; + tex = create_bitmap_ex(8, tex_width, tex_height); + clear_bitmap(tex); + } + + if(tile > 0) // TILE + { + TileHelper::OverTile(tex, tile, 0, 0, w, h, col[0], flip); + } + else // COMBO + { + const newcombo & c = combobuf[ vbound(abs(tile), 0, 0xffff) ]; + const int tiletodraw = combo_tile(c, 0, 0); + flip = flip ^ c.flip; + + TileHelper::OldPutTile(tex, tiletodraw, 0, 0, w, h, col[0], flip); + } + + V3D_f V1 = { static_cast(pos[0]+xoffset), static_cast(pos[1] +yoffset), static_cast(pos[2]), static_cast(uv[0]), static_cast(uv[1]), col[0] }; + V3D_f V2 = { static_cast(pos[3]+xoffset), static_cast(pos[4] +yoffset), static_cast(pos[5]), static_cast(uv[2]), static_cast(uv[3]), col[1] }; + V3D_f V3 = { static_cast(pos[6]+xoffset), static_cast(pos[7] +yoffset), static_cast(pos[8]), static_cast(uv[4]), static_cast(uv[5]), col[2] }; + V3D_f V4 = { static_cast(pos[9]+xoffset), static_cast(pos[10]+yoffset), static_cast(pos[11]), static_cast(uv[6]), static_cast(uv[7]), col[3] }; + + quad3d_f(bmp, polytype, tex, &V1, &V2, &V3, &V4); + + if(mustDestroyBmp) + destroy_bitmap(tex); + +} + + + +void do_drawtriangle3dr(BITMAP *bmp, int i, int *sdci, int xoffset, int yoffset) +{ + //sdci[1]=layer + //sdci[2]=pos[9] + //sdci[3]=uv[6] + //sdci[4]=color[3] + //sdci[5]=size[2] + //sdci[6]=flip + //sdci[7]=tile/combo + //sdci[8]=polytype + + std::vector* v_ptr = (std::vector*)script_drawing_commands[i].GetPtr(); + + if(!v_ptr) + { + al_trace("Quad3d: Vector pointer is null! Internal error. \n"); + return; + } + + std::vector &v = *v_ptr; + + if(v.empty()) + return; + + long* pos = &v[0]; + long* uv = &v[9]; + long* col = &v[15]; + long* size = &v[18]; + + int w = size[0]; //magic numerical constants... yuck. + int h = size[1]; + int flip = (sdci[6]/10000)&3; + int tile = sdci[7]/10000; + int polytype = sdci[8]/10000; + + polytype = vbound(polytype, 0, 14); + + if(((w-1) & w) != 0 || ((h-1) & h) != 0) return; //non power of two error + + int tex_width = w*16; + int tex_height = h*16; + + bool mustDestroyBmp = false; + BITMAP *tex = script_drawing_commands.GetSmallTextureBitmap(w,h); + + if(!tex) + { + mustDestroyBmp = true; + tex = create_bitmap_ex(8, tex_width, tex_height); + clear_bitmap(tex); + } + + if(tile > 0) // TILE + { + TileHelper::OverTile(tex, tile, 0, 0, w, h, col[0], flip); + } + else // COMBO + { + const newcombo & c = combobuf[ vbound(abs(tile), 0, 0xffff) ]; + const int tiletodraw = combo_tile(c, 0, 0); + flip = flip ^ c.flip; + + TileHelper::OldPutTile(tex, tiletodraw, 0, 0, w, h, col[0], flip); + } + + V3D_f V1 = { static_cast(pos[0]+xoffset), static_cast(pos[1] +yoffset), static_cast(pos[2]), static_cast(uv[0]), static_cast(uv[1]), col[0] }; + V3D_f V2 = { static_cast(pos[3]+xoffset), static_cast(pos[4] +yoffset), static_cast(pos[5]), static_cast(uv[2]), static_cast(uv[3]), col[1] }; + V3D_f V3 = { static_cast(pos[6]+xoffset), static_cast(pos[7] +yoffset), static_cast(pos[8]), static_cast(uv[4]), static_cast(uv[5]), col[2] }; + + triangle3d_f(bmp, polytype, tex, &V1, &V2, &V3); + + if(mustDestroyBmp) + destroy_bitmap(tex); + +} + + +bool is_layer_transparent(const mapscr& m, int layer) +{ + layer = vbound(layer, 0, 5); + return m.layeropacity[layer] == 128; +} + +mapscr *getmapscreen(int map_index, int screen_index, int layer) //returns NULL for invalid or non-existent layer +{ + mapscr *base_screen; + int index = map_index*MAPSCRS+screen_index; + + if((unsigned int)layer > 6 || (unsigned int)index >= TheMaps.size()) + return NULL; + + if(layer != 0) + { + layer = layer - 1; + + base_screen=&(TheMaps[index]); + + if(base_screen->layermap[layer]==0) + return NULL; + + index=(base_screen->layermap[layer]-1)*MAPSCRS+base_screen->layerscreen[layer]; + + if((unsigned int)index >= TheMaps.size()) // Might as well make sure + return NULL; + } + + return &(TheMaps[index]); +} + +void draw_mapscr(BITMAP *b, const mapscr& m, int x, int y, bool transparent) +{ + for(int i(0); i < 176; ++i) + { + const int x2 = ((i&15)<<4) + x; + const int y2 = (i&0xF0) + y; + + const newcombo & c = combobuf[ m.data[i] ]; + const int tile = combo_tile(c, x2, y2); + + if(transparent) + overtiletranslucent16(b, tile, x2, y2, m.cset[i], c.flip, 128); + else + overtile16(b, tile, x2, y2, m.cset[i], c.flip); + } +} + + +void do_drawlayerr(BITMAP *bmp, int *sdci, int xoffset, int yoffset, bool isOffScreen) +{ + //sdci[1]=layer + //sdci[2]=map + //sdci[3]=screen + //sdci[4]=layer + //sdci[5]=x + //sdci[6]=y + //sdci[7]=rotation + //sdci[8]=opacity + + int map = (sdci[2]/10000)-1; //zscript map indices start at 1. + int scrn = sdci[3]/10000; + int sourceLayer = vbound(sdci[4]/10000, 0, 6); + int x = sdci[5]/10000; + int y = sdci[6]/10000; + int x1 = x + xoffset; + int y1 = y + yoffset; + int rotation = sdci[7]/10000; + int opacity = sdci[8]/10000; + + const unsigned int index = (unsigned int)(map * MAPSCRS + scrn); + const mapscr* m = getmapscreen(map, scrn, sourceLayer); + + if(!m) //no need to log it. + return; + + if(index >= TheMaps.size()) + { + al_trace("DrawLayer: invalid map index \"%i\". Map count is %d.\n", index, TheMaps.size()); + return; + } + + const mapscr & l = *m; + + BITMAP* b = bmp; + + if(rotation != 0) + b = script_drawing_commands.AquireSubBitmap(256, 176); + + + const int maxX = isOffScreen ? 512 : 256; + const int maxY = isOffScreen ? 512 : 176 + yoffset; + bool transparent = opacity <= 128; + + if(rotation != 0) // rotate + { + draw_mapscr(b, l, x1, y1, transparent); + + rotate_sprite(bmp, b, x1, y1, degrees_to_fixed(rotation)); + script_drawing_commands.ReleaseSubBitmap(b); + } + else + { + for(int i(0); i < 176; ++i) + { + const int x2 = ((i&15)<<4) + x1; + const int y2 = (i&0xF0) + y1; + + if(x2 > -16 && x2 < maxX && y2 > -16 && y2 < maxY) //in clipping rect + { + const newcombo & c = combobuf[ l.data[i] ]; + const int tile = combo_tile(c, x2, y2); + + if(opacity < 128) + overtiletranslucent16(b, tile, x2, y2, l.cset[i], c.flip, opacity); + else + overtile16(b, tile, x2, y2, l.cset[i], c.flip); + + //putcombo( b, xx, yy, l.data[i], l.cset[i] ); + } + } + } + + //putscr +} + + + +void do_drawscreenr(BITMAP *bmp, int *sdci, int xoffset, int yoffset, bool isOffScreen) +{ + //sdci[1]=layer + //sdci[2]=map + //sdci[3]=screen + //sdci[4]=x + //sdci[5]=y + //sdci[6]=rotation + + int map = (sdci[2]/10000)-1; //zscript map indices start at 1. + int scrn = sdci[3]/10000; + int x = sdci[4]/10000; + int y = sdci[5]/10000; + int x1 = x + xoffset; + int y1 = y + yoffset; + int rotation = sdci[6]/10000; + + const unsigned int index = (unsigned int)(map * MAPSCRS + scrn); + + if(index >= TheMaps.size()) + { + al_trace("DrawScreen: invalid map or screen index. \n"); + return; + } + + const mapscr & m = TheMaps[index]; + + + BITMAP* b = bmp; + + if(rotation != 0) + b = script_drawing_commands.AquireSubBitmap(256, 176); + + //draw layer 0 + draw_mapscr(b, m, x1, y1, false); + + for(int i(0); i < 6; ++i) + { + if(m.layermap[i] == 0) continue; + + unsigned int layer_screen_index = (m.layermap[i]-1) * MAPSCRS + m.layerscreen[i]; + + if(layer_screen_index >= TheMaps.size()) + continue; + + bool trans = m.layeropacity[i] == 128; + + //draw valid layers + draw_mapscr(b, TheMaps[ layer_screen_index ], x1, y1, trans); + } + + if(rotation != 0) // rotate + { + rotate_sprite(bmp, b, x1, y1, degrees_to_fixed(rotation)); + script_drawing_commands.ReleaseSubBitmap(b); + } +} + + + +///////////////////////////////////////////////////////// +// do primitives +//////////////////////////////////////////////////////// + +void do_primitives(BITMAP *targetBitmap, int type, mapscr *, int xoff, int yoff) +{ + color_map = &trans_table2; + + //was this next variable ever used? -- DN + //bool drawsubscr=false; + + if(type > 7) + return; + + //--script_drawing_commands[][] reference-- + //[][0]: type + //[][1-16]: defined by type + //[][17]: unused + //[][18]: rendertarget + //[][19]: unused + + bool isTargetOffScreenBmp = false; + const int type_mul_10000 = type * 10000; + const int numDrawCommandsToProcess = script_drawing_commands.Count(); + + for(int i(0); i < numDrawCommandsToProcess; ++i) + { + int xoffset = 0; + int yoffset = 0; + int *sdci = &script_drawing_commands[i][0]; + + if(sdci[1] != type_mul_10000) + continue; + + // get the correct render target, if set. + BITMAP *bmp = zscriptDrawingRenderTarget->GetTargetBitmap(sdci[18]); + + if(!bmp) + { + // draw to screen with subscreen offset + xoffset = xoff; + yoffset = yoff; + bmp = targetBitmap; + } + else + { + //not drawing to screen, so no subscreen offset + //xoffset = 0; + //yoffset = 0; + isTargetOffScreenBmp = true; + } + + switch(sdci[0]) + { + case RECTR: + { + do_rectr(bmp, sdci, xoffset, yoffset); + } + break; + + case CIRCLER: + { + do_circler(bmp, sdci, xoffset, yoffset); + } + break; + + case ARCR: + { + do_arcr(bmp, sdci, xoffset, yoffset); + } + break; + + case ELLIPSER: + { + do_ellipser(bmp, sdci, xoffset, yoffset); + } + break; + + case LINER: + { + do_liner(bmp, sdci, xoffset, yoffset); + } + break; + + case SPLINER: + { + do_spliner(bmp, sdci, xoffset, yoffset); + } + break; + + case PUTPIXELR: + { + do_putpixelr(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWTILER: + { + do_drawtiler(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWCOMBOR: + { + do_drawcombor(bmp, sdci, xoffset, yoffset); + } + break; + + case FASTTILER: + { + do_fasttiler(bmp, sdci, xoffset, yoffset); + } + break; + + case FASTCOMBOR: + { + do_fastcombor(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWCHARR: + { + do_drawcharr(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWINTR: + { + do_drawintr(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWSTRINGR: + { + do_drawstringr(bmp, i, sdci, xoffset, yoffset); + } + break; + + case QUADR: + { + do_drawquadr(bmp, sdci, xoffset, yoffset); + } + break; + + case QUAD3DR: + { + do_drawquad3dr(bmp, i, sdci, xoffset, yoffset); + } + break; + + case TRIANGLER: + { + do_drawtriangler(bmp, sdci, xoffset, yoffset); + } + break; + + case TRIANGLE3DR: + { + do_drawtriangle3dr(bmp, i, sdci, xoffset, yoffset); + } + break; + + case BITMAPR: + { + do_drawbitmapr(bmp, sdci, xoffset, yoffset); + } + break; + + case DRAWLAYERR: + { + do_drawlayerr(bmp, sdci, xoffset, yoffset, isTargetOffScreenBmp); + } + break; + + case DRAWSCREENR: + { + do_drawscreenr(bmp, sdci, xoffset, yoffset, isTargetOffScreenBmp); + } + break; + + } + } + + + color_map=&trans_table; +} diff --git a/src/script_drawing.h b/src/script_drawing.h new file mode 100644 index 0000000000..ef2b397edd --- /dev/null +++ b/src/script_drawing.h @@ -0,0 +1,401 @@ + +#ifndef _zc_script_drawing_h +#define _zc_script_drawing_h + +#include +#include + + +#define MAX_SCRIPT_DRAWING_COMMANDS 1000 +#define SCRIPT_DRAWING_COMMAND_VARIABLES 20 + + +// For Quad and Triangle. *allegro Bug-Fix* -Gleeok +class SmallBitmapTextureCache +{ +public: + SmallBitmapTextureCache() + { + is_init = false; + + for(int i(0); i < 4; ++i) + for(int j(0); j < 4; ++j) + _bmp[i][j] = 0; + } + + void Init() + { + if(is_init) + return; + + int size[4] = { 16, 32, 64, 128 }; + + for(int i(0); i < 4; ++i) + { + for(int j(0); j < 4; ++j) + _bmp[i][j] = create_bitmap_ex(8, size[i], size[j]); + } + + is_init = true; + } + + ~SmallBitmapTextureCache() + { + Dispose(); + } + + void Dispose() + { + for(int i(0); i < 4; ++i) + for(int j(0); j < 4; ++j) + { + if(_bmp[i][j]) + destroy_bitmap(_bmp[i][j]); + + _bmp[i][j] = 0; + } + + is_init = false; + } + + inline BITMAP* GetTexture(int bw, int bh) + { + BITMAP* ret = 0; + + if(!is_init) + Init(); + + if(bw == 1 || bw == 2 || bw == 4 || bw == 8) + { + int x = bw >> 1; + + if(x > 3) x = 3; + + if(bh == 1) ret = _bmp[x][0]; + + if(bh == 2) ret = _bmp[x][1]; + + if(bh == 4) ret = _bmp[x][2]; + + if(bh == 8) ret = _bmp[x][3]; + } + + if(ret) + clear_bitmap(ret); + + return ret; + } + +protected: + BITMAP* _bmp[4][4]; + bool is_init; +}; + + +//simple class that manages allegro bitmaps for script drawing +class ScriptDrawingBitmapPool +{ +public: + ScriptDrawingBitmapPool() + { + } + + void Dispose() + { + if(_parent_bmp) + destroy_bitmap(_parent_bmp), _parent_bmp = 0; + } + + inline BITMAP* AquireSubBitmap(int w, int h) + { + return AquireSubBitmap(0, 0, w, h); + } + inline BITMAP* AquireSubBitmap(int x, int y, int w, int h) + { + //todo: can currently only partition out one bitmap at a time. + if(!_parent_bmp) + _parent_bmp = create_bitmap_ex(8,512,512); + + BITMAP* bmp = _parent_bmp; + + if(w <= 512 && h <= 512) + bmp = create_sub_bitmap(_parent_bmp, x, y, w, h); + + clear_bitmap(bmp); + + return bmp; + } + + inline void ReleaseSubBitmap(BITMAP* b) + { + if(is_sub_bitmap(b) || b != _parent_bmp) + destroy_bitmap(b); + } + + +protected: + static BITMAP *_parent_bmp; + //static int _rc = 0; +}; + + +class DrawingContainer +{ +public: + DrawingContainer() : + drawstring(), current_string_count(0), + drawdata(), current_drawdata_count(0) + {} + + ~DrawingContainer() + { + this->Dispose(); + } + + void Dispose() + { + for(size_t i(0); i < drawstring.size(); ++i) + delete drawstring[i]; + + drawstring.clear(); + + + for(size_t i(0); i < drawdata.size(); ++i) + delete drawdata[i]; + + drawdata.clear(); + } + + void Clear() + { + current_string_count = 0; + current_drawdata_count = 0; + } + + std::string* GetString() + { + std::string* str; + + if(drawstring.size() > current_string_count) + { + str = drawstring[current_string_count]; + str->clear(); + } + else + { + str = new std::string(); + drawstring.push_back(str); + } + + current_string_count++; + + return str; + } + + std::vector* GetVector() + { + std::vector* v; + + if(drawdata.size() > current_drawdata_count) + { + v = drawdata[current_drawdata_count]; + v->clear(); + } + else + { + v = new std::vector(); + drawdata.push_back(v); + } + + current_drawdata_count++; + + return v; + } + +protected: + //for drawstring + std::vector drawstring; + size_t current_string_count; + + //for other dynamic drawing (quad3d etc..) + std::vector*> drawdata; + size_t current_drawdata_count; + +}; + + + + +class CScriptDrawingCommandVars +{ +public: + CScriptDrawingCommandVars() + { + this->Clear(); + } + + void Clear() + { + memset((void*)this, 0, sizeof(CScriptDrawingCommandVars)); + } + + void SetString(std::string* str) + { + ptr = (void*)str; + } + + void SetVector(std::vector* v) + { + ptr = (void*)v; + } + + void* GetPtr() + { + return ptr; + } + + int &operator [](const int i) + { + return data[i]; + } + const int &operator [](const int i) const + { + return data[i]; + } + +protected: + int data[ SCRIPT_DRAWING_COMMAND_VARIABLES ]; + void* ptr; //will be changed later +}; + + + +class CScriptDrawingCommands +{ +public: + typedef CScriptDrawingCommandVars value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::vector vec_type; + typedef vec_type ::iterator vec_type_iter; + + // Unlikely people will be using all 1000 commands. + const static int DefaultCapacity = 256; //176 + some extra + + CScriptDrawingCommands() : commands(), count(0) {} + ~CScriptDrawingCommands() {} + + void Dispose() + { + bitmap_pool.Dispose(); + small_tex_cache.Dispose(); + } + + void Init() + { + // Interesting bit here; legacy quests have no need for script drawing, + // therefore zc should not allocate memory for them. We can instead + // do that when zc first queries for a valid command index. -Gleeok + + //commands.resize(DefaultCapacity); + //small_tex_cache.Init(); + } + + void Clear() + { + if(commands.empty()) + return; + + //only clear what was used. + memset((void*)&commands[0], 0, count * sizeof(CScriptDrawingCommandVars)); + count = 0; + + draw_container.Clear(); + } + + int Count() const + { + return count; + } + std::string* GetString() + { + return draw_container.GetString(); + } + std::vector* GetVector() + { + return draw_container.GetVector(); + } + + int GetNext() + { + if(count>=MAX_SCRIPT_DRAWING_COMMANDS) + return -1; + + const int next_index = count; + const int capacity = commands.capacity(); + + if(++count > capacity) + { + if(commands.empty()) + { + //first use + commands.resize(DefaultCapacity); + } + else + { + //might as well just max it out + commands.resize(MAX_SCRIPT_DRAWING_COMMANDS); + } + } + + return next_index; + } + + reference operator [](const int i) + { + return commands[i]; + } + const_reference operator [](const int i) const + { + return commands[i]; + } + + + inline BITMAP* AquireSubBitmap(int w, int h) + { + return bitmap_pool.AquireSubBitmap(w,h); + } + + inline void ReleaseSubBitmap(BITMAP* b) + { + bitmap_pool.ReleaseSubBitmap(b); + } + + inline BITMAP* GetSmallTextureBitmap(int bw, int bh) + { + return small_tex_cache.GetTexture(bw, bh); + } + + +protected: + vec_type commands; + int count; + + DrawingContainer draw_container; + ScriptDrawingBitmapPool bitmap_pool; + SmallBitmapTextureCache small_tex_cache; + +private: + CScriptDrawingCommands(const CScriptDrawingCommands&) {} + // Warning: no return statement in function returning non-void + //CScriptDrawingCommands& operator =(const CScriptDrawingCommands&) {} +}; + + +extern CScriptDrawingCommands script_drawing_commands; + + + + +#endif + diff --git a/src/sequence.cpp b/src/sequence.cpp new file mode 100644 index 0000000000..68998ec43b --- /dev/null +++ b/src/sequence.cpp @@ -0,0 +1,85 @@ +#include "precompiled.h" +#include "sequence.h" +#include "link.h" +#include "sfx.h" +#include "sfxManager.h" +#include "sequence/sequence.h" +#include "sequence/gameOver.h" +#include "sequence/ganonIntro.h" +#include "sequence/getBigTriforce.h" +#include "sequence/getTriforce.h" +#include "sequence/potion.h" +#include "sequence/whistle.h" +extern LinkClass Link; +extern SFXManager sfxMgr; + +static Sequence* specialSequence=0; + +void beginSpecialSequence(sequenceID id, int itemID) +{ + switch(id) + { + case seq_ganonIntro: + specialSequence=new GanonIntro(Link); + break; + + case seq_getTriforce: + specialSequence=new GetTriforce(itemID, Link); + break; + + case seq_getBigTriforce: + specialSequence=new GetBigTriforce(itemID, Link); + break; + + case seq_gameOver: + specialSequence=new GameOver(Link); + break; + + case seq_whistle: + specialSequence=new WhistleSequence(itemID, Link, + sfxMgr.getSFX(itemsbuf[itemID].usesound)); + break; + + case seq_potion: + specialSequence=new PotionSequence(itemID, Link, + sfxMgr.getSFX(WAV_REFILL), sfxMgr.getSFX(WAV_MSG)); + break; + + default: + return; // Maybe throw something instead. This shouldn't happen. + } + + if(specialSequence->isFinished()) + { + // This can happen, e.g. Ganon's intro if he's already been beaten. + // Maybe that should be checked beforehand, though... + delete specialSequence; + specialSequence=0; + } + else + specialSequence->activate(); +} + +bool specialSequenceIsActive() +{ + return specialSequence; +} + +void updateSpecialSequence() +{ + specialSequence->update(); + if(specialSequence->isFinished()) + { + delete specialSequence; + specialSequence=0; + } +} + +void clearSpecialSequence() +{ + if(specialSequence) + { + delete specialSequence; + specialSequence=0; + } +} diff --git a/src/sequence.h b/src/sequence.h new file mode 100644 index 0000000000..8c29c36127 --- /dev/null +++ b/src/sequence.h @@ -0,0 +1,15 @@ +#ifndef _ZC_SEQUENCE_H_ +#define _ZC_SEQUENCE_H_ + +enum sequenceID +{ + seq_ganonIntro, seq_getTriforce, seq_getBigTriforce, seq_gameOver, + seq_whistle, seq_potion +}; + +void beginSpecialSequence(sequenceID id, int itemID=0); +bool specialSequenceIsActive(); +void updateSpecialSequence(); +void clearSpecialSequence(); + +#endif diff --git a/src/sequence/gameOver.cpp b/src/sequence/gameOver.cpp new file mode 100644 index 0000000000..09b35b15fe --- /dev/null +++ b/src/sequence/gameOver.cpp @@ -0,0 +1,348 @@ +#include +#include "gameOver.h" +#include +#include +#include +#include + +extern mapscr tmpscr[2]; +extern mapscr tmpscr2[6]; + +static void red_shift() +{ + int tnum=176; + + // set up the new palette + for(int i=CSET(2); i < CSET(4); i++) + { + int r = (i-CSET(2)) << 1; + RAMpal[i+tnum].r = r; + RAMpal[i+tnum].g = r >> 3; + RAMpal[i+tnum].b = r >> 4; + } + + // color scale the game screen + for(int y=0; y<168; y++) + { + for(int x=0; x<256; x++) + { + int c = framebuf->line[y+playing_field_offset][x]; + int r = zc_min(int(RAMpal[c].r*0.4 + RAMpal[c].g*0.6 + RAMpal[c].b*0.4)>>1,31); + framebuf->line[y+playing_field_offset][x] = (c ? (r+tnum+CSET(2)) : 0); + } + } + + refreshpal = true; +} + +static void slide_in_color(int color) +{ + for(int i=1; i<16; i+=3) + { + RAMpal[CSET(2)+i+2] = RAMpal[CSET(2)+i+1]; + RAMpal[CSET(2)+i+1] = RAMpal[CSET(2)+i]; + RAMpal[CSET(2)+i] = NESpal(color); + } + + refreshpal=true; +} + +GameOver::GameOver(LinkClass& l): + counter(0), + link(l), + subscrbmp(create_bitmap_ex(8, framebuf->w, framebuf->h)) +{ + +} + +void GameOver::activate() +{ + link.setAction(none); + Playing=false; + + if(!debug_enabled) + Paused=false; + + game->set_deaths(zc_min(game->get_deaths()+1,999)); + link.dir=down; + music_stop(); + kill_sfx(); + link.cancelAttack(); + link.setHitTimer(0); + link.setInvincible(false); + link.scriptcoldet = 1; + + for(int i=0; i<16; i++) + link.miscellaneous[i] = 0; + + //get rid off all sprites but Link + guys.clear(); + items.clear(); + Ewpns.clear(); + Lwpns.clear(); + Sitems.clear(); + chainlinks.clear(); + decorations.clear(); + + playing_field_offset=56; // otherwise, red_shift() may go past the bottom of the screen + quakeclk=wavy=0; + + //in original Z1, Link marker vanishes at death. + //code in subscr.cpp, put_passive_subscr checks the following value. + //color 255 is a GUI color, so quest makers shouldn't be using this value. + //Also, subscreen is static after death in Z1. + int tmp_link_dot = QMisc.colors.link_dot; + QMisc.colors.link_dot = 255; + //doesn't work + //scrollbuf is tampered with by draw_screen() + //put_passive_subscr(scrollbuf, &QMisc, 256, passive_subscreen_offset, false, false);//save this and reuse it. + clear_bitmap(subscrbmp); + put_passive_subscr(subscrbmp, &QMisc, 0, passive_subscreen_offset, false, sspUP); + QMisc.colors.link_dot = tmp_link_dot; +} + +void GameOver::update() +{ + if(counter<254) + { + if(counter<=32) + link.setHitTimer(32-counter); + + if(counter>=62 && counter<138) + { + switch((counter-62)%20) + { + case 0: + link.dir=right; + break; + + case 5: + link.dir=up; + break; + + case 10: + link.dir=left; + break; + + case 15: + link.dir=down; + break; + } + + link.linkstep(); + } + + if(counter>=194 && counter<208) + { + if(counter==194) + link.setAction(dying); + + link.extend = 0; + link.cs = wpnsbuf[iwDeath].csets&15; + link.tile = wpnsbuf[iwDeath].tile; + + if(BSZ) + link.tile+=(counter-194)/3; + else if(counter>=204) + link.tile++; + } + + if(counter==208) + link.setDontDraw(true); + + if(get_bit(quest_rules,qr_FADE)) + { + if(counter < 170) + { + if(counter<60) + { + draw_screen(tmpscr); + //reuse our static subscreen + set_clip_rect(framebuf, 0, 0, framebuf->w, framebuf->h); + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + } + + if(counter==60) + { + red_shift(); + create_rgb_table_range(&rgb_table, RAMpal, 208, 239, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; q=60 && counter<=169) + { + draw_screen(tmpscr); + //reuse our static subscreen + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + red_shift(); + + } + + if(counter>=139 && counter<=169)//fade from red to black + { + fade_interpolate(RAMpal,black_palette,RAMpal, (counter-138)<<1, 224, 255); + create_rgb_table_range(&rgb_table, RAMpal, 208, 239, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; q=170 + { + if(counter==170)//make Link grayish + { + fade_interpolate(RAMpal,black_palette,RAMpal,64, 224, 255); + + for(int i=CSET(6); i < CSET(7); i++) + { + int g = (RAMpal[i].r + RAMpal[i].g + RAMpal[i].b)/3; + RAMpal[i] = _RGB(g,g,g); + } + + refreshpal = true; + } + + //draw only link. otherwise black layers might cover him. + rectfill(framebuf,0,playing_field_offset,255,167+playing_field_offset,0); + link.draw(framebuf); + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + } + } + else //!qr_FADE + { + if(counter==58) + { + for(int i = 0; i < 96; i++) + tmpscr->cset[i] = 3; + + for(int j=0; j<6; j++) + if(tmpscr->layermap[j]>0) + for(int i=0; i<96; i++) + tmpscr2[j].cset[i] = 3; + } + + if(counter==59) + { + for(int i = 96; i < 176; i++) + tmpscr->cset[i] = 3; + + for(int j=0; j<6; j++) + if(tmpscr->layermap[j]>0) + for(int i=96; i<176; i++) + tmpscr2[j].cset[i] = 3; + } + + if(counter==60) + { + for(int i=0; i<176; i++) + { + tmpscr->cset[i] = 2; + } + + for(int j=0; j<6; j++) + if(tmpscr->layermap[j]>0) + for(int i=0; i<176; i++) + tmpscr2[j].cset[i] = 2; + + for(int i=1; i<16; i+=3) + { + RAMpal[CSET(2)+i] = NESpal(0x17); + RAMpal[CSET(2)+i+1] = NESpal(0x16); + RAMpal[CSET(2)+i+2] = NESpal(0x26); + } + + refreshpal=true; + } + + if(counter==139) + slide_in_color(0x06); + + if(counter==149) + slide_in_color(0x07); + + if(counter==159) + slide_in_color(0x0F); + + if(counter==169) + { + slide_in_color(0x0F); + slide_in_color(0x0F); + } + + if(counter==170) + { + for(int i=1; i<16; i+=3) + { + RAMpal[CSET(6)+i] = NESpal(0x10); + RAMpal[CSET(6)+i+1] = NESpal(0x30); + RAMpal[CSET(6)+i+2] = NESpal(0x00); + refreshpal = true; + } + } + + if(counter < 169) + { + draw_screen(tmpscr); + //reuse our static subscreen + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + } + else + { + //draw only link. otherwise black layers might cover him. + rectfill(framebuf,0,playing_field_offset,255,167+playing_field_offset,0); + link.draw(framebuf); + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + } + } + } + else if(counter<350)//draw 'GAME OVER' text + { + clear_bitmap(framebuf); + blit(subscrbmp,framebuf,0,0,0,0,256,passive_subscreen_height); + textout_ex(framebuf,zfont,"GAME OVER",96,playing_field_offset+80,1,-1); + } + else + { + clear_bitmap(framebuf); + } + + //SFX... put them all here + switch(counter) + { + case 0: + sfx(WAV_OUCH,pan(int(link.x))); + break; + + case 60: + sfx(WAV_SPIRAL); + break; + + case 194: + sfx(WAV_MSG); + break; + } + + //advanceframe(true); + counter++; + if(counter<353) + return; + + finish(); + destroy_bitmap(subscrbmp); + link.setAction(none); + link.setDontDraw(false); +} diff --git a/src/sequence/gameOver.h b/src/sequence/gameOver.h new file mode 100644 index 0000000000..feaf6e6528 --- /dev/null +++ b/src/sequence/gameOver.h @@ -0,0 +1,21 @@ +#ifndef _ZC_SEQUENCE_GAMEOVER_H_ +#define _ZC_SEQUENCE_GAMEOVER_H_ + +#include "sequence.h" +struct BITMAP; +class LinkClass; + +class GameOver: public Sequence +{ +public: + GameOver(LinkClass& link); + void activate(); + void update(); + +private: + int counter; + LinkClass& link; + BITMAP* subscrbmp; +}; + +#endif diff --git a/src/sequence/ganonIntro.cpp b/src/sequence/ganonIntro.cpp new file mode 100644 index 0000000000..b0a4f817e8 --- /dev/null +++ b/src/sequence/ganonIntro.cpp @@ -0,0 +1,100 @@ +#include +#include "ganonIntro.h" +#include +#include +#include +#include +#include +#include + + +GanonIntro::GanonIntro(LinkClass& l): + counter(0), + link(l) +{ + if(game->lvlitems[dlevel]&liBOSS) + finish(); +} + +void GanonIntro::activate() +{ + loaded_guys=true; + loaditem(); + link.dir=down; + link.setAction(landhold2); + link.setHeldItem(getItemID(itemsbuf, itype_triforcepiece, 1)); +} + +void GanonIntro::update() +{ + /* + ************************ + * GANON INTRO SEQUENCE * + ************************ + -25 DOT updates + -24 LINK in + 0 TRIFORCE overhead - code begins at this point (counter == 0) + 47 GANON in + 58 LIGHT step + 68 LIGHT step + 78 LIGHT step + 255 TRIFORCE out + 256 TRIFORCE in + 270 TRIFORCE out + 271 GANON out, LINK face up + */ + + if(counter==47) + { + music_stop(); + stop_sfx(WAV_ROAR); + sfx(WAV_GASP); + sfx(WAV_GANON); + int Id=0; + + for(int i=0; i +#include "getBigTriforce.h" +#include +#include +#include + + +GetBigTriforce::GetBigTriforce(int tid, LinkClass& l): + link(l), + triforceID(tid), + counter(0) +{ +} + +void GetBigTriforce::activate() +{ + sfx(itemsbuf[triforceID].playsound); + guys.clear(); + + if(itemsbuf[triforceID].flags & ITEM_GAMEDATA) + game->lvlitems[dlevel]|=liTRIFORCE; +} + +void GetBigTriforce::update() +{ + /* + ************************* + * BIG TRIFORCE SEQUENCE * + ************************* + 0 BIGTRI out, WHITE flash in + 4 WHITE flash out, PILE cset white + 8 WHITE in + ... + 188 WHITE out + 191 PILE cset red + 200 top SHUTTER opens + 209 bottom SHUTTER opens + */ + + if(counter==4) + { + for(int i=1; i<16; i++) + RAMpal[CSET(9)+i]=_RGB(63,63,63); + } + + if((counter&7)==0) + { + for(int cs=2; cs<5; cs++) + { + for(int i=1; i<16; i++) + RAMpal[CSET(cs)+i]=_RGB(63,63,63); + } + + refreshpal=true; + } + + if((counter&7)==4) + { + if(currscr<128) + loadlvlpal(DMaps[currdmap].color); + else + loadlvlpal(0xB); + } + + if(counter==191) + loadpalset(9,pSprite(spPILE)); + + //advanceframe(true); + counter++; + if(counter<24*8) + return; + + finish(); + playLevelMusic(); + + if(itemsbuf[triforceID].flags & ITEM_FLAG1 && currscr < 128) + link.dowarp(1,0); //side warp +} diff --git a/src/sequence/getBigTriforce.h b/src/sequence/getBigTriforce.h new file mode 100644 index 0000000000..36363e97b8 --- /dev/null +++ b/src/sequence/getBigTriforce.h @@ -0,0 +1,20 @@ +#ifndef _ZC_SEQUENCE_GETBIGTRIFORCE_H_ +#define _ZC_SEQUENCE_GETBIGTRIFORCE_H_ + +#include "sequence.h" +class LinkClass; + +class GetBigTriforce: public Sequence +{ +public: + GetBigTriforce(int id, LinkClass& link); + void activate(); + void update(); + +private: + LinkClass& link; + int triforceID; + int counter; +}; + +#endif diff --git a/src/sequence/getTriforce.cpp b/src/sequence/getTriforce.cpp new file mode 100644 index 0000000000..ade6b9c3ee --- /dev/null +++ b/src/sequence/getTriforce.cpp @@ -0,0 +1,164 @@ +#include +#include "getTriforce.h" +#include +#include +#include + +extern int draw_screen_clip_rect_x1; +extern int draw_screen_clip_rect_x2; + +GetTriforce::GetTriforce(int tid, LinkClass& l): + link(l), + triforceID(tid), + counter(0), + counter2(0), + x2(0) +{ + for(int i=0; i<256; i++) + flash_pal[i] = get_bit(quest_rules,qr_FADE) ? _RGB(63,63,0) : _RGB(63,63,63); +} +void GetTriforce::activate() +{ + //get rid off all sprites but Link + guys.clear(); + items.clear(); + Ewpns.clear(); + Lwpns.clear(); + Sitems.clear(); + chainlinks.clear(); + + //decorations.clear(); + if(!COOLSCROLL) + show_subscreen_items=false; + + sfx(itemsbuf[triforceID].playsound); + music_stop(); + + if(itemsbuf[triforceID].misc1) + jukebox(itemsbuf[triforceID].misc1+ZC_MIDI_COUNT-1); + else + try_zcmusic((char*)"zelda.nsf",5, ZC_MIDI_TRIFORCE); + + if(itemsbuf[triforceID].flags & ITEM_GAMEDATA) + game->lvlitems[dlevel]|=liTRIFORCE; +} + +void GetTriforce::update() +{ + if(counter==40) + { + actiontype oldaction = (actiontype)link.getAction(); + ALLOFF(true, false); + link.setAction(oldaction); // have to reset this + } + + if(counter>=40 && counter<88) + { + if(get_bit(quest_rules,qr_FADE)) + { + if((counter&3)==0) + { + fade_interpolate(RAMpal,flash_pal,RAMpal,42,0,CSET(6)-1); + refreshpal=true; + } + + if((counter&3)==2) + { + loadpalset(0,0); + loadpalset(1,1); + loadpalset(5,5); + + if(currscr<128) loadlvlpal(DMaps[currdmap].color); + else loadlvlpal(0xB); // TODO: Cave/Item Cellar distinction? + } + } + else + { + if((counter&7)==0) + { + for(int cs2=2; cs2<5; cs2++) + { + for(int i=1; i<16; i++) + { + RAMpal[CSET(cs2)+i]=flash_pal[CSET(cs2)+i]; + } + } + + refreshpal=true; + } + + if((counter&7)==4) + { + if(currscr<128) loadlvlpal(DMaps[currdmap].color); + else loadlvlpal(0xB); + + loadpalset(5,5); + } + } + } + + if(itemsbuf[triforceID].flags & ITEM_GAMEDATA) + { + if(counter==88) + { + refill_what=REFILL_ALL; + refill_why=triforceID; + link.StartRefill(REFILL_ALL); + link.refill(); + } + + if(counter==89) + { + if(link.refill()) + counter--; + } + } + + if(itemsbuf[triforceID].flags & ITEM_FLAG1) // Warp out flag + { + if(counter>=208 && counter<288) + { + x2++; + counter2++; + switch(counter2) + { + case 5: + counter2=0; + + case 0: + case 2: + case 3: + x2++; + break; + } + } + + do_dcounters(); + + if(counter<288) + { + int curtain_x=x2&0xF8; + draw_screen_clip_rect_x1=curtain_x; + draw_screen_clip_rect_x2=255-curtain_x; + } + } + + counter++; + if(counter<408) + return; + if(midi_pos > 0 || (zcmusic && zcmusic->position<800)) // 800 may not be just right, but it works + return; + + finish(); + draw_screen_clip_rect_x1=0; + draw_screen_clip_rect_x2=255; + show_subscreen_items=true; + + if(itemsbuf[triforceID].flags & ITEM_FLAG1 && currscr < 128) + { + link.setScrollDir(link.dir); + link.dowarp(1,0); //side warp + } + else + playLevelMusic(); +} diff --git a/src/sequence/getTriforce.h b/src/sequence/getTriforce.h new file mode 100644 index 0000000000..c65f6320af --- /dev/null +++ b/src/sequence/getTriforce.h @@ -0,0 +1,24 @@ +#ifndef _ZC_SEQUENCE_GETTRIFORCE_H_ +#define _ZC_SEQUENCE_GETTRIFORCE_H_ + +#include "sequence.h" +#include +class LinkClass; + +class GetTriforce: public Sequence +{ +public: + GetTriforce(int id, LinkClass& link); + void activate(); + void update(); + +private: + LinkClass& link; + int triforceID; + int counter; + int counter2; + PALETTE flash_pal; + int x2; +}; + +#endif diff --git a/src/sequence/potion.cpp b/src/sequence/potion.cpp new file mode 100644 index 0000000000..1d58116487 --- /dev/null +++ b/src/sequence/potion.cpp @@ -0,0 +1,83 @@ +#include +#include "potion.h" +#include "sequence.h" +#include +#include + + +PotionSequence::PotionSequence(int id, LinkClass& l, const SFX& s1, + const SFX& s2): + itemID(id), + link(l), + fillSound(s1), + endSound(s2), + timer(1) +{ + healthToRefill=itemsbuf[id].misc1; // Values entered in the item editor + magicToRefill=itemsbuf[id].misc2; + + // Percent or blocks? + if(healthToRefill>0 && (itemsbuf[id].flags&ITEM_FLAG1)!=0) + healthToRefill*=game->get_maxlife()/100.0; + else + healthToRefill*=HP_PER_HEART; + + if(magicToRefill>0 && (itemsbuf[id].flags&ITEM_FLAG2)!=0) + magicToRefill*=game->get_maxlife()/100.0; + else + magicToRefill*=MAGICPERBLOCK; + + // Don't fill beyond full + int maxFill=game->get_maxlife()-game->get_life(); + if(healthToRefill>maxFill) + healthToRefill=maxFill; + + maxFill=game->get_maxmagic()-game->get_magic(); + if(magicToRefill>maxFill) + magicToRefill=maxFill; +} + +void PotionSequence::activate() +{ + fillSound.startLooping(); + + // Clear jinxes + if(!get_bit(quest_rules,qr_NONBUBBLEMEDICINE)) + { + link.setSwordClk(0); + if(get_bit(quest_rules,qr_ITEMBUBBLE)) + link.setItemClk(0); + } +} + +void PotionSequence::update() +{ + timer--; + if(timer==0) + { + if(healthToRefill>0) + { + game->change_life(HP_PER_HEART/2); + healthToRefill-=HP_PER_HEART/2; + if(healthToRefill<0) + healthToRefill=0; + } + + if(magicToRefill>0) + { + game->change_magic(MAGICPERBLOCK/4); + magicToRefill-=MAGICPERBLOCK/4; + if(magicToRefill<0) + magicToRefill=0; + } + + if(healthToRefill==0 && magicToRefill==0) + { + finish(); + fillSound.stopLooping(); + endSound.play(); + } + else + timer=get_bit(quest_rules,qr_FASTFILL) ? 6 : 22; + } +} diff --git a/src/sequence/potion.h b/src/sequence/potion.h new file mode 100644 index 0000000000..7837029262 --- /dev/null +++ b/src/sequence/potion.h @@ -0,0 +1,24 @@ +#ifndef _ZC_SEQUENCE_POTION_H_ +#define _ZC_SEQUENCE_POTION_H_ + +#include "sequence.h" +#include +class LinkClass; + +class PotionSequence: public Sequence +{ +public: + PotionSequence(int itemID, LinkClass& link, const SFX& fillSound, + const SFX& endSound); + void activate(); + void update(); + +private: + int itemID; + LinkClass& link; + SFX fillSound, endSound; + int timer; + int healthToRefill, magicToRefill; +}; + +#endif diff --git a/src/sequence/sequence.cpp b/src/sequence/sequence.cpp new file mode 100644 index 0000000000..ce2e9768ed --- /dev/null +++ b/src/sequence/sequence.cpp @@ -0,0 +1,108 @@ +#include +#include "sequence.h" +#include +#include +#include +#include +#include +#include +#include +#include +//#include +extern LinkClass Link; +extern SFXManager sfxMgr; +extern mapscr tmpscr[2]; + +extern int draw_screen_clip_rect_x1; +extern int draw_screen_clip_rect_x2; +extern int draw_screen_clip_rect_y1; +extern int draw_screen_clip_rect_y2; + +#include "gameOver.h" +#include "ganonIntro.h" +#include "getBigTriforce.h" +#include "getTriforce.h" +#include "potion.h" +#include "whistle.h" + +static Sequence* specialSequence=0; + +Sequence::Sequence(): + finished(false) +{ +} + +Sequence::~Sequence() +{ +} + +void beginSpecialSequence(sequenceID id, int itemID) +{ + switch(id) + { + case seq_ganonIntro: + specialSequence=new GanonIntro(Link); + break; + + case seq_getTriforce: + specialSequence=new GetTriforce(itemID, Link); + break; + + case seq_getBigTriforce: + specialSequence=new GetBigTriforce(itemID, Link); + break; + + case seq_gameOver: + specialSequence=new GameOver(Link); + break; + + case seq_whistle: + specialSequence=new WhistleSequence(itemID, Link, + sfxMgr.getSFX(itemsbuf[itemID].usesound)); + break; + + case seq_potion: + specialSequence=new PotionSequence(itemID, Link, + sfxMgr.getSFX(WAV_REFILL), sfxMgr.getSFX(WAV_MSG)); + break; + + default: + return; // Maybe throw something instead. This shouldn't happen. + } + + if(specialSequence->isFinished()) + { + // This can happen, e.g. Ganon's intro if he's already been beaten. + // Maybe that should be checked beforehand, though... + delete specialSequence; + specialSequence=0; + } + else + specialSequence->activate(); +} + +bool specialSequenceIsActive() +{ + return specialSequence; +} + +void updateSpecialSequence() +{ + specialSequence->update(); + if(specialSequence->isFinished()) + { + delete specialSequence; + specialSequence=0; + } +} + +void clearSpecialSequence() +{ + if(specialSequence) + { + delete specialSequence; + specialSequence=0; + } +} + + diff --git a/src/sequence/sequence.h b/src/sequence/sequence.h new file mode 100644 index 0000000000..5fde75ce39 --- /dev/null +++ b/src/sequence/sequence.h @@ -0,0 +1,33 @@ +#ifndef _ZC_SEQUENCE_SEQUENCE_H_ +#define _ZC_SEQUENCE_SEQUENCE_H_ + +enum sequenceID +{ + seq_ganonIntro, seq_getTriforce, seq_getBigTriforce, seq_gameOver, + seq_whistle, seq_potion +}; + +void beginSpecialSequence(sequenceID id, int itemID=0); +bool specialSequenceIsActive(); +void updateSpecialSequence(); +void clearSpecialSequence(); + + +// Sequences are special events that suspend gameplay entirely. +class Sequence +{ +public: + Sequence(); + virtual ~Sequence(); + virtual void activate()=0; + virtual void update()=0; + inline bool isFinished() const { return finished; } + +protected: + inline void finish() { finished=true; } + +private: + bool finished; +}; + +#endif diff --git a/src/sequence/whistle.cpp b/src/sequence/whistle.cpp new file mode 100644 index 0000000000..bb8aa470ff --- /dev/null +++ b/src/sequence/whistle.cpp @@ -0,0 +1,61 @@ +#include +#include "whistle.h" +#include "sequence.h" +#include +#include +#include +#include +extern int whistleitem; + +WhistleSequence::WhistleSequence(int id, LinkClass& l, const SFX& s): + itemID(id), + link(l), + sound(s) +{ +} + +void WhistleSequence::activate() +{ + sound.play(link.getX()); +} + +void WhistleSequence::update() +{ + if(sound.isPlaying()) + return; + + finish(); + fix x=link.getX(), y=link.getY(), z=link.getZ(); + int dir=link.getDir(); + if(dir==up || dir==right) + link.modWhistleCounter(1); + else + link.modWhistleCounter(-1); + + Lwpns.add(new weapon(x,y,z,wWhistle,0,0,dir,itemID,link.getUID())); + + bool foundEntrance=findentrance(x,y,mfWHISTLE,false); + + //if(((didstuff&did_whistle) && itemsbuf[itemid].flags&ITEM_FLAG1) || currscr>=128) + if(foundEntrance || currscr>=128) + return; + + //if(itemsbuf[itemID].flags&ITEM_FLAG1) didstuff |= did_whistle; + + if((tmpscr->flags&fWHISTLE) || (tmpscr->flags7 & fWHISTLEWATER) + || (tmpscr->flags7&fWHISTLEPAL)) + whistleclk=0; // signal to start drying lake or doing other stuff + else + { + int where = itemsbuf[itemID].misc1; + + if(where>right) where=dir^1; + + if(((DMaps[currdmap].flags&dmfWHIRLWIND && TriforceCount()) || DMaps[currdmap].flags&dmfWHIRLWINDRET) && + itemsbuf[itemID].misc2 >= 0 && itemsbuf[itemID].misc2 <= 8 && !foundEntrance) + Lwpns.add(new weapon((fix)(where==left?240:where==right?0:x),(fix)(where==down?0:where==up?160:y), + (fix)0,wWind,0,0,where,itemID,link.getUID())); + + whistleitem=itemID; + } +} diff --git a/src/sequence/whistle.h b/src/sequence/whistle.h new file mode 100644 index 0000000000..8c43035014 --- /dev/null +++ b/src/sequence/whistle.h @@ -0,0 +1,21 @@ +#ifndef _ZC_SEQUENCE_WHISTLE_H_ +#define _ZC_SEQUENCE_WHISTLE_H_ + +#include "sequence.h" +#include +class LinkClass; + +class WhistleSequence: public Sequence +{ +public: + WhistleSequence(int itemID, LinkClass& link, const SFX& sound); + void activate(); + void update(); + +private: + int itemID; + LinkClass& link; + SFX sound; +}; + +#endif diff --git a/src/sfx.h b/src/sfx.h new file mode 100644 index 0000000000..612d90883b --- /dev/null +++ b/src/sfx.h @@ -0,0 +1,68 @@ +/* Allegro datafile object indexes, produced by grabber v4.2.2, MacOS X */ +/* Datafile: /zc/trunk/output/common/sfx.dat */ +/* Date: Sun Feb 6 19:53:24 2011 */ +/* Do not hand edit! */ + +#define _SIGNATURE 0 /* DATA */ +#define WAV_ARROW 1 /* SAMP */ +#define WAV_BEAM 2 /* SAMP */ +#define WAV_BOMB 3 /* SAMP */ +#define WAV_BRANG 4 /* SAMP */ +#define WAV_CHIME 5 /* SAMP */ +#define WAV_CHINK 6 /* SAMP */ +#define WAV_CLEARED 7 /* SAMP */ +#define WAV_DODONGO 8 /* SAMP */ +#define WAV_DOOR 9 /* SAMP */ +#define WAV_EDEAD 10 /* SAMP */ +#define WAV_EHIT 11 /* SAMP */ +#define WAV_ER 12 /* SAMP */ +#define WAV_FIRE 13 /* SAMP */ +#define WAV_GANON 14 /* SAMP */ +#define WAV_GASP 15 /* SAMP */ +#define WAV_HAMMER 16 /* SAMP */ +#define WAV_HOOKSHOT 17 /* SAMP */ +#define WAV_MSG 18 /* SAMP */ +#define WAV_OUCH 19 /* SAMP */ +#define WAV_PICKUP 20 /* SAMP */ +#define WAV_PLACE 21 /* SAMP */ +#define WAV_PLINK 22 /* SAMP */ +#define WAV_REFILL 23 /* SAMP */ +#define WAV_ROAR 24 /* SAMP */ +#define WAV_SCALE 25 /* SAMP */ +#define WAV_SEA 26 /* SAMP */ +#define WAV_SECRET 27 /* SAMP */ +#define WAV_SPIRAL 28 /* SAMP */ +#define WAV_STAIRS 29 /* SAMP */ +#define WAV_SWORD 30 /* SAMP */ +#define WAV_VADER 31 /* SAMP */ +#define WAV_WAND 32 /* SAMP */ +#define WAV_WHISTLE 33 /* SAMP */ +#define WAV_ZELDA 34 /* SAMP */ +#define WAV_ZN1CHARGE 35 /* SAMP */ +#define WAV_ZN1CHARGE2 36 /* SAMP */ +#define WAV_ZN1DINSFIRE 37 /* SAMP */ +#define WAV_ZN1FALL 38 /* SAMP */ +#define WAV_ZN1FARORESWIND 39 /* SAMP */ +#define WAV_ZN1FIREBALL 40 /* SAMP */ +#define WAV_ZN1GRASSCUT 41 /* SAMP */ +#define WAV_ZN1HAMMERPOST 42 /* SAMP */ +#define WAV_ZN1HOVER 43 /* SAMP */ +#define WAV_ZN1ICE 44 /* SAMP */ +#define WAV_ZN1JUMP 45 /* SAMP */ +#define WAV_ZN1LENSOFF 46 /* SAMP */ +#define WAV_ZN1LENSON 47 /* SAMP */ +#define WAV_ZN1NAYRUSLOVE1 48 /* SAMP */ +#define WAV_ZN1NAYRUSLOVE2 49 /* SAMP */ +#define WAV_ZN1PUSHBLOCK 50 /* SAMP */ +#define WAV_ZN1ROCK 51 /* SAMP */ +#define WAV_ZN1ROCKETDOWN 52 /* SAMP */ +#define WAV_ZN1ROCKETUP 53 /* SAMP */ +#define WAV_ZN1SPINATTACK 54 /* SAMP */ +#define WAV_ZN1SPLASH 55 /* SAMP */ +#define WAV_ZN1SUMMON 56 /* SAMP */ +#define WAV_ZN1TAP 57 /* SAMP */ +#define WAV_ZN1TAP2 58 /* SAMP */ +#define WAV_ZN1WHIRLWIND 59 /* SAMP */ +#define WAV_ZN2CANE 60 /* SAMP */ +#define Z35 61 /* SAMP */ + diff --git a/src/sfxAllegro.cpp b/src/sfxAllegro.cpp new file mode 100644 index 0000000000..8467778ff9 --- /dev/null +++ b/src/sfxAllegro.cpp @@ -0,0 +1,46 @@ +#include "sfxAllegro.h" + +#include "sound.h" +#include + +// This can all be rewritten once it's used exclusively... + +AllegroSFX::AllegroSFX(int sfxID): + id(sfxID), + numLoopers(0) +{ +} + +AllegroSFX::~AllegroSFX() +{ + stop_sfx(id); +} + +void AllegroSFX::play() +{ + sfx(id, 63, numLoopers>0, true); +} + +void AllegroSFX::play(int x) +{ + sfx(id, pan(x), numLoopers>0, true); +} + +void AllegroSFX::addLoop() +{ + numLoopers++; + if(numLoopers==1) + cont_sfx(id); +} + +void AllegroSFX::removeLoop() +{ + numLoopers--; + if(numLoopers==0) + stop_sfx(id); // ?? +} + +bool AllegroSFX::isPlaying() const +{ + return sfx_allocated(id); +} diff --git a/src/sfxAllegro.h b/src/sfxAllegro.h new file mode 100644 index 0000000000..41bd49a192 --- /dev/null +++ b/src/sfxAllegro.h @@ -0,0 +1,20 @@ +#ifndef _ZC_SFXALLEGRO_H_ +#define _ZC_SFXALLEGRO_H_ + +class AllegroSFX +{ +public: + AllegroSFX(int id); + ~AllegroSFX(); + void play(); + void play(int x); + void addLoop(); + void removeLoop(); + bool isPlaying() const; + +private: + int id; + int numLoopers; +}; + +#endif diff --git a/src/sfxClass.cpp b/src/sfxClass.cpp new file mode 100644 index 0000000000..0b4bbc9bc2 --- /dev/null +++ b/src/sfxClass.cpp @@ -0,0 +1,52 @@ +#include "sfxClass.h" + +SFX::SFX(): + alSFX(0), + looping(false) +{ +} + +SFX::SFX(AllegroSFX* a): + alSFX(a), + looping(false) +{ +} + +SFX::SFX(const SFX& other): + alSFX(other.alSFX), + looping(false) +{ +} + +SFX::~SFX() +{ + if(looping && alSFX) + alSFX->removeLoop(); +} + +SFX& SFX::operator=(const SFX& other) +{ + if(looping && alSFX) + alSFX->removeLoop(); + alSFX=other.alSFX; + looping=false; + return *this; +} + +void SFX::startLooping() +{ + if(!looping && alSFX) + { + alSFX->addLoop(); + looping=true; + } +} + +void SFX::stopLooping() +{ + if(looping) + { + alSFX->removeLoop(); + looping=false; + } +} diff --git a/src/sfxClass.h b/src/sfxClass.h new file mode 100644 index 0000000000..9cd6549228 --- /dev/null +++ b/src/sfxClass.h @@ -0,0 +1,46 @@ +#ifndef _ZC_SFXCLASS_H_ +#define _ZC_SFXCLASS_H_ + +#include "sfxAllegro.h" + +class SFX +{ +public: + SFX(); + SFX(AllegroSFX* alSFX); + SFX(const SFX& other); + ~SFX(); + + SFX& operator=(const SFX& other); + + void startLooping(); + void stopLooping(); + + inline void play(int x) + { + if(alSFX) + alSFX->play(x); + } + + inline void play() + { + if(alSFX) + alSFX->play(); + } + + inline bool isLooping() const + { + return looping; + } + + inline bool isPlaying() const + { + return looping || alSFX->isPlaying(); + } + +private: + AllegroSFX* alSFX; + bool looping; +}; + +#endif diff --git a/src/sfxManager.cpp b/src/sfxManager.cpp new file mode 100644 index 0000000000..870ce290c8 --- /dev/null +++ b/src/sfxManager.cpp @@ -0,0 +1,13 @@ +#include "sfxManager.h" + +SFXManager::SFXManager() +{ + for(int i=0; iplay(); + } + + inline SFX getSFX(int id) + { + return SFX(sfx[id]); + } + +private: + static const int numSFX=256; + AllegroSFX* sfx[numSFX]; +}; + +#endif diff --git a/src/single_instance.h b/src/single_instance.h new file mode 100644 index 0000000000..0d0831c820 --- /dev/null +++ b/src/single_instance.h @@ -0,0 +1,6 @@ +#ifndef _SINGLE_INSTANCE_H_ +#define _SINGLE_INSTANCE_H_ + +bool is_only_instance(const char* name); + +#endif diff --git a/src/single_instance_unix.cpp b/src/single_instance_unix.cpp new file mode 100644 index 0000000000..3d7f511b33 --- /dev/null +++ b/src/single_instance_unix.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include + +#include "single_instance.h" + +#ifndef UNIX_PATH_MAX + #define UNIX_PATH_MAX 108 +#endif + +bool is_only_instance(const char* name) +{ + unsigned int fd; + sockaddr_un sun; + unsigned int length; + + fd=socket(AF_UNIX, SOCK_STREAM, 0); + if(fd==-1) + return false; + + sun.sun_family=AF_UNIX; + strncpy(sun.sun_path, name, UNIX_PATH_MAX); + sun.sun_path[UNIX_PATH_MAX-1]='\0'; + length=strlen(sun.sun_path)+sizeof(sun.sun_family); + + if(connect(fd, (sockaddr*)&sun, length)!=-1) + // Connect succeeded; there must be another instance running already + return false; + + unlink(sun.sun_path); + if(bind(fd, (sockaddr*)&sun, length)==-1) + return false; + if(listen(fd, 5)==-1) + return false; + + return true; +} diff --git a/src/sound.cpp b/src/sound.cpp new file mode 100644 index 0000000000..6cf6bf47f8 --- /dev/null +++ b/src/sound.cpp @@ -0,0 +1,490 @@ +#include "sound.h" +#include "zc_alleg.h" +#include "zc_sys.h" +#include "zelda.h" +#include "zeldadat.h" + +/*****************************/ +/**** Custom Sound System ****/ +/*****************************/ + +static bool midi_paused=false; +static int sfx_voice[WAV_COUNT]; + +static inline int mixvol(int v1,int v2) +{ + return (zc_min(v1,255)*zc_min(v2,255)) >> 8; +} + +// Run an NSF, or a MIDI if the NSF is missing somehow. +bool try_zcmusic(char *filename, int track, int midi) +{ + ZCMUSIC *newzcmusic = NULL; + + // Try the ZC directory first + { + char exepath[2048]; + char musicpath[2048]; + get_executable_name(exepath, 2048); + replace_filename(musicpath, exepath, filename, 2048); + newzcmusic=(ZCMUSIC*)zcmusic_load_file(musicpath); + } + + // Not in ZC directory, try the quest directory + if(newzcmusic==NULL) + { + char musicpath[2048]; + replace_filename(musicpath, qstpath, filename, 2048); + newzcmusic=(ZCMUSIC*)zcmusic_load_file(musicpath); + } + + // Found it + if(newzcmusic!=NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + stop_midi(); + + zcmusic=newzcmusic; + zcmusic_play(zcmusic, emusic_volume); + + if(track>0) + zcmusic_change_track(zcmusic,track); + + return true; + } + + // Not found, play MIDI - unless this was called by a script (yay, magic numbers) + else if(midi>-1000) + jukebox(midi); + + return false; +} + +void jukebox(int index,int loop) +{ + music_stop(); + + if(index<0) index=MAXMIDIS-1; + + if(index>=MAXMIDIS) index=0; + + music_stop(); + + // Allegro's DIGMID driver (the one normally used on on Linux) gets + // stuck notes when a song stops. This fixes it. + if(strcmp(midi_driver->name, "DIGMID")==0) + set_volume(0, 0); + + set_volume(-1, mixvol(tunes[index].volume,midi_volume>>1)); + play_midi((MIDI*)tunes[index].data,loop); + + if(tunes[index].start>0) + midi_seek(tunes[index].start); + + midi_loop_end = tunes[index].loop_end; + midi_loop_start = tunes[index].loop_start; + + currmidi=index; + master_volume(digi_volume,midi_volume); + midi_paused=false; +} + +void jukebox(int index) +{ + if(index<0) index=MAXMIDIS-1; + + if(index>=MAXMIDIS) index=0; + + // do nothing if it's already playing + if(index==currmidi && midi_pos>=0) + { + midi_paused=false; + return; + } + + jukebox(index,tunes[index].loop); +} + +void play_DmapMusic() +{ + static char tfile[2048]; + static int ttrack=0; + bool domidi=false; + + // Seems like this ought to call try_zcmusic()... + + if(DMaps[currdmap].tmusic[0]!=0) + { + if(zcmusic==NULL || + strcmp(zcmusic->filename,DMaps[currdmap].tmusic)!=0 || + (zcmusic->type==ZCMF_GME && zcmusic->track != DMaps[currdmap].tmusictrack)) + { + if(zcmusic != NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + zcmusic = NULL; + } + + // Try the ZC directory first + { + char exepath[2048]; + char musicpath[2048]; + get_executable_name(exepath, 2048); + replace_filename(musicpath, exepath, DMaps[currdmap].tmusic, 2048); + zcmusic=(ZCMUSIC*)zcmusic_load_file(musicpath); + } + + // Not in ZC directory, try the quest directory + if(zcmusic==NULL) + { + char musicpath[2048]; + replace_filename(musicpath, qstpath, DMaps[currdmap].tmusic, 2048); + zcmusic=(ZCMUSIC*)zcmusic_load_file(musicpath); + } + + if(zcmusic!=NULL) + { + stop_midi(); + strcpy(tfile,DMaps[currdmap].tmusic); + zcmusic_play(zcmusic, emusic_volume); + int temptracks=0; + temptracks=zcmusic_get_tracks(zcmusic); + temptracks=(temptracks<2)?1:temptracks; + ttrack = vbound(DMaps[currdmap].tmusictrack,0,temptracks-1); + zcmusic_change_track(zcmusic,ttrack); + } + else + { + tfile[0] = 0; + domidi=true; + } + } + } + else + { + domidi=true; + } + + if(domidi) + { + int m=DMaps[currdmap].midi; + + switch(m) + { + case 1: + jukebox(ZC_MIDI_OVERWORLD); + break; + + case 2: + jukebox(ZC_MIDI_DUNGEON); + break; + + case 3: + jukebox(ZC_MIDI_LEVEL9); + break; + + default: + if(m>=4 && m<4+MAXCUSTOMMIDIS) + jukebox(m-4+ZC_MIDI_COUNT); + else + music_stop(); + } + } +} + +void playLevelMusic() +{ + int m=tmpscr->screen_midi; + + switch(m) + { + case -2: + music_stop(); + break; + + case -1: + play_DmapMusic(); + break; + + case 1: + jukebox(ZC_MIDI_OVERWORLD); + break; + + case 2: + jukebox(ZC_MIDI_DUNGEON); + break; + + case 3: + jukebox(ZC_MIDI_LEVEL9); + break; + + default: + if(m>=4 && m<4+MAXCUSTOMMIDIS) + jukebox(m-4+ZC_MIDI_COUNT); + else + music_stop(); + } +} + +bool get_midi_paused() +{ + return midi_paused; +} + +void set_midi_paused(bool paused) +{ + midi_paused=paused; +} + +void music_pause() +{ + //al_pause_duh(tmplayer); + zcmusic_pause(zcmusic, ZCM_PAUSE); + midi_pause(); + set_midi_paused(true); +} + +void music_resume() +{ + //al_resume_duh(tmplayer); + zcmusic_pause(zcmusic, ZCM_RESUME); + midi_resume(); + set_midi_paused(false); +} + +void music_stop() +{ + //al_stop_duh(tmplayer); + //unload_duh(tmusic); + //tmusic=NULL; + //tmplayer=NULL; + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + stop_midi(); + set_midi_paused(false); + currmidi=0; +} + +void master_volume(int dv,int mv) +{ + if(dv>=0) digi_volume=zc_max(zc_min(dv,255),0); + + if(mv>=0) midi_volume=zc_max(zc_min(mv,255),0); + + int i = zc_min(zc_max(currmidi,0),MAXMIDIS-1); + set_volume(digi_volume,mixvol(tunes[i].volume,midi_volume)); +} + +void set_all_voice_volume(int sfx_volume) +{ + for(int i=0; i 0) + voice_set_volume(sfx_voice[i], sfx_volume); + } +} + +/*****************/ +/***** SFX *****/ +/*****************/ + + +// array of voices, one for each sfx sample in the data file +// 0+ = voice # +// -1 = voice not allocated +void Z_init_sound() +{ + for(int i=0; i=WAV_COUNT) + return false; + + if(sfx_voice[index]==-1) + { + if(sfxdat) + { + if(index0 && index=WAV_COUNT || sfx_voice[index]==-1) + return; + + voice_set_playmode(sfx_voice[index],loop?PLAYMODE_LOOP:PLAYMODE_PLAY); + voice_set_pan(sfx_voice[index],pan); +} + +// pauses a voice +void pause_sfx(int index) +{ + if(index>0 && index0 && index=WAV_COUNT) + return; + + if(sfx_voice[index]!=-1) + { + deallocate_voice(sfx_voice[index]); + sfx_voice[index]=-1; + } +} + +// Stops SFX played by Link's item of the given family +void stop_item_sfx(int family) +{ + int id=current_item_id(family); + + if(id<0) + return; + + stop_sfx(itemsbuf[id].usesound); +} + +void kill_sfx() +{ + for(int i=0; i>1)+68,0,255); + + case 2: + return vbound(((x*3)>>2)+36,0,255); + } + + return vbound(x,0,255); +} diff --git a/src/sound.h b/src/sound.h new file mode 100644 index 0000000000..ea66b574a6 --- /dev/null +++ b/src/sound.h @@ -0,0 +1,43 @@ +#ifndef _ZC_SOUND_H_ +#define _ZC_SOUND_H_ + +bool try_zcmusic(char *filename, int track, int midi); +void jukebox(int index); +void jukebox(int index,int loop); +void play_DmapMusic(); +void playLevelMusic(); +bool get_midi_paused(); +void set_midi_paused(bool paused); +void music_pause(); +void music_resume(); +void music_stop(); +void master_volume(int dv,int mv); +void set_all_voice_volume(int sfx_volume); +void Z_init_sound(); +void sfx_cleanup(); +bool sfx_init(int index); +void sfx(int index,int pan,bool loop, bool restart = true); +bool sfx_allocated(int index); +void cont_sfx(int index); +void stop_sfx(int index); +void adjust_sfx(int index,int pan,bool loop); +void pause_sfx(int index); +void resume_sfx(int index); +void pause_all_sfx(); +void resume_all_sfx(); +void stop_sfx(int index); +void stop_item_sfx(int family); +void kill_sfx(); +int pan(int x); + +inline void sfx(int index) +{ + sfx(index, 128, false); +} + +inline void sfx(int index,int pan) +{ + sfx(index, pan<0 ? 0 : (pan>255 ? 255 : pan), false); +} + +#endif diff --git a/src/sprite.cpp b/src/sprite.cpp new file mode 100644 index 0000000000..fa796fa600 --- /dev/null +++ b/src/sprite.cpp @@ -0,0 +1,1053 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include "sprite.h" +#include "entityPtr.h" +#include "zdefs.h" +#include "tiles.h" +#include "angelscript/scriptData.h" + +extern bool get_debug(); +extern bool halt; +extern bool show_sprites; +extern bool show_hitboxes; +extern bool is_zquest(); +extern void debugging_box(int x1, int y1, int x2, int y2); +extern BITMAP* scriptDrawingTarget; + +/**********************************/ +/******* Sprite Base Class ********/ +/**********************************/ + +sprite::sprite(): + scriptData(0), + toBeDeleted(false), + ref(new EntityRef()) +{ + uid = getNextUID(); + x=y=z=tile=shadowtile=cs=flip=c_clk=clk=xofs=yofs=zofs=hxofs=hyofs=fall=0; + txsz=1; + tysz=1; + id=-1; + hxsz=hysz=16; + hzsz=1; + yofs=playing_field_offset; + dir=down; + angular=canfreeze=false; + drawstyle=0; + extend=0; + lasthitclk=0; + lasthit=0; + angle=0; + misc=0; + for(int i=0; i<16; i++) miscellaneous[i] = 0; + + scriptcoldet = 1; +} + +sprite::sprite(sprite const & other): + x(other.x), + y(other.y), + z(other.z), + fall(other.fall), + tile(other.tile), + shadowtile(other.shadowtile), + cs(other.cs), + flip(other.flip), + c_clk(other.c_clk), + clk(other.clk), + misc(other.misc), + xofs(other.xofs), + yofs(other.yofs), + zofs(other.zofs), + hxofs(other.hxofs), + hyofs(other.hyofs), + hxsz(other.hxsz), + hysz(other.hysz), + hzsz(other.hzsz), + txsz(other.txsz), + tysz(other.tysz), + id(other.id), + dir(other.dir), + angular(other.angular), + canfreeze(other.canfreeze), + angle(other.angle), + lasthit(other.lasthit), + lasthitclk(other.lasthitclk), + drawstyle(other.drawstyle), + extend(other.extend), + scriptData(0), + toBeDeleted(false), + ref(new EntityRef()) +{ + uid = getNextUID(); + for(int i=0; i<16; i++) miscellaneous[i] = other.miscellaneous[i]; + + scriptcoldet = other.scriptcoldet; +} + +sprite::sprite(fix X,fix Y,int T,int CS,int F,int Clk,int Yofs): + x(X),y(Y),tile(T),cs(CS),flip(F),clk(Clk),yofs(Yofs), + scriptData(0), + toBeDeleted(false), + ref(new EntityRef()) +{ + uid = getNextUID(); + hxsz=hysz=16; + hxofs=hyofs=xofs=0; + txsz=1; + tysz=1; + id=-1; + dir=down; + angular=canfreeze=false; + extend=0; + for(int i=0; i<16; i++) miscellaneous[i] = 0; + + scriptcoldet = 1; + drawstyle=0; + lasthitclk=0; + lasthit=0; + angle=0; + hzsz=1; + misc=0; + c_clk=0; + shadowtile=0; +} + +sprite::~sprite() +{ + ref->onEntityDelete(); + delete scriptData; +} + +long sprite::getNextUID() +{ + static long nextid = 0; + return nextid++; +} + +void sprite::draw2(BITMAP *) // top layer for special needs +{ +} + +void sprite::drawcloaked2(BITMAP *) // top layer for special needs +{ +} + +bool sprite::animate(int) +{ + ++c_clk; + return false; +} +int sprite::real_x(fix fx) +{ + int rx=fx.v>>16; + + switch(dir) + { + case 9: + case 13: + if(fx.v&0xFFFF) + ++rx; + + break; + } + + return rx; +} + +int sprite::real_y(fix fy) +{ + return fy.v>>16; +} + +int sprite::real_z(fix fz) +{ + return fz.v>>16; +} + +bool sprite::hit(sprite *s) +{ + if(!(scriptcoldet&1)) return false; + + if(id<0 || s->id<0 || clk<0) return false; + + if(halt) + { + } + + return hit(s->x+s->hxofs,s->y+s->hyofs,s->z+s->zofs,s->hxsz,s->hysz,s->hzsz); +} + +bool sprite::hit(int tx,int ty,int tz,int txsz2,int tysz2,int tzsz2) +{ + if(!(scriptcoldet&1)) return false; + + if(id<0 || clk<0) return false; + + return tx+txsz2>x+hxofs && + ty+tysz2>y+hyofs && + tz+tzsz2>z+zofs && + + tx>1); + int cy1=y+hyofs+(hysz>>1); + int cx2=tx+(txsz2>>1); + int cy2=ty+(tysz2>>1); + + if(dir2>=left && abs(cy1-cy2)<=8) + return (cx2-cx1<0)?left:right; + + return (cy2-cy1<0)?up:down; +} + +void sprite::move(fix dx,fix dy) +{ + x+=dx; + y+=dy; +} + +void sprite::move(fix s) +{ + if(angular) + { + x += cos(angle)*s; + y += sin(angle)*s; + return; + } + + switch(dir) + { + case 8: + case up: + y-=s; + break; + + case 12: + case down: + y+=s; + break; + + case 14: + case left: + x-=s; + break; + + case 10: + case right: + x+=s; + break; + + case 15: + case l_up: + x-=s; + y-=s; + break; + + case 9: + case r_up: + x+=s; + y-=s; + break; + + case 13: + case l_down: + x-=s; + y+=s; + break; + + case 11: + case r_down: + x+=s; + y+=s; + break; + + case -1: + break; + } +} + +void sprite::draw(BITMAP* dest) +{ + if(!show_sprites) + { + return; + } + + int sx = real_x(x+xofs); + int sy = real_y(y+yofs)-real_z(z+zofs); + + if(id<0) + return; + + int e = extend>=3 ? 3 : extend; + + if(clk>=0) + { + switch(e) + { + BITMAP *temp; + + case 1: + temp = create_bitmap_ex(8,16,32); + blit(dest, temp, sx, sy-16, 0, 0, 16, 32); + + if(drawstyle==0 || drawstyle==3) + { + overtile16(temp,tile-TILES_PER_ROW,0,0,cs,flip); + overtile16(temp,tile,0,16,cs,flip); + } + + if(drawstyle==1) + { + overtiletranslucent16(temp,tile-TILES_PER_ROW,0,0,cs,flip,128); + overtiletranslucent16(temp,tile,0,16,cs,flip,128); + } + + if(drawstyle==2) + { + overtilecloaked16(temp,tile-TILES_PER_ROW,0,0,flip); + overtilecloaked16(temp,tile,0,16,flip); + } + + masked_blit(temp, dest, 0, 0, sx, sy-16, 16, 32); + destroy_bitmap(temp); + break; + + case 2: + temp = create_bitmap_ex(8,48,32); + blit(dest, temp, sx-16, sy-16, 0, 0, 48, 32); + + if(drawstyle==0 || drawstyle==3) + { + overtile16(temp,tile-TILES_PER_ROW,16,0,cs,flip); + overtile16(temp,tile-TILES_PER_ROW-(flip?-1:1),0,0,cs,flip); + overtile16(temp,tile-TILES_PER_ROW+(flip?-1:1),32,0,cs,flip); + overtile16(temp,tile,16,16,cs,flip); + overtile16(temp,tile-(flip?-1:1),0,16,cs,flip); + overtile16(temp,tile+(flip?-1:1),32,16,cs,flip); + } + + if(drawstyle==1) + { + overtiletranslucent16(temp,tile-TILES_PER_ROW,16,0,cs,flip,128); + overtiletranslucent16(temp,tile-TILES_PER_ROW-(flip?-1:1),0,0,cs,flip,128); + overtiletranslucent16(temp,tile-TILES_PER_ROW+(flip?-1:1),32,0,cs,flip,128); + overtiletranslucent16(temp,tile,16,16,cs,flip,128); + overtiletranslucent16(temp,tile-(flip?-1:1),0,16,cs,flip,128); + overtiletranslucent16(temp,tile+(flip?-1:1),32,16,cs,flip,128); + } + + if(drawstyle==2) + { + overtilecloaked16(temp,tile-TILES_PER_ROW,16,0,flip); + overtilecloaked16(temp,tile-TILES_PER_ROW-(flip?-1:1),0,0,flip); + overtilecloaked16(temp,tile-TILES_PER_ROW+(flip?-1:1),32,0,flip); + overtilecloaked16(temp,tile,16,16,flip); + overtilecloaked16(temp,tile-(flip?-1:1),0,16,flip); + overtilecloaked16(temp,tile+(flip?-1:1),32,16,flip); + } + + masked_blit(temp, dest, 8, 0, sx-8, sy-16, 32, 32); + destroy_bitmap(temp); + break; + + case 3: + { + int tileToDraw; + + switch(flip) + { + case 1: + for(int i=0; i=0; j--) + { + tileToDraw=tile+(i*TILES_PER_ROW)+j; + + if(tileToDraw%TILES_PER_ROW=0; i--) + { + for(int j=0; j=0; i--) + { + for(int j=txsz-1; j>=0; j--) + { + tileToDraw=tile+(i*TILES_PER_ROW)+j; + + if(tileToDraw%TILES_PER_ROW=-10) ++t; + + if(clk>=-5) ++t; + } + else + { + if(clk>=-12) ++t; + + if(clk>=-6) ++t; + } + + overtile16(dest,t,sx,sy,cs2,0); + } + else + { + sprite w((fix)sx,(fix)sy,wpnsbuf[extend].tile,wpnsbuf[extend].csets&15,0,0,0); + w.xofs = xofs; + w.yofs = yofs; + w.zofs = zofs; + w.txsz = txsz; + w.tysz = tysz; + w.extend = 3; + + if(BSZ) + { + if(clk>=-10) + { + if(tile/TILES_PER_ROW==(tile+txsz)/TILES_PER_ROW) + w.tile+=txsz; + else + w.tile+=txsz+(tysz-1)*TILES_PER_ROW; + } + + if(clk>=-5) + { + if(tile/TILES_PER_ROW==(tile+txsz)/TILES_PER_ROW) + w.tile+=txsz; + else + w.tile+=txsz+(tysz-1)*TILES_PER_ROW; + } + } + else + { + if(clk>=-12) + { + if(tile/TILES_PER_ROW==(tile+txsz)/TILES_PER_ROW) + w.tile+=txsz; + else + w.tile+=txsz+(tysz-1)*TILES_PER_ROW; + } + + if(clk>=-6) + { + if(tile/TILES_PER_ROW==(tile+txsz)/TILES_PER_ROW) + w.tile+=txsz; + else + w.tile+=txsz+(tysz-1)*TILES_PER_ROW; + } + } + + w.draw(dest); + } + } + + if(show_hitboxes && !is_zquest()) + rect(dest,x+hxofs,y+playing_field_offset+hyofs-(z+zofs),x+hxofs+hxsz-1,(y+playing_field_offset+hyofs+hysz-(z+zofs))-1,vc((id+16)%255)); +} + +void sprite::draw8(BITMAP* dest) +{ + int sx = real_x(x+xofs); + int sy = real_y(y+yofs)-real_z(z+zofs); + + if(id<0) + return; + + if(clk>=0) + { + switch(drawstyle) + { + case 0: //normal + overtile8(dest,tile,sx,sy,cs,flip); + break; + + case 1: //phantom + overtiletranslucent8(dest,tile,sx,sy,cs,flip,128); + break; + } + } +} + +void sprite::drawcloaked(BITMAP* dest) +{ + int sx = real_x(x+xofs); + int sy = real_y(y+yofs)-real_z(z+zofs); + + if(id<0) + return; + + if(clk>=0) + { + overtilecloaked16(dest,tile,sx,sy,flip); + } + else + { + int t = wpnsbuf[iwSpawn].tile; + int cs2 = wpnsbuf[iwSpawn].csets&15; + + if(BSZ) + { + if(clk>=-10) ++t; + + if(clk>=-5) ++t; + } + else + { + if(clk>=-12) ++t; + + if(clk>=-6) ++t; + } + + overtile16(dest,t,x,sy,cs2,0); + } + + if(get_debug() && key[KEY_O]) + rectfill(dest,x+hxofs,sy+hyofs,x+hxofs+hxsz-1,sy+hyofs+hysz-1,vc(id)); +} + +void sprite::drawshadow(BITMAP* dest,bool translucent) +{ + if(extend == 4 || shadowtile==0 || id<0) + { + return; + } + + int shadowcs = wpnsbuf[iwShadow].csets & 0xFFFF; + int shadowflip = wpnsbuf[iwShadow].misc & 0xFF; + + int sx = real_x(x+xofs)+(txsz-1)*8; + int sy = real_y(y+yofs+(tysz-1)*16); + + if(clk>=0) + { + if(translucent) + { + overtiletranslucent16(dest,shadowtile,sx,sy,shadowcs,shadowflip,128); + } + else + { + overtile16(dest,shadowtile,sx,sy,shadowcs,shadowflip); + } + } +} + +asIScriptObject* sprite::getScriptObject() +{ + return scriptData->getObject(); +} + +void sprite::scriptDraw() +{ + sprite::draw(scriptDrawingTarget); +} + +void sprite::scriptDrawCloaked() +{ + sprite::drawcloaked(scriptDrawingTarget); +} + +/***************************************************************************/ + +/**********************************/ +/********** Sprite List ***********/ +/**********************************/ + +#define SLMAX 255 + +//class enemy; + +sprite_list::sprite_list() : count(0) {} +void sprite_list::clear() +{ + while(count>0) del(0); +} + +sprite *sprite_list::spr(int index) +{ + if(index<0 || index>=count) + return NULL; + + return sprites[index]; +} + +bool sprite_list::swap(int a,int b) +{ + if(a<0 || a>=count || b<0 || b>=count) + return false; + + sprite* c=sprites[a]; + sprites[a] = sprites[b]; + sprites[b] = c; + containedUIDs[sprites[a]->getUID()] = a; + containedUIDs[sprites[b]->getUID()] = b; +// checkConsistency(); + return true; +} + +bool sprite_list::add(sprite *s) +{ + if(count>=SLMAX) + { + delete s; + return false; + } + + containedUIDs[s->getUID()] = count; + sprites[count++]=s; + //checkConsistency(); + return true; +} + +bool sprite_list::addAtFront(sprite *s) +{ + if(count>=SLMAX) + { + delete s; + return false; + } + + for(int i=count-1; i>=0; i--) + { + containedUIDs[sprites[i]->getUID()]=i+1; + sprites[i+1]=sprites[i]; + } + + containedUIDs[s->getUID()]=0; + sprites[0]=s; + count++; + return true; +} + +bool sprite_list::remove(sprite *s) +// removes pointer from list but doesn't delete it +{ + map::iterator it = containedUIDs.find(s->getUID()); + + if(it != containedUIDs.end()) + containedUIDs.erase(it); + + int j=0; + + for(; jgetUID()] = i; + } + + --count; + //checkConsistency(); + return true; +} + +fix sprite_list::getX(int j) +{ + if((j>=count)||(j<0)) + { + return (fix)1000000; + } + + return sprites[j]->x; +} + +fix sprite_list::getY(int j) +{ + if((j>=count)||(j<0)) + { + return (fix)1000000; + } + + return sprites[j]->y; +} + +int sprite_list::getID(int j) +{ + if((j>=count)||(j<0)) + { + return -1; + } + + return sprites[j]->id; +} + +int sprite_list::getMisc(int j) +{ + if((j>=count)||(j<0)) + { + return -1; + } + + return sprites[j]->misc; +} + +bool sprite_list::del(int j) +{ + if(j<0||j>=count) + return false; + + map::iterator it = containedUIDs.find(sprites[j]->getUID()); + + if(it != containedUIDs.end()) + containedUIDs.erase(it); + + delete sprites[j]; + + for(int i=j; igetUID()] = i; + } + + --count; + //checkConsistency(); + return true; +} + +void sprite_list::draw(BITMAP* dest,bool lowfirst) +{ + switch(lowfirst) + { + case true: + for(int i=0; idraw(dest); + } + + break; + + case false: + for(int i=count-1; i>=0; i--) + { + sprites[i]->draw(dest); + } + + break; + } +} + +void sprite_list::drawshadow(BITMAP* dest,bool translucent, bool lowfirst) +{ + switch(lowfirst) + { + case true: + for(int i=0; idrawshadow(dest,translucent); + + break; + + case false: + for(int i=count-1; i>=0; i--) + sprites[i]->drawshadow(dest,translucent); + + break; + } +} + +void sprite_list::draw2(BITMAP* dest,bool lowfirst) +{ + switch(lowfirst) + { + case true: + for(int i=0; idraw2(dest); + + break; + + case false: + for(int i=count-1; i>=0; i--) + sprites[i]->draw2(dest); + + break; + } +} + +void sprite_list::drawcloaked2(BITMAP* dest,bool lowfirst) +{ + switch(lowfirst) + { + case true: + for(int i=0; idrawcloaked2(dest); + + break; + + case false: + + for(int i=count-1; i>=0; i--) + sprites[i]->drawcloaked2(dest); + + break; + } +} + +void sprite_list::animate() +{ + int i=0; + + while(iisMarkedForDeletion()) + { + del(i); + continue; + } + + if(!(freeze_guys && sprites[i]->canfreeze)) + { + if(sprites[i]->animate(i)) + { + del(i); + --i; + } + } + + ++i; + } +} + +void sprite_list::check_conveyor() +{ + int i=0; + + while(icheck_conveyor(); + ++i; + } +} + +int sprite_list::Count() +{ + return count; +} + +int sprite_list::hit(sprite *s) +{ + for(int i=0; ihit(s)) + return i; + + return -1; +} + +int sprite_list::hit(int x,int y,int z, int xsize, int ysize, int zsize) +{ + for(int i=0; ihit(x,y,z,xsize,ysize,zsize)) + return i; + + return -1; +} + +// returns the number of sprites with matching id +int sprite_list::idCount(int id, int mask) +{ + int c=0; + + for(int i=0; iid)&mask) == (id&mask)) + { + ++c; + } + } + + return c; +} + +// returns index of first sprite with matching id, -1 if none found +int sprite_list::idFirst(int id, int mask) +{ + for(int i=0; iid)&mask) == (id&mask)) + { + return i; + } + } + + return -1; +} + +// returns index of last sprite with matching id, -1 if none found +int sprite_list::idLast(int id, int mask) +{ + for(int i=count-1; i>=0; i--) + { + if(((sprites[i]->id)&mask) == (id&mask)) + { + return i; + } + } + + return -1; +} + +// returns the number of sprites with matching id +int sprite_list::idCount(int id) +{ + return idCount(id,0xFFFF); +} + +// returns index of first sprite with matching id, -1 if none found +int sprite_list::idFirst(int id) +{ + return idFirst(id,0xFFFF); +} + +// returns index of last sprite with matching id, -1 if none found +int sprite_list::idLast(int id) +{ + return idLast(id,0xFFFF); +} + +sprite * sprite_list::getByUID(long uid) +{ + map::iterator it = containedUIDs.find(uid); + + if(it != containedUIDs.end()) + return spr(it->second); + + return NULL; +} + +void sprite_list::checkConsistency() +{ + assert((int)containedUIDs.size() == count); + + for(int i=0; igetUID())); +} + +/**********************************/ +/********** Moving Block **********/ +/**********************************/ + +movingblock::movingblock() : sprite() +{ + id=1; +} + +void movingblock::draw(BITMAP *dest) +{ + if(clk) + { + // sprite::draw(dest); + overcombo(dest,real_x(x+xofs),real_y(y+yofs),bcombo ,cs); + } +} + +/*** end of sprite.cc ***/ + diff --git a/src/sprite.h b/src/sprite.h new file mode 100644 index 0000000000..d199541153 --- /dev/null +++ b/src/sprite.h @@ -0,0 +1,214 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- + +#ifndef _SPRITE_H_ +#define _SPRITE_H_ + +#include "zc_alleg.h" +#include "zdefs.h" +#include +#include + +class EntityScriptData; +class asIScriptObject; + +using std::map; +// this code needs some patching for use in zquest.cc + +extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; +extern bool freeze_guys; +extern int fadeclk; +extern int frame; +extern bool BSZ; +extern int conveyclk; + +/**********************************/ +/******* Sprite Base Class ********/ +/**********************************/ + +template class EntityPtr; +class EntityRef; + +class sprite +{ +private: + static long getNextUID(); + //unique sprite ID + //given upon construction + long uid; + +public: + long getUID() + { + return uid; + } + fix x,y,z,fall; + int tile,shadowtile,cs,flip,c_clk,clk,misc; + + fix xofs,yofs,zofs; + // no hzofs - it's always equal to zofs. + int hxofs,hyofs,hxsz,hysz,hzsz; + int txsz,tysz; + /* + * Explanation of hzsz: + * Hzsz is how "tall" a sprite is. + * To jump over a sprite, you must be higher than its z+hzsz. + * Enemies have hzsz of 0 so that Link can jump over them (see LA.) + */ + int id,dir; + bool angular,canfreeze; + double angle; + int lasthit, lasthitclk; + int drawstyle; //0=normal, 1=translucent, 2=cloaked + int extend; + // Scripting additions + long miscellaneous[16]; + byte scriptcoldet; + + sprite(); + sprite(sprite const & other); + sprite(fix X,fix Y,int T,int CS,int F,int Clk,int Yofs); + virtual ~sprite(); + virtual void draw(BITMAP* dest); // main layer + virtual void draw8(BITMAP* dest); // main layer + virtual void drawcloaked(BITMAP* dest); // main layer + virtual void drawshadow(BITMAP* dest, bool translucent);// main layer + virtual void draw2(BITMAP* dest); // top layer for special needs + virtual void drawcloaked2(BITMAP* dest); // top layer for special needs + virtual bool animate(int index); + virtual void check_conveyor(); + int real_x(fix fx); + int real_y(fix fy); + int real_ground_y(fix fy); + int real_z(fix fz); + virtual bool hit(sprite *s); + virtual bool hit(int tx,int ty,int tz,int txsz,int tysz,int tzsz); + + + virtual int hitdir(int tx,int ty,int txsz,int tysz,int dir); + virtual void move(fix dx,fix dy); + virtual void move(fix s); + + inline fix getX() const { return x; } + inline fix getY() const { return y; } + inline fix getZ() const { return z; } + + inline void setX(fix newX) { x=newX; } + inline void setY(fix newY) { y=newY; } + inline void setZ(fix newZ) { z=newZ; } + + inline int getDir() const { return dir; } + inline void setDir(int newDir) { dir=(newDir<0) ? 0 : (newDir>7) ? 7 : newDir; } + + inline void markForDeletion() { toBeDeleted=true; } + inline bool isMarkedForDeletion() const { return toBeDeleted; } + + inline void setScriptData(EntityScriptData* esd) { scriptData=esd; } + asIScriptObject* getScriptObject(); + +protected: + EntityScriptData* scriptData; + +private: + bool toBeDeleted; + EntityRef* ref; + + void scriptDraw(); // main layer + void scriptDrawCloaked(); // main layer + + template friend class EntityPtr; + friend void registerSprite(); +}; + + +/***************************************************************************/ + +/**********************************/ +/********** Sprite List ***********/ +/**********************************/ + +#define SLMAX 255 + +class sprite_list +{ + sprite *sprites[SLMAX]; + int count; + map containedUIDs; + +public: + sprite_list(); + + sprite *getByUID(long uid); + void clear(); + sprite *spr(int index); + bool swap(int a,int b); + bool add(sprite *s); + bool addAtFront(sprite *s); + // removes pointer from list but doesn't delete it + bool remove(sprite *s); + fix getX(int j); + fix getY(int j); + int getID(int j); + int getMisc(int j); + bool del(int j); + void draw(BITMAP* dest,bool lowfirst); + void drawshadow(BITMAP* dest,bool translucent, bool lowfirst); + void draw2(BITMAP* dest,bool lowfirst); + void drawcloaked2(BITMAP* dest,bool lowfirst); + void animate(); + void check_conveyor(); + int Count(); + int hit(sprite *s); + int hit(int x,int y,int z,int xsize, int ysize, int zsize); + // returns the number of sprites with matching id + int idCount(int id, int mask); + // returns index of first sprite with matching id, -1 if none found + int idFirst(int id, int mask); + // returns index of last sprite with matching id, -1 if none found + int idLast(int id, int mask); + // returns the number of sprites with matching id + int idCount(int id); + // returns index of first sprite with matching id, -1 if none found + int idFirst(int id); + // returns index of last sprite with matching id, -1 if none found + int idLast(int id); + +private: + + void checkConsistency(); //for debugging +}; + +/**********************************/ +/********** Moving Block **********/ +/**********************************/ + +class movingblock : public sprite +{ +public: + int bcombo; + int oldflag; + int oldcset; + int endx, endy; + bool trigger; + byte undercset; + + movingblock(); + void push(fix bx,fix by,int d,int f); + virtual bool animate(int index); + virtual void draw(BITMAP *dest); +}; +#endif +/*** end of sprite.cc ***/ + diff --git a/src/subscr.cpp b/src/subscr.cpp new file mode 100644 index 0000000000..43c00b0d87 --- /dev/null +++ b/src/subscr.cpp @@ -0,0 +1,5364 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// subscr.cc +// +// Subscreen code for zelda.cc +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + + +#include "precompiled.h" //always first + +#include "subscr.h" +#include "zelda.h" +#include "zc_sys.h" +#include "tiles.h" +#include "zsys.h" +#include "guys.h" +#include "link.h" +#include "gamedata.h" +#include "items.h" +#include +#include + +bool show_subscreen_dmap_dots=true; +bool show_subscreen_numbers=true; +bool show_subscreen_items=true; +bool show_subscreen_life=true; +bool new_sel=false; + +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations; +extern LinkClass Link; + +subscreen_group *current_subscreen_active; +subscreen_group *current_subscreen_passive; + +subscreen_group custom_subscreen[MAXCUSTOMSUBSCREENS]; + +static const int notscrolling = sspUP | sspDOWN; +static const int pos = notscrolling | sspSCROLLING; + +subscreen_object z3_active_a[80]= +{ + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 0, 19, 12, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 96, 19, 9, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 0, 10, 6, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 48, 10, 7, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 104, 10, 8, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 0, 19, 12, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 96, 19, 9, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 0, 10, 6, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 48, 10, 7, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 104, 10, 8, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 176, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_sword, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 224, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 200, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 28, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 124, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 28, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 124, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_quiver, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_bowandarrow, 1, 0, 10, 5, 14, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 44, 26, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 1, 11, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 2, 12, 7, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 3, 13, 8, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 116, 26, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 4, 14, 9, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 5, 0, 10, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 6, 1, 11, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 68, 50, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 7, 2, 12, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 8, 3, 13, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 9, 4, 14, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 10, 5, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 6, 1, 10, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 12, 7, 2, 11, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 13, 8, 3, 12, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 14, 9, 4, 13, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 177, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 181, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 185, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 189, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 193, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 197, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 201, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 205, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 209, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 213, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 217, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 221, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 225, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 229, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 233, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 237, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTEDITEMNAME, pos, 173, 24, 70, 16, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfPROP, sstaCENTER, sstsSHADOWED, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 24, 1, 16, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 24, 1, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"ITEM" }, + { ssoTEXT, pos, 17, 105, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"INVENTORY" }, + { ssoTEXT, pos, 177, 57, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"TRIFORCE" }, + { ssoTEXT, pos, 177, 113, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"EQUIPMENT" }, + { ssoTRIFORCE, pos, 192, 64, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 64, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 176, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 224, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 192, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 2, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 192, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 3, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTILEBLOCK, pos, 16, 8, 1, 1, 1, 0, 0, 0, 0, 0, 28201, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } +}; +subscreen_object z3_active_ab[82]= +{ + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 0, 19, 12, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 96, 19, 9, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 0, 10, 6, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 48, 10, 7, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 104, 10, 8, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 0, 19, 12, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 8, 96, 19, 9, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 0, 10, 6, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 48, 10, 7, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 168, 104, 10, 8, 8, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 176, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_sword, 1, 15, 14, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 200, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 224, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 200, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 28, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 124, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 28, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 124, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_quiver, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_bowandarrow, 1, 0, 10, 5, 15, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 44, 26, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 1, 11, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 2, 12, 7, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 3, 13, 8, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 116, 26, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 16, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 4, 14, 9, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 5, 0, 10, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 6, 1, 11, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 68, 50, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 0, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 7, 2, 12, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 8, 3, 13, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 40, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 9, 4, 14, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 10, 5, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 6, 1, 10, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 12, 7, 2, 11, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 13, 8, 3, 12, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 128, 64, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 14, 9, 4, 13, 15, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 177, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 181, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 185, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 189, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 193, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 197, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 201, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 205, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 209, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 213, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 217, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 221, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 225, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 229, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 233, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 237, 139, 2, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 200, 8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 212, 18, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTEDITEMNAME, pos, 173, 24, 70, 16, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfPROP, sstaCENTER, sstsSHADOWED, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 24, 1, 16, 6, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 24, 1, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"ITEM" }, + { ssoTILEBLOCK, pos, 16, 73, 1, 1, 1, 0, 0, 0, 0, 0, 28201, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 17, 105, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"INVENTORY" }, + { ssoTEXT, pos, 177, 57, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"TRIFORCE" }, + { ssoTEXT, pos, 177, 113, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfZ3SMALL, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"EQUIPMENT" }, + { ssoTRIFORCE, pos, 192, 64, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 64, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 176, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 224, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 192, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 2, 1, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 192, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 1, 1, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 3, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTRIFORCE, pos, 208, 80, 1, 1, ssctMISC, sscsTRIFORCECSET, 0, 0, 0, 0, 0, 0, 1, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTILEBLOCK, pos, 16, 8, 1, 1, 1, 0, 0, 0, 0, 0, 28200, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } +}; +subscreen_object z3_passive_a[66]= +{ + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 74, 6, 0, 0, 5, 0, 0, 0, 0, 0, 101069, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 101, 6, 0, 0, 0, 0, 0, 0, 0, 0, 101369, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 126, 7, 0, 0, 1, 0, 0, 0, 0, 0, 101683, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 6, 0, 0, 1, 0, 0, 0, 0, 0, 101212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 8, 8, 8, 5, 5, 5, 0, 0, 0, 9, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 12, 8, 8, 5, 5, 5, 0, 0, 0, 8, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 16, 8, 8, 5, 5, 5, 0, 0, 0, 7, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 20, 8, 8, 5, 5, 5, 0, 0, 0, 6, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 24, 8, 8, 5, 5, 5, 0, 0, 0, 5, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 28, 8, 8, 5, 5, 5, 0, 0, 0, 4, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 32, 8, 8, 5, 5, 5, 0, 0, 0, 3, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 36, 8, 8, 5, 5, 5, 0, 0, 0, 2, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 40, 8, 8, 5, 5, 5, 0, 0, 0, 1, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 44, 8, 8, 5, 5, 5, 5, 0, 0, 0, 100322, 100260, 100322, 100322, 1, 0, 0, 2, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 8, 8, 8, 5, 5, 5, 0, 0, 0, 9, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 12, 8, 8, 5, 5, 5, 0, 0, 0, 8, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 16, 8, 8, 5, 5, 5, 0, 0, 0, 7, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 20, 8, 8, 5, 5, 5, 0, 0, 0, 6, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 24, 8, 8, 5, 5, 5, 0, 0, 0, 5, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 28, 8, 8, 5, 5, 5, 0, 0, 0, 4, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 32, 8, 8, 5, 5, 5, 0, 0, 0, 3, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 36, 8, 8, 5, 5, 5, 0, 0, 0, 2, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 40, 8, 8, 5, 5, 5, 0, 0, 0, 1, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 44, 8, 8, 5, 5, 5, 0, 0, 0, 0, 100323, 100260, 100262, 100263, 1, 0, 0, 2, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 44, 8, 8, 5, 5, 5, 5, 0, 0, 0, 100402, 100260, 100322, 100322, 1, 0, 0, 1, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 44, 8, 8, 5, 5, 5, 0, 0, 0, 0, 100403, 100260, 100262, 100263, 1, 0, 0, 1, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 32, 4, 4, 4, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 40, 12, 16, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 22, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 22, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 22, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 200, 6, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"LIFE" }, + { ssoRECT, pos, 178, 8, 12, 2, 0, 15, 0, 15, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 179, 8, 10, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 210, 8, 12, 2, 0, 15, 0, 15, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 211, 8, 10, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 15, 8, 8, 1, 1, 1, 1, 0, 0, 1, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 15, 8, 8, 1, 1, 1, 1, 0, 0, 2, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 15, 8, 8, 1, 1, 1, 1, 0, 0, 3, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 15, 8, 8, 1, 1, 1, 1, 0, 0, 4, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 15, 8, 8, 1, 1, 1, 1, 0, 0, 5, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 15, 8, 8, 1, 1, 1, 1, 0, 0, 6, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 15, 8, 8, 1, 1, 1, 1, 0, 0, 7, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 15, 8, 8, 1, 1, 1, 1, 0, 0, 8, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 23, 8, 8, 1, 1, 1, 1, 0, 0, 9, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 23, 8, 8, 1, 1, 1, 1, 0, 0, 10, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 23, 8, 8, 1, 1, 1, 1, 0, 0, 11, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 23, 8, 8, 1, 1, 1, 1, 0, 0, 12, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 23, 8, 8, 1, 1, 1, 1, 0, 0, 13, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 23, 8, 8, 1, 1, 1, 1, 0, 0, 14, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 23, 8, 8, 1, 1, 1, 1, 0, 0, 15, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 23, 8, 8, 1, 1, 1, 1, 0, 0, 16, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 31, 8, 8, 1, 1, 1, 1, 0, 0, 17, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 31, 8, 8, 1, 1, 1, 1, 0, 0, 18, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 31, 8, 8, 1, 1, 1, 1, 0, 0, 19, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 31, 8, 8, 1, 1, 1, 1, 0, 0, 20, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 31, 8, 8, 1, 1, 1, 1, 0, 0, 21, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 31, 8, 8, 1, 1, 1, 1, 0, 0, 22, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 31, 8, 8, 1, 1, 1, 1, 0, 0, 23, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 31, 8, 8, 1, 1, 1, 1, 0, 0, 24, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 77, 15, 25, 9, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 3, '~', 1, sscRUPEES, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 105, 15, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 2, '~', 1, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 129, 15, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 2, '~', 1, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 148, 15, 9, 9, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 1, '~', 1, sscGENKEYMAGIC, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } +}; +subscreen_object z3_passive_ab[75]= +{ + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 80, 6, 0, 0, 5, 0, 0, 0, 0, 0, 101069, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 107, 6, 0, 0, 0, 0, 0, 0, 0, 0, 101369, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 132, 7, 0, 0, 1, 0, 0, 0, 0, 0, 101683, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 150, 6, 0, 0, 1, 0, 0, 0, 0, 0, 101212, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 8, 8, 8, 5, 5, 5, 0, 0, 0, 9, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 12, 8, 8, 5, 5, 5, 0, 0, 0, 8, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 16, 8, 8, 5, 5, 5, 0, 0, 0, 7, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 20, 8, 8, 5, 5, 5, 0, 0, 0, 6, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 24, 8, 8, 5, 5, 5, 0, 0, 0, 5, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 28, 8, 8, 5, 5, 5, 0, 0, 0, 4, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 32, 8, 8, 5, 5, 5, 0, 0, 0, 3, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 36, 8, 8, 5, 5, 5, 0, 0, 0, 2, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 40, 8, 8, 5, 5, 5, 0, 0, 0, 1, 100320, 100640, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 44, 8, 8, 5, 5, 5, 5, 0, 0, 0, 100322, 100260, 100322, 100322, 1, 0, 0, 2, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 8, 8, 8, 5, 5, 5, 0, 0, 0, 9, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 12, 8, 8, 5, 5, 5, 0, 0, 0, 8, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 16, 8, 8, 5, 5, 5, 0, 0, 0, 7, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 20, 8, 8, 5, 5, 5, 0, 0, 0, 6, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 24, 8, 8, 5, 5, 5, 0, 0, 0, 5, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 28, 8, 8, 5, 5, 5, 0, 0, 0, 4, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 32, 8, 8, 5, 5, 5, 0, 0, 0, 3, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 36, 8, 8, 5, 5, 5, 0, 0, 0, 2, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 40, 8, 8, 5, 5, 5, 0, 0, 0, 1, 100480, 100720, 100262, 100263, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 44, 8, 8, 5, 5, 5, 0, 0, 0, 0, 100323, 100260, 100262, 100263, 1, 0, 0, 2, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 16, 44, 8, 8, 5, 5, 5, 5, 0, 0, 0, 100402, 100260, 100322, 100322, 1, 0, 0, 1, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICGAUGE, pos, 24, 44, 8, 8, 5, 5, 5, 0, 0, 0, 0, 100403, 100260, 100262, 100263, 1, 0, 0, 1, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 32, 26, 4, 4, 8, 0, 0, 0, 0, 0, 20040, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 32, 0, 4, 4, 7, 0, 0, 0, 0, 0, 20040, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 40, 8, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 18, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 18, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 18, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 40, 34, 16, 16, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 44, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 44, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 52, 44, 9, 7, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfZ3SMALL, sstaCENTER, sstsOUTLINEDPLUS, 2, '~', 2, sscSBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 200, 6, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"LIFE" }, + { ssoRECT, pos, 178, 8, 12, 2, 0, 15, 0, 15, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 179, 8, 10, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 210, 8, 12, 2, 0, 15, 0, 15, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, pos, 211, 8, 10, 1, ssctMISC, ssctTEXT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 15, 8, 8, 1, 1, 1, 1, 0, 0, 1, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 15, 8, 8, 1, 1, 1, 1, 0, 0, 2, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 15, 8, 8, 1, 1, 1, 1, 0, 0, 3, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 15, 8, 8, 1, 1, 1, 1, 0, 0, 4, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 15, 8, 8, 1, 1, 1, 1, 0, 0, 5, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 15, 8, 8, 1, 1, 1, 1, 0, 0, 6, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 15, 8, 8, 1, 1, 1, 1, 0, 0, 7, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 15, 8, 8, 1, 1, 1, 1, 0, 0, 8, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 23, 8, 8, 1, 1, 1, 1, 0, 0, 9, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 23, 8, 8, 1, 1, 1, 1, 0, 0, 10, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 23, 8, 8, 1, 1, 1, 1, 0, 0, 11, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 23, 8, 8, 1, 1, 1, 1, 0, 0, 12, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 23, 8, 8, 1, 1, 1, 1, 0, 0, 13, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 23, 8, 8, 1, 1, 1, 1, 0, 0, 14, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 23, 8, 8, 1, 1, 1, 1, 0, 0, 15, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 23, 8, 8, 1, 1, 1, 1, 0, 0, 16, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 169, 31, 8, 8, 1, 1, 1, 1, 0, 0, 17, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 177, 31, 8, 8, 1, 1, 1, 1, 0, 0, 18, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 185, 31, 8, 8, 1, 1, 1, 1, 0, 0, 19, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 193, 31, 8, 8, 1, 1, 1, 1, 0, 0, 20, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 201, 31, 8, 8, 1, 1, 1, 1, 0, 0, 21, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 209, 31, 8, 8, 1, 1, 1, 1, 0, 0, 22, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 217, 31, 8, 8, 1, 1, 1, 1, 0, 0, 23, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoLIFEGAUGE, pos, 225, 31, 8, 8, 1, 1, 1, 1, 0, 0, 24, 100240, 100240, 100261, 100261, 1, 0, 0, 0, 3, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 83, 15, 25, 9, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 3, '~', 1, sscRUPEES, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 111, 15, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 2, '~', 1, sscBOMBS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 135, 15, 0, 0, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 2, '~', 1, sscARROWS, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTER, pos, 154, 15, 9, 9, ssctMISC, ssctTEXT, 0, 15, ssctSYSTEM, -1, ssfSS4, sstaCENTER, sstsSHADOWED, 1, '~', 1, sscGENKEYMAGIC, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 59, 11, 4, 10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, pos, 59, 37, 4, 10, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 61, 13, 8, 8, 0, 1, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"A" }, + { ssoTEXT, pos, 61, 38, 8, 8, 0, 1, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *)"B" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } +}; + +subscreen_object default_subscreen_active[ssdtMAX][2][66]=//[zinit.subscreen][dungeon] +{ + { + //ssdtOLD + { + //ssdtOLD, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 68, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 56, 34, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 64, 66, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "USE B BUTTON" }, + { ssoTEXT, pos, 64, 74, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "FOR THIS" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 128, 154, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 80, 98, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 34, 13, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, notscrolling, 64, 42, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 148, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 160, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 192, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 204, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 172, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 180, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 152, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 200, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 152, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 200, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtOLD, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 68, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 56, 34, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 64, 66, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "USE B BUTTON" }, + { ssoTEXT, pos, 64, 74, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "FOR THIS" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 96, 82, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 52, 90, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "MAP" }, + { ssoTEXT, pos, 52, 130, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "COMPASS" }, + { ssoCURRENTITEM, notscrolling, 44, 106, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 44, 146, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 34, 13, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, notscrolling, 64, 42, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 148, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 160, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 192, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 204, 18, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 172, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 180, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 152, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 200, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 128, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 152, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 176, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, notscrolling, 200, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtNEWSUBSCR + { + //ssdtNEWSUBSCR, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 68, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 12, 34, 14, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 128, 154, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 80, 98, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 136, 18, 13, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 20, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 36, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 20, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 36, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 188, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 196, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 11, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtNEWSUBSCR, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 68, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 12, 34, 14, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 96, 82, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 52, 90, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "MAP" }, + { ssoTEXT, pos, 52, 130, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "COMPASS" }, + { ssoCURRENTITEM, pos, 44, 106, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 44, 146, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 136, 18, 13, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 20, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 36, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 20, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 36, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 52, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 100, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 188, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 196, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 11, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 144, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 192, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 216, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtREV2 + { + //ssdtREV2, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 62, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 6, 34, 14, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 128, 154, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 80, 98, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 118, 18, 16, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 30, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 46, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 78, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 94, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 30, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 46, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 78, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 94, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 170, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 178, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 14, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 12, 14, 13, 3, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 12, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 13, 12, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 13, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 14, 13, 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtREV2, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 62, 18, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 6, 34, 14, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 16, 98, 9, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 96, 82, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 106, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 44, 106, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 64, 106, 0, 0, 0, 0, 0, 0, 0, 0, itype_bosskey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 118, 18, 16, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 30, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 46, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 78, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 94, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 30, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 46, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 78, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 94, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 170, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 178, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 14, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 26, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 12, 14, 13, 3, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 12, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 42, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 13, 12, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 126, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 13, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 150, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 174, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 198, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 222, 58, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 14, 13, 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDA + { + //ssdtBSZELDA, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 24, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 80, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 80, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 96, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 20, 40, 13, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 136, 48, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 136, 56, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 112, 14, 7, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 88, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 64, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 25, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 25, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 25, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 32, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 26, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDA, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 24, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 80, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 80, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 96, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 20, 40, 13, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 160, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 192, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 144, 88, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 176, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Compass" }, + { ssoTEXT, pos, 208, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Map" }, + { ssoCURRENTITEM, pos, 200, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 112, 14, 7, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 88, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 96, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 64, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 25, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 25, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 25, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 32, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 26, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDAMODIFIED + { + //ssdtBSZELDAMODIFIED, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 24, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 80, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 80, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 96, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 40, 15, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 136, 48, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 136, 56, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 112, 14, 7, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 88, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 25, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 25, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 25, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 32, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 26, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDAMODIFIED, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 24, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 24, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 80, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 80, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 96, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 40, 15, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 160, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 192, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 144, 88, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 176, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Compass" }, + { ssoTEXT, pos, 208, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Map" }, + { ssoCURRENTITEM, pos, 200, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 112, 14, 7, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 88, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 4, 4, 7, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 5, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 6, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 120, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 7, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 0, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 1, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 2, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 25, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 25, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 25, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 32, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 26, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDAENHANCED + { + //ssdtBSZELDAENHANCED, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 72, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 72, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 80, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 20, 15, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 136, 48, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 136, 56, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 104, 14, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 80, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 11, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 9, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 9, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 9, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 16, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 10, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDAENHANCED, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 72, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 72, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 80, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 20, 15, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 160, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 192, 40, 4, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 144, 88, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 176, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Compass" }, + { ssoTEXT, pos, 208, 72, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "Map" }, + { ssoCURRENTITEM, pos, 200, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 168, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 20, 104, 14, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 80, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 76, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 84, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 11, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 3, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 32, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 80, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 9, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 9, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 9, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 16, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 10, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDACOMPLETE + { + //ssdtBSZELDACOMPLETE, overworld + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 72, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 72, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 80, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 20, 15, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 136, 48, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "TRIFORCE" }, + { ssoTRIFRAME, pos, 136, 56, 0, 0, ssctMISC, ssctTRIFRAMECOLOR, ssctMISC, ssctCAPTION, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 4, 104, 16, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 80, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 58, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 14, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 12, 14, 13, 3, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 12, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 13, 12, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 13, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 14, 13, 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 9, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 9, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 9, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 16, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 10, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDACOMPLETE, dungeon + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoRECT, pos, 0, 0, 256, 168, ssctMISC, ssctSUBSCRBG, ssctMISC, ssctSUBSCRBG, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 0, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 8, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 88, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 96, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 104, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 112, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 120, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 128, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 136, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 144, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 9, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 152, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINITILE, pos, 248, 8, 0, 0, ssctMISC, sscsSSVINECSET, 0, 0, 0, 0, -1, ssmstSSVINETILE, 11, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 51, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "INVENTORY" }, + { sso2X2FRAME, pos, 28, 72, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 40, 72, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 56, 80, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B Button" }, + { ssoTEXT, pos, 56, 88, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfSS2, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "to use item" }, + { sso2X2FRAME, pos, 12, 20, 15, 6, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 152, 40, 10, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLARGEMAP, pos, 144, 88, 0, 0, ssctMISC, ssctBMAPFG, ssctMISC, ssctLINKDOT, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 160, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_map, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 184, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_compass, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 208, 48, 0, 0, 0, 0, 0, 0, 0, 0, itype_bosskey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 4, 104, 16, 8, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 32, 80, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_raft, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_book, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ring, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_ladder, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_magickey, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, itype_bracelet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 24, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_shield, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 40, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_wallet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 56, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_amulet, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 72, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_flippers, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 88, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_boots, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 104, 44, 0, 0, 0, 0, 0, 0, 0, 0, itype_heartpiece, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSELECTOR2, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 58, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 68, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bow, 1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_brang, 1, 0, 8, 4, 14, 1, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_bomb, 1, 1, 9, 5, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_arrow, 0, 2, 10, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_candle, 1, 3, 11, 7, 2, 12, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 112, 0, 0, 0, 0, 0, 0, 0, 0, itype_dinsfire, 1, 12, 14, 13, 3, 4, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_whistle, 1, 4, 0, 8, 12, 5, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_bait, 1, 5, 1, 9, 4, 6, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_letterpotion, 1, 6, 2, 10, 5, 7, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_wand, 1, 7, 3, 11, 6, 13, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 128, 0, 0, 0, 0, 0, 0, 0, 0, itype_faroreswind, 1, 13, 12, 14, 7, 8, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 14, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hookshot, 1, 8, 4, 0, 13, 9, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 38, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_sbomb, 1, 9, 5, 1, 8, 10, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 62, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_lens, 1, 10, 6, 2, 9, 11, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 86, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_hammer, 1, 11, 7, 3, 10, 14, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCURRENTITEM, pos, 110, 144, 0, 0, 0, 0, 0, 0, 0, 0, itype_nayruslove, 1, 14, 13, 12, 11, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspDOWN, 208, 9, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspDOWN, 160, 9, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 204, 9, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspDOWN, 160, 16, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspDOWN, 161, 10, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoSELECTOR1, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + } +}; +subscreen_object default_subscreen_passive[ssdtMAX][2][21]= //[zinit.subscreen][no magic] +{ + { + //ssdtOLD + { + //ssdtOLD, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, sspUP, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, sspUP, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 12, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 176, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtOLD, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, sspUP, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, sspUP, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 16, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtNEWSUBSCR + { + //ssdtNEWSUBSCR, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 12, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 176, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtNEWSUBSCR, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 16, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtREV2 + { + //ssdtREV2, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 12, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 176, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtREV2, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, 0, 0, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, 1, sstsNORMAL, 3, 'A', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 120, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 144, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 124, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 148, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 132, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 156, 16, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctMISC, ssctSUBSCRBG, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 208, 16, 0, 0, ssctMISC, ssctCAPTION, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaCENTER, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "-LIFE-" }, + { ssoLIFEMETER, pos, 176, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDA + { + //ssdtBSZELDA, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 220, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 188, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 188, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDA, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 216, 16, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 184, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDAMODIFIED + { + //ssdtBSZELDAMODIFIED, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 220, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 188, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 188, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDAMODIFIED, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 216, 16, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 184, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDAENHANCED + { + //ssdtBSZELDAENHANCED, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 220, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 188, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 188, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDAENHANCED, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 216, 16, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 184, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + } + }, + { + //ssdtBSZELDACOMPLETE + { + //ssdtBSZELDACOMPLETE, magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 220, 8, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 188, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMAGICMETER, pos, 188, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL } + }, + { + //ssdtBSZELDACOMPLETE, no magic + //object position x y w h color type 1 color 1 color type 2 color 2 color type 3 color 3 d1 d2 d3 d4 d5 d6 d7 d8 d9 d10 frames speed delay frame dp1 + { ssoCLEAR, pos, 0, 0, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAP, pos, 8, 8, 0, 0, ssctMISC, ssctLINKDOT, ssctMISC, ssctCOMPASSLT, ssctMISC, ssctCOMPASSDK, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoMINIMAPTITLE, pos, 48, 0, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS3, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoCOUNTERS, pos, 88, 16, 32, 32, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, 1, sstsSHADOWED, 4, '~', 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoSSTIME, pos, 240, 0, 0, 0, ssctMISC, ssctTEXT, 0, 0, ssctSYSTEM, -1, ssfZELDA, sstaRIGHT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 132, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { sso2X2FRAME, pos, 156, 16, 3, 4, ssctMISC, sscsBLUEFRAMECSET, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 136, 24, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBUTTONITEM, pos, 160, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 144, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWEDU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "B" }, + { ssoTEXT, pos, 168, 16, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsOUTLINED8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "A" }, + { ssoLINE, pos, 163, 15, 174, 1, ssctMISC, ssctSUBSCRBG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, pos, 216, 16, 0, 0, ssctMISC, ssctCAPTION, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaCENTER, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "- life -" }, + { ssoLIFEMETER, pos, 184, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoNONE, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoBSTIME, sspUP, 208, 48, 0, 0, ssctMISC, ssctTEXT, ssctMISC, ssctSUBSCRSHADOW, ssctSYSTEM, -1, ssfSS1, sstaLEFT, sstsSHADOWED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoRECT, sspUP, 160, 48, 44, 7, ssctMISC, ssctTEXT, ssctMISC, ssctTEXT, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 204, 48, 1, 8, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoLINE, sspUP, 160, 55, 45, 1, ssctMISC, ssctSUBSCRSHADOW, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + { ssoTEXT, sspUP, 161, 49, 0, 0, ssctMISC, ssctSUBSCRBG, 0, 0, ssctSYSTEM, -1, ssfZTIME, sstaLEFT, sstsNORMAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (void *) "ZELDA TIME" }, + { ssoNULL, pos, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL }, + } + } +}; + +void textout_styled_aligned_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int textstyle, int alignment, int color, int shadow, int bg) +{ + switch(alignment) + { + case sstaRIGHT: + switch(textstyle) + { + case sstsSHADOW: + textout_shadow_right_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWU: + textout_shadow_right_u_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINE8: + textout_shadow_right_o_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEPLUS: + textout_shadow_right_plus_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEX: + textout_shadow_right_x_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWED: + textout_shadowed_right_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsSHADOWEDU: + textout_shadowed_right_u_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINED8: + textout_shadowed_right_o_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDPLUS: + textout_shadowed_right_plus_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDX: + textout_shadowed_right_x_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsNORMAL: + default: + textout_right_ex(bmp, f, s, x, y, color, bg); + break; + } + + break; + + case sstaCENTER: + switch(textstyle) + { + case sstsSHADOW: + textout_shadow_centre_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWU: + textout_shadow_centre_u_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINE8: + textout_shadow_centre_o_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEPLUS: + textout_shadow_centre_plus_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEX: + textout_shadow_centre_x_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWED: + textout_shadowed_centre_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsSHADOWEDU: + textout_shadowed_centre_u_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINED8: + textout_shadowed_centre_o_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDPLUS: + textout_shadowed_centre_plus_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDX: + textout_shadowed_centre_x_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsNORMAL: + default: + textout_centre_ex(bmp, f, s, x, y, color, bg); + break; + } + + break; + + case sstaLEFT: + default: + switch(textstyle) + { + case sstsSHADOW: + textout_shadow_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWU: + textout_shadow_u_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINE8: + textout_shadow_o_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEPLUS: + textout_shadow_plus_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsOUTLINEX: + textout_shadow_x_ex(bmp, f, s, x, y, shadow, bg); + break; + + case sstsSHADOWED: + textout_shadowed_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsSHADOWEDU: + textout_shadowed_u_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINED8: + textout_shadowed_o_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDPLUS: + textout_shadowed_plus_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsOUTLINEDX: + textout_shadowed_x_ex(bmp, f, s, x, y, color, shadow, bg); + break; + + case sstsNORMAL: + default: + textout_ex(bmp, f, s, x, y, color, bg); + break; + } + + break; + } +} + +void textprintf_styled_aligned_ex(BITMAP *bmp, const FONT *f, int x, int y, int textstyle, int alignment, int color, int shadow, int bg, const char *format, ...) +{ + + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_styled_aligned_ex(bmp, f, buf, x, y, textstyle, alignment, color, shadow, bg); +} + + +void draw_textbox(BITMAP *dest, int x, int y, int w, int h, FONT *tempfont, char *thetext, bool wword, int tabsize, int alignment, int textstyle, int color, int shadowcolor, int backcolor) +{ + int y1 = y; + int x1; + int len; + char s[16]; + char text[16]; + char space[16]; + char *printed = text; + char *scanned = text; + char *oldscan = text; + char *ignore = NULL; + char *tmp, *ptmp; + int width; + int i = 0; + int noignore; + + usetc(s+usetc(s, '.'), 0); + usetc(text+usetc(text, ' '), 0); + usetc(space+usetc(space, ' '), 0); + + /* find the correct text */ + if(thetext != NULL) + { + printed = thetext; + scanned = thetext; + } + + /* loop over the entire string */ + for(;;) + { + width = 0; + + /* find the next break */ + while(ugetc(scanned)) + { + /* check for a forced break */ + if(ugetc(scanned) == '\n') + { + scanned += uwidth(scanned); + /* we are done parsing the line end */ + break; + } + + /* the next character length */ + usetc(s+usetc(s, ugetc(scanned)), 0); + len = text_length(tempfont, s); + + /* modify length if its a tab */ + if(ugetc(s) == '\t') + { + len = tabsize * text_length(tempfont, space); + } + + /* check for the end of a line by excess width of next char */ + if(width+len >= w) + { + /* we have reached end of line do we go back to find start */ + if(wword) + { + /* remember where we were */ + oldscan = scanned; + noignore = FALSE; + + /* go backwards looking for start of word */ + while(!uisspace(ugetc(scanned))) + { + /* don't wrap too far */ + if(scanned == printed) + { + /* the whole line is filled, so stop here */ + tmp = ptmp = scanned; + + while(ptmp != oldscan) + { + ptmp = tmp; + tmp += uwidth(tmp); + } + + scanned = ptmp; + noignore = TRUE; + break; + } + + /* look further backwards to wrap */ + tmp = ptmp = printed; + + while(tmp < scanned) + { + ptmp = tmp; + tmp += uwidth(tmp); + } + + scanned = ptmp; + } + + /* put the space at the end of the line */ + if(!noignore) + { + ignore = scanned; + scanned += uwidth(scanned); + } + else + { + ignore = NULL; + } + + /* check for endline at the convenient place */ + if(ugetc(scanned) == '\n') + { + scanned += uwidth(scanned); + } + } + + /* we are done parsing the line end */ + break; + } + + /* the character can be added */ + scanned += uwidth(scanned); + width += len; + } + + /* check if we are to print it */ + if((y1+text_height(tempfont) <= (y+h))) + { + int tempw=0; + char *tempprinted=printed; + + /* print up to the marked character */ + while(printed != scanned) + { + /* do special stuff for each charater */ + switch(ugetc(printed)) + { + case '\r': + case '\n': + /* don't print endlines in the text */ + break; + + /* possibly expand the tabs */ + case '\t': + for(i=0; iobjects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3,css->objects[i].d4); +void frame2x2(BITMAP *dest,miscQdata *misc,int x,int y,int tile,int cset,int w,int h,int /*flip*/,bool overlay,bool trans) +{ + /* + /- -- -- -\ + | | + | | + \_ __ __ _/ + + 0 1 4 5 + 2 3 6 7 + 80 81 84 85 + 82 83 86 87 + */ + if(tile==0) + { + tile=misc->colors.blueframe_tile; + } + + int t8 = tile<<2; + + if(overlay) + { + if(trans) + { + for(int dx=0; dx= (w>>1)) ? ((dx==w-1) ? t8+5 : t8+4) : ((dx==0) ? t8 : t8+1); + int bottom = (dx >= (w>>1)) ? ((dx==w-1) ? t8+87 : t8+86) : ((dx==0) ? t8+82 : t8+83); + + overtiletranslucent8(dest,top,(dx<<3)+x,y,cset,0,128); + overtiletranslucent8(dest,bottom,(dx<<3)+x,((h-1)<<3)+y,cset,0,128); + } + + for(int dy=1; dy= (h>>1)) ? t8+80 : t8+2; + int right = (dy >= (h>>1)) ? t8+85 : t8+7; + + overtiletranslucent8(dest,left,x,(dy<<3)+y,cset,0,128); + overtiletranslucent8(dest,right,((w-1)<<3)+x,(dy<<3)+y,cset,0,128); + + for(int dx=1; dx= (h>>1)) ? ((dx >= (w>>1)) ? t8+84 : t8+81) : ((dx >= (w>>1)) ? t8+6 : t8+3); + overtiletranslucent8(dest,fill,(dx<<3)+x,(dy<<3)+y,cset,0,128); + } + } + } + else + { + for(int dx=0; dx= (w>>1)) ? ((dx==w-1) ? t8+5 : t8+4) : ((dx==0) ? t8 : t8+1); + int bottom = (dx >= (w>>1)) ? ((dx==w-1) ? t8+87 : t8+86) : ((dx==0) ? t8+82 : t8+83); + + overtile8(dest,top,(dx<<3)+x,y,cset,0); + overtile8(dest,bottom,(dx<<3)+x,((h-1)<<3)+y,cset,0); + } + + for(int dy=1; dy= (h>>1)) ? t8+80 : t8+2; + int right = (dy >= (h>>1)) ? t8+85 : t8+7; + + overtile8(dest,left,x,(dy<<3)+y,cset,0); + overtile8(dest,right,((w-1)<<3)+x,(dy<<3)+y,cset,0); + + for(int dx=1; dx= (h>>1)) ? ((dx >= (w>>1)) ? t8+84 : t8+81) : ((dx >= (w>>1)) ? t8+6 : t8+3); + overtile8(dest,fill,(dx<<3)+x,(dy<<3)+y,cset,0); + } + } + } + } + else + { + if(trans) + { + for(int dx=0; dx= (w>>1)) ? ((dx==w-1) ? t8+5 : t8+4) : ((dx==0) ? t8 : t8+1); + int bottom = (dx >= (w>>1)) ? ((dx==w-1) ? t8+87 : t8+86) : ((dx==0) ? t8+82 : t8+83); + + puttiletranslucent8(dest,top,(dx<<3)+x,y,cset,0,128); + puttiletranslucent8(dest,bottom,(dx<<3)+x,((h-1)<<3)+y,cset,0,128); + } + + for(int dy=1; dy= (h>>1)) ? t8+80 : t8+2; + int right = (dy >= (h>>1)) ? t8+85 : t8+7; + + puttiletranslucent8(dest,left,x,(dy<<3)+y,cset,0,128); + puttiletranslucent8(dest,right,((w-1)<<3)+x,(dy<<3)+y,cset,0,128); + + for(int dx=1; dx= (h>>1)) ? ((dx >= (w>>1)) ? t8+84 : t8+81) : ((dx >= (w>>1)) ? t8+6 : t8+3); + puttiletranslucent8(dest,fill,(dx<<3)+x,(dy<<3)+y,cset,0,128); + } + } + } + else + { + for(int dx=0; dx= (w>>1)) ? ((dx==w-1) ? t8+5 : t8+4) : ((dx==0) ? t8 : t8+1); + int bottom = (dx >= (w>>1)) ? ((dx==w-1) ? t8+87 : t8+86) : ((dx==0) ? t8+82 : t8+83); + + oldputtile8(dest,top,(dx<<3)+x,y,cset,0); + oldputtile8(dest,bottom,(dx<<3)+x,((h-1)<<3)+y,cset,0); + } + + for(int dy=1; dy= (h>>1)) ? t8+80 : t8+2; + int right = (dy >= (h>>1)) ? t8+85 : t8+7; + + oldputtile8(dest,left,x,(dy<<3)+y,cset,0); + oldputtile8(dest,right,((w-1)<<3)+x,(dy<<3)+y,cset,0); + + for(int dx=1; dx= (h>>1)) ? ((dx >= (w>>1)) ? t8+84 : t8+81) : ((dx >= (w>>1)) ? t8+6 : t8+3); + oldputtile8(dest,fill,(dx<<3)+x,(dy<<3)+y,cset,0); + } + } + } + } +} + +void drawgrid(BITMAP *dest,int x,int y,int c1,int c2) +{ + int si=0; + + for(int y2=0; y2<=7; ++y2) + { + byte dl = DMaps[get_currdmap()].grid[si]; + + for(int x2=0; x2<=7; ++x2) + { + if(c2==-1) + { + if(dl&0x80) + rectfill(dest,(x2*8)+x,(y2*4)+y,(x2*8)+x+6,(y2*4)+y+2,c1); + } + else + { + rectfill(dest,(x2*8)+x,(y2*4)+y,(x2*8)+x+6,(y2*4)+y+2,c2); + + if(dl&0x80) + rectfill(dest,(x2*8)+x+2,(y2*4)+y,(x2*8)+x+4,(y2*4)+y+2,c1); + } + + dl<<=1; + } + + ++si; + } +} + +void draw_block(BITMAP *dest,int x,int y,int tile,int cset,int w,int h) +{ + for(int j=0; jcolors; + int type = (DMaps[get_currdmap()].type&dmfTYPE); + + if(showmap) + { + switch(type) + { + case dmOVERW: + case dmBSOVERW: + + if(DMaps[get_currdmap()].minimap_1_tile) + { + draw_block(dest,x,y,DMaps[get_currdmap()].minimap_1_tile,DMaps[get_currdmap()].minimap_1_cset,5,3); + } + else if(c.overworld_map_tile) + { + draw_block(dest,x,y,c.overworld_map_tile,c.overworld_map_cset,5,3); + } + else + { + rectfill(dest,x+8,y+8,x+71,y+39,c.overw_bg); + } + + if(!DMaps[get_currdmap()].minimap_1_tile && ((DMaps[get_currdmap()].type&dmfTYPE) == dmBSOVERW)) + { + drawgrid(dest,x+8,y+8,c.bs_goal,c.bs_dk); + } + + break; + + case dmDNGN: + case dmCAVE: + int maptile=has_item(itype_map, get_dlevel())?DMaps[get_currdmap()].minimap_2_tile:DMaps[get_currdmap()].minimap_1_tile; + int mapcset=has_item(itype_map, get_dlevel())?DMaps[get_currdmap()].minimap_2_cset:DMaps[get_currdmap()].minimap_1_cset; + + if(maptile) + { + draw_block(dest,x,y,maptile,mapcset,5,3); + } + else if(c.dungeon_map_tile) + { + draw_block(dest,x,y,c.dungeon_map_tile,c.dungeon_map_cset,5,3); + } + else + { + rectfill(dest,x+8,y+8,x+71,y+39,c.dngn_bg); + } + + if(!DMaps[get_currdmap()].minimap_2_tile && has_item(itype_map, get_dlevel())) + { + if((DMaps[get_currdmap()].flags&dmfMINIMAPCOLORFIX) != 0) + { + drawgrid(dest,x+8,y+8,c.cave_fg,-1); + } + else + { + drawgrid(dest,x+8,y+8,c.dngn_fg,-1); + } + } + + break; + } + } + + if(showcompass) + { + if(type==dmDNGN || type==dmCAVE) + { + if(show_subscreen_dmap_dots&&has_item(itype_compass, get_dlevel())) + { + int c2 = dccolor; + + if(!has_item(itype_triforcepiece, get_dlevel()) && (frame&16)) + c2 = lccolor; + + int cx = ((DMaps[get_currdmap()].compass&15)<<3)+x+10; + int cy = ((DMaps[get_currdmap()].compass&0xF0)>>2)+y+8; + putdot(dest,cx,cy,c2); + } + } + } + + if(showlink) + { + if(show_subscreen_dmap_dots && linkcolor != 255) + { + if(type==dmOVERW) + { + putdot(dest,((get_homescr()&15)<<2)+x+9,((get_homescr()&0xF0)>>2)+y+8,linkcolor); + } + else if(type==dmBSOVERW || ((type==dmDNGN || type==dmCAVE) && get_currscr()<128)) + { + putdot(dest,(((get_homescr()&15)-DMaps[get_currdmap()].xoff)<<3)+x+10,((get_homescr()&0xF0)>>2)+y+8,linkcolor); + } + } + } +} + + + +void lifemeter(BITMAP *dest,int x,int y,int tile,bool bs_style) +{ + if(!show_subscreen_life) + { + return; + } + + if(!bs_style) + { + y+=24; + } + + for(int i=0; i<(game != NULL ? zc_min(game->get_maxlife(),16*24) : 1); i+=HP_PER_HEART) + { + if(game != NULL) + { + if(get_bit(quest_rules,qr_QUARTERHEART)) + { + if(i+((HP_PER_HEART/4)*3)>=game->get_life()) tile=(wpnsbuf[iwQuarterHearts].tile*4)+2; + + if(i+(HP_PER_HEART/2)>=game->get_life()) tile=1; + + if(i+((HP_PER_HEART/4)*1)>=game->get_life()) tile=(wpnsbuf[iwQuarterHearts].tile*4)+3; + } + else if(i+(HP_PER_HEART/2)>=game->get_life()) tile=1; + + if(i>=game->get_life()) tile=4; + } + else + tile=4; + + overtile8(dest,tile,x,y,1,0); + x+=8; + + if(((i>>4)&7)==7) + { + x-=64; + y+=bs_style?8:-8; + } + } +} + +void magicgauge(BITMAP *dest,int x,int y, int container, int notlast_tile, int notlast_cset, bool notlast_mod, int last_tile, int last_cset, bool last_mod, + int cap_tile, int cap_cset, bool cap_mod, int aftercap_tile, int aftercap_cset, bool aftercap_mod, int frames, int speed, int delay, bool unique_last, int show) +{ + //these are here to bypass compiler warnings about unused arguments + frames=frames; + speed=speed; + delay=delay; + + if(((game->get_magicdrainrate()==1)&&show==2)|| + ((game->get_magicdrainrate()==2)&&show==1)) + { + return; + } + + int containers=game->get_maxmagic()/MAGICPERBLOCK; + int tile=rand()%32767, cset=rand()%15; + bool mod_value=(rand()%2)!=0; + + if(containercontainers+1) + { + tile=aftercap_tile; + cset=aftercap_cset; + mod_value=aftercap_mod; + } + + if(mod_value) + { + if(!game->get_magicdrainrate() || game->get_magic()>=container*MAGICPERBLOCK) + { + //tile=tile; //full block + if(game->get_magic()==container*MAGICPERBLOCK) + { + if(unique_last) + { + tile+=35; + } + } + } + else + { + if(((container-1)*MAGICPERBLOCK)>game->get_magic()) + { + tile+=4; //empty block + } + else + { + tile+=4+((game->get_magic()-((container-1)*MAGICPERBLOCK))%MAGICPERBLOCK); + } + } + } + + //tile=14161*4; + overtile8(dest,tile,x,y,cset,0); + +} + +void lifegauge(BITMAP *dest,int x,int y, int container, int notlast_tile, int notlast_cset, bool notlast_mod, int last_tile, int last_cset, bool last_mod, + int cap_tile, int cap_cset, bool cap_mod, int aftercap_tile, int aftercap_cset, bool aftercap_mod, int frames, int speed, int delay, bool unique_last) +{ + //these are here to bypass compiler warnings about unused arguments + frames=frames; + speed=speed; + delay=delay; + + int containers=game->get_maxlife()/HP_PER_HEART; + int tile=rand()%32767, cset=rand()%15; + bool mod_value=(rand()%2)!=0; + + if(containercontainers+1) + { + tile=aftercap_tile; + cset=aftercap_cset; + mod_value=aftercap_mod; + } + + if(mod_value) + { + if(game->get_life()>=container*HP_PER_HEART) + { + //tile=tile; //full block + if(game->get_life()==container*HP_PER_HEART) + { + if(unique_last) + { + tile+=19; + } + } + } + else + { + if(((container-1)*HP_PER_HEART)>game->get_life()) + { + tile+=4; //empty block + } + else + { + tile+=4+((game->get_life()-((container-1)*HP_PER_HEART))%HP_PER_HEART); + } + } + } + + overtile8(dest,tile,x,y,cset,0); + +} + + +void magicmeter(BITMAP *dest,int x,int y) +{ + if(!get_bit(quest_rules,qr_ENABLEMAGIC)) return; + + if(game->get_maxmagic()==0) return; + + int tile; + int mmtile=wpnsbuf[iwMMeter].tile; + int mmcset=wpnsbuf[iwMMeter].csets&15; + overtile8(dest,(mmtile*4)+2,x-8,y,mmcset,0); + + if(game->get_magicdrainrate()==1) + { + overtile8(dest,(mmtile*4)+1,x-10,y,mmcset,0); + } + + for(int i=0; iget_maxmagic(); i+=MAGICPERBLOCK) + { + if(game->get_magic()>=i+MAGICPERBLOCK) + { + tile=mmtile*4; //full block + } + else + { + if(i>game->get_magic()) + { + tile=((mmtile+1)*4); //empty block + } + else + { + tile=((mmtile+1)*4)+((game->get_magic()-i)%MAGICPERBLOCK); + } + } + + overtile8(dest,tile,x,y,mmcset,0); + x+=8; + } + + overtile8(dest,(mmtile*4)+3,x,y,mmcset,0); + +} + +void putxnum(BITMAP *dest,int x,int y,int num,FONT *tempfont,int color,int shadowcolor,int bgcolor,int textstyle,bool usex,int digits,bool infinite,char idigit) +{ + if(!show_subscreen_numbers) + { + return; + } + + int found_digits=5; + + if(num<10000) + { + found_digits=4; + } + + if(num<1000) + { + found_digits=3; + } + + if(num<100) + { + found_digits=2; + } + + if(num<10) + { + found_digits=1; + } + + if(infinite) + { + textprintf_styled_aligned_ex(dest,tempfont,x,y,textstyle,sstaLEFT,color,shadowcolor,bgcolor,"%s%c",usex?"X":"",idigit); + } + else + { + textprintf_styled_aligned_ex(dest,tempfont,x,y,textstyle,sstaLEFT,color,shadowcolor,bgcolor,"%s%d",(usex && found_digits 0) + { + Bitem = new item((fix)0, (fix)0, (fix)0, Bwpn&0x0FFF, 0, 0); + Bitem->alsoHaveBow=false; + + switch(itemsbuf[Bwpn&0x0FFF].family) + { + case itype_arrow: + if((Bwpn&0xF000)==0xF000) + { + Bitem->alsoHaveBow=true; + } + + break; + } + + // Bitem = new item((fix)(zinit.subscreenyofs = 0; + Bitem->pickup |= ipDUMMY; + } + } + } + + if(Aid != Awpn) + { + Aid = 0; + + if(Aitem) + { + delete Aitem; + Aitem = NULL; + } + + if(Awpn > 0) + { + Aitem = new item((fix)0, (fix)0,(fix)0,Awpn&0x0FFF, 0, 0); + + switch(itemsbuf[Awpn&0x0FFF].family) + { + case itype_arrow: + if((Awpn&0xF000)==0xF000) + { + Aitem->alsoHaveBow=true; + } + + break; + } + + if(Aitem != NULL) + { + Aid = Awpn; + Aitem->yofs = 0; + Aitem->pickup |= ipDUMMY; + } + } + } + + if(Bitem) + Bitem->animate(0); + + if(Aitem) + Aitem->animate(0); +} + +void add_subscr_item(item *newItem) +{ + newItem->subscreenItem=true; + Sitems.add(newItem); +} + +/****/ +int stripspaces(char *source, char *target, int stop) +{ + int begin, end; + + for(begin=0; ((beginget_bombs() + // Remote Bombs: the bomb icon can still be used when an undetonated bomb is onscreen. + || (itemsbuf[current_item_id(itype_bomb)].misc1==0 && Lwpns.idCount(wLitBomb)>0) + || current_item_power(itype_bombbag))) + || (itemtype == itype_sbomb && + !(game->get_sbombs() + || (itemsbuf[current_item_id(itype_sbomb)].misc1==0 && Lwpns.idCount(wLitSBomb)>0) + || (current_item_power(itype_bombbag) + && itemsbuf[current_item_id(itype_bombbag)].flags & ITEM_FLAG1)))) + return false; + + if(itemtype!=itype_bowandarrow || + d!=itype_arrow || + ((get_bit(quest_rules,qr_TRUEARROWS)&&game->get_arrows()) || + (!get_bit(quest_rules,qr_TRUEARROWS)&&game->get_rupies()))) + return true; + + return false; +} + +void subscreenitem(BITMAP *dest, int x, int y, int itemtype) +{ + // We need to do a reverse loop to prevent the Bow from being drawn above the Arrow (Bow & Arrow). + int overridecheck = 0xFFFF; + + for(int i=Sitems.Count()-1; i>=0; i--) + { + if(itemtype & 0x8000) // if 0x8000, then itemtype is actually an item ID. + { + if(overridecheck==0xFFFF) + if(Sitems.spr(i)->id == (itemtype&0xFFF) && Sitems.spr(i)->misc==-1) overridecheck = i; + } + else if(Sitems.spr(i)->misc!=-1) + { + int d= itemsbuf[Sitems.spr(i)->id].family; + + if((d==itemtype)|| + (itemtype==itype_letterpotion&&((d==itype_letter && current_item_id(itype_potion)==-1)||d==itype_potion))|| + (itemtype==itype_bowandarrow&&(d==itype_bow||d==itype_arrow))) + { + Sitems.spr(i)->x = x; + Sitems.spr(i)->y = y; + Sitems.spr(i)->yofs=0; + + if(displaysubscreenitem(itemtype, d)) + { + Sitems.spr(i)->draw(dest); + } + + if(itemtype!=itype_bowandarrow) + { + return; + } + } + } + } + + //Item Override stuff here + if((itemtype & 0x8000) && (has_item(itemsbuf[itemtype&0xFFF].family,itemsbuf[itemtype&0xFFF].fam_type)) + && !item_disabled(itemtype&0xFFF) && displaysubscreenitem(itemsbuf[itemtype&0xFFF].family, 0)) + { + if(overridecheck == 0xFFFF) + { + add_subscr_item(new item((fix)x,(fix)y,(fix)0,(itemtype&0xFFF),0,0)); + overridecheck = Sitems.Count()-1; + Sitems.spr(overridecheck)->misc = -1; + } + + Sitems.spr(overridecheck)->x = x; + Sitems.spr(overridecheck)->y = y; + Sitems.spr(overridecheck)->yofs=0; + Sitems.spr(overridecheck)->draw(dest); + } +} + +int subscreen_color(miscQdata *misc, int c1, int c2) +{ + int ret; + + switch(c1) + { + case ssctSYSTEM: + ret=(c2==-1)?c2:vc(c2); + break; + + case ssctMISC: + switch(c2) + { + case ssctTEXT: + ret=misc->colors.text; + break; + + case ssctCAPTION: + ret=misc->colors.caption; + break; + + case ssctOVERWBG: + ret=misc->colors.overw_bg; + break; + + case ssctDNGNBG: + ret=misc->colors.dngn_bg; + break; + + case ssctDNGNFG: + ret=misc->colors.dngn_fg; + break; + + case ssctCAVEFG: + ret=misc->colors.cave_fg; + break; + + case ssctBSDK: + ret=misc->colors.bs_dk; + break; + + case ssctBSGOAL: + ret=misc->colors.bs_goal; + break; + + case ssctCOMPASSLT: + ret=misc->colors.compass_lt; + break; + + case ssctCOMPASSDK: + ret=misc->colors.compass_dk; + break; + + case ssctSUBSCRBG: + ret=misc->colors.subscr_bg; + break; + + case ssctSUBSCRSHADOW: + ret=misc->colors.subscr_shadow; + break; + + case ssctTRIFRAMECOLOR: + ret=misc->colors.triframe_color; + break; + + case ssctBMAPBG: + ret=misc->colors.bmap_bg; + break; + + case ssctBMAPFG: + ret=misc->colors.bmap_fg; + break; + + case ssctLINKDOT: + ret=misc->colors.link_dot; + break; + + default: + ret=(rand()*1000)%256; + break; + } + + break; + + default: + ret=(c1<<4)+c2; + } + + return ret; +} + + + +int subscreen_cset(miscQdata *misc,int c1, int c2) +{ + int ret=c1; + + switch(c1) + { + case ssctMISC: + switch(c2) + { + case sscsTRIFORCECSET: + ret=misc->colors.triforce_cset; + break; + + case sscsTRIFRAMECSET: + ret=misc->colors.triframe_cset; + break; + + case sscsOVERWORLDMAPCSET: + ret=misc->colors.overworld_map_cset; + break; + + case sscsDUNGEONMAPCSET: + ret=misc->colors.dungeon_map_cset; + break; + + case sscsBLUEFRAMECSET: + ret=misc->colors.blueframe_cset; + break; + + case sscsHCPIECESCSET: + ret=misc->colors.HCpieces_cset; + break; + + case sscsSSVINECSET: + ret=wpnsbuf[iwSubscreenVine].csets&15; + break; + + default: + ret=(rand()*1000)%256; + break; + } + + break; + + default: + ret=c1; + } + + return ret; +} + +FONT *ss_font(int fontnum) +{ + FONT *tempfont; + + switch(fontnum) + { + case ssfSMALL: + tempfont=sfont; + break; + + case ssfSMALLPROP: + tempfont=spfont; + break; + + case ssfSS1: + tempfont=ssfont1; + break; + + case ssfSS2: + tempfont=ssfont2; + break; + + case ssfSS3: + tempfont=ssfont3; + break; + + case ssfSS4: + tempfont=ssfont4; + break; + + case ssfZTIME: + tempfont=ztfont; + break; + + case ssfZELDA: + tempfont=zfont; + break; + + case ssfZ3: + tempfont=z3font; + break; + + case ssfZ3SMALL: + tempfont=z3smallfont; + break; + + case ssfGBLA: + tempfont=gblafont; + break; + + case ssfGORON: + tempfont=goronfont; + break; + + case ssfZORAN: + tempfont=zoranfont; + break; + + case ssfHYLIAN1: + tempfont=hylian1font; + break; + + case ssfHYLIAN2: + tempfont=hylian2font; + break; + + case ssfHYLIAN3: + tempfont=hylian3font; + break; + + case ssfHYLIAN4: + tempfont=hylian4font; + break; + + case ssfPROP: + tempfont=font; + break; + + case ssfGBORACLE: + tempfont=gboraclefont; + break; + + case ssfGBORACLEP: + tempfont=gboraclepfont; + break; + + case ssfDSPHANTOM: + tempfont=dsphantomfont; + break; + + case ssfDSPHANTOMP: + tempfont=dsphantompfont; + break; + + default: + fontnum=rand()%ssfMAX; + tempfont=ss_font(fontnum); + break; + } + + return tempfont; +} + +item *sel_a=NULL, *sel_b=NULL; + + +void delete_selectors() +{ + if(sel_a) + { + delete sel_a; + sel_a=NULL; + } + + if(sel_b) + { + delete sel_b; + sel_b=NULL; + } +} + + +void animate_selectors() +{ + if(new_sel) + { + delete_selectors(); + new_sel = false; + } + + if(!sel_a) + sel_a = new item((fix)0, (fix)0, (fix)0, iSelectA, 0, 0); + + if(!sel_b) + sel_b = new item((fix)0, (fix)0, (fix)0, iSelectB, 0, 0); + + sel_a->yofs=0; + sel_a->animate(0); + sel_b->yofs=0; + sel_b->animate(0); +} + +void show_custom_subscreen(BITMAP *dest, miscQdata *misc, subscreen_group *css, int xofs, int yofs, bool showtime, int pos2) +{ + //this is not a good place to be clearing the bitmap + //other stuff might already have been drawn on it that needs to be kept + //(eg the game screen when pulling down the subscreen) -DD + //clear_to_color(dest, 0); + color_map=&trans_table; + set_trans_blender(0, 0, 0, 128); + + //doing animation here leads to 2x speed when drawing both active and passive subscreen -DD + /*static item sel_a((fix)0,(fix)0,(fix)0,iSelectA,0,0); + static item sel_b((fix)0,(fix)0,(fix)0,iSelectB,0,0); + if (new_sel) + { + sel_a=item((fix)0,(fix)0,(fix)0,iSelectA,0,0); + sel_b=item((fix)0,(fix)0,(fix)0,iSelectB,0,0); + new_sel=false; + } + sel_a.yofs=0; + sel_a.animate(0); + sel_b.yofs=0; + sel_b.animate(0);*/ + if(!sel_a || !sel_b) + animate_selectors(); + + for(int i=0; iobjects[i].type>ssoNULL; ++i) + { + if((css->objects[i].pos & pos2) != 0) + { + FONT *tempfont=zfont; + int fontnum=css->objects[i].d1; + tempfont=ss_font(fontnum); + int x=css->objects[i].x+xofs; + int y=css->objects[i].y+yofs; + + switch(css->objects[i].type) + { + case sso2X2FRAME: + { + frame2x2(dest, misc, x, y, css->objects[i].d1, subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1), css->objects[i].w, css->objects[i].h, css->objects[i].d2, css->objects[i].d3 != 0, css->objects[i].d4 != 0); + } + break; + + case ssoBSTIME: + { + char *ts; + + if(game) + ts = time_str_short2(game->get_time()); + else + ts = time_str_short2(0); + +// textout_shadowed_ex(dest,tempfont,ts,x,y,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + textout_styled_aligned_ex(dest,tempfont,ts,x,y,css->objects[i].d3,css->objects[i].d2,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + } + break; + + case ssoSSTIME: + case ssoTIME: + { + if(showtime||css->objects[i].type==ssoTIME) + { + char *ts; + + if(game) + ts = time_str_med(game->get_time()); + else + ts = time_str_med(0); + +// textout_right_ex(dest,tempfont,ts,x,y,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2)); + textout_styled_aligned_ex(dest,tempfont,ts,x,y,css->objects[i].d3,css->objects[i].d2,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + } + } + break; + + case ssoTEXT: + { + //textout_styled_aligned_ex(bmp, f, s, x,y,textstyle, alignment, color, shadow, bg) + textout_styled_aligned_ex(dest,tempfont,(char *)css->objects[i].dp1,x,y,css->objects[i].d3,css->objects[i].d2,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + } + break; + + case ssoLINE: + { + if(css->objects[i].d4) + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + line(dest, x, y, x+css->objects[i].w-1, y+css->objects[i].h-1, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1)); + + if(css->objects[i].d4) + { + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + } + } + break; + + case ssoRECT: + { + if(css->objects[i].d2) + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + if(css->objects[i].d1!=0) + { + rectfill(dest, x, y, x+css->objects[i].w-1, y+css->objects[i].h-1, subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2)); + } + + rect(dest, x, y, x+css->objects[i].w-1, y+css->objects[i].h-1, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1)); + + if(css->objects[i].d2) + { + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + } + } + break; + + case ssoMAGICMETER: + { + magicmeter(dest, x, y); + } + break; + + case ssoLIFEMETER: + { + lifemeter(dest, x, y, css->objects[i].d1, css->objects[i].d2 != 0); + } + break; + + case ssoBUTTONITEM: + { + if(css->objects[i].d2) + { + drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0); + } + + buttonitem(dest, css->objects[i].d1, x, y); + + if(css->objects[i].d2) + { + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + } + } + break; + + case ssoCOUNTERS: + { + defaultcounters(dest, x, y, tempfont,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3),css->objects[i].d2 != 0,css->objects[i].d3,css->objects[i].d4,css->objects[i].d5); + } + break; + + case ssoCOUNTER: + { + counter(dest, x, y, tempfont,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3),css->objects[i].d2,css->objects[i].d3,css->objects[i].d4,css->objects[i].d5,css->objects[i].d6&1, css->objects[i].d7, css->objects[i].d8, css->objects[i].d9, css->objects[i].d10, (css->objects[i].d6&2)!=0); + } + break; + + case ssoMINIMAPTITLE: + { + if(!css->objects[i].d4 || has_item(itype_map, get_dlevel())) + { + minimaptitle(dest, x, y, tempfont, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1),subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2),subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3), css->objects[i].d2, css->objects[i].d3); + } + } + break; + + case ssoMINIMAP: + { + //drawdmap(dest, misc, x, y, showmap, showlink, showcompass, linkcolor, lccolor, dccolor) + drawdmap(dest, misc, x, y, css->objects[i].d1 != 0, css->objects[i].d2 && !(TheMaps[(DMaps[get_currdmap()].map*MAPSCRS)+get_homescr()].flags7&fNOLINKMARK), + css->objects[i].d3 && !(DMaps[get_currdmap()].flags&dmfNOCOMPASS), subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + } + break; + + case ssoLARGEMAP: + { + //putBmap(dest, misc, x, y, showmap, showlink, showrooms, roomcolor, linkcolor, large) + putBmap(dest, misc, x, y, css->objects[i].d1 != 0, css->objects[i].d2!=0, css->objects[i].d3!=0, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), css->objects[i].d10 != 0); + } + break; + + case ssoCLEAR: + { + clear_to_color(dest,subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1)); + } + break; + + case ssoCURRENTITEM: + { + if(css->objects[i].d2) + { + subscreenitem(dest, x, y, css->objects[i].d8>0 ? ((css->objects[i].d8-1) | 0x8000) : css->objects[i].d1); + } + } + break; + + case ssoTEXTBOX: + { + //draw_textbox(dest, x, y, w, h, tempfont, thetext, wword, tabsize, alignment, textstyle, color, shadowcolor, backcolor) + draw_textbox(dest, x, y, css->objects[i].w, css->objects[i].h, tempfont, (char *)css->objects[i].dp1, css->objects[i].d4!=0, css->objects[i].d5, css->objects[i].d2, css->objects[i].d3, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); +// draw_textbox(dest, 0, 0, 200, 50, sfont, "This is a test", 1, 4, 0, 0, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + } + break; + + case ssoSELECTEDITEMNAME: + { + int itemid=Bweapon(Bpos); + + // If it's a combined bow and arrow, the item ID will have 0xF000 added. + if(itemid>=0xF000) + itemid-=0xF000; + + // 0 can mean either the item with index 0 is selected or there's no + // valid item to select, so be sure Link has whatever it would be. + if(!game->get_item(itemid)) + break; + + char itemname[140]=""; + sprintf(itemname, "%s", item_string[itemid]); + + switch(itemsbuf[itemid].family) + { + case itype_arrow: + if(Bitem->alsoHaveBow) + { + if(current_item_id(itype_bow)) + { + bool hasarrows=((get_bit(quest_rules,qr_TRUEARROWS)&&(game==NULL || game->get_arrows()))||(!get_bit(quest_rules,qr_TRUEARROWS)&&(game==NULL || game->get_rupies()))); + sprintf(itemname, "%s%s%s", item_string[current_item_id(itype_bow)], hasarrows?" & ":"",hasarrows?item_string[Bitem->id]:""); + /*switch (current_item_power(itype_bow)) + { + case 1: + sprintf(itemname, "Short Bow%s%s", hasarrows?" & ":"",hasarrows?item_string[Bitem->id]:""); + break; + case 2: + sprintf(itemname, "Long Bow%s%s", hasarrows?" & ":"",hasarrows?item_string[Bitem->id]:""); + break; + }*/ + } + } + + break; + } + + draw_textbox(dest, x, y, css->objects[i].w, css->objects[i].h, tempfont, itemname, css->objects[i].d4!=0, css->objects[i].d5, css->objects[i].d2, css->objects[i].d3, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), subscreen_color(misc, css->objects[i].colortype3, css->objects[i].color3)); + // draw_textbox(dest, x, y, w, h, tempfont, thetext, wword, tabsize, alignment, textstyle, color, shadowcolor, backcolor); + } + break; + + case ssoTRIFRAME: + { +// puttriframe(dest, misc, x, y, triframecolor, numbercolor, triframetile, triframecset, triforcetile, triforcecset, showframe, showpieces, largepieces) + puttriframe(dest, misc, x, y, subscreen_color(misc, css->objects[i].colortype1, css->objects[i].color1), subscreen_color(misc, css->objects[i].colortype2, css->objects[i].color2), css->objects[i].d1, css->objects[i].d2, css->objects[i].d3, css->objects[i].d4, css->objects[i].d5!=0, css->objects[i].d6!=0, css->objects[i].d7!=0); + } + break; + + case ssoTRIFORCE: + { + puttriforce(dest,misc,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3!=0,css->objects[i].d4!=0,css->objects[i].d5); + } + break; + + case ssoTILEBLOCK: + { + draw_block_flip(dest,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3!=0,css->objects[i].d4!=0); + } + break; + + case ssoMINITILE: + { + int t=css->objects[i].d1; + + if(t==-1) + { + switch(css->objects[i].d2) + { + case ssmstSSVINETILE: + t=wpnsbuf[iwSubscreenVine].tile*4; + break; + + case ssmstMAGICMETER: + t=wpnsbuf[iwMMeter].tile*4; + break; + + default: + t=(rand()*100000)%32767; + break; + } + } + + t+=css->objects[i].d3; + + if(css->objects[i].d5) + { + if(css->objects[i].d6) + { + overtiletranslucent8(dest,t,x,y,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].d4,128); + } + else + { + overtile8(dest,t,x,y,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].d4); + } + } + else + { + if(css->objects[i].d6) + { + puttiletranslucent8(dest,t,x,y,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].d4,128); + } + else + { + oldputtile8(dest,t,x,y,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].d4); + } + } + } + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + { + int p=-1; + + for(int j=0; jobjects[j].type!=ssoNULL; ++j) + { + if(css->objects[j].type==ssoCURRENTITEM) + { + if(css->objects[j].d3==(int)Bpos) + { + p=j; + break; + } + } + } + + bool big_sel=css->objects[i].d5 != 0; + item *tempsel=(css->objects[i].type==ssoSELECTOR1)?sel_a:sel_b; + int temptile=tempsel->tile; + tempsel->drawstyle=0; + + if(css->objects[i].d4) + { + tempsel->drawstyle=1; + } + + for(int j=0; j<4; ++j) + { + if(p!=-1) + { + tempsel->x=css->objects[p].x+xofs+(big_sel?(j%2?8:-8):0); + tempsel->y=css->objects[p].y+yofs+(big_sel?(j>1?8:-8):0); + tempsel->tile+=(zc_max(itemsbuf[tempsel->id].frames,1)*j); + + if(temptile) + { + tempsel->draw(dest); + tempsel->tile=temptile; + } + + if(!big_sel) + { + break; + } + } + } + + } + break; + + case ssoMAGICGAUGE: + { + // void magicgauge(BITMAP *dest,int x,int y, int container, int notlast_tile, int notlast_cset, bool notlast_mod, int last_tile, int last_cset, bool last_mod, + // int cap_tile, int cap_cset, bool cap_mod, int aftercap_tile, int aftercap_cset, bool aftercap_mod, int frames, int speed, int delay, bool unique_last, + // int show) + magicgauge(dest,x,y, css->objects[i].d1, css->objects[i].d2, css->objects[i].colortype1, ((css->objects[i].d10&1)?1:0), css->objects[i].d3, css->objects[i].color1, ((css->objects[i].d10&2)?1:0), + css->objects[i].d4, css->objects[i].colortype2, ((css->objects[i].d10&4)?1:0), css->objects[i].d5, css->objects[i].color2, ((css->objects[i].d10&8)?1:0), css->objects[i].d6, css->objects[i].d7, css->objects[i].d8, ((css->objects[i].d10&16)?1:0), + css->objects[i].d9); + } + break; + + case ssoLIFEGAUGE: + { + lifegauge(dest,x,y, css->objects[i].d1, css->objects[i].d2, css->objects[i].colortype1, ((css->objects[i].d10&1)?1:0), css->objects[i].d3, css->objects[i].color1, ((css->objects[i].d10&2)?1:0), + css->objects[i].d4, css->objects[i].colortype2, ((css->objects[i].d10&4)?1:0), css->objects[i].d5, css->objects[i].color2, ((css->objects[i].d10&8)?1:0), css->objects[i].d6, css->objects[i].d7, css->objects[i].d8, ((css->objects[i].d10&16)?1:0)); + } + break; + + default: + { + } + break; + } + + //sso_bounding_box(dest, css, i, vc(15)); + } + } +} + + +void buttonitem(BITMAP *dest, int button, int x, int y) +{ + switch(button) + { + case 0: //A button + if(Aitem&&show_subscreen_items) + { + Aitem->x=x; + Aitem->y=y; + + switch(itemsbuf[Aitem->id].family) + { + case itype_arrow: + if(Aitem->alsoHaveBow) + { + if(current_item_id(itype_bow)>-1) + { + subscreenitem(dest, x, y, itype_bow); + + if(((get_bit(quest_rules,qr_TRUEARROWS)&&!game->get_arrows()) + ||(!get_bit(quest_rules,qr_TRUEARROWS)&&!game->get_rupies()&&!current_item_power(itype_wallet))) + &&!current_item_power(itype_quiver)) + { + return; + } + } + } + + break; + } + + Aitem->draw(dest); + } + + break; + + case 1: //B button + if(Bitem&&show_subscreen_items) + { + Bitem->x=x; + Bitem->y=y; + + switch(itemsbuf[Bitem->id].family) + { + case itype_arrow: + if(Bitem->alsoHaveBow) + { + if(current_item_id(itype_bow)>-1) + { + subscreenitem(dest, x, y, itype_bow); + + if(((get_bit(quest_rules,qr_TRUEARROWS)&&(game != NULL && !game->get_arrows())) + ||(!get_bit(quest_rules,qr_TRUEARROWS)&&(game != NULL && !game->get_rupies())&&!current_item_power(itype_wallet))) + &&!current_item_power(itype_quiver)) + { + return; + } + } + } + + break; + } + + Bitem->draw(dest); + } + + break; + + default: + break; + } +} + +void defaultcounters(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, bool usex, int textstyle, int digits, char idigit) +{ + int yofs = (game==NULL || (game->get_sbombs() && current_item_id(itype_sbomb)>-1)) ? 8 : 0; + + //88, 16 + overtile8(dest,5,x,y,1,0); + overtile8(dest,8,x,y+16-yofs,1,0); + overtile8(dest,9,x,y+24-yofs,0,0); + + if(game) + { + bool magickey = false; + int itemid = current_item_id(itype_magickey); + + if(itemid>-1) + { + if(itemsbuf[itemid].flags&ITEM_FLAG1) + magickey = itemsbuf[itemid].power>=get_dlevel(); + else + magickey = itemsbuf[itemid].power==get_dlevel(); + } + + putxnum(dest,x+8,y,game->get_rupies(),tempfont,color,shadowcolor,bgcolor,textstyle,usex,digits,current_item_power(itype_wallet)>0,idigit); + putxnum(dest,x+8,y+16-yofs,game->get_keys()+game->get_lkeys(),tempfont,color,shadowcolor,bgcolor, textstyle,usex,digits,magickey,idigit); + putxnum(dest,x+8,y+24-yofs,game->get_bombs(),tempfont,color,shadowcolor,bgcolor,textstyle,usex,digits,current_item_power(itype_bombbag)>0,idigit); + } + + if(game==NULL || (game->get_sbombs() && current_item_id(itype_sbomb)>-1)) + { + overtile8(dest,13,x,y+24,1,0); + + if(game) + { + int itemid = current_item_id(itype_bombbag); + bool superbomb = (itemid>=0 && itemsbuf[itemid].power>0 && itemsbuf[itemid].flags & ITEM_FLAG1); + + putxnum(dest,x+8,y+24,game->get_sbombs(),tempfont,color,shadowcolor,bgcolor,textstyle,usex,digits,superbomb,idigit); + } + } +} + +bool is_counter_item(int itemtype, int countertype) +{ + switch(countertype) + { + case sscBOMBS: + if(itemsbuf[itemtype].family==itype_bomb) + { + return true; + } + + break; + + case sscSBOMBS: + if(itemsbuf[itemtype].family==itype_sbomb) + { + return true; + } + + break; + + case sscARROWS: + if(itemsbuf[itemtype].family==itype_arrow) + { + return true; + } + + break; + } + + return false; +} + +void counter(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, int alignment, int textstyle, int digits, char idigit, bool showzero, int itemtype1, int itemtype2, int itemtype3, int infiniteitem, bool onlyselected) +{ + int value=0; + bool infinite=false; + + if(game != NULL && game->get_item(infiniteitem) && !item_disabled(infiniteitem)) + { + infinite=true; + } + + char valstring[80]; + char formatstring[80]; + sprintf(valstring,"01234567890123456789"); + sprintf(formatstring, "%%0%dd", digits); + + if(onlyselected && !(((Bitem&&(is_counter_item(Bitem->id,itemtype1)||is_counter_item(Bitem->id,itemtype2)||is_counter_item(Bitem->id,itemtype3)))||(Aitem&&(is_counter_item(Aitem->id,itemtype1)||is_counter_item(Aitem->id,itemtype2)||is_counter_item(Aitem->id,itemtype3)))))) + { + return; + } + + int itemtype; + /* + for (int i=0; i<3; ++i) + { + switch (i) + { + case 0: + itemtype=itemtype1; + break; + case 1: + itemtype=itemtype2; + break; + case 2: + itemtype=itemtype3; + break; + } + */ + itemtype=itemtype1; + /* commented out until I find out what it does - it's messing up custom subscreens now as + itemtype2 and 3 are zero - so link's life gets added to the counters */ + + switch(itemtype) + { + case sscRUPEES: + if(current_item_power(itype_wallet)) + infinite=true; + + value+=game->get_rupies(); + break; + + case sscBOMBS: + if(current_item_power(itype_bombbag)) + infinite=true; + + value+=game->get_bombs(); + break; + + case sscSBOMBS: + { + int itemid = current_item_id(itype_bombbag); + + if(itemid>-1 && itemsbuf[itemid].power>0 && itemsbuf[itemid].flags & ITEM_FLAG1) + infinite=true; + + value+=game->get_sbombs(); + break; + } + + case sscARROWS: + if((!get_bit(quest_rules,qr_TRUEARROWS) && current_item_power(itype_wallet)) || current_item_power(itype_quiver)) + infinite=true; + + // If Link somehow got ammunition before getting the arrow, + // or if the arrow was disabled in a DMap, + // we shouldn't put the value as zero. +// if(/*current_item_id(itype_arrow)>-1*/ true) + { + if(get_bit(quest_rules,qr_TRUEARROWS)) + { + value+=game->get_arrows(); + } + else + { + value+=game->get_rupies(); + } + } + break; + + case sscGENKEYMAGIC: + case sscLEVKEYMAGIC: + case sscANYKEYMAGIC: + { + int itemid = current_item_id(itype_magickey); + + if(itemid>-1 && !infinite) + { + if(itemsbuf[itemid].flags&ITEM_FLAG1) + infinite = itemsbuf[itemid].power>=get_dlevel(); + else + infinite = itemsbuf[itemid].power==get_dlevel(); + } + } + + //fall through + case sscANYKEYNOMAGIC: + case sscLEVKEYNOMAGIC: + case sscGENKEYNOMAGIC: + if(itemtype == sscGENKEYNOMAGIC || itemtype == sscANYKEYNOMAGIC + || itemtype == sscGENKEYMAGIC || itemtype == sscANYKEYMAGIC) + value += game->get_keys(); + + if(itemtype == sscLEVKEYNOMAGIC || itemtype == sscANYKEYNOMAGIC + || itemtype == sscLEVKEYMAGIC || itemtype == sscANYKEYMAGIC) + value += game->get_lkeys(); + + break; + + case sscSCRIPT1: + case sscSCRIPT2: + case sscSCRIPT3: + case sscSCRIPT4: + case sscSCRIPT5: + case sscSCRIPT6: + case sscSCRIPT7: + case sscSCRIPT8: + case sscSCRIPT9: + case sscSCRIPT10: + case sscSCRIPT11: + case sscSCRIPT12: + case sscSCRIPT13: + case sscSCRIPT14: + case sscSCRIPT15: + case sscSCRIPT16: + case sscSCRIPT17: + case sscSCRIPT18: + case sscSCRIPT19: + case sscSCRIPT20: + case sscSCRIPT21: + case sscSCRIPT22: + case sscSCRIPT23: + case sscSCRIPT24: + case sscSCRIPT25: + value += game->get_counter(itemtype-3); + + default: + break; + } + + // (for loop) } + if(!showzero&&!value&&!infinite) + { + return; + } + + if(infinite) + { + sprintf(valstring, "%c", idigit); + } + else + { + sprintf(valstring, formatstring, value); + } + + textout_styled_aligned_ex(dest,tempfont,valstring,x,y,textstyle,alignment,color,shadowcolor,bgcolor); + + // putxnum(dest,x+8,y,game->get_rupies(),tempfont,color,shadowcolor,bgcolor,shadowed,usex,digits,0,idigit); +} + +void minimaptitle(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, int alignment, int textstyle) +{ + char dmaptitlesource[2][11]; + char dmaptitle[2][11]; + sprintf(dmaptitlesource[0], "%.10s", DMaps[get_currdmap()].title); + sprintf(dmaptitlesource[1], "%.10s", DMaps[get_currdmap()].title+10); + + int title_len1=stripspaces(dmaptitlesource[0], dmaptitle[0], 10); + int title_len2=stripspaces(dmaptitlesource[1], dmaptitle[1], 10); + + if((title_len1>0)||(title_len2>0)) + { + if((title_len1>0)&&(title_len2>0)) + { + textprintf_styled_aligned_ex(dest,tempfont,x,y+8,textstyle,alignment,color,shadowcolor,bgcolor,"%s",dmaptitle[1]); + textprintf_styled_aligned_ex(dest,tempfont,x,y,textstyle,alignment,color,shadowcolor,bgcolor,"%s",dmaptitle[0]); + } + else + { + if(title_len1>0) + { + textprintf_styled_aligned_ex(dest,tempfont,x,y+8,textstyle,alignment,color,shadowcolor,bgcolor,"%s",dmaptitle[0]); + } + else + { + textprintf_styled_aligned_ex(dest,tempfont,x,y+8,textstyle,alignment,color,shadowcolor,bgcolor,"%s",dmaptitle[1]); + } + } + } +} + +void put_passive_subscr(BITMAP *dest,miscQdata *misc,int x,int y,bool showtime,int pos2) +{ + // uncomment this? + // load_Sitems(); + Sitems.animate(); + update_subscr_items(); + BITMAP *subscr = create_sub_bitmap(dest,x,y,256,passive_subscreen_height); + + if(no_subscreen()) + { + clear_to_color(subscr,0); + destroy_bitmap(subscr); + return; + } + + show_custom_subscreen(subscr, misc, current_subscreen_passive, 0, 0, showtime, pos2); + destroy_bitmap(subscr); +} + +/* + const byte tripiece[8*3] = + { + 112,112,0, 128,112,1, 96,128,0, 144,128,1, + 112,128,2, 112,128,1, 128,128,3, 128,128,0 + }; + */ + +void puttriframe(BITMAP *dest, miscQdata *misc, int x, int y, int triframecolor, int numbercolor, int triframetile, int triframecset, int triforcetile, int triforcecset, bool showframe, bool showpieces, bool largepieces) +{ + if(triframetile==0) + { + triframetile=misc->colors.triframe_tile; + triframecset=misc->colors.triframe_cset; + } + + if(triforcetile==0) + { + triforcetile=misc->colors.triforce_tile; + triforcecset=misc->colors.triforce_cset; + } + + if(!largepieces) + { + if(showframe) + { + if(triframetile) + { + draw_block(dest,x,y,triframetile,triframecset,6,3); + } + else + { + line(dest,x+47,y,x+1,y+46,triframecolor); + line(dest,x+48,y,x+94,y+46,triframecolor); + _allegro_hline(dest,x,y+47,x+95,triframecolor); + line(dest,x+47,y+7,x+15,y+39,triframecolor); + line(dest,x+48,y+7,x+80,y+39,triframecolor); + _allegro_hline(dest,x+15,y+40,x+80,triframecolor); + } + } + + if(showpieces) + { + for(int i=0; i<8; i++) + { + int lvl = i+1; + + if(get_bit(quest_rules,qr_4TRI) && lvl>4) + lvl -= 4; + + if(has_item(itype_triforcepiece, lvl)) + { + int tp=0; + + for(; tp<8; tp++) + if(misc->triforce[tp] == i+1) + break; + + overtile16(dest,triforcetile,x+tripiece[0][tp][0],y+tripiece[0][tp][1],triforcecset,tripiece[0][tp][2]); + } + } + } + } + else + { + if(showframe) + { + if(triframetile) + { + draw_block(dest,x,y,triframetile,triframecset,7,7); + } + else + { + if(!get_bit(quest_rules,qr_4TRI)) + { + //left inside vertical + _allegro_vline(dest,x+31,y+56,y+103,triframecolor); + _allegro_vline(dest,x+32,y+56,y+103,triframecolor); + + //center inside vertical top + _allegro_vline(dest,x+55,y+8 ,y+55,triframecolor); + _allegro_vline(dest,x+56,y+8 ,y+55,triframecolor); + + //right inside vertical + _allegro_vline(dest,x+79,y+56,y+103,triframecolor); + _allegro_vline(dest,x+80,y+56,y+103,triframecolor); + + if(!get_bit(quest_rules,qr_3TRI)) + { + //center inside vertical bottom + _allegro_vline(dest,x+55,y+56,y+103,triframecolor); + _allegro_vline(dest,x+56,y+56,y+103,triframecolor); + } + } + + //middle inside horizontal + _allegro_hline(dest,x+32,y+55,x+79,triframecolor); + _allegro_hline(dest,x+32,y+56,x+79,triframecolor); + + //bottom outside horizontal + _allegro_hline(dest,x+8,y+103,x+103,triframecolor); + + //left outside diagonal + line(dest,x+8,y+103,x+55,y+8,triframecolor); + line(dest,x+9,y+102,x+55,y+9,triframecolor); + + //right outside diagonal + line(dest,x+56,y+8,x+103,y+103,triframecolor); + line(dest,x+56,y+9,x+102,y+102,triframecolor); + + //left inside diagonal + line(dest,x+32,y+56,x+55,y+103,triframecolor); + line(dest,x+32,y+57,x+54,y+102,triframecolor); + line(dest,x+32,y+55,x+55,y+102,triframecolor); + + //right inside diagonal + line(dest,x+56,y+103,x+79,y+56,triframecolor); + line(dest,x+57,y+102,x+79,y+57,triframecolor); + line(dest,x+56,y+102,x+79,y+55,triframecolor); + + for(int i=0; i<8; i++) + { + int lvl = i+1; + + if(get_bit(quest_rules,qr_4TRI) && lvl>4) + { + lvl -= 4; + } + + int tp=0; + + for(; tp<8; tp++) + { + if(misc->triforce[tp] == i+1) + { + break; + } + } + + if(!has_item(itype_triforcepiece, lvl)) + { + textprintf_ex(dest, pfont, x+tripiece[1][tp][0]+((tripiece[1][tp][2]&1)?8:14),y+tripiece[1][tp][1]+((tripiece[1][tp][2]&2)?9:32), numbercolor, -1, "%d", lvl); + } + } + } + } + + if(showpieces) + { + for(int i=0; i<8; i++) + { + int lvl = i+1; + + if(get_bit(quest_rules,qr_4TRI) && lvl>4) + { + lvl -= 4; + } + + int tp=0; + + for(; tp<8; tp++) + { + if(misc->triforce[tp] == i+1) + { + break; + } + } + + if(has_item(itype_triforcepiece, lvl)) + { + draw_block_flip(dest,x+tripiece[1][tp][0]-(tripiece[1][tp][2]&1?0:8),y+tripiece[1][tp][1],triforcetile,triforcecset,2,3,tripiece[1][tp][2],1,0); + } + } + } + } +} + + +void puttriforce(BITMAP *dest, miscQdata *misc, int x, int y, int tile, int cset, int w, int h, int flip, bool overlay, bool trans, int trinum) +{ + if(tile==0) + { + tile=misc->colors.triforce_tile; + } + + for(int i=0; i<8; i++) + { + int lvl = i+1; + + if(get_bit(quest_rules,qr_4TRI) && lvl>4) + lvl -= 4; + + if(lvl==trinum && has_item(itype_triforcepiece, lvl)) + { + int tp=0; + + for(; tp<8; tp++) + if(misc->triforce[tp] == i+1) + break; + + draw_block_flip(dest,x,y,tile,cset,w,h,flip,overlay,trans); + } + } +} + +/* + const byte bmap[16*2] = { + 0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0, + 0,3,0,0,0,3,0,0,0,0,3,0,0,0,3,0 }; + + const int fringe[8] = { 6,2,4,7,6,8,7,5 }; + + const byte bmaptiles[8*5] = { + 0, 1, 2, 3, 2, 3, 3, 4, + 20,21,22,23,22,23,23,24, + 20,21,22,23,22,23,23,24, + 20,21,22,23,22,23,23,24, + 40,41,42,43,42,43,43,44 }; + */ + +void draw_block(BITMAP *dest,int x,int y,int tile,int cset,int w,int h); +void putBmap(BITMAP *dest, miscQdata *misc, int x, int y,bool showmap, bool showrooms, bool showlink, int roomcolor, int linkcolor, bool large) +{ + int si=0; + + int maptile=has_item(itype_map, get_dlevel())?DMaps[get_currdmap()].largemap_2_tile:DMaps[get_currdmap()].largemap_1_tile; + int mapcset=has_item(itype_map, get_dlevel())?DMaps[get_currdmap()].largemap_2_cset:DMaps[get_currdmap()].largemap_1_cset; + + if(showmap) + { + if(maptile) + { + draw_block(dest,x,y,maptile,mapcset,large?9:7,5); + } + else if(misc->colors.dungeon_map_tile) + { + for(int y2=0; y2<5; y2++) + { + for(int x2=0; x2<(large?8:6); x2++) + { + overtile16(dest,misc->colors.dungeon_map_tile+(large?bmaptiles_original[y2][x2]:bmaptiles_bs[y2][x2]),x+(x2<<4),y+(y2<<4),misc->colors.dungeon_map_cset,0); + //++si; + } + } + } + else + { + BITMAP *bmp = create_bitmap_ex(8,8,8); + + if(!bmp) + return; + + clear_bitmap(bmp); + + for(int x2=0; x2<8; x2++) + { + for(int y2=8-fringe[x2]; y2<8; y2++) + { + putpixel(bmp,x2,y2,misc->colors.bmap_bg); + } + } + + rectfill(dest,x,y,x+(large?127:95),y+79,misc->colors.bmap_bg); + + for(int y2=0; y2<2; ++y2) + { + for(int x2=0; x2<(large?16:12); ++x2) + { + if((large?bmap_original[y2][x2]:bmap_bs[y2][x2])) + { + rectfill(dest,(x2<<3)+x,(y2*72)+y,(x2<<3)+x+7,(y2*72)+y+7,misc->colors.subscr_bg); + + switch((large?bmap_original[y2][x2]:bmap_bs[y2][x2])) + { + case 3: + draw_sprite_v_flip(dest,bmp,(x2<<3)+x,(y2*72)+y); + break; + + case 1: + default: + draw_sprite(dest,bmp,(x2<<3)+x,(y2*72)+y); + break; + } + } + } + } + + destroy_bitmap(bmp); + } + } + + if(showrooms) + { + if(roomcolor==-1) + { + roomcolor = misc->colors.bmap_fg; + } + + si=(get_currdmap()-1)<<6; + + for(int y2=y+8; y2colors.link_dot; + } + + int xoff = (((DMaps[get_currdmap()].type&dmfTYPE)==dmOVERW) ? 0 : DMaps[get_currdmap()].xoff); + putdot(dest,(((get_homescr()&15)-xoff)<<3)+x+(large?34:18)+(maptile?8:0),((get_homescr()&0xF0)>>1)+y+11,linkcolor); + } + } +} + + +void load_Sitems(miscQdata *misc) +{ + Sitems.clear(); + + // HC Pieces + if(misc->colors.HCpieces_tile) + { + // item *HCP = new item((fix)(inventory_x[5]-ofs),(fix)y,iMax,0,0); + item *HCP = new item((fix)0,(fix)0,(fix)0,iHCPiece,0,0); + + if(HCP) + { + int hcpphc = game->get_hcp_per_hc(); + HCP->tile = misc->colors.HCpieces_tile + vbound(game->get_HCpieces(),0,hcpphc > 0 ? hcpphc-1 : 0); + HCP->o_tile = HCP->tile; + HCP->cs = misc->colors.HCpieces_cset; + HCP->frames = 0; + add_subscr_item(HCP); + } + } + + if(has_item(itype_map, get_dlevel())) + { + add_subscr_item(new item((fix)0,(fix)0,(fix)0,iMap,0,0)); + } + + if(has_item(itype_compass, get_dlevel())) + { + add_subscr_item(new item((fix)0,(fix)0,(fix)0,iCompass,0,0)); + } + + if(has_item(itype_bosskey, get_dlevel())) + { + add_subscr_item(new item((fix)0,(fix)0,(fix)0,iBossKey,0,0)); + } + + for(int i=0; i-1) + { + int j = current_item_id(i,false); + + if(itemsbuf[j].tile) + add_subscr_item(new item((fix)0, (fix)0,(fix)0,j,0,0)); + } + } + + new_sel=true; +} + +void update_subscreens(int dmap) +{ + if(dmap<0) + dmap=get_currdmap(); + + int index=DMaps[dmap].active_subscreen; + + int i=-1, j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL&&i!=index) + { + if(custom_subscreen[j].ss_type==sstACTIVE) + { + ++i; + } + + ++j; + } + + current_subscreen_active=&custom_subscreen[j-1]; + + index=DMaps[dmap].passive_subscreen; + + i=-1, j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL&&i!=index) + { + if(custom_subscreen[j].ss_type==sstPASSIVE) + { + ++i; + } + + ++j; + } + + current_subscreen_passive=&custom_subscreen[j-1]; +} + +int ss_objects(subscreen_group *tempss) +{ + int i=0; + + while(iobjects[i].type!=ssoNULL) + { + ++i; + } + + return i; +} + + +void purge_blank_subscreen_objects(subscreen_group *tempss) +{ + int objects=ss_objects(tempss); + subscreen_object tempsso; + + //filter all the ssoNONE items to the end (yeah, bubble sort; sue me) + for(int j=0; jobjects[k].type==ssoNONE) + { + tempsso=tempss->objects[k]; + tempss->objects[k]=tempss->objects[k+1]; + tempss->objects[k+1]=tempsso; + } + } + } + + //NULL out the ssoNONE items + for(int j=0; jobjects[j].type==ssoNONE) + { + tempss->objects[j].type=ssoNULL; + } + } +} + + + +int get_alignment(subscreen_object *tempsso) +{ + switch(tempsso->type) + { + case ssoTEXT: + return tempsso->d2; + break; + + case ssoBSTIME: + return sstaLEFT; + break; + + case ssoTIME: + return sstaRIGHT; + break; + + case ssoSSTIME: + return sstaRIGHT; + break; + + case ssoCOUNTER: + return tempsso->d2; + break; + + case ssoMINIMAPTITLE: + return tempsso->d2; + break; + + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMNAME: + case ssoSELECTEDITEMNAME: + case ssoCURRENTITEMCLASSTEXT: + case ssoCURRENTITEMCLASSNAME: + case ssoSELECTEDITEMCLASSNAME: + return sstaLEFT; + break; + + case ssoNONE: + case sso2X2FRAME: + case ssoLINE: + case ssoRECT: + case ssoMAGICMETER: + case ssoLIFEMETER: + case ssoBUTTONITEM: + case ssoICON: + case ssoCOUNTERS: + case ssoMINIMAP: + case ssoLARGEMAP: + case ssoCLEAR: + case ssoCURRENTITEM: + case ssoITEM: + case ssoTRIFRAME: + case ssoTRIFORCE: + case ssoTILEBLOCK: + case ssoMINITILE: + case ssoSELECTOR1: + case ssoSELECTOR2: + case ssoMAGICGAUGE: + case ssoLIFEGAUGE: + case ssoTEXTBOX: + case ssoCURRENTITEMTILE: + case ssoSELECTEDITEMTILE: + default: + return sstaLEFT; + break; + } + +// return false;//UNREACHABLE +} + +//enum { sstsNORMAL, sstsSHADOW, sstsSHADOWU, sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsSHADOWED, sstsSHADOWEDU, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX, sstsMAX }; +// "None", "Shadow", "Shadow (U)","Shadow (O)", "Shadow (+)", "Shadow (X)", "Shadowed", "Shadowed (U)","Shadowed (O)","Shadowed (+)", "Shadowed (X)" +//x-1 +//sstsSHADOWU, sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsSHADOWEDU, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX +//w+1 +//sstsSHADOW, sstsSHADOWU, sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsSHADOWED, sstsSHADOWEDU, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX +//y-1 +//sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX +//h+1 +//sstsSHADOW, sstsSHADOWU, sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsSHADOWED, sstsSHADOWEDU, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX + +int sso_y(subscreen_object *tempsso) +{ + int y=0; + + switch(tempsso->type) + { + case ssoLIFEMETER: + y=tempsso->y+(tempsso->d2?0:(tempsso->d3?8:16)); + break; + + case ssoNONE: + case sso2X2FRAME: + case ssoTEXT: + case ssoLINE: + case ssoRECT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoMAGICMETER: + case ssoBUTTONITEM: + case ssoICON: + case ssoCOUNTER: + case ssoCOUNTERS: + case ssoMINIMAPTITLE: + case ssoMINIMAP: + case ssoLARGEMAP: + case ssoCLEAR: + case ssoCURRENTITEM: + case ssoITEM: + case ssoTRIFRAME: + case ssoTRIFORCE: + case ssoTILEBLOCK: + case ssoMINITILE: + case ssoSELECTOR1: + case ssoSELECTOR2: + case ssoMAGICGAUGE: + case ssoLIFEGAUGE: + case ssoTEXTBOX: + case ssoCURRENTITEMTILE: + case ssoSELECTEDITEMTILE: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMNAME: + case ssoSELECTEDITEMNAME: + case ssoCURRENTITEMCLASSTEXT: + case ssoCURRENTITEMCLASSNAME: + case ssoSELECTEDITEMCLASSNAME: + y=tempsso->y; + break; + + default: + y=(rand()*1000)%64; + break; + } + + switch(tempsso->type) + { + case ssoTEXT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoCOUNTER: + case ssoCOUNTERS: + switch(tempsso->d3) + { + case sstsOUTLINE8: + case sstsOUTLINEPLUS: + case sstsOUTLINEX: + case sstsOUTLINED8: + case sstsOUTLINEDPLUS: + case sstsOUTLINEDX: + y-=1; + break; + } + + break; + } + + return y; +} + +int sso_x(subscreen_object *tempsso) +{ + int x=0; + + switch(tempsso->type) + { + case ssoMAGICMETER: + x=tempsso->x-10; + break; + + case ssoNONE: + case sso2X2FRAME: + case ssoTEXT: + case ssoLINE: + case ssoRECT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoLIFEMETER: + case ssoBUTTONITEM: + case ssoICON: + case ssoCOUNTER: + case ssoCOUNTERS: + case ssoMINIMAPTITLE: + case ssoMINIMAP: + case ssoLARGEMAP: + case ssoCLEAR: + case ssoCURRENTITEM: + case ssoITEM: + case ssoTRIFRAME: + case ssoTRIFORCE: + case ssoTILEBLOCK: + case ssoMINITILE: + case ssoSELECTOR1: + case ssoSELECTOR2: + case ssoMAGICGAUGE: + case ssoLIFEGAUGE: + case ssoTEXTBOX: + case ssoCURRENTITEMTILE: + case ssoSELECTEDITEMTILE: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMNAME: + case ssoSELECTEDITEMNAME: + case ssoCURRENTITEMCLASSTEXT: + case ssoCURRENTITEMCLASSNAME: + case ssoSELECTEDITEMCLASSNAME: + x=tempsso->x; + break; + + default: + x=(rand()*1000)%64; + break; + } + + switch(tempsso->type) + { + case ssoTEXT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoCOUNTER: + case ssoCOUNTERS: + switch(tempsso->d3) + { + case sstsSHADOWU: + case sstsOUTLINE8: + case sstsOUTLINEPLUS: + case sstsOUTLINEX: + case sstsSHADOWEDU: + case sstsOUTLINED8: + case sstsOUTLINEDPLUS: + case sstsOUTLINEDX: + x-=1; + break; + } + + break; + } + + return x; +} + + + +int sso_h(subscreen_object *tempsso) +{ + int h=0; + + switch(tempsso->type) + { + case ssoNONE: + h=5; + break; + + case sso2X2FRAME: + h=tempsso->h*8; + break; + + case ssoTEXT: + h=text_height(ss_font(tempsso->d1)); + break; + + case ssoLINE: + h=tempsso->h; + break; + + case ssoRECT: + h=tempsso->h; + break; + + case ssoBSTIME: + h=text_height(ss_font(tempsso->d1)); + break; + + case ssoTIME: + h=text_height(ss_font(tempsso->d1)); + break; + + case ssoSSTIME: + h=text_height(ss_font(tempsso->d1)); + break; + + case ssoMAGICMETER: + h=8; + break; + + case ssoLIFEMETER: + h=tempsso->d3?24:16; + break; + + case ssoBUTTONITEM: + h=16; + break; + + case ssoICON: + h=8; + break; + + case ssoCOUNTER: + h=text_height(ss_font(tempsso->d1)); + break; + + case ssoCOUNTERS: + h=32; + break; + + case ssoMINIMAPTITLE: + h=16; + break; + + case ssoMINIMAP: + h=48; + break; + + case ssoLARGEMAP: + h=80; + break; + + case ssoCLEAR: + h=5; + break; + + case ssoCURRENTITEM: + h=16; + break; + + case ssoITEM: + h=16; + break; + + case ssoTRIFRAME: + h=16*((tempsso->d7)?7:3); + break; + + case ssoTRIFORCE: + h=16; + break; + + case ssoTILEBLOCK: + h=16*(tempsso->h); + break; + + case ssoMINITILE: + h=8; + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + h=tempsso->d5?32:16; + break; + + case ssoMAGICGAUGE: + h=8; + break; + + case ssoLIFEGAUGE: + h=8; + break; + + case ssoTEXTBOX: + h=tempsso->h; + break; + + case ssoCURRENTITEMTILE: + h=16; + break; + + case ssoSELECTEDITEMTILE: + h=16; + break; + + case ssoCURRENTITEMTEXT: + h=16; + break; + + case ssoCURRENTITEMNAME: + h=tempsso->h; + break; + + case ssoSELECTEDITEMNAME: + h=tempsso->h; + break; + + case ssoCURRENTITEMCLASSTEXT: + h=tempsso->h; + break; + + case ssoCURRENTITEMCLASSNAME: + h=tempsso->h; + break; + + case ssoSELECTEDITEMCLASSNAME: + h=tempsso->h; + break; + + default: + h=(rand()*1000)%64; + break; + } + + switch(tempsso->type) + { + case ssoTEXT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoCOUNTER: + case ssoCOUNTERS: + switch(tempsso->d3) + { + case sstsSHADOW: + case sstsSHADOWU: + case sstsOUTLINE8: + case sstsOUTLINEPLUS: + case sstsOUTLINEX: + case sstsSHADOWED: + case sstsSHADOWEDU: + case sstsOUTLINED8: + case sstsOUTLINEDPLUS: + case sstsOUTLINEDX: + h+=1; + break; + } + + break; + } + + return h; +} + +int sso_w(subscreen_object *tempsso) +{ + int w=0; + + switch(tempsso->type) + { + case ssoNONE: + w=5; + break; + + case sso2X2FRAME: + w=tempsso->w*8; + break; + + case ssoTEXT: + w=text_length(ss_font(tempsso->d1), (char *)tempsso->dp1); + break; + + case ssoLINE: + w=tempsso->w; + break; + + case ssoRECT: + w=tempsso->w; + break; + + case ssoBSTIME: + w=text_length(ss_font(tempsso->d1), time_str_short2(game->get_time())); + break; + + case ssoTIME: + w=text_length(ss_font(tempsso->d1), time_str_med(game->get_time())); + break; + + case ssoSSTIME: + w=text_length(ss_font(tempsso->d1), time_str_med(game->get_time())); + break; + + case ssoMAGICMETER: + w=82; + break; + + case ssoLIFEMETER: + w=64; + break; + + case ssoBUTTONITEM: + w=16; + break; + + case ssoICON: + w=8; + break; + + case ssoCOUNTER: + w=text_length(ss_font(tempsso->d1), "0")*tempsso->d4; + break; + + case ssoCOUNTERS: + w=32; + break; + + case ssoMINIMAPTITLE: + w=80; + break; + + case ssoMINIMAP: + w=80; + break; + + case ssoLARGEMAP: + w=16*((tempsso->d4)?9:7); + break; + + case ssoCLEAR: + w=5; + break; + + case ssoCURRENTITEM: + w=16; + break; + + case ssoITEM: + w=16; + break; + + case ssoTRIFRAME: + w=16*((tempsso->d7)?7:6); + break; + + case ssoTRIFORCE: + w=16; + break; + + case ssoTILEBLOCK: + w=16*(tempsso->w); + break; + + case ssoMINITILE: + w=8; + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + w=tempsso->d5?32:16; + break; + + case ssoMAGICGAUGE: + w=8; + break; + + case ssoLIFEGAUGE: + w=8; + break; + + case ssoTEXTBOX: + w=tempsso->w; + break; + + case ssoCURRENTITEMTILE: + w=16; + break; + + case ssoSELECTEDITEMTILE: + w=16; + break; + + case ssoCURRENTITEMTEXT: + w=16; + break; + + case ssoCURRENTITEMNAME: + w=tempsso->w; + break; + + case ssoSELECTEDITEMNAME: + w=tempsso->w; + break; + + case ssoCURRENTITEMCLASSTEXT: + w=tempsso->w; + break; + + case ssoCURRENTITEMCLASSNAME: + w=tempsso->w; + break; + + case ssoSELECTEDITEMCLASSNAME: + w=tempsso->w; + break; + + default: + w=(rand()*1000)%64; + break; + } + + switch(tempsso->type) + { + case ssoTEXT: + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + case ssoCOUNTER: + case ssoCOUNTERS: + switch(tempsso->d3) + { + case sstsSHADOW: + case sstsSHADOWU: + case sstsOUTLINE8: + case sstsOUTLINEPLUS: + case sstsOUTLINEX: + case sstsSHADOWED: + case sstsSHADOWEDU: + case sstsOUTLINED8: + case sstsOUTLINEDPLUS: + case sstsOUTLINEDX: + w+=1; + break; + } + + break; + } + + return w; +} + +void sso_bounding_box(BITMAP *bmp, subscreen_group *tempss, int index, int color) +{ + if(index<0) + { + return; + } + + int x=sso_x(&tempss->objects[index]); + int y=sso_y(&tempss->objects[index]); + int w=sso_w(&tempss->objects[index]); + int h=sso_h(&tempss->objects[index]); + + switch(get_alignment(&tempss->objects[index])) + { + case sstaCENTER: + x-=(w/2); + break; + + case sstaRIGHT: + x-=w; + break; + + case sstaLEFT: + default: + break; + } + + int c=x+w/2; + int m=y+h/2; + bool normalrect=true; + + if(color==-1) + { + color=jwin_pal[jcTITLER]; + } + else if(color==-2) + { + color=jwin_pal[jcTITLEL]; + } + + //draw a bounding box around the current object + if(normalrect) + { + rect(bmp, x, y, x+w-1, y+h-1, color); + } + else + { + rect(bmp, x-1, y-1, x+1, y+1, color); + rect(bmp, x-1, y+h-2, x+1, y+h, color); + rect(bmp, x+w-2, y-1, x+w, y+1, color); + rect(bmp, x+w-2, y+h-2, x+w, y+h, color); + + if(w>=9) + { + rect(bmp, c-1, y-1, c+1, y+1, color); + rect(bmp, c-1, y+h-2, c+1, y+h, color); + _allegro_hline(bmp, x+2, y, c-2, color); + _allegro_hline(bmp, c+2, y, x+w-3, color); + _allegro_hline(bmp, x+2, y+h-1, c-2, color); + _allegro_hline(bmp, c+2, y+h-1, x+w-3, color); + } + else + { + _allegro_hline(bmp, x+2, y, x+w-3, color); + _allegro_hline(bmp, x+2, y+h-1, x+w-3, color); + } + + if(h>=9) + { + rect(bmp, x-1, m-1, x+1, m+1, color); + rect(bmp, x+w-2, m-1, x+w, m+1, color); + _allegro_vline(bmp, x, y+2, m-2, color); + _allegro_vline(bmp, x, m+2, y+h-3, color); + _allegro_vline(bmp, x+w-1, y+2, m-2, color); + _allegro_vline(bmp, x+w-1, m+2, y+h-3, color); + } + else + { + _allegro_vline(bmp, x, y+2, y+h-3, color); + _allegro_vline(bmp, x+w-1, y+2, y+h-3, color); + } + } +} + + +/*** end of subscr.cc ***/ + diff --git a/src/subscr.h b/src/subscr.h new file mode 100644 index 0000000000..b48009e9e9 --- /dev/null +++ b/src/subscr.h @@ -0,0 +1,281 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// subscr.cc +// +// Subscreen code for zelda.cc +// +//-------------------------------------------------------- + +#ifndef _SUBSCR_H_ +#define _SUBSCR_H_ + +#include "sprite.h" +#include "items.h" +#include + +#define ssflagSHOWGRID 1 + + +extern bool show_subscreen_dmap_dots; +extern bool show_subscreen_numbers; +extern bool show_subscreen_items; +extern bool show_subscreen_life; + +void frame2x2(BITMAP *dest,miscQdata *misc,int x,int y,int tile,int cset,int w,int h,int flip,bool overlay,bool trans); +void drawgrid(BITMAP *dest,int x,int y,int c1,int c2); +void draw_block(BITMAP *dest,int x,int y,int tile,int cset,int w,int h); +void drawdmap(BITMAP *dest, miscQdata *misc, int x, int y, bool showmap, int showlink, int showcompass, int linkcolor, int lccolor, int dccolor); +void lifemeter(BITMAP *dest,int x,int y,int tile,bool bs_style); +void magicmeter(BITMAP *dest,int x,int y); +void buttonitem(BITMAP *dest, int button, int x, int y); +void putxnum(BITMAP *dest,int x,int y,int num,FONT *tempfont,int color,int shadowcolor,int bgcolor,int textstyle,bool usex,int digits,bool infinite,char idigit); +void defaultcounters(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, bool usex, int textstyle, int digits, char idigit); +void counter(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, int alignment, int textstyle, int digits, char idigit, bool showzero, int itemtype1, int itemtype2, int itemtype3, int infiniteitem, bool onlyselected); +void minimaptitle(BITMAP *dest, int x, int y, FONT *tempfont, int color, int shadowcolor, int bgcolor, int alignment, int textstyle); +void animate_selectors(); +void delete_selectors(); + +INLINE void putdot(BITMAP *dest,int x,int y,int c) +{ + rectfill(dest,x,y,x+2,y+2,c); +} + +// subscreen default types +enum { ssdtOLD, ssdtNEWSUBSCR, ssdtREV2, ssdtBSZELDA, ssdtBSZELDAMODIFIED, ssdtBSZELDAENHANCED, ssdtBSZELDACOMPLETE, ssdtZ3, ssdtMAX }; + +enum { sstACTIVE, sstPASSIVE, sstMAX }; + +enum { sssFULLPUSH, sssFULLSLIDEDOWN, sssMAX }; + +// subscreen object types +enum { ssoNULL, ssoNONE, sso2X2FRAME, ssoTEXT, + ssoLINE, ssoRECT, ssoBSTIME, ssoTIME, ssoSSTIME, ssoMAGICMETER, ssoLIFEMETER, ssoBUTTONITEM, ssoICON, ssoCOUNTER, + ssoCOUNTERS, ssoMINIMAPTITLE, ssoMINIMAP, ssoLARGEMAP, ssoCLEAR, ssoCURRENTITEM, ssoITEM, ssoTRIFRAME, ssoTRIFORCE, ssoTILEBLOCK, ssoMINITILE, ssoSELECTOR1, ssoSELECTOR2, + ssoMAGICGAUGE, ssoLIFEGAUGE, ssoTEXTBOX, ssoCURRENTITEMTILE, ssoSELECTEDITEMTILE, ssoCURRENTITEMTEXT, ssoCURRENTITEMNAME, ssoSELECTEDITEMNAME, ssoCURRENTITEMCLASSTEXT, + ssoCURRENTITEMCLASSNAME, ssoSELECTEDITEMCLASSNAME, ssoMAX + }; +//ssoCURRENTITEM shows what item of that type you currently have. if the itemtype is sword, it will show what sword you have +//ssoBUTTONITEM shows what item is currently assigned to the A or B button +//ssoITEMTILE shows a requested item +//ssoCURRENTITEMTILE shows a tile (or animation) if you have the item requested. if itemtype is set to wooden boomerang and you have a wooden boomerang, it will show the tile you choose +//ssoSELECTEDITEMTILE shows a tile (or animation) if the selection cursor is on the item requested. +//ssoCURRENTITEMTEXT shows the requested text if you have the item requested. if itemtype is set to wooden boomerang and you have a wooden boomerang, it will show the text you choose, "Curved stick", for instance. +//ssoCURRENTITEMNAME shows the name of an item if you have the item requested. if itemtype is set to wooden boomerang and you have a wooden boomerang, it will show the name of the item "Wooden Boomerang" +//ssoSELECTEDITEMNAME shows the name of of the item that the selection cursor is on. +//ssoCURRENTITEMCLASSTEXT shows the requested text if you have the item requested. if itemtype is set to boomerang and you have a wooden boomerang, it will show the text you choose, "Curved stick", for instance. +//ssoCURRENTITEMCLASSNAME shows the name of an item if you have the item requested. if itemtype is set to boomerang and you have a wooden boomerang, it will show the name of the item "Wooden Boomerang" +//ssoSELECTEDITEMCLASSNAME shows the name of of the item class that the selection cursor is on. + +//text styles +enum { sstsNORMAL, sstsSHADOW, sstsSHADOWU, sstsOUTLINE8, sstsOUTLINEPLUS, sstsOUTLINEX, sstsSHADOWED, sstsSHADOWEDU, sstsOUTLINED8, sstsOUTLINEDPLUS, sstsOUTLINEDX, sstsMAX }; + +//subscreen fonts +enum { ssfZELDA, ssfSS1, ssfSS2, ssfSS3, ssfSS4, ssfZTIME, ssfSMALL, ssfSMALLPROP, ssfZ3SMALL, ssfGBLA, ssfZ3, + ssfGORON, ssfZORAN, ssfHYLIAN1, ssfHYLIAN2, ssfHYLIAN3, ssfHYLIAN4, ssfPROP, ssfGBORACLE, ssfGBORACLEP, + ssfDSPHANTOM, ssfDSPHANTOMP, ssfMAX + }; + +// subscreen color types +enum { ssctSYSTEM=0xFE, ssctMISC=0xFF }; + +// special colors +enum { ssctTEXT, ssctCAPTION, ssctOVERWBG, ssctDNGNBG, ssctDNGNFG, ssctCAVEFG, ssctBSDK, ssctBSGOAL, ssctCOMPASSLT, ssctCOMPASSDK, ssctSUBSCRBG, ssctSUBSCRSHADOW, + ssctTRIFRAMECOLOR, ssctBMAPBG, ssctBMAPFG, ssctLINKDOT, ssctMSGTEXT, ssctMAX + }; + +// special csets +enum { sscsTRIFORCECSET, sscsTRIFRAMECSET, sscsOVERWORLDMAPCSET, sscsDUNGEONMAPCSET, sscsBLUEFRAMECSET, sscsHCPIECESCSET, sscsSSVINECSET, sscsMAX }; + +// special tiles +enum { ssmstSSVINETILE, ssmstMAGICMETER, ssmstMAX }; + +// counter objects +enum { sscRUPEES, sscBOMBS, sscSBOMBS, sscARROWS, + sscGENKEYMAGIC, sscGENKEYNOMAGIC, sscLEVKEYMAGIC, sscLEVKEYNOMAGIC, + sscANYKEYMAGIC, sscANYKEYNOMAGIC, sscSCRIPT1, sscSCRIPT2, + sscSCRIPT3, sscSCRIPT4, sscSCRIPT5, sscSCRIPT6, + sscSCRIPT7, sscSCRIPT8, sscSCRIPT9, sscSCRIPT10, + sscSCRIPT11, sscSCRIPT12, sscSCRIPT13, sscSCRIPT14, + sscSCRIPT15, sscSCRIPT16, sscSCRIPT17, sscSCRIPT18, + sscSCRIPT19, sscSCRIPT20, sscSCRIPT21, sscSCRIPT22, + sscSCRIPT23, sscSCRIPT24, sscSCRIPT25, sscMAX + }; + + +//subscreen items +/*enum { ssiBOMB, ssiSWORD, ssiSHIELD, ssiCANDLE, ssiLETTER, ssiPOTION, ssiLETTERPOTION, ssiBOW, ssiARROW, ssiBOWANDARROW, ssiBAIT, ssiRING, ssiBRACELET, ssiMAP, + ssiCOMPASS, ssiBOSSKEY, ssiMAGICKEY, ssiBRANG, ssiWAND, ssiRAFT, ssiLADDER, ssiWHISTLE, ssiBOOK, ssiWALLET, ssiSBOMB, ssiHCPIECE, ssiAMULET, ssiFLIPPERS, + ssiHOOKSHOT, ssiLENS, ssiHAMMER, ssiBOOTS, ssiDINSFIRE, ssiFARORESWIND, ssiNAYRUSLOVE, ssiQUIVER, ssiBOMBBAG, ssiCBYRNA, ssiROCS, ssiHOVERBOOTS, + ssiSPINSCROLL, ssiCROSSSCROLL, ssiQUAKESCROLL, ssiWHISPRING, ssiCHARGERING, ssiPERILSCROLL, ssiWEALTHMEDAL, ssiHEARTRING, ssiMAGICRING, ssiSPINSCROLL2, + ssiQUAKESCROLL2, ssiAGONY, ssiSTOMPBOOTS, ssiWHIMSICALRING, ssiPERILRING, ssiMAX };*/ + +//subscreen text alignment +enum { sstaLEFT, sstaCENTER, sstaRIGHT }; + +//when to display an element +#define sspUP 1 +#define sspDOWN 2 +#define sspSCROLLING 4 + +struct sso_struct +{ + char *s; + int i; +}; + +extern sso_struct bisso[ssoMAX]; + + +struct subscreen_object +{ + byte type; + byte pos; + word x; + word y; + word w; + word h; + byte colortype1; + short color1; + byte colortype2; + short color2; + byte colortype3; + short color3; + int d1; + int d2; + int d3; //pos + int d4; //up + int d5; //down + int d6; //left + int d7; //right + int d8; + int d9; + int d10; + byte frames; + byte speed; + byte delay; + word frame; + void *dp1; +}; + +struct subscreen_group +{ + byte ss_type; + char name[64]; + subscreen_object objects[MAXSUBSCREENITEMS]; +}; + + + +/**** Subscr items code ****/ +extern subscreen_object default_subscreen_active[ssdtMAX][2][66]; +extern subscreen_object default_subscreen_passive[ssdtMAX][2][21]; +//extern subscreen_object z3_active[200]; +//extern subscreen_object z3_passive[200]; +extern subscreen_object z3_active_a[80]; +extern subscreen_object z3_passive_a[66]; +extern subscreen_object z3_active_ab[82]; +extern subscreen_object z3_passive_ab[75]; +extern subscreen_group custom_subscreen[MAXCUSTOMSUBSCREENS]; +extern subscreen_group *current_subscreen_active; +extern subscreen_group *current_subscreen_passive; + +extern item *Bitem, *Aitem; +extern int Bid, Aid; +const byte tripiece[2][8][3] = +{ + // 112,112,0, 128,112,1, 96,128,0, 144,128,1, + // 112,128,2, 112,128,1, 128,128,3, 128,128,0 + { + //old style + {32,8,0}, + {48,8,1}, + {16,24,0}, + {64,24,1}, + {32,24,2}, + {32,24,1}, + {48,24,3}, + {48,24,0} + }, + { + //bs style + {32,8,0}, + {56,8,1}, + {8,56,0}, + {80,56,1}, + {32,56,2}, + {32,56,1}, + {56,56,3}, + {56,56,0} + } +}; +const byte bmap_original[2][16] = +{ + {0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0}, + {0,3,0,0,0,3,0,0,0,0,3,0,0,0,3,0} +}; +const byte bmap_bs[2][12] = +{ + {0,0,1,0,0,1,0,0,1,0,1,0}, + {0,3,0,0,3,0,0,3,0,3,0,0} +}; +const int fringe[8] = { 6,2,4,7,6,8,7,5 }; +const byte bmaptiles_old[8*5] = +{ + 0, 1, 2, 3, 2, 3, 3, 4, + 20,21,22,23,22,23,23,24, + 20,21,22,23,22,23,23,24, + 20,21,22,23,22,23,23,24, + 40,41,42,43,42,43,43,44 +}; + +const byte bmaptiles_original[5][8] = +{ + {0, 1, 2, 3, 2, 3, 3, 4}, + {20,21,22,23,22,23,23,24}, + {20,21,22,23,22,23,23,24}, + {20,21,22,23,22,23,23,24}, + {40,41,42,43,42,43,43,44} +}; + +const byte bmaptiles_bs[5][6] = +{ + {0, 1, 2, 3, 3, 4}, + {20,21,22,23,23,24}, + {20,21,22,23,23,24}, + {20,21,22,23,23,24}, + {40,41,42,43,43,44} +}; + +void reset_subscr_items(); +void update_subscr_items(); +void add_subscr_item(item *newItem); +int stripspaces(char *source, char *target, int stop); +void put_passive_subscr(BITMAP *dest,miscQdata *misc,int x,int y,bool showtime,int pos2); +void puttriframe(BITMAP *dest, miscQdata *misc, int x, int y, int triframecolor, int numbercolor, int triframetile, int triframecset, int triforcetile, int triforcecset, bool showframe, bool showpieces, bool largepieces); +void puttriforce(BITMAP *dest, miscQdata *misc, int x, int y, int tile, int cset, int w, int h, int flip, bool overlay, bool trans, int trinum); +void draw_block(BITMAP *dest,int x,int y,int tile,int cset,int w,int h); +void draw_block_flip(BITMAP *dest,int x,int y,int tile,int cset,int w,int h,int flip,bool overlay,bool trans); +void putBmap(BITMAP *dest, miscQdata *misc, int x, int y,bool showmap, bool showrooms, bool showlink, int roomcolor, int linkcolor, bool large); +void load_Sitems(miscQdata *misc); +void textout_styled_aligned_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int textstyle, int alignment, int color, int shadow, int bg); +void textprintf_styled_aligned_ex(BITMAP *bmp, const FONT *f, int x, int y, int textstyle, int alignment, int color, int shadow, int bg, const char *format, ...); +void update_subscreens(int dmap=-1); +void show_custom_subscreen(BITMAP *dest, miscQdata *misc, subscreen_group *css, int xofs, int yofs, bool showtime, int pos2); +FONT *ss_font(int fontnum); +int ss_objects(subscreen_group *tempss); +void purge_blank_subscreen_objects(subscreen_group *tempss); +int subscreen_cset(miscQdata *misc,int c1, int c2); + +int sso_x(subscreen_object *tempsso); +int sso_y(subscreen_object *tempsso); +int sso_h(subscreen_object *tempsso); +int sso_w(subscreen_object *tempsso); +int get_alignment(subscreen_object *tempsso); +void sso_bounding_box(BITMAP *bmp, subscreen_group *tempss, int index, int color); + +#endif + +/*** end of subscr.cc ***/ + diff --git a/src/tab_ctl.cpp b/src/tab_ctl.cpp new file mode 100644 index 0000000000..031894b318 --- /dev/null +++ b/src/tab_ctl.cpp @@ -0,0 +1,710 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.c + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ + +/* This code is not fully tested */ + +#include "precompiled.h" //always first + +#define ALLEGRO_NO_COMPATIBILITY +#include +#include "tab_ctl.h" +#include "zc_malloc.h" + +//#ifdef _ZQUEST_SCALE_ +extern volatile int myvsync; +extern int zqwin_scale; +extern BITMAP *hw_screen; +//#endif + +extern bool is_zquest(); + +int vc2(int x) +{ + switch(x) + { + case 0: //black + return makecol(0, 0, 0); + break; + + case 1: //blue + return makecol(0, 0, 170); + break; + + case 2: //green + return makecol(0, 170, 0); + break; + + case 3: //cyan + return makecol(0, 170, 170); + break; + + case 4: //red + return makecol(170, 0, 0); + break; + + case 5: //magenta + return makecol(170, 0, 170); + break; + + case 6: //brown + return makecol(170, 85, 170); + break; + + case 7: //light grey + return makecol(170, 170, 170); + break; + + case 8: //dark grey + return makecol(85, 85, 85); + break; + + case 9: //light blue + return makecol(85, 85, 255); + break; + + case 10: //light green + return makecol(85, 255, 85); + break; + + case 11: //light cyan + return makecol(85, 255, 255); + break; + + case 12: //light red (pink) + return makecol(255, 85, 85); + break; + + case 13: //light magenta (lavender) + return makecol(255, 85, 255); + break; + + case 14: //light brown (yellow) + return makecol(255, 255, 85); + break; + + case 15: //white + return makecol(255, 255, 255); + break; + } + + return -1; +} + + +INLINE int is_in_rect(int x,int y,int rx1,int ry1,int rx2,int ry2) +{ + return x>=rx1 && x<=rx2 && y>=ry1 && y<=ry2; +} + +void draw_button(BITMAP *dest,int x,int y,int w,int h,const char *text,int bg,int fg,int flags) +{ + int temp; + + if(flags&D_SELECTED) + { + temp=fg; + fg=bg; + bg=temp; + } + + rect(dest,x+1,y+1,x+w-1,y+h-1,fg); + rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg); + rect(dest,x,y,x+w-2,y+h-2,fg); + textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1); +} + +bool do_text_button(int x,int y,int w,int h,const char *text,int bg,int fg) +{ + bool over=false; + + while(gui_mouse_b()) + { + vsync(); + + if(is_in_rect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_button(screen,x,y,w,h,text,bg,fg,D_SELECTED); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_button(screen,x,y,w,h,text,bg,fg,0); + unscare_mouse(); + over=false; + } + } + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + return over; +} + +bool do_text_button_reset(int x,int y,int w,int h,const char *text,int bg,int fg) +{ + bool over=false; + + while(gui_mouse_b()) + { + vsync(); + + if(is_in_rect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_button(screen,x,y,w,h,text,bg,fg,D_SELECTED); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_button(screen,x,y,w,h,text,bg,fg,0); + unscare_mouse(); + over=false; + } + } + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + if(over) + { + vsync(); + scare_mouse(); + draw_button(screen,x,y,w,h,text,bg,fg,0); + unscare_mouse(); + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif + } + + return over; +} + +int tab_count(TABPANEL *panel) +{ + int i=0; + + for(i=0; panel[i].text; ++i) + { + /* do nothing */ + } + + return i; +} + +int tabs_width(TABPANEL *panel) +{ + int i=0; + int w=0; + + for(i=0; panel[i].text; ++i) + { + w+=text_length(font, (char *)panel[i].text)+15; + } + + return w+1; +} + +bool uses_tab_arrows(TABPANEL *panel, int maxwidth) +{ +// return (((d->d1&0xFF00)>>8)!=0||last_visible_tab(panel,((d->d1&0xFF00)>>8),d->w)+1maxwidth); +} + +int last_visible_tab(TABPANEL *panel, int first_tab, int maxwidth) +{ + int i=0; + int w=0; + + if(uses_tab_arrows(panel, maxwidth)) + { + maxwidth-=28; + } + + for(i=first_tab; panel[i].text; ++i) + { + w+=text_length(font, (char *)panel[i].text)+15; + + if(w>maxwidth) + { + return i-1; + } + } + + return i-1; +} + +int displayed_tabs_width(TABPANEL *panel, int first_tab, int maxwidth) +{ + int i=0; + int w=0; + + for(i=first_tab; panel[i].text&&i<=last_visible_tab(panel, first_tab, maxwidth); ++i) + { + w+=text_length(font, (char *)panel[i].text)+15; + } + + return w+1; +} + +int discern_tab(TABPANEL *panel, int first_tab, int x) +{ + int i=0; + int w=0; + + for(i=first_tab; panel[i].text; i++) + { + w+=text_length(font, (char *)panel[i].text)+15; + + if(w>x) + { + return i; + } + } + + return -1; +} + +int d_tab_proc(int msg, DIALOG *d, int c) +{ + int fg; + int i; + int tx; + int sd=2; //selected delta + TABPANEL *panel=(TABPANEL *)d->dp; + DIALOG *panel_dialog=NULL, *current_object=NULL; + int selected=0; + int counter=0; + ASSERT(d); + (void) c; + int temp_d, temp_d2; + + if(d->dp==NULL) + { + return 0; + } + + //d->d1&(0xFF00)>>8 is the first visible tab + //d->d1&0x00FF is the currently? selected tab + switch(msg) + { + case MSG_START: + { + d->d1&=0xFF00; + d->d1|=0x00FF; + + //for each tab... + for(i=0; panel[i].text; i++) + { + panel[i].objects=0; + + //see how many controls (i) are handled by this tab + while(panel[i].dialog[(panel[i].objects)++]!=-1) + { + /* do nothing */ + } + + //because the -1 is counted, drop back one + (panel[i].objects)--; + //allocate space to store the x and y coordinates for them + panel[i].xy=(int*)zc_malloc(panel[i].objects*2*sizeof(int)); + //what dialog is this tab control in (programmer must set manually) + panel_dialog=(DIALOG *)d->dp3; + + //for each object handled by this tab... + for(counter=0; counterx; + panel[i].xy[counter*2+1]=current_object->y; + //move the control offscreen + current_object->x=SCREEN_W*3; + current_object->y=SCREEN_H*3; + current_object->flags|=D_HIDDEN; + } + } + + d->d2=1; + } + break; + + case MSG_END: + { + for(i=0; panel[i].text; i++) + { + //what dialog is this tab control in (programmer must set manually) + panel_dialog=(DIALOG *)d->dp3; + + //for each object handled by this tab... + for(counter=0; counterx=panel[i].xy[counter*2]; + current_object->y=panel[i].xy[counter*2+1]; + } + } + } + break; + + case MSG_IDLE: + { + //if we are off-screen + if(d->x>SCREEN_W||d->y>SCREEN_H) + { + if(d->d2==1) + { + //for each tab + for(i=0; panel[i].text; i++) + { + //what dialog is this tab control in (programmer must set manually) + panel_dialog=(DIALOG *)d->dp3; + + //for each object handled by this tab... + for(counter=0; counterx=SCREEN_W*3; + current_object->y=SCREEN_H*3; + } + } + + d->d2=0; + } + } + else + { + d->d2=1; + } + } + break; + + case MSG_DCLICK: + case MSG_LPRESS: + case MSG_LRELEASE: + case MSG_MPRESS: + case MSG_MRELEASE: + case MSG_RPRESS: + case MSG_RRELEASE: + case MSG_GOTMOUSE: + case MSG_LOSTMOUSE: + break; + + + case MSG_DRAW: + { + //backup the default font + FONT *oldfont = font; + + if(d->xydp2) + { + font = (FONT *)d->dp2; + } + + panel_dialog=(DIALOG *)d->dp3; + rectfill(screen, d->x, d->y, d->x+d->w-1, d->y+8+text_height(font), d->bg); //tab area + fg = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + rectfill(screen, d->x+1, d->y+sd+text_height(font)+7, d->x+d->w-2, d->y+sd+d->h-2, d->bg); //panel + //left, right, and bottom borders of the tab control + _allegro_vline(screen, d->x, d->y+sd+7+text_height(font), d->y+sd+d->h-1, fg); + _allegro_vline(screen, d->x+d->w-1, d->y+sd+7+text_height(font), d->y+sd+d->h-1, fg); + _allegro_hline(screen, d->x+1, d->y+sd+d->h-1, d->x+d->w-2, fg); + //tx=tab control x position + tx=d->x; + + //if the programmer gave us a tab panel set to use... + if(d->dp) + { + //if the first tab is not selected + if(!(panel[((d->d1&0xFF00)>>8)].flags&D_SELECTED)) + { + //draw the initial tab panel top border + _allegro_hline(screen, tx, d->y+sd+6+text_height(font), tx+1, fg); //initial bottom + } + + tx+=2; + + //for each tab (that actually has text) + for(i=0; panel[i].text; ++i) + { + if(panel[i].flags&D_SELECTED) + { + selected=i; + } + } + + for(i=((d->d1&0xFF00)>>8); panel[i].text&&i<=last_visible_tab(panel,((d->d1&0xFF00)>>8),d->w); ++i) + { + //sd is 2 if the panel is not selected, 0 if it is + sd=(panel[i].flags&D_SELECTED)?0:2; + + //if this is the first tab or if the previous tab is not selected (doesn't cover the left side of this tab) + if((i==((d->d1&0xFF00)>>8)) || (!(panel[i-1].flags&D_SELECTED))) + { + //draw the left side of the tab + _allegro_vline(screen, tx-(2-sd), d->y+sd+2, d->y+8+text_height(font), fg); //left side + putpixel(screen, tx+1-(2-sd), d->y+sd+1, fg); //left angle + } + + _allegro_hline(screen, tx+2-(2-sd), d->y+sd, tx+12+(2-sd)+text_length(font, (char *)panel[i].text), fg); //top + + //if the tab is not selected... + if(!(panel[i].flags&D_SELECTED)) + { + //draw the top border of the tab panel under the tab itself + _allegro_hline(screen, tx+1, d->y+sd+6+text_height(font), tx+13+text_length(font, (char *)panel[i].text), fg); //bottom + } + + tx+=4; + //draw the text of the panel + gui_textout_ex(screen, (char *)panel[i].text, tx+4, d->y+sd+4, fg, d->bg, FALSE); + tx+=text_length(font, (char *)panel[i].text)+10; + + //if this is the last tab or the next tab is not selected... + if(!(panel[i+1].text) || (!(panel[i+1].flags&D_SELECTED))) + { + //draw the right side of this tab + putpixel(screen, tx-1+(2-sd), d->y+sd+1, fg); //right angle + _allegro_vline(screen, tx+(2-sd), d->y+sd+2, d->y+8+text_height(font), fg); //right side + } + + tx++; + } + + if(uses_tab_arrows(panel, d->w)) + { + draw_button(screen,d->x+d->w-28,d->y+2, 14, 14, "\x8A", vc2(15), vc2(0), 0); + draw_button(screen,d->x+d->w-14,d->y+2, 14, 14, "\x8B", vc2(15), vc2(0), 0); + } + } + + //draw the remaining top border of the tab panel control + _allegro_hline(screen, tx+(2-sd), d->y+8+text_height(font), d->x+d->w-1, fg); //ending bottom + //restore the default font + font = oldfont; + + //what dialog is this tab control in (programmer must set manually) + panel_dialog=(DIALOG *)d->dp3; + + //for each object handled by the currently selected tab... + for(counter=0; counterx=panel[selected].xy[counter*2]; + current_object->y=panel[selected].xy[counter*2+1]; + object_message(current_object, MSG_DRAW, 0); + } + } + + //if there was a previously selected tab... + if((d->d1&0x00FF)!=0x00FF) + { + //for each object handled by the tab + for(counter=0; counterd1&0x00FF].objects; counter++) + { + //assign current_object to one of the controls handled by the tab + current_object=panel_dialog+(panel[d->d1&0x00FF].dialog[counter]); + //move them off screen + current_object->x=SCREEN_W*3; + current_object->y=SCREEN_H*3; + } + } + + for(i=0; panel[i].text; i++) + { + //if the tab is the selected one... + if(panel[i].flags&D_SELECTED) + { + //remember it + d->d1&=0xFF00; + d->d1|=(i&0x00FF); + } + } + } + break; + + case MSG_CLICK: + { + FONT *oldfont = font; + + //do the tabs have a custom font? + if(d->dp2) + { + font = (FONT *)d->dp2; + } + + d->d1&=0xFF00; + d->d1|=0x00FF; + + // is the mouse on one of the tab arrows (if visible) or in the tab area? + if(uses_tab_arrows(panel, d->w)&&(is_in_rect(gui_mouse_x(),gui_mouse_y(), d->x+d->w-28, d->y+2, d->x+d->w-1, d->y+15))) + { + if(is_in_rect(gui_mouse_x(),gui_mouse_y(), d->x+d->w-28, d->y+2, d->x+d->w-15, d->y+15)) + { + if(do_text_button_reset(d->x+d->w-28, d->y+2, 14, 14, "\x8A",d->bg,d->fg)) + { + temp_d=((d->d1&0xFF00)>>8); + temp_d2=(d->d1&0x00FF); + + if(temp_d>0) + { + --temp_d; + } + + d->d1=(temp_d<<8)|temp_d2; + d->flags|=D_DIRTY; + } + } + else if(is_in_rect(gui_mouse_x(),gui_mouse_y(), d->x+d->w-14, d->y+2, d->x+d->w-1, d->y+15)) + { + if(do_text_button_reset(d->x+d->w-14, d->y+2, 14, 14, "\x8B",d->bg,d->fg)) + { + temp_d=((d->d1&0xFF00)>>8); + temp_d2=(d->d1&0x00FF); + + if(last_visible_tab(panel, temp_d, d->w)<(tab_count(panel)-1)) + { + ++temp_d; + } + + d->d1=(temp_d<<8)|temp_d2; + d->flags|=D_DIRTY; + } + } + } + else if(is_in_rect(gui_mouse_x(),gui_mouse_y(), d->x+2, d->y+2, d->x+displayed_tabs_width(panel,((d->d1&0xFF00)>>8),d->w), d->y+text_height(font)+9)) + { + // for each tab... + for(i=0; panel[i].text; i++) + { + // see if it's the selected tab and make note of it (in d->d1&0x00FF) + if(panel[i].flags&D_SELECTED) + { + d->d1&=0xFF00; + d->d1|=(i&0x00FF); + } + } + + // find out what the new tab (tb) will be (where the mouse is) + selected=discern_tab(panel, ((d->d1&0xFF00)>>8), gui_mouse_x()-d->x-2); + + if(selected!=-1&&selected!=(d->d1&0x00FF)) + { + for(i=0; panel[i].text; i++) + { + panel[i].flags &= ~D_SELECTED; + } + + panel[selected].flags |= D_SELECTED; + object_message(d, MSG_DRAW, 0); + } + } + + font = oldfont; + } + break; + } + + return D_O_K; +} + +/*** The End ***/ + diff --git a/src/tab_ctl.h b/src/tab_ctl.h new file mode 100644 index 0000000000..051c4af99a --- /dev/null +++ b/src/tab_ctl.h @@ -0,0 +1,60 @@ +/* __ __ + * /_/\ __ __ __ /_/\ ______ + * _\_\/ / /\/ /\/ /\ _\_\/ / ____ \ + * / /\ / / / / / / / / /\ / /\_ / /\ + * __ / / / / /_/ /_/ / / / / / / / / / / / + * / /_/ / / /_________/ / /_/ / /_/ / /_/ / + * \____/ / \_________\/ \_\/ \_\/ \_\/ + * \___\/ + * + * + * + * jwin.c + * + * Windows(R) style GUI for Allegro. + * by Jeremy Craner + * + * Most routines are adaptations of Allegro code. + * Allegro is by Shawn Hargreaves, et al. + * + * Version: 3/22/00 + * Allegro version: 3.1x (don't know if it works with WIP) + * + */ + +/* This code is not fully tested */ + +#ifndef _TAB_INTERN_H_ +#define _TAB_INTERN_H_ + +#include "zc_alleg.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif +int vc2(int x); +/* a tab panel */ +typedef struct TABPANEL +{ + char *text; /* menu item text */ + // AL_METHOD(int, proc, (void)); /* callback function */ + // struct MENU *child; /* to allow nested menus */ + int flags; /* flags about the menu state */ + int *dialog; /* pointer to group of dialog objects that this tab contains */ + int objects; /* count of number of objects this tab handles; auto-calculated */ + int *xy; /* x and y coords of those dialog objects. */ +} TABPANEL; + +bool uses_tab_arrows(TABPANEL *panel, int maxwidth); +int tab_count(TABPANEL *panel); +int last_visible_tab(TABPANEL *panel, int first_tab, int maxwidth); +int d_tab_proc(int msg, DIALOG *d, int c); +#ifdef __cplusplus +} +#endif +#endif + +/*** The End ***/ + diff --git a/src/tiles.cpp b/src/tiles.cpp new file mode 100644 index 0000000000..05bfa695a2 --- /dev/null +++ b/src/tiles.cpp @@ -0,0 +1,2629 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// tiles.cc +// +// Tile drawing routines for ZC. +// +// !! Don't use them on "screen"; use memory BITMAPs only. +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +#include "precompiled.h" //always first + +#include "zc_alleg.h" +#include + +#include "zdefs.h" +#include "zsys.h" +#include "tiles.h" +#include "mem_debug.h" + +extern RGB_MAP rgb_table; +extern COLOR_MAP trans_table; +extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; +extern byte quest_rules[QUESTRULES_SIZE]; +//extern byte *tilebuf; +//BITMAP* tilebuf[NEWMAXTILES]; +tiledata *newtilebuf, *grabtilebuf; +newcombo *combobuf; + +word animated_combo_table[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +word animated_combo_table4[MAXCOMBOS][2]; //[0]=combo, [1]=clock +word animated_combos; +word animated_combo_table2[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +word animated_combo_table24[MAXCOMBOS][2]; //[0]=combo, [1]=clock +word animated_combos2; + +bool blank_tile_table[NEWMAXTILES]; //keeps track of blank tiles +bool used_tile_table[NEWMAXTILES]; //keeps track of used tiles +bool blank_tile_quarters_table[NEWMAXTILES*4]; //keeps track of blank tile quarters +extern fix LinkModifiedX(); +extern fix LinkModifiedY(); + +bool unused_tile_table[NEWMAXTILES]; //keeps track of unused tiles + +byte unpackbuf[UNPACKSIZE]; + +bool isblanktile(tiledata *buf, int i) +{ + // byte *tilestart=tilebuf+(i*128); + byte *tilestart=buf[i].data; + qword *di=(qword*)tilestart; + int parts=tilesize(buf[i].format)>>3; + + for(int j=0; j>6; + + for(int r=0; r<16; ++r) + { + for(int j=0; j(parts/2-1))?1:0); + blank_tile_quarters_table[q]=false; + } + } + } +} + + + +void register_blank_tiles() +{ + //int tiles_used=count_tiles(newtilebuf); + for(int i=0; i0; --tiles_used) + { + /* + used=false; + for (x=0; x<128; ++x) + { + used=used || (tilebuf[(tiles_used-1)*128+x]!=0); + } + if (used) + { + break; + } + */ + if(!isblanktile(buf, tiles_used-1)) + { + break; + } + } + + return tiles_used; +} + +//returns the number of combos +word count_combos() +{ + word combos_used; + + for(combos_used=MAXCOMBOS; combos_used>0; --combos_used) + { + if(combobuf[combos_used-1].tile!=0) + { + break; + } + } + + return combos_used; +} + +void setup_combo_animations() +{ + memset(animated_combo_table, 0, MAXCOMBOS*2*2); + memset(animated_combo_table4, 0, MAXCOMBOS*2*2); + int y=0; + + for(word x=0; x1 || combobuf[x].nextcombo != 0)&&!(combobuf[x].animflags & AF_FRESH)) + { + animated_combo_table4[y][0]=x; + animated_combo_table4[y][1]=0; + ++y; + } + } + + animated_combos=y; +} + +void setup_combo_animations2() +{ + memset(animated_combo_table2, 0, MAXCOMBOS*2*2); + memset(animated_combo_table24, 0, MAXCOMBOS*2*2); + int y=0; + + for(word x=0; x1 || combobuf[x].nextcombo != 0)&&combobuf[x].animflags & AF_FRESH) + { + animated_combo_table24[y][0]=x; + animated_combo_table24[y][1]=0; + ++y; + } + } + + animated_combos2=y; +} + +void reset_combo_animation(int c) +{ + const int count = animated_combos; + for(int x=0; x=combobuf[y].speed) //time to animate + { + //this is a mess. + if(combobuf[y].tile- + (combobuf[y].frames+((combobuf[y].frames-1)*combobuf[y].skipanim)+ + (combobuf[y].skipanimy*TILES_PER_ROW)) + >=animated_combo_table[y][1]-1) + { + combobuf[y].tile=animated_combo_table[y][1]; //reset tile + } + else + { + int temp=combobuf[y].tile; + combobuf[y].tile+=1+(combobuf[y].skipanim); //increment tile + + if(temp/TILES_PER_ROW!=combobuf[y].tile/TILES_PER_ROW) + combobuf[y].tile+=TILES_PER_ROW*combobuf[y].skipanimy; + } + + animated_combo_table4[x][1]=0; //reset clock + } + else + { + ++animated_combo_table4[x][1]; //increment clock + } + } + + const int count2 = animated_combos2; + for(int x=0; x=combobuf[y].speed) //time to animate + { + if(combobuf[y].tile- + (combobuf[y].frames+((combobuf[y].frames-1)*combobuf[y].skipanim)+ + (combobuf[y].frames-1)*combobuf[y].skipanimy*TILES_PER_ROW) + >=animated_combo_table2[y][1]-1) + { + combobuf[y].tile=animated_combo_table2[y][1]; //reset tile + } + else + { + int temp=combobuf[y].tile; + combobuf[y].tile+=1+(combobuf[y].skipanim); //increment tile + + if(temp/TILES_PER_ROW!=combobuf[y].tile/TILES_PER_ROW) + combobuf[y].tile+=TILES_PER_ROW*combobuf[y].skipanimy; + } + + animated_combo_table24[x][1]=0; //reset clock + } + else + { + ++animated_combo_table24[x][1]; //increment clock + } + } +} + +/* +bool isonline(float x1, float y1, float x2, float y2, float x3, float y3) +{ + float slope; + float intercept; + + slope = (y2-y1)/(x2-x1); + intercept = y1 - (slope*x1); + return (y3 == (slope*x3)+intercept) && x3>zc_min(x1,x2) && x3zc_min(y1,y2) && y3= 0 && nondegenq <= nondegend; +} + +//clears a tile +/* +void clear_tile(tiledata *buf, word tile) +{ + buf[tile].format=tf4Bit; + if (buf[tile].data!=NULL) + { + zc_free(buf[tile].data); + buf[tile].data = NULL; + } + buf[tile].data=(byte *)zc_malloc(tilesize(buf[tile].format)); + if (buf[tile].data==NULL) + { + Z_error("Unable to initialize tile #%d.\n", tile); + exit(1); + } + memset(buf[tile].data,0,tilesize(buf[tile].format)); +} +*/ + +void reset_tile(tiledata *buf, int t, int format=1) +{ + buf[t].format=format; + + if(buf[t].data!=NULL) + { + zc_free(buf[t].data); + } + + buf[t].data=(byte *)zc_malloc(tilesize(buf[t].format)); + + if(buf[t].data==NULL) + { + quit_game(); + Z_error("Unable to initialize tile #%d.\n", t); + } + + for(int i=0; iline[i/8][(i%8)*2] = buf[t].data[i]>>4; + tilebuf[t]->line[i/8][(i%8)*2+1] = buf[t].data[i]&0xF; + } + } + else + { + for(int i=0; i<256; i++) + { + tilebuf[t]->line[i/16][i%16] = buf[t].data[i]; + } + } + }*/ +} + +//clears the tile buffer +void clear_tiles(tiledata *buf) +{ + for(word i=0; itf4Bit) + { + cs=0; + } + + cs &= 15; + cs <<= CSET_SHFT; + + for(int i=0; i<256; i++) + { + if(backwards) + { + if(!upbuf[i]) + { + upbuf[i] = unpackbuf[i]+cs; + } + } + else + { + if(unpackbuf[i]) + { + upbuf[i] = unpackbuf[i]+cs; + } + } + } + + if(!blank_tile_table[src]) + { + blank_tile_table[dest]=false; + } + + pack_tile(buf, upbuf,dest); +} + +bool copy_tile(tiledata *buf, int src, int dest, bool swap) +{ + if(src==dest) + { + return true; + } + + int tempformat=buf[dest].format; + byte *temptiledata=(byte *)zc_malloc(tilesize(tempformat)); + + if(swap) + { + for(int j=0; j=0; --i) + { + switch(buf[tile].format) + { + case tf4Bit: + di=unpackbuf + (i<<4) - 1; + + for(j=7; j>=0; --j) + { + (*(++di)) = (*(--si)) >> 4; + (*(++di)) = (*si) & 15; + } + + break; + + case tf8Bit: + di=unpackbuf + (i<<4) - 1; + + for(j=1; j>=0; --j) + { + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + (*(++di)) = (*(--si)); + } + + break; + } + } + + break; + + case 4: //rotated + si = buf[tile].data+tilesize(buf[tile].format); + + for(i=15; i>=0; --i) + { + switch(buf[tile].format) + { + case tf4Bit: + di=unpackbuf + 271 - i; //256 + 15 - i + + for(j=7; j>=0; --j) + { + di-=16; + *di = (*(--si)) >> 4; + di-=16; + *di = (*si) & 15; + } + + break; + + case tf8Bit: + di=unpackbuf + 271 - i; //256 + 15 - i + + for(j=1; j>=0; --j) + { + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + } + + break; + } + } + + break; + + case 5: //rotated and horizontal + si = buf[tile].data+tilesize(buf[tile].format); + + for(i=15; i>=0; --i) + { + switch(buf[tile].format) + { + case tf4Bit: + di=unpackbuf + 256 + i; + + for(j=7; j>=0; --j) + { + di-=16; + *di = (*(--si)) >> 4; + di-=16; + *di = (*si) & 15; + } + + break; + + case tf8Bit: + di=unpackbuf + 256 + i; + + for(j=1; j>=0; --j) + { + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + di-=16; + *di = (*(--si)); + } + + break; + } + } + + break; + + default: //none or invalid + switch(buf[tile].format) + { + case tf4Bit: + si = buf[tile].data+tilesize(buf[tile].format); + di = unpackbuf + 256; + + for(i=127; i>=0; --i) + { + (*(--di)) = (*(--si)) >> 4; + (*(--di)) = (*si) & 15; + } + + break; + + case tf8Bit: + si = buf[tile].data+tilesize(buf[tile].format); + di = unpackbuf + 256; + + for(i=31; i>=0; --i) + { + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + (*(--di)) = (*(--si)); + } + + break; + } + + break; + } +} + +// packs from src[256] to tilebuf +void pack_tile(tiledata *buf, byte *src,int tile) +{ + pack_tiledata(buf[tile].data, src, buf[tile].format); +} + +void pack_tiledata(byte *dest, byte *src, byte format) +{ + byte *di = dest; + + switch(format) + { + case tf4Bit: + for(int si=0; si<256; si+=2) + { + *di = (src[si]&15) + ((src[si+1]&15) << 4); + ++di; + } + + break; + + case tf8Bit: + for(int si=0; si<32; si+=1) + { + *di = src[si*8]; + ++di; + *di = src[si*8+1]; + ++di; + *di = src[si*8+2]; + ++di; + *di = src[si*8+3]; + ++di; + *di = src[si*8+4]; + ++di; + *di = src[si*8+5]; + ++di; + *di = src[si*8+6]; + ++di; + *di = src[si*8+7]; + ++di; + } + + break; + } +} + +// packs a whole set of tiles from old size to new size +void pack_tiles(byte *buf) +{ + int di = 0; + + for(int si=0; si dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(newtilebuf[tile>>2].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile>>2, 0, false); + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + if(flip&1) //horizontal + { + si+=7; + } + + if((flip&2)==0) //not flipped vertically + { + if(y<0) + { + si+=(0-y)<<4; + } + + for(int dy=(y<0 ? 0-y : 0); (dy<8)&&(dy+yh); ++dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = trans_table.data[(*di)][((*si) + cset)]; + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } //flipped vertically + else + { + if(y+7>=dest->h) + { + si+=(8+y-dest->h)<<4; + } + + for(int dy=(y+7>=dest->h ? dest->h-y-1 : 7); (dy>=0)&&(dy+y>=0); --dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = trans_table.data[(*di)][((*si) + cset)]; + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } +} + +void overtiletranslucent8(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity) +{ + //these are here to bypass compiler warnings about unused arguments + opacity=opacity; + + if(x<-7 || y<-7) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(blank_tile_quarters_table[tile]) + { + return; + } + + if(newtilebuf[tile>>2].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile>>2, 0, false); + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + if(flip&1) + { + si+=7; + } + + if((flip&2)==0) //not flipped vertically + { + if(y<0) + { + si+=(0-y)<<4; + } + + for(int dy=(y<0 ? 0-y : 0); (dy<8)&&(dy+yh); ++dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + if(*si) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } //flipped vertically + else + { + if(y+7>=dest->h) + { + si+=(8+y-dest->h)<<4; + } + + for(int dy=(y+7>=dest->h ? dest->h-y-1 : 7); (dy>=0)&&(dy+y>=0); --dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + if(*si) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } +} + +void puttiletranslucent16(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity) +{ + //these are here to bypass compiler warnings about unused arguments + opacity=opacity; + + if(x<-15 || y<-15) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile, 0, false); + byte *si = unpackbuf; + byte *di; + + if(flip&1) + si+=15; + + if((flip&2)==0) + { + if(y<0) + si+=(0-y)<<4; + + for(int dy=(y<0 ? 0-y : 0); (dy<16)&&(dy+yh); ++dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + flip&1 ? si-=0-x : si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + ++di; + flip&1 ? --si : ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + ++di; + } + + flip&1 ? --si : ++si; + } + } + + if(flip&1) + si+=32; + } + } + else + { + if(y+15>=dest->h) + si+=(16+y-dest->h)<<4; + + for(int dy=(y+15>=dest->h ? dest->h-y-1 : 15); (dy>=0)&&(dy+y>=0); --dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + flip&1 ? si-=0-x : si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + ++di; + flip&1 ? --si : ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + ++di; + } + + flip&1 ? --si : ++si; + } + } + + if(flip&1) + si+=32; + } + } +} + +void overtiletranslucent16(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity) +{ + //these are here to bypass compiler warnings about unused arguments + opacity=opacity; + + if(x<-15 || y<-15) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + if(blank_tile_table[tile]) + { + return; + } + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile,flip&5, false); + byte *si = unpackbuf; + byte *di; + + if((flip&2)==0) + { + if(y<0) + si+=(0-y)<<4; + + for(int dy=(y<0 ? 0-y : 0); (dy<16)&&(dy+yh); ++dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + { + // *di=*si+cset; + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + { + // *di=*si+cset; + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + } + + ++si; + } + } + } + } + else + { + if(y+15>=dest->h) + si+=(16+y-dest->h)<<4; + + for(int dy=(y+15>=dest->h ? dest->h-y-1 : 15); (dy>=0)&&(dy+y>=0); --dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + { + // *di=*si+cset; + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + { + // *di=*si+cset; + // *di=(opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *di=trans_table.data[(*di)][((*si) + cset)]; + } + + ++di; + } + + ++si; + } + } + } + } +} + +void overtilecloaked16(BITMAP* dest,int tile,int x,int y,int flip) +{ + if(x<-15 || y<-15) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + unpack_tile(newtilebuf, tile, 0, false); + byte *si = unpackbuf; + byte *di; + + if(flip&1) + si+=15; + + if((flip&2)==0) + { + if(y<0) + si+=(0-y)<<4; + + for(int dy=(y<0 ? 0-y : 0); (dy<16)&&(dy+yh); ++dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + flip&1 ? si-=0-x : si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + { + *di=dest->line[((y+dy)^1)][((x+dx)^1)]; + } + + ++di; + flip&1 ? --si : ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + { + *di=dest->line[((y+dy)^1)][(x^1)]; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + } + + if(flip&1) + si+=32; + } + } + else + { + if(y+15>=dest->h) + si+=(16+y-dest->h)<<4; + + for(int dy=(y+15>=dest->h ? dest->h-y-1 : 15); (dy>=0)&&(dy+y>=0); --dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + flip&1 ? si-=0-x : si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + { + *di=dest->line[((y+dy)^1)][((x+dx)^1)]; + } + + ++di; + flip&1 ? --si : ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + { + *di=dest->line[((y+dy)^1)][(x^1)]; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + } + + if(flip&1) + si+=32; + } + } +} + +void putblocktranslucent8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask,int opacity) +{ + int t[4]; + + for(int i=0; i<4; ++i) + t[i]=tile+i; + + switch(mask) + { + case 1: + puttiletranslucent8(dest,tile,x,y,csets[0],flip,opacity); + break; + + case 3: + if(flip&2) + { + zc_swap(t[0],t[1]); + } + + puttiletranslucent8(dest,t[0],x,y, csets[0],flip,opacity); + puttiletranslucent8(dest,t[1],x,y+8,csets[1],flip,opacity); + break; + + case 5: + if(flip&1) + { + zc_swap(t[0],t[1]); + } + + puttiletranslucent8(dest,t[0],x, y,csets[0],flip,opacity); + puttiletranslucent8(dest,t[1],x+8,y,csets[1],flip,opacity); + break; + + case 15: + if(flip&1) + { + zc_swap(t[0],t[1]); + zc_swap(t[2],t[3]); + } + + if(flip&2) + { + zc_swap(t[0],t[2]); + zc_swap(t[1],t[3]); + } + + puttiletranslucent8(dest,t[0],x, y, csets[0],flip,opacity); + puttiletranslucent8(dest,t[1],x+8,y, csets[1],flip,opacity); + puttiletranslucent8(dest,t[2],x, y+8,csets[2],flip,opacity); + puttiletranslucent8(dest,t[3],x+8,y+8,csets[3],flip,opacity); + break; + } +} + +void overblocktranslucent8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask,int opacity) +{ + int t[4]; + + for(int i=0; i<4; ++i) + t[i]=tile+i; + + switch(mask) + { + case 1: + overtiletranslucent8(dest,tile,x,y,csets[0],flip,opacity); + break; + + case 3: + if(flip&2) + { + zc_swap(t[0],t[1]); + zc_swap(csets[0],csets[1]); + } + + overtiletranslucent8(dest,t[0],x,y, csets[0],flip,opacity); + overtiletranslucent8(dest,t[1],x,y+8,csets[1],flip,opacity); + break; + + case 5: + if(flip&1) + { + zc_swap(t[0],t[1]); + } + + overtiletranslucent8(dest,t[0],x, y,csets[0],flip,opacity); + overtiletranslucent8(dest,t[1],x+8,y,csets[1],flip,opacity); + break; + + case 15: + if(flip&1) + { + zc_swap(t[0],t[1]); + zc_swap(t[2],t[3]); + } + + if(flip&2) + { + zc_swap(t[0],t[2]); + zc_swap(t[1],t[3]); + } + + overtiletranslucent8(dest,t[0],x, y, csets[0],flip,opacity); + overtiletranslucent8(dest,t[1],x+8,y, csets[1],flip,opacity); + overtiletranslucent8(dest,t[2],x, y+8,csets[2],flip,opacity); + overtiletranslucent8(dest,t[3],x+8,y+8,csets[3],flip,opacity); + break; + } +} + +// cmbdat: fffffsss cccccccc +// (f:flags, s:cset, c:combo) + +int combo_tile(const newcombo &c, int x, int y) +{ + int drawtile=c.tile; + int tframes=zc_max(1, c.frames); + + switch(combo_class_buf[c.type].directional_change_type) + { + default: + break; + + case 1: //cOLD_EYEBALL_A + { + double ddir=atan2((double)(y-LinkModifiedY()-playing_field_offset), (double)(LinkModifiedX()-x)); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + { + drawtile+=tframes*5; //dl + } + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + { + drawtile+=tframes*4; //d + } + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + { + drawtile+=tframes*3; //dr + } + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + { + drawtile+=tframes*2; //r + } + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + { + drawtile+=tframes*1; //ur + } + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + { + drawtile+=tframes*0; //u + } + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + { + drawtile+=tframes*7; //ul + } + else + { + drawtile+=tframes*6; //l + } + + break; + } + + case 3: // 4-way Eyeball (up-down-left-right) + { + double ddir=atan2((double)(y-LinkModifiedY()-playing_field_offset), (double)(LinkModifiedX()-x)); + + if((ddir<=(((-2)*PI)/8))&&(ddir>(((-6)*PI)/8))) + { + drawtile+=tframes*1; //d + } + else if((ddir<=(((2)*PI)/8))&&(ddir>(((-2)*PI)/8))) + { + drawtile+=tframes*3; //r + } + else if((ddir<=(((6)*PI)/8))&&(ddir>(((2)*PI)/8))) + { + drawtile+=tframes*0; //u + } + else + { + drawtile+=tframes*2; //l + } + + break; + } + + case 2: //cOLD_EYEBALL_B + { + double ddir=atan2((double)(y-LinkModifiedY()-playing_field_offset), (double)(LinkModifiedX()-x)); + + if((ddir<=(((-6)*PI)/8))&&(ddir>(((-8)*PI)/8))) + { + drawtile+=tframes*5; //dl + } + else if((ddir<=(((-4)*PI)/8))&&(ddir>(((-6)*PI)/8))) + { + drawtile+=tframes*4; //d + } + else if((ddir<=(((-2)*PI)/8))&&(ddir>(((-4)*PI)/8))) + { + drawtile+=tframes*3; //dr + } + else if((ddir<=(((0)*PI)/8))&&(ddir>(((-2)*PI)/8))) + { + drawtile+=tframes*2; //r + } + else if((ddir<=(((2)*PI)/8))&&(ddir>(((0)*PI)/8))) + { + drawtile+=tframes*1; //ur + } + else if((ddir<=(((4)*PI)/8))&&(ddir>(((2)*PI)/8))) + { + drawtile+=tframes*0; //u + } + else if((ddir<=(((6)*PI)/8))&&(ddir>(((4)*PI)/8))) + { + drawtile+=tframes*7; //ul + } + else + { + drawtile+=tframes*6; //l + } + + break; + } + } + + return drawtile; +} + +int combo_tile(int cmbdat, int x, int y) +{ + const newcombo & c = combobuf[cmbdat]; + return combo_tile(c, x, y); +} + +void putcombotranslucent(BITMAP* dest,int x,int y,int cmbdat,int cset,int opacity) +{ + newcombo c = combobuf[cmbdat]; + int drawtile=combo_tile(c, x, y); + + if(!(c.csets&0xF0) || !(c.csets&0x0F) || (newtilebuf[drawtile].format>tf4Bit)) + puttiletranslucent16(dest,drawtile,x,y,cset,c.flip,opacity); + else + { + int csets[4]; + int cofs = c.csets&15; + + if(cofs&8) + cofs |= ~int(0xF); + + for(int i=0; i<4; ++i) + csets[i] = c.csets&(16<tf4Bit)) + overtiletranslucent16(dest,tiletodraw,x+16*woff,y+16*hoff,cset,c.flip,opacity); + else + { + int csets[4]; + int cofs = c.csets&15; + + if(cofs&8) + cofs |= ~int(0xF); + + for(int i=0; i<4; ++i) + csets[i] = c.csets&(16< dest->h-8) + return; + + if(y == dest->h-8 && x > dest->w-8) + return; + + if(newtilebuf[tile>>2].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + dword lcset = (cset<<24)+(cset<<16)+(cset<<8)+cset; + unpack_tile(newtilebuf, tile>>2, 0, false); + + // to go to 24-bit color, do this kind of thing... + // ((long *)bmp->line[y])[x] = color; + + switch(flip&3) + { + case 1: // 1 byte at a time + { + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + for(int dy=0; dy<8; ++dy) + { + byte *di = &(dest->line[y+dy][x+7]); + + for(int i=0; i<8; ++i) + *(di--) = *(si++) + cset; + + si+=8; + } + } + break; + + case 2: // 4 bytes at a time + { + dword *si = ((dword*)unpackbuf) + ((tile&2)<<4) + ((tile&1)<<1); + + for(int dy=7; dy>=0; --dy) + { + dword *di=&((dword*)dest->line[y+dy])[x>>2]; + *(di++) = *(si++) + lcset; + *(di++) = *(si++) + lcset; + si+=2; + } + } + break; + + case 3: // 1 byte at a time + { + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + for(int dy=7; dy>=0; --dy) + { + byte *di = &(dest->line[y+dy][x+7]); + + for(int i=0; i<8; ++i) + *(di--) = *(si++) + cset; + + si+=8; + } + } + break; + + default: // 4 bytes at a time + { + dword *si = ((dword*)unpackbuf) + ((tile&2)<<4) + ((tile&1)<<1); + + for(int dy=0; dy<8; ++dy) + { + dword *di = &((dword*)dest->line[y+dy])[x>>2]; + *(di++) = *(si++) + lcset; + *(di++) = *(si++) + lcset; + si+=2; + } + } + break; + } +} + + +void oldputtile8(BITMAP* dest,int tile,int x,int y,int cset,int flip) +{ + if(x<-7 || y<-7) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(newtilebuf[tile>>2].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile>>2, 0, false); + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + if(flip&1) + { + si+=7; + } + + if((flip&2)==0) //not flipped vertically + { + if(y<0) + { + si+=(0-y)<<4; + } + + for(int dy=(y<0 ? 0-y : 0); (dy<8)&&(dy+yh); ++dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + *(di) = (*si) + cset; + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + + } + } + } //flipped vertically + else + { + if(y+7>=dest->h) + { + si+=(8+y-dest->h)<<4; + } + + for(int dy=(y+7>=dest->h ? dest->h-y-1 : 7); (dy>=0)&&(dy+y>=0); --dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + *(di) = (*si) + cset; + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } +} + + +void overtile8(BITMAP* dest,int tile,int x,int y,int cset,int flip) +{ + if(x<-7 || y<-7) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(blank_tile_quarters_table[tile]) + { + return; + } + + if(newtilebuf[tile>>2].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile>>2, 0, false); + byte *si = unpackbuf + ((tile&2)<<6) + ((tile&1)<<3); + + if(flip&1) + { + si+=7; + } + + if((flip&2)==0) //not flipped vertically + { + if(y<0) + { + si+=(0-y)<<4; + } + + for(int dy=(y<0 ? 0-y : 0); (dy<8)&&(dy+yh); ++dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + if(*si) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = (*si) + cset; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + + } + } + } //flipped vertically + else + { + if(y+7>=dest->h) + { + si+=(8+y-dest->h)<<4; + } + + for(int dy=(y+7>=dest->h ? dest->h-y-1 : 7); (dy>=0)&&(dy+y>=0); --dy) + { + byte* di = &(dest->line[y+dy][x<0 ? 0 : x]); + + for(int i=0; i<8; ++i) + { + if(x+iw) + { + if(*si) + { + // *(di) = (opacity==255)?((*si) + cset):trans_table.data[(*di)][((*si) + cset)]; + *(di) = (*si) + cset; + } + + ++di; + } + + flip&1 ? --si : ++si; + } + + if(flip&1) + { + si+=24; + } + else + { + si+=8; + } + } + } +} + +void puttile16(BITMAP* dest,int tile,int x,int y,int cset,int flip) //fixed +{ + if(x<0 || y<0) + return; + + if(y > dest->h-16) + return; + + if((y == dest->h-16) && (x > dest->w-16)) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + + unpack_tile(newtilebuf, tile, flip&5, false); + + switch(flip&2) + { + /* + case 1: + { + byte *si = unpackbuf; + for(int dy=0; dy<16; ++dy) + { + // 1 byte at a time + byte *di = &(dest->line[y+dy][x+15]); + for(int i=0; i<16; ++i) + *(di--) = *(si++) + cset; + } + } break; + */ + case 2: //vertical + { + /* + dword *si = (dword*)unpackbuf; + for(int dy=15; dy>=0; --dy) + { + // 4 bytes at a time + dword *di=&((dword*)dest->line[y+dy])[x>>2]; + for(int i=0; i<16; i+=4) + *(di++) = *(si++) + lcset; + } + */ + qword llcset = (((qword)cset)<<56)+(((qword)cset)<<48)+(((qword)cset)<<40)+(((qword)cset)<<32)+(((qword)cset)<<24)+(cset<<16)+(cset<<8)+cset; + // qword llcset = (((qword)cset)<<56)|(((qword)cset)<<48)|(((qword)cset)<<40)|(((qword)cset)<<32)|(((qword)cset)<<24)|(cset<<16)|(cset<<8)|cset; + qword *si = (qword*)unpackbuf; + + for(int dy=15; dy>=0; --dy) + { + // 4 bytes at a time + // qword *di=&((qword*)dest->line[y+dy])[x>>3]; + qword *di=(qword*)(dest->line[y+dy]+x); + + for(int i=0; i<16; i+=8) + *(di++) = *(si++) + llcset; + } + } + break; + + /* + case 3: + { + byte *si = unpackbuf; + for(int dy=15; dy>=0; --dy) + { + // 1 byte at a time + byte *di = &(dest->line[y+dy][x+15]); + for(int i=0; i<16; ++i) + *(di--) = *(si++) + cset; + } + } break; + */ + default: //none or invalid + { + /* + dword *si = (dword*)unpackbuf; + for(int dy=0; dy<16; ++dy) + { + // 4 bytes at a time + dword *di=&((dword*)dest->line[y+dy])[x>>2]; + for(int i=0; i<16; i+=4) + *(di++) = *(si++) + lcset; + } + */ + qword llcset = (((qword)cset)<<56)+(((qword)cset)<<48)+(((qword)cset)<<40)+(((qword)cset)<<32)+(((qword)cset)<<24)+(cset<<16)+(cset<<8)+cset; + // qword llcset = (((qword)cset)<<56)|(((qword)cset)<<48)|(((qword)cset)<<40)|(((qword)cset)<<32)|(((qword)cset)<<24)|(cset<<16)|(cset<<8)|cset; + qword *si = (qword*)unpackbuf; + + for(int dy=0; dy<16; ++dy) + { + // 4 bytes at a time + // qword *di=&((qword*)dest->line[y+dy])[x>>3]; + qword *di=(qword*)(dest->line[y+dy]+x); + + for(int i=0; i<16; i+=8) + *(di++) = *(si++) + llcset; + } + } + break; + } +} + +void oldputtile16(BITMAP* dest,int tile,int x,int y,int cset,int flip) //fixed +{ + if(x<-15 || y<-15) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile, flip&5, false); + byte *si = unpackbuf; + byte *di; + + if((flip&2)==0) + { + if(y<0) + si+=(0-y)<<4; + + for(int dy=(y<0 ? 0-y : 0); (dy<16)&&(dy+yh); ++dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + *di=*si+cset; + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + *di=*si+cset; + ++di; + } + + ++si; + } + } + } + } + else + { + if(y+15>=dest->h) + si+=(16+y-dest->h)<<4; + + for(int dy=(y+15>=dest->h ? dest->h-y-1 : 15); (dy>=0)&&(dy+y>=0); --dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + *di=*si+cset; + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + *di=*si+cset; + ++di; + } + + ++si; + } + } + } + } +} + +void overtile16(BITMAP* dest,int tile,int x,int y,int cset,int flip) //fixed +{ + if(x<-15 || y<-15) + return; + + if(y > dest->h) + return; + + if(y == dest->h && x > dest->w) + return; + + if(tile<0 || tile>=NEWMAXTILES) + { + rectfill(dest,x,y,x+15,y+15,0); + return; + } + + if(blank_tile_table[tile]) + { + return; + } + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + cset &= 15; + cset <<= CSET_SHFT; + unpack_tile(newtilebuf, tile, flip&5, false); + byte *si = unpackbuf; + byte *di; + + if((flip&2)==0) + { + if(y<0) + si+=(0-y)<<4; + + for(int dy=(y<0 ? 0-y : 0); (dy<16)&&(dy+yh); ++dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + *di=*si+cset; + + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + *di=*si+cset; + + ++di; + } + + ++si; + } + } + } + } + else + { + if(y+15>=dest->h) + si+=(16+y-dest->h)<<4; + + for(int dy=(y+15>=dest->h ? dest->h-y-1 : 15); (dy>=0)&&(dy+y>=0); --dy) + { + di = &(dest->line[y+dy][x<0 ? 0 : x]); + + if(x+15w) + { + if(x<0) + si+=0-x; + + for(int dx=(x<0 ? 0-x : 0); dx<16; ++dx) + { + if(*si) + *di=*si+cset; + + ++di; + ++si; + } + } + else + { + for(int i=0; i<16; ++i) + { + if(x+iw) + { + if(*si) + *di=*si+cset; + + ++di; + } + + ++si; + } + } + } + } +} + +void putblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask) +{ + int t[4]; + + for(int i=0; i<4; ++i) + t[i]=tile+i; + + switch(mask) + { + case 1: //top-left quarter + puttile8(dest,tile,x,y,csets[0],flip); + break; + + case 3: //vertical + if(flip&2) + { + zc_swap(t[0],t[1]); + } + + puttile8(dest,t[0],x,y, csets[0],flip); + puttile8(dest,t[1],x,y+8,csets[1],flip); + break; + + case 5: //horizontal + if(flip&1) + { + zc_swap(t[0],t[1]); + } + + puttile8(dest,t[0],x, y,csets[0],flip); + puttile8(dest,t[1],x+8,y,csets[1],flip); + break; + + case 15: //all 4 quarters + if(flip&1) + { + zc_swap(t[0],t[1]); + zc_swap(t[2],t[3]); + } + + if(flip&2) + { + + zc_swap(t[0],t[2]); + zc_swap(t[1],t[3]); + } + + puttile8(dest,t[0],x, y, csets[0],flip); + puttile8(dest,t[1],x+8,y, csets[1],flip); + puttile8(dest,t[2],x, y+8,csets[2],flip); + puttile8(dest,t[3],x+8,y+8,csets[3],flip); + break; + } +} + +void oldputblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask) +{ + int t[4]; + + for(int i=0; i<4; ++i) + t[i]=tile+i; + + switch(mask) + { + case 1: + oldputtile8(dest,tile,x,y,csets[0],flip); + break; + + case 3: + if(flip&2) + { + zc_swap(t[0],t[1]); + } + + oldputtile8(dest,t[0],x,y, csets[0],flip); + oldputtile8(dest,t[1],x,y+8,csets[1],flip); + break; + + case 5: + if(flip&1) + { + zc_swap(t[0],t[1]); + } + + oldputtile8(dest,t[0],x, y,csets[0],flip); + oldputtile8(dest,t[1],x+8,y,csets[1],flip); + break; + + case 15: + if(flip&1) + { + zc_swap(t[0],t[1]); + zc_swap(t[2],t[3]); + } + + if(flip&2) + { + zc_swap(t[0],t[2]); + zc_swap(t[1],t[3]); + } + + oldputtile8(dest,t[0],x, y, csets[0],flip); + oldputtile8(dest,t[1],x+8,y, csets[1],flip); + oldputtile8(dest,t[2],x, y+8,csets[2],flip); + oldputtile8(dest,t[3],x+8,y+8,csets[3],flip); + break; + } +} + +void overblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask) +{ + int t[4]; + + for(int i=0; i<4; ++i) + t[i]=tile+i; + + switch(mask) + { + case 1: + overtile8(dest,tile,x,y,csets[0],flip); + break; + + case 3: + if(flip&2) + { + zc_swap(t[0],t[1]); + } + + overtile8(dest,t[0],x,y, csets[0],flip); + overtile8(dest,t[1],x,y+8,csets[1],flip); + break; + + case 5: + if(flip&1) + { + zc_swap(t[0],t[1]); + } + + overtile8(dest,t[0],x, y,csets[0],flip); + overtile8(dest,t[1],x+8,y,csets[1],flip); + break; + + case 15: + if(flip&1) + { + zc_swap(t[0],t[1]); + zc_swap(t[2],t[3]); + } + + if(flip&2) + { + zc_swap(t[0],t[2]); + zc_swap(t[1],t[3]); + } + + overtile8(dest,t[0],x, y, csets[0],flip); + overtile8(dest,t[1],x+8,y, csets[1],flip); + overtile8(dest,t[2],x, y+8,csets[2],flip); + overtile8(dest,t[3],x+8,y+8,csets[3],flip); + break; + } +} + +// cmbdat: fffffsss cccccccc +// (f:flags, s:cset, c:combo) + +void putcombo(BITMAP* dest,int x,int y,int cmbdat,int cset) +{ + newcombo c = combobuf[cmbdat]; + int drawtile=combo_tile(c, x, y); + + if(!(c.csets&0xF0) || !(c.csets&0x0F) || (newtilebuf[drawtile].format>tf4Bit)) + puttile16(dest,drawtile,x,y,cset,c.flip); + // puttile16(dest,c.drawtile,x,y,cset,c.flip); + else + { + int csets[4]; + int cofs = c.csets&15; + // if(cofs&8) + // cofs |= ~int(0xF); + + for(int i=0; i<4; ++i) + { + csets[i] = c.csets&(16<tf4Bit)) + oldputtile16(dest,drawtile,x,y,cset,c.flip); + // oldputtile16(dest,c.drawtile,x,y,cset,c.flip); + else + { + int csets[4]; + int cofs = c.csets&15; + // if(cofs&8) + // cofs |= ~int(0xF); + + for(int i=0; i<4; ++i) + { + csets[i] = c.csets&(16<tf4Bit)) + overtile16(dest,tiletodraw,x+16*woff,y+16*hoff,cset,c.flip); + else + { + int csets[4]; + int cofs = c.csets&15; + + if(cofs&8) + cofs |= ~int(0xF); + + for(int i=0; i<4; ++i) + csets[i] = c.csets&(16<> 1; + result+=(layermask&4) >> 2; + result+=(layermask&8) >> 3; + result+=(layermask&16) >> 4; + result+=(layermask&32) >> 5; + return result; +} + +/* end of tiles.cc */ + diff --git a/src/tiles.h b/src/tiles.h new file mode 100644 index 0000000000..cba7a2851b --- /dev/null +++ b/src/tiles.h @@ -0,0 +1,99 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// tiles.h +// +// Tile drawing routines for ZC. +// +// !! Don't use them on "screen"; use memory BITMAPs only. +// +//-------------------------------------------------------- + +#ifndef _ZC_TILES_H_ +#define _ZC_TILES_H_ + +#define UNPACKSIZE 256 + +#include "zc_alleg.h" +#include "zdefs.h" + +//extern byte *tilebuf; +extern tiledata *newtilebuf, *grabtilebuf; +extern newcombo *combobuf; +extern word animated_combo_table[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table4[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos; +extern word animated_combo_table2[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table24[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos2; +extern bool blank_tile_table[NEWMAXTILES]; //keeps track of blank tiles +extern bool used_tile_table[NEWMAXTILES]; //keeps track of used tiles +extern bool blank_tile_quarters_table[NEWMAXTILES*4]; //keeps track of blank tile quarters + +// in tiles.cc +extern byte unpackbuf[UNPACKSIZE]; +extern const char *tileformat_string[tfMax]; +extern comboclass *combo_class_buf; + +void register_blank_tiles(); +word count_tiles(tiledata *buf); +word count_combos(); +void setup_combo_animations(); +void reset_combo_animation(int c); +void reset_combo_animations(); +void setup_combo_animations2(); +void reset_combo_animation2(int c); +void reset_combo_animations2(); +void animate_combos(); +bool isonline(long x1, long y1, long x2, long y2, long x3, long y3); +void reset_tile(tiledata *buf, int t, int format); +//void clear_tile(tiledata *buf, word tile); +void clear_tiles(tiledata *buf); +void overlay_tile(tiledata *buf,int dest,int src,int cs,bool backwards); +bool copy_tile(tiledata *buf, int src, int dest, bool swap); +void unpack_tile(tiledata *buf, int tile, int flip, bool force); + +void pack_tile(tiledata *buf, byte *src,int tile); +void pack_tiledata(byte *dest, byte *src, byte format); +void pack_tiles(byte *buf); +int rotate_value(int flip); + +void puttile8(BITMAP* dest,int tile,int x,int y,int cset,int flip); +void oldputtile8(BITMAP* dest,int tile,int x,int y,int cset,int flip); +void overtile8(BITMAP* dest,int tile,int x,int y,int cset,int flip); +void puttile16(BITMAP* dest,int tile,int x,int y,int cset,int flip); +void oldputtile16(BITMAP* dest,int tile,int x,int y,int cset,int flip); +void overtile16(BITMAP* dest,int tile,int x,int y,int cset,int flip); + +void putblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask); +void oldputblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask); +void overblock8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask); + +int combo_tile(const newcombo &c, int x, int y); +int combo_tile(int cmbdat, int x, int y); + +void putcombo(BITMAP* dest,int x,int y,int cmbdat,int cset); +void oldputcombo(BITMAP* dest,int x,int y,int cmbdat,int cset); +void overcombo(BITMAP* dest,int x,int y,int cmbdat,int cset); +void overcomboblock(BITMAP *dest, int x, int y, int cmbdat, int cset, int w, int h); +void overcombo2(BITMAP* dest,int x,int y,int cmbdat,int cset); + +void puttiletranslucent8(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity); +void overtiletranslucent8(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity); +void puttiletranslucent16(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity); +void overtiletranslucent16(BITMAP* dest,int tile,int x,int y,int cset,int flip,int opacity); +void overtilecloaked16(BITMAP* dest,int tile,int x,int y,int flip); + +void putblocktranslucent8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask,int opacity); +void overblocktranslucent8(BITMAP *dest,int tile,int x,int y,int csets[],int flip,int mask,int opacity); + +void putcombotranslucent(BITMAP* dest,int x,int y,int cmbdat,int cset,int opacity); +void overcombotranslucent(BITMAP* dest,int x,int y,int cmbdat,int cset,int opacity); +void overcomboblocktranslucent(BITMAP *dest, int x, int y, int cmbdat, int cset, int w, int h, int opacity); + +bool is_valid_format(byte format); +int tilesize(byte format); +int comboa_lmasktotal(byte layermask); +#endif // _ZC_TILES_H_ + diff --git a/src/title.cpp b/src/title.cpp new file mode 100644 index 0000000000..a041308958 --- /dev/null +++ b/src/title.cpp @@ -0,0 +1,3737 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// title.cc +// +// Title screen and intro for zelda.cc +// Also has game loading and select screen code. +// +//-------------------------------------------------------- + +#include "precompiled.h" //always first + +#include +#include +#include +#include "zc_alleg.h" + +#include "encryption.h" +#include "zdefs.h" +#include "zelda.h" +#include "zc_sys.h" +#include "zsys.h" +#include "qst.h" +#include "tiles.h" +#include "colors.h" +#include "pal.h" +#include "gui.h" +#include "sprite.h" +#include "subscr.h" +//#include "jwin.h" +#include "jwinfsel.h" +#include "title.h" +#include "gamedata.h" +#include "link.h" +#include "mem_debug.h" +#include "sound.h" + +#ifdef _MSC_VER +#define strupr _strupr +#define stricmp _stricmp +#define snprintf _snprintf +#endif + +extern int loadlast; +extern int skipcont; +extern int skipicon; + +bool load_custom_game(int file); + +struct savedicon +{ + byte loaded; + byte ring; + byte pal[4][48]; + byte icon[4][128]; +}; + +savedicon iconbuffer[15]; + +static bool chosecustomquest = false; + +/********************************/ +/***** NES title screen *****/ +/********************************/ + +#define BKGDATA 224*256/32 + +static byte titlepal[24] = +{ + 0x0F,0x00,0x10, 0x17,0x27,0x0F, 0x08,0x1A,0x28, 0x30,0x3B,0x22, + 0x30,0x3B,0x16, 0x17,0x27,0x0F, 0x08,0x1A,0x28, 0x30,0x3B,0x22 +}; + +static byte darkpal1[24] = +{ + 0x0F,0x0F,0x00, 0x01,0x11,0x0F, 0x0C,0x01,0x02, 0x00,0x01,0x0C, + 0x00,0x01,0x0C, 0x01,0x11,0x0F, 0x0C,0x01,0x02, 0x00,0x01,0x0C +}; + +static byte darkpal2[24] = +{ + 0x0F,0x0F,0x00, 0x01,0x11,0x0F, 0x0F,0x0C,0x01, 0x01,0x0C,0x0F, + 0x01,0x0C,0x0F, 0x01,0x11,0x0F, 0x0F,0x0C,0x01, 0x01,0x0C,0x0F +}; + +static byte darkpal3[24] = +{ + 0x0F,0x0F,0x0F, 0x01,0x0F,0x0F, 0x0F,0x0C,0x0F, 0x0F,0x0C,0x0F, + 0x0F,0x0C,0x0F, 0x01,0x0F,0x0F, 0x0F,0x0C,0x0F, 0x0F,0x0C,0x0F +}; + +static byte itemspal[24] = +{ + 0x30,0x30,0x30, 0x21,0x30,0x30, 0x16,0x30,0x30, 0x29,0x1A,0x09, + 0x29,0x37,0x17, 0x02,0x22,0x30, 0x16,0x27,0x30, 0x0B,0x1B,0x2B +}; + +static void loadtitlepal(int clear,byte *dataofs,int shift) +{ + for(int i=0; i<4; i++) + { + RAMpal[CSET(i)+shift] = NESpal(clear); + + for(int c=1; c<4; c++) + RAMpal[CSET(i)+c+shift] = NESpal(*dataofs++); + } + + for(int i=6; i<10; i++) + { + RAMpal[CSET(i)+shift] = NESpal(clear); + + for(int c=1; c<4; c++) + RAMpal[CSET(i)+c+shift] = NESpal(*dataofs++); + } + + refreshpal=true; +} + +static byte tricolor[] = {0x27,0x37,0x27,0x17,0x07,0x17}; +static byte tridelay[] = {6,12,6,6,12,16}; +static word dusktime[] = {522,522+8,522+14,522+19,522+23,522+26,522+28,522+30}; +static byte duskcolor[]= {0x39,0x31,0x3C,0x3B,0x2C,0x1C,0x02,0x0C}; +static byte wave[3]= {}; + +static void cyclewaves() +{ + for(int i=0; i<3; i++) + { + wave[i]+=2; + + if(wave[i]==50) + wave[i]=0; + + int y=wave[i]+170; + + if(wave[i]<8) + { + overtile16(framebuf,204,80,y,4,0); + overtile16(framebuf,205,96,y,4,0); + } + + + else if(wave[i]<16) + { + overtile16(framebuf,206,80,y,4,0); + overtile16(framebuf,207,96,y,4,0); + } + else + { + overtile16(framebuf,208,80,y,4,0); + overtile16(framebuf,209,96,y,4,0); + } + } +} + +static byte tri,fcnt; + +static void mainscreen(int f) +{ + if(f>=1010) + return; + + if(f==0) + { + blit((BITMAP*)data[BMP_TITLE_NES].dat,scrollbuf,0,0,0,0,256,224); + blit(scrollbuf,framebuf,0,0,0,0,256,224); + char tbuf[80]; + sprintf(tbuf, "%c1986 NINTENDO", 0xBB); + textout_ex(framebuf,zfont,tbuf,104,128,13,-1); + sprintf(tbuf, "%c2014 AG", 0xBC); + //tbuf[0]=(char)0xBC; + textout_ex(framebuf,zfont,tbuf,104,136,13,-1); + } + + if(f<554+192+10) + { + blit(scrollbuf,framebuf,80,160,80,160,32,64); + + if(f&8) + { + puttile16(framebuf,200,80,160,4,0); + puttile16(framebuf,201,96,160,4,0); + } + else + { + puttile16(framebuf,202,80,160,4,0); + puttile16(framebuf,203,96,160,4,0); + } + + cyclewaves(); + } + + if(f<58*9) + ++fcnt; + + if(fcnt==tridelay[tri]) + { + fcnt=0; + tri = tri<5 ? tri+1 : 0; + RAMpal[CSET(2)+2]=NESpal(tricolor[tri]); + refreshpal=true; + } + + for(int i=0; i<8; i++) + { + if(f==dusktime[i]) + loadtitlepal(duskcolor[i],titlepal,4); + } + + if(f==554) + loadtitlepal(0x0F,darkpal1,4); + + if(f==554+192) + loadtitlepal(0x0F,darkpal2,4); + + if(f==554+192+6) + loadtitlepal(0x0F,darkpal3,4); + + if(f==554+192+10) + { + clear_bitmap(framebuf); + clear_bitmap(scrollbuf); + } + + if(f==554+192+10+193) + loadtitlepal(0x0F,itemspal,0); +} + +void putstring(int x,int y,const char* str,int cset) +{ + textout_ex(scrollbuf,zfont,str,x,y,(cset<=1804) return; + + if(f==1010) + { + puttile8(scrollbuf,vine[4],16,232,3,1); + puttile8(scrollbuf,vine[2],24,232,3,1); + puttile8(scrollbuf,vine[3],32,232,3,1); + putstring(48,232,"THE LEGEND OF ZELDA",2); + puttile8(scrollbuf,vine[3],208,232,3,0); + puttile8(scrollbuf,vine[2],216,232,3,1); + puttile8(scrollbuf,vine[3],224,232,3,1); + puttile8(scrollbuf,vine[4],232,232,3,1); + } + + if(f==16*3 +1010) + putstring(32,232,"MANY YEARS AGO PRINCE",0); + + if(f==16*4 +1010) + { + puttile8(scrollbuf,ii,104,232,2,0); + puttile8(scrollbuf,ii,168,232,2,0); + } + + if(f==16*5 +1010) + { + putstring(32,232,"DARKNESS",0); + putstring(120,232,"GANNON",2); + putstring(184,232,"STOLE",0); + } + + if(f==16*7 +1010) + { + putstring(32,232,"ONE OF THE",0); + putstring(120,232,"TRIFORCE",1); + putstring(192,232,"WITH",0); + } + + if(f==16*9 +1010) + { + putstring(32,232,"POWER. PRINCESS",0); + putstring(184,232,"ZELDA",2); + } + + if(f==16*11 +1010) + { + putstring(32,232,"HAD ONE OF THE",0); + putstring(160,232,"TRIFORCE",1); + } + + if(f==16*13 +1010) + putstring(32,232,"WITH WISDOM. SHE DIVIDED",0); + + if(f==16*14 +1010) + { + puttile8(scrollbuf,ii,88,232,1,0); + puttile8(scrollbuf,ii,112,232,1,0); + } + + if(f==16*15 +1010) + { + putstring(32,232,"IT INTO UNITS TO HIDE",0); + putstring(104,232,"8",1); + } + + if(f==16*16 +1010) + { + puttile8(scrollbuf,ii,96,232,2,0); + puttile8(scrollbuf,ii,160,232,2,0); + } + + if(f==16*17 +1010) + { + putstring(32,232,"IT FROM",0); + putstring(112,232,"GANNON",2); + putstring(176,232,"BEFORE",0); + } + + if(f==16*19 +1010) + putstring(32,232,"SHE WAS CAPTURED.",0); + + if(f==16*20 +1010) + { + puttile8(scrollbuf,ii,136,232,2,0); + puttile8(scrollbuf,ii,160,232,2,0); + } + + if(f==16*21 +1010) + putstring(48,232,"GO FIND THE 8 UNITS",2); + + if(f==16*22 +1010) + { + puttile8(scrollbuf,ii,48,232,3,0); + puttile8(scrollbuf,ii,96,232,3,0); + } + + if(f==16*23 +1010) + { + putstring(64,232,"LINK",3); + putstring(112,232,"TO SAVE HER.",2); + } + + if(f==16*25 +1010) + { + puttile8(scrollbuf,vine[4],16,232,3,1); + + for(int x=24; x<232; x+=16) + { + puttile8(scrollbuf,vine[2],x,232,3,0); + puttile8(scrollbuf,vine[3],x+8,232,3,0); + } + + puttile8(scrollbuf,vine[4],232,232,3,1); + } + + + if((f>1010) && (f <= 16*24 + 1010)) + { + if(((f-1010)&15) == 0) + { + if((f-1010)&16) + { + puttile8(scrollbuf,vine[0],16,232,3,0); + puttile8(scrollbuf,vine[1],232,232,3,0); + } + else + { + puttile8(scrollbuf,vine[1],16,232,3,0); + puttile8(scrollbuf,vine[0],232,232,3,0); + } + } + } + + blit(scrollbuf,framebuf,0,8,0,0,256,224); + + if((f>=1010) && (f<= 16*26 + 1010) && (f&1)) + blit(scrollbuf,scrollbuf,0,8,0,7,256,248); + +} + + +static int trstr; +static byte tr_items[] = +{ + iHeart,iHeartC,iFairyMoving,iClock,iRupy,i5Rupies,iBPotion,iRPotion,iLetter,iBait,iSword,iWSword,iMSword,iShield,iBrang,iMBrang,iBombs,iBow,iArrow,iSArrow,iBCandle,iRCandle, + iBRing,iRRing,iBracelet,iWhistle,iRaft,iLadder,iWand,iBook,iKey,iMKey,iMap,iCompass,iTriforce +}; + +static const char* treasure_str[] = +{ + "ALL OF TREASURES", + " HEART CONTAINER ", + " HEART ", + " FAIRY CLOCK ", + " ", + " RUPY 5 RUPIES ", + " ", + "LIFE POTION 2ND POTION ", + " ", + " LETTER FOOD ", + " ", + " SWORD WHITE ", + " SWORD ", + " MAGICAL MAGICAL ", + " SWORD SHIELD ", + " BOOMERANG MAGICAL ", + " BOOMERANG ", + " BOMB BOW ", + " ", + " ARROW SILVER ", + " ARROW ", + " BLUE RED ", + " CANDLE CANDLE ", + " BLUE RED ", + " RING RING ", + " POWER RECORDER ", + " BRACELET ", + " RAFT STEPLADDER ", + " ", + " MAGICAL BOOK OF ", + " ROD MAGIC ", + " KEY MAGICAL ", + " KEY ", + " MAP COMPASS ", + " ", + " ", + " TRIFORCE " +}; + +static void treasures(int f) +{ + if(f<1804) return; + + if(f>4492) return; + + if(f == 1804) + + { + for(int x=0; x<48; x+=16) + { + puttile8(scrollbuf,vine[2],x,232,3,0); + puttile8(scrollbuf,vine[3],x+8,232,3,0); + puttile8(scrollbuf,vine[2],x+208,232,3,0); + puttile8(scrollbuf,vine[3],x+216,232,3,0); + } + + puttile8(scrollbuf,vine[4],48,232,3,1); + puttile8(scrollbuf,vine[4],200,232,3,1); + putstring(64,232,treasure_str[trstr++],0); + } + + int y = (1820 + 96 + 448 - f) >>1; + y += f&1; + + for(int i=0; i<34; i+=2) + { + if((y>=0)&&(y<240)) + { + if(i==2) // fairy + puttile16(scrollbuf,((f&4)>>2)+63,68,y,8,0); + else + // putitem(scrollbuf,68,y,tr_items[i],lens_hint_item[tr_items[i]][0], lens_hint_item[tr_items[i]][1], 0); + // putitem(scrollbuf,172,y,tr_items[i+1],lens_hint_item[tr_items[i+1]][0],lens_hint_item[tr_items[i+1]][1], 0); + putitem(scrollbuf,68,y,tr_items[i]); + + putitem(scrollbuf,172,y,tr_items[i+1]); + } + + y+=64; + } + + y+=8; + + if((y>=0)&&(y<240)) + putitem(scrollbuf,120,y,iTriforce); + + y+=80; + + if(y>=0) + for(int i=177; i<=217; i+=20) + { + if(y<240) + { + puttile16(scrollbuf,i,104,y,6,0); + puttile16(scrollbuf,i+1,120,y,6,0); + puttile16(scrollbuf,i+2,136,y,6,0); + } + + y+=16; + } + + if(y<240) //Link holding item + puttile16(scrollbuf,29,120,y,6,0); + + if(f < 18*8*16 + 1820+128) + { + if(((f-1820)&15)==0) + { + int ax=(f-1820)>>4; + + if((ax&0xF8) && ((ax&7)<2)) + putstring(32,232,treasure_str[trstr++],0); + } + } + + blit(scrollbuf,framebuf,0,8,0,0,256,224); +} + +static void NES_titlescreen() +{ + int f=0; + bool done=false; + wave[0]=0; + wave[1]=16; + wave[2]=32; + tri=0; + fcnt=0; + trstr=0; + set_palette(black_palette); + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + clear_bitmap(screen); + clear_bitmap(framebuf); + init_NES_mode(); + reset_items(true, &QHeader); + CSET_SIZE=4; + CSET_SHFT=2; + loadtitlepal(0x36,titlepal,4); + ALLOFF(); + + do + { + load_control_state(); + mainscreen(f); + storyscreen(f); + treasures(f); + + if((f>1676)&&(f<=4492)&&(f&1)) + blit(scrollbuf,scrollbuf,0,8,0,7,256,248); + + if(f>=4492) + putitem(framebuf,120,24,iTriforce); + + ++f; + + if((f>4750&&midi_pos<0) || f>6000) + { + wave[0]=0; + wave[1]=16; + wave[2]=32; + tri=fcnt=trstr=f=0; + clear_bitmap(framebuf); + loadtitlepal(0x36,titlepal,4); + music_stop(); + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + } + + advanceframe(true); + + if(rSbtn()) + done=true; + } + while(!done && !Quit); + + + + music_stop(); + clear_to_color(screen,BLACK); + CSET_SIZE=16; + CSET_SHFT=4; +} + +/************************************/ +/******** DX title screen *********/ +/************************************/ + +static void DX_mainscreen(int f) +{ + set_uformat(U_ASCII); + + static int pic=0; + char tbuf[80]; + + if(f>=1010) + return; + + DATAFILE *dat = (DATAFILE*)data[TITLE_DX].dat; + BITMAP *bmp; + + if(f==0) + { + copy_pal((RGB*)dat[TITLE_DX_PAL_1].dat,RAMpal); + refreshpal=true; + } + + if(f<680+256 && (f&15)==0) + { + bmp = (BITMAP*)dat[pic<4 ? pic : 6-pic].dat; + pic = (pic+1)%6; + blit(bmp,framebuf, 0,0, 0,0, 256,224); + // text_mode(-1); + sprintf(tbuf, "%c1986 Nintendo",0xBB); + //tbuf[0]=0xBB; + textout_ex(framebuf,font,tbuf,46,138,255,-1); + sprintf(tbuf, "%c2014 Armageddon Games",0xBC); + //tbuf[0]=0xBC; + textout_ex(framebuf,font,tbuf,46,146,255,-1); + // text_mode(0); + } + + if(f>=680 && f<680+256 && (f%3)==0) + { + fade_interpolate((RGB*)dat[TITLE_DX_PAL_1].dat,black_palette,RAMpal, + (f-680)>>2,0,255); + refreshpal=true; + } + + if(f==680+256) + { + clear_bitmap(framebuf); + clear_bitmap(scrollbuf); + } + + if(f==680+256+2) + loadtitlepal(0x0F,itemspal,0); +} + +static void DX_titlescreen() +{ + // JGMOD *yea; + int f=0; + bool done=false; + trstr=0; + set_palette(black_palette); + + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + clear_to_color(screen,BLACK); + clear_bitmap(framebuf); + init_NES_mode(); + reset_items(true, &QHeader); + CSET_SIZE=4; + CSET_SHFT=2; + ALLOFF(); + clear_keybuf(); + + do + { + load_control_state(); + DX_mainscreen(f); + storyscreen(f); + treasures(f); + + if((f>1676)&&(f<=4492)&&(f&1)) + blit(scrollbuf,scrollbuf,0,8,0,7,256,248); + + if(f>=4492) + putitem(framebuf,120,24,iTriforce); + + ++f; + + if((f>4750&&midi_pos<0) || f>6000) + { + trstr=f=0; + clear_bitmap(framebuf); + music_stop(); + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + } + + advanceframe(true); + + if(rSbtn()) + done=true; + } + while(!done && !Quit); + + music_stop(); + // stop_mod(); + + clear_to_color(screen,BLACK); + CSET_SIZE=16; + CSET_SHFT=4; +} + +/*************************************/ +/******** 2.5 title screen *********/ +/*************************************/ + +static void v25_mainscreen(int f) +{ + set_uformat(U_ASCII); + + static int pic=0; + char tbuf[80]; + + if(f>=1010) + return; + + DATAFILE *dat = (DATAFILE*)data[TITLE_25].dat; + BITMAP *bmp; + + if(f==0) + { + copy_pal((RGB*)dat[TITLE_25_PAL_1].dat,RAMpal); + refreshpal=true; + } + + if(f<680+256 && (f&15)==0) + { + bmp = (BITMAP*)dat[pic<5 ? pic : 8-pic].dat; + pic = (pic+1)%8; + blit(bmp,framebuf, 0,0, 0,0, 256,224); + // text_mode(-1); + sprintf(tbuf, "%c1986 Nintendo",0xBB); + //tbuf[0]=0xBB; + textout_ex(framebuf,font,tbuf,80,134,255,-1); + sprintf(tbuf, "%c2014 Armageddon Games",0xBC); + //tbuf[0]=0xBC; + textout_ex(framebuf,font,tbuf,80,142,255,-1); + // text_mode(0); + } + + if(f>=680 && f<680+256 && (f%3)==0) + { + fade_interpolate((RGB*)dat[TITLE_25_PAL_1].dat,black_palette,RAMpal, + (f-680)>>2,0,255); + refreshpal=true; + } + + if(f==680+256) + { + clear_bitmap(framebuf); + clear_bitmap(scrollbuf); + } + + if(f==680+256+2) + loadtitlepal(0x0F,itemspal,0); +} + +static void v25_titlescreen() +{ + // JGMOD *yea; + int f=0; + bool done=false; + trstr=0; + set_palette(black_palette); + + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + clear_to_color(screen,BLACK); + clear_bitmap(framebuf); + init_NES_mode(); + reset_items(true, &QHeader); + CSET_SIZE=4; + CSET_SHFT=2; + ALLOFF(); + clear_keybuf(); + + do + { + load_control_state(); + v25_mainscreen(f); + storyscreen(f); + treasures(f); + + if((f>1676)&&(f<=4492)&&(f&1)) + blit(scrollbuf,scrollbuf,0,8,0,7,256,248); + + if(f>=4492) + putitem(framebuf,120,24,iTriforce); + + ++f; + + if((f>4750&&midi_pos<0) || f>6000) + { + trstr=f=0; + clear_bitmap(framebuf); + music_stop(); + try_zcmusic((char*)"zelda.nsf",0, ZC_MIDI_TITLE); + } + + advanceframe(true); + + if(rSbtn()) + done=true; + } + while(!done && !Quit); + + music_stop(); + // stop_mod(); + + clear_to_color(screen,BLACK); + CSET_SIZE=16; + CSET_SHFT=4; +} + +/***********************************/ +/**** Game Selection Screens *****/ +/***********************************/ + +// first the game saving & loading system + +static const char *SAVE_HEADER = "Zelda Classic Save File"; +extern char *SAVE_FILE; + +int readsaves(gamedata *savedata, PACKFILE *f) +{ + //word item_count; + word qstpath_len; + word save_count; + char name[9]; + byte tempbyte; + short tempshort; + // long templong; + word tempword; + dword tempdword; + long section_id=0; + word section_version=0; + word section_cversion=0; + dword section_size; + + //section id + if(!p_mgetl(§ion_id,f,true)) + { + return 1; + } + + //section version info + if(!p_igetw(§ion_version,f,true)) + { + return 2; + } + + if(!p_igetw(§ion_cversion,f,true)) + { + return 3; + } + + if(section_version < 11) //Sorry! + { + //Currently unsupported + return 1; + } + + //section size + if(!p_igetl(§ion_size,f,true)) + { + return 4; + } + + if(!p_igetw(&save_count,f,true)) + { + return 5; + } + + // Excess saves would get deleted, so... + if(standalone_mode && save_count>1) + { + system_pal(); + jwin_alert("Invalid save file", + "This save file cannot be", + "used in standalone mode.", + "", + "OK",NULL,'o',0,lfont); + exit(0); + } + else if(!standalone_mode && save_count==1) + { + system_pal(); + + if(jwin_alert3("Standalone save file", + "This save file was created in standalone mode.", + "If you continue, you will no longer be able", + "to use it in standalone mode. Continue anyway?", + "No","Yes",NULL, 'n','y', 0, lfont)!=2) + { + exit(0); + } + } + + for(int i=0; i1) + { + if(section_version <= 5) + { + for(int j=0; j2) + { + for(int j=0; j<32; j++) + { + if(!p_igetw(&tempword,f,true)) + { + return 46; + } + + savedata[i].set_counter(tempword, j); + + if(!p_igetw(&tempword,f,true)) + { + return 47; + } + + savedata[i].set_maxcounter(tempword, j); + + if(!p_igetw(&tempshort,f,true)) + { + return 48; + } + + savedata[i].set_dcounter(tempshort, j); + } + } + + if(section_version>3) + { + for(int j=0; j<256; j++) + { + if(!p_getc(&tempbyte,f,true)) + { + return 49; + } + + savedata[i].set_generic(tempbyte, j); + } + } + + if(section_version>6) + { + if(!p_getc(&tempbyte, f, true)) + { + return 50; + } + + savedata[i].awpn = tempbyte; + + if(!p_getc(&tempbyte, f, true)) + { + return 51; + } + + savedata[i].bwpn = tempbyte; + } + else + { + savedata[i].awpn = 0; + savedata[i].bwpn = 0; + } + + //First we get the size of the vector + if(!p_igetl(&tempdword, f, true)) + return 53; + + if(tempdword != 0) //Might not be any at all + { + //Then we allocate the vector + savedata[i].globalRAM.resize(tempdword); + + for(dword j = 0; j < savedata[i].globalRAM.size(); j++) + { + ZScriptArray& a = savedata[i].globalRAM[j]; + + //We get the size of each container + if(!p_igetl(&tempdword, f, true)) + return 54; + + //We allocate the container + a.Resize(tempdword); + + //And then fill in the contents + for(dword k = 0; k < a.Size(); k++) + if(!p_igetl(&(a[k]), f, true)) + return 55; + } + } + } + + return 0; +} + +void set_up_standalone_save() +{ + char *fn=get_filename(standalone_quest); + saves[0].set_name(fn); + + qstpath=(char*)zc_malloc(2048); + strncpy(qstpath, standalone_quest, 2047); + qstpath[2047]='\0'; + chosecustomquest=true; + load_custom_game(0); + + // Why does the continue screen need set when + // everything else gets set automatically? + saves[0].set_continue_dmap(0); + saves[0].set_continue_scrn(0xFF); + saves[0].set_hasplayed(false); + + load_game_icon_to_buffer(false, 0); + load_game_icon(saves, true, 0); +} + +// call once at startup +int load_savedgames() +{ + char *fname = SAVE_FILE; + char *iname = (char *)zc_malloc(2048); + int ret; + PACKFILE *f=NULL; + FILE *f2=NULL; + char tmpfilename[32]; + temp_name(tmpfilename); +// const char *passwd = datapwd; + + if(saves == NULL) + { + saves = new gamedata[MAXSAVES]; + + if(saves==NULL) + return 1; + } + + // see if it's there + if(!exists(fname)) + { + goto newdata; + } + + if(file_size_ex_password(fname, "") == 0) + { + if(errno==0) // No error, file's empty + { + goto init; + } + else // Error... + { + goto cantopen; + } + } + + // decode to temp file + ret = decode_file_007(fname, tmpfilename, SAVE_HEADER, ENC_METHOD_MAX-1, strstr(fname, ".dat#")!=NULL, ""); + + if(ret) + { + goto cantopen; + } + + fname = tmpfilename; + + // load the games + f = pack_fopen_password(fname, F_READ_PACKED, ""); + + if(!f) + goto cantopen; + + if(readsaves(saves,f)!=0) + goto reset; + + strcpy(iname, SAVE_FILE); + + for(int i=0; iname[i]!='\0'; iname[i]=='.'?iname[i]='\0':i++) + { + /* do nothing */ + } + + strcat(iname,".icn"); + + if(!exists(iname)) + { + byte *di2 = (byte *)iconbuffer; + + for(dword i=0; iicon[j] = *(si++); + } + + si = iconbuffer[index].pal[i]; + + for(int j=0; j<48; j++) + { + g->pal[j] = *(si++); + } +} + +void load_game_icon_to_buffer(bool forceDefault, int index) +{ + int ring=0; + + if(!forceDefault) + { + flushItemCache(); + int maxringid = getHighestLevelOfFamily(&zinit, itemsbuf, itype_ring); + + if(maxringid != -1) + { + ring = itemsbuf[maxringid].fam_type; + } + } + + //blue rings now start at level 2 for some reason, account for that -DD + ring = ring ? ring-1 : 0; + iconbuffer[index].ring = zc_min(ring, 3); + + int t=0; + //if(!forceDefault) + //t = QMisc.icons[i]; + + for(int i=0; i<4; i++) + { + t = QMisc.icons[i]; + + if(t<0 || t>=NEWMAXTILES) + { + t=0; + } + + int tileind = t ? t : 28; + + byte *si = newtilebuf[tileind].data; + + if(newtilebuf[tileind].format==tf8Bit) + { + for(int j=0; j<128; j++) + { + iconbuffer[index].icon[i][j] =0; + } + } + else + { + for(int j=0; j<128; j++) + { + iconbuffer[index].icon[i][j] = *(si++); + } + } + + if(t) + { + si = colordata + CSET(pSprite(i+spICON1))*3; + } + else + { + if(i) + { + si = colordata + CSET(pSprite(i-1+spBLUE))*3; + } + else + { + si = colordata + CSET(6)*3; + } + } + + if(newtilebuf[tileind].format==tf8Bit) + { + for(int j=0; j<48; j++) + { + iconbuffer[index].pal[i][j] = 0; + } + } + else + { + for(int j=0; j<48; j++) + { + iconbuffer[index].pal[i][j] = *(si++); + } + } + } + + iconbuffer[index].loaded=1; +} + +static void select_mode() +{ + textout_ex(scrollbuf,zfont,"REGISTER YOUR NAME",48,152,1,0); + textout_ex(scrollbuf,zfont,"COPY FILE",48,168,1,0); + textout_ex(scrollbuf,zfont,"DELETE FILE",48,184,1,0); +} + +static void register_mode() +{ + textout_ex(scrollbuf,zfont,"REGISTER YOUR NAME",48,152,CSET(2)+3,0); +} + +static void copy_mode() +{ + textout_ex(scrollbuf,zfont,"COPY FILE",48,168,CSET(2)+3,0); +} + +static void delete_mode() +{ + textout_ex(scrollbuf,zfont,"DELETE FILE",48,184,CSET(2)+3,0); +} + +static void selectscreen() +{ + // text_mode(0); + init_NES_mode(); + // loadfullpal(); + loadlvlpal(1); + clear_bitmap(scrollbuf); + QMisc.colors.blueframe_tile = 237; + QMisc.colors.blueframe_cset = 0; +// blueframe(scrollbuf,&QMisc,24,48,26,20); + frame2x2(scrollbuf,&QMisc,24,48,QMisc.colors.blueframe_tile,QMisc.colors.blueframe_cset,26,20,0,1,0); + textout_ex(scrollbuf,zfont,"- S E L E C T -",64,24,1,0); + textout_ex(scrollbuf,zfont," NAME ",80,48,1,0); + textout_ex(scrollbuf,zfont," LIFE ",152,48,1,0); + select_mode(); + RAMpal[CSET(9)+1]=NESpal(0x15); + RAMpal[CSET(9)+2]=NESpal(0x27); + RAMpal[CSET(9)+3]=NESpal(0x30); + RAMpal[CSET(13)+1]=NESpal(0x30); +} + +static byte left_arrow_str[] = {132,0}; +static byte right_arrow_str[] = {133,0}; + +static int savecnt; + +static void list_save(int save_num, int ypos) +{ + bool r = refreshpal; + + if(save_numset_maxlife(saves[save_num].get_maxlife()); + game->set_life(saves[save_num].get_maxlife()); + wpnsbuf[iwQuarterHearts].tile = 4; + //boogie! + lifemeter(framebuf,144,ypos+((game->get_maxlife()>16*(HP_PER_HEART))?8:0),0,0); + textout_ex(framebuf,zfont,saves[save_num].get_name(),72,ypos+16,1,0); + + if(saves[save_num].get_quest()) + textprintf_ex(framebuf,zfont,72,ypos+24,1,0,"%3d",saves[save_num].get_deaths()); + + if(saves[save_num].get_quest()==2) + overtile16(framebuf,41,56,ypos+14,9,0); //put sword on second quests + + if(saves[save_num].get_quest()==3) + { + overtile16(framebuf,41,56,ypos+14,9,0); //put sword on second quests + overtile16(framebuf,41,41,ypos+14,9,0); //put sword on third quests + } + + if(saves[save_num].get_quest()==4) + { + overtile16(framebuf,176,52,ypos+14,0,1); //dust pile + overtile16(framebuf,175,52,ypos+14,9,0); //triforce + } + + if(saves[save_num].get_quest()==5) + { + overtile16(framebuf,176,52,ypos+14,0,1); //dust pile + overtile16(framebuf,175,52,ypos+14,9,0); //triforce + } + + textprintf_ex(framebuf,zfont,72,ypos+16,1,0,"%s",saves[save_num].get_name()); + } + + byte *hold = newtilebuf[0].data; + byte holdformat=newtilebuf[0].format; + newtilebuf[0].format=tf4Bit; + newtilebuf[0].data = saves[save_num].icon; + overtile16(framebuf,0,48,ypos+17,(save_num%3)+10,0); //link + newtilebuf[0].format=holdformat; + newtilebuf[0].data = hold; + + hold = colordata; + colordata = saves[save_num].pal; + loadpalset((save_num%3)+10,0); + colordata = hold; + + textout_ex(framebuf,zfont,"-",136,ypos+16,1,0); + + refreshpal = r; +} + +static void list_saves() +{ + // Fourth Quest turns the menu red. + bool red = false; + + for(int i=0; i3) + { + if(listpos>=3) + textout_ex(framebuf,zfont,(char *)left_arrow_str,96,60,3,0); + + if(listpos+3=MAXSAVES) + return false; + + int NameEntryMode2=NameEntryMode; + + saves[savecnt].set_maxlife(3*HP_PER_HEART); + saves[savecnt].set_maxbombs(8); + saves[savecnt].set_continue_dmap(0); + saves[savecnt].set_continue_scrn(0xFF); + + int s=savecnt; + ++savecnt; + listpos=(s/3)*3; +// clear_bitmap(framebuf); + rectfill(framebuf,32,56,223,151,0); + list_saves(); + blit(framebuf,scrollbuf,0,0,0,0,256,224); + + int pos=s%3; + int y=((NameEntryMode2>0)?0:(pos*24))+72; + int x=0; + int spos=0; + char name[9]; + + memset(name,0,9); + register_mode(); + clear_keybuf(); + SystemKeys=(NameEntryMode2>0); + refreshpal=true; + bool done=false; + bool cancel=false; + + int letter_grid_x=(NameEntryMode2==2)?34:44; + int letter_grid_y=120; + int letter_grid_offset=(NameEntryMode2==2)?10:8; + int letter_grid_width=(NameEntryMode2==2)?16:11; + int letter_grid_height=(NameEntryMode2==2)?6:4; + int letter_grid_spacing=(NameEntryMode2==2)?12:16; + + const char *simple_grid="ABCDEFGHIJKLMNOPQRSTUVWXYZ-.,!'&.0123456789 "; + const char *complete_grid=" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; + + if(NameEntryMode2>0) + { + //int pos=file%3; + BITMAP *info = create_bitmap_ex(8,168,32); + clear_bitmap(info); + blit(framebuf,info,40,pos*24+70,0,0,168,26); + rectfill(info,40,0,168,1,0); + rectfill(info,0,24,39,25,0); + rectfill(info,0,0,7,15,0); + rectfill(framebuf,40,64,216,192,0); + rectfill(framebuf,96,60,183,67,0); + + int i=pos*24+70; + + do + { + blit(info,framebuf,0,0,40,i,168,32); + advanceframe(true); + i-=pos+pos; + } + while(pos && i>=70); + + clear_bitmap(framebuf); + frame2x2(framebuf,&QMisc,24,48,QMisc.colors.blueframe_tile,QMisc.colors.blueframe_cset,26,8,0,1,0); + textout_ex(framebuf,zfont," NAME ",80,48,1,0); + textout_ex(framebuf,zfont," LIFE ",152,48,1,0); + + blit(info,framebuf,0,0,40,70,168,32); + destroy_bitmap(info); + + frame2x2(framebuf,&QMisc,letter_grid_x-letter_grid_offset,letter_grid_y-letter_grid_offset,QMisc.colors.blueframe_tile,QMisc.colors.blueframe_cset,(NameEntryMode2==2)?26:23,(NameEntryMode2==2)?11:9,0,1,0); + + if(NameEntryMode2==1) + { + textout_ex(framebuf,zfont,"A B C D E F G H I J K",letter_grid_x,letter_grid_y,1,-1); + textout_ex(framebuf,zfont,"L M N O P Q R S T U V",letter_grid_x,letter_grid_y+16,1,-1); + textout_ex(framebuf,zfont,"W X Y Z - . , ! ' & .",letter_grid_x,letter_grid_y+32,1,-1); + textout_ex(framebuf,zfont,"0 1 2 3 4 5 6 7 8 9 ",letter_grid_x,letter_grid_y+48,1,-1); + } + else + { + textout_ex(framebuf,zfont," \" $ & ( * , .",letter_grid_x, letter_grid_y, 1,-1); + textout_ex(framebuf,zfont, "! # % ' ) + - /",letter_grid_x+12,letter_grid_y, 1,-1); + textout_ex(framebuf,zfont,"0 2 4 6 8 : < >", letter_grid_x, letter_grid_y+12,1,-1); + textout_ex(framebuf,zfont, "1 3 5 7 9 ; = ?",letter_grid_x+12,letter_grid_y+12,1,-1); + textout_ex(framebuf,zfont,"@ B D F H J L N", letter_grid_x, letter_grid_y+24,1,-1); + textout_ex(framebuf,zfont, "A C E G I K M O",letter_grid_x+12,letter_grid_y+24,1,-1); + textout_ex(framebuf,zfont,"P R T V X Z \\ ^",letter_grid_x, letter_grid_y+36,1,-1); + textout_ex(framebuf,zfont, "Q S U W Y [ ] _",letter_grid_x+12,letter_grid_y+36,1,-1); + textout_ex(framebuf,zfont,"` b d f h j l n", letter_grid_x, letter_grid_y+48,1,-1); + textout_ex(framebuf,zfont, "a c e g i k m o",letter_grid_x+12,letter_grid_y+48,1,-1); + textout_ex(framebuf,zfont,"p r t v x z | ~", letter_grid_x, letter_grid_y+60,1,-1); + textout_ex(framebuf,zfont, "q s u w y { }", letter_grid_x+12,letter_grid_y+60,1,-1); + } + + advanceframe(true); + blit(framebuf,scrollbuf,0,0,0,0,256,224); + + } + + int grid_x=0; + int grid_y=0; + + + do + { + if(NameEntryMode2>0) + { + spos = grid_y*letter_grid_width+grid_x; + load_control_state(); + + if(rLeft()) + { + --grid_x; + + if(grid_x<0) + { + grid_x=letter_grid_width-1; + --grid_y; + + if(grid_y<0) + { + grid_y=letter_grid_height-1; + } + } + + sfx(WAV_CHIME); + } + else if(rRight()) + { + ++grid_x; + + if(grid_x>=letter_grid_width) + { + grid_x=0; + ++grid_y; + + if(grid_y>=letter_grid_height) + { + grid_y=0; + } + } + + sfx(WAV_CHIME); + } + else if(rUp()) + { + --grid_y; + + if(grid_y<0) + { + grid_y=letter_grid_height-1; + } + + sfx(WAV_CHIME); + } + else if(rDown()) + { + ++grid_y; + + if(grid_y>=letter_grid_height) + { + grid_y=0; + } + + sfx(WAV_CHIME); + } + else if(rBbtn()) + { + ++x; + + if(x>=8) + { + x=0; + } + } + else if(rAbtn()) + { + name[zc_min(x,7)]=(NameEntryMode2==2)?complete_grid[spos]:simple_grid[spos]; + ++x; + + if(x>=8) + { + x=0; + } + + sfx(WAV_PLACE); + } + else if(rSbtn()) + { + done=true; + int ltrs=0; + + for(int i=0; i<8; i++) + { + if(name[i]!=' ' && name[i]!=0) + { + ++ltrs; + } + } + + if(!ltrs) + { + cancel=true; + } + } + + } + else + { + if(keypressed()) + { + int k=readkey(); + + if(isprint(k&255)) + { + name[zc_min(x,7)]=k&0xFF; + + if(x<8) + { + ++x; + } + + sfx(WAV_PLACE); + } + else + { + switch(k>>8) + { + case KEY_LEFT: + if(x>0) + { + if(x==8) + { + x=6; + } + else + { + --x; + } + + sfx(WAV_CHIME); + } + + break; + + case KEY_RIGHT: + if(x<8 && name[zc_min(x,7)]) + { + ++x; + sfx(WAV_CHIME); + } + + break; + + case KEY_ENTER: + case KEY_ENTER_PAD: + { + done=true; + int ltrs=0; + + for(int i=0; i<8; i++) + { + if(name[i]!=' ' && name[i]!=0) + { + ++ltrs; + } + } + + if(!ltrs) + { + cancel=true; + } + } + break; + + case KEY_BACKSPACE: + if(x>0) + { + --x; + + for(int i=zc_min(x,7); i<8; i++) + { + name[i]=name[i+1]; + } + + sfx(WAV_OUCH); + } + + break; + + case KEY_DEL: + for(int i=zc_min(x,7); i<8; i++) + { + name[i]=name[i+1]; + } + + sfx(WAV_OUCH); + break; + + case KEY_ESC: + x=-1; + done=true; + + while(key[KEY_ESC]) + { + /* do nothing */ + } + + break; + } + } + } + } + + saves[s].set_name(name); + blit(scrollbuf,framebuf,0,0,0,0,256,224); +// list_saves(); + list_save(s,56+((NameEntryMode2>0)?0:(pos*24))); + + int x2=letter_grid_x + grid_x*letter_grid_spacing; + int y2=letter_grid_y + grid_y*letter_grid_spacing; + + if(frame&8) + { + int tx=(zc_min(x,7)<<3)+72; + + for(int dy=0; dy<8; dy++) + { + for(int dx=0; dx<8; dx++) + { + if(framebuf->line[y+dy][tx+dx]==0) + { + framebuf->line[y+dy][tx+dx]=CSET(9)+1; + } + + if(NameEntryMode2>0) + { + if(framebuf->line[y2+dy][x2+dx]==0) + { + framebuf->line[y2+dy][x2+dx]=CSET(9)+1; + } + } + } + } + } + + draw_cursor((NameEntryMode2>0)?0:pos,0); + advanceframe(true); + /* + if(rBbtn()) + { + x=-1; + done=true; + } + */ + } + while(!done && !Quit); + + if(x<0 || cancel) + { + done=false; + } + + if(done) + { + int quest=1; + char buf[9]; + strcpy(buf,name); + strupr(buf); + + if(!stricmp(buf,"ZELDA")) + quest=2; + + if(!stricmp(buf,"ALPHA")) + quest=3; + + if(!stricmp(buf,"GANON")) + quest=4; + + if(!stricmp(buf,"JEAN")) // This is what BigJoe wanted. I have no problem with it. + quest=5; + + saves[s].set_quest(quest); + +// setPackfilePassword(datapwd); + //0 is success + int ret = load_quest(saves+s); + + if(ret==qe_OK) + { + flushItemCache(); + //messy hack to get this to work, since game is not yet initialized -DD + gamedata *oldgame = game; + game = saves+s; + saves[s].set_maxlife(zinit.hc*HP_PER_HEART); + //saves[s].items[itype_ring]=0; + removeItemsOfFamily(&saves[s], itemsbuf, itype_ring); + int maxringid = getHighestLevelOfFamily(&zinit, itemsbuf, itype_ring); + + if(maxringid != -1) + getitem(maxringid, true); + + // game->set_maxbombs(&saves[s], zinit.max_bombs); + selectscreen(); // refresh palette + game = oldgame; + ringcolor(false); + load_game_icon_to_buffer(false,s); + load_game_icon(saves+s, true, s); + } + else + { + ringcolor(true); + load_game_icon(saves+s, true, s); + } + +// setPackfilePassword(NULL); + saves[s].set_timevalid(1); + } + + if(x<0 || cancel) + { + for(int i=s; isavecnt-1) + listpos=zc_max(listpos-3,0); + } + + SystemKeys=true; + selectscreen(); + list_saves(); + select_mode(); + return done; +} + +static bool copy_file(int file) +{ + if(savecntsavecnt-1) + listpos=zc_max(listpos-3,0); + + sfx(WAV_OUCH); + select_mode(); + return true; + } + + return false; +} + +/** game mode stuff **/ + +DIALOG gamemode_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 40, 44, 240, 180, 0, 0, 0, D_EXIT, 0, 0, (void *) "Select Custom Quest", NULL, NULL }, + // 1 + { jwin_button_proc, 205, 76, 61, 21, 0, 0, 'b', D_EXIT, 0, 0, (void *) "&Browse", NULL, NULL }, + { jwin_textbox_proc, 55, 78, 140, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 76, 106, 64, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Info:", NULL, NULL }, + { jwin_textbox_proc, 76, 118, 168, 60, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 5 + { jwin_button_proc, 90, 191, 61, 21, 0, 0, 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 191, 61, 21, 0, 0, 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +static int get_quest_info(zquestheader *header,char *str) +{ + if(strlen(get_filename(qstpath)) == 0) + { + str[0]=0; + return 0; + } + + bool oldquest=false; + + // default error + strcpy(str,"Error: Invalid quest file"); + + char tmpfilename[32]; + temp_name(tmpfilename); + int ret; + PACKFILE *f; + + const char *passwd = datapwd; + ret = decode_file_007(qstpath, tmpfilename, ENC_STR, ENC_METHOD_MAX-1, strstr(qstpath, ".dat#")!=NULL, passwd); + + if(ret) + { + switch(ret) + { + case 1: + strcpy(str,"Error: Unable to open file"); + break; + + case 2: + strcpy(str,"Internal error occurred"); + break; + // be sure not to delete tmpfilename now... + } + + if(ret==5) //old encryption? + { + ret = decode_file_007(qstpath, tmpfilename, ENC_STR, ENC_METHOD_211B9, strstr(qstpath, ".dat#")!=NULL,passwd); + } + + if(ret==5) //old encryption? + { + ret = decode_file_007(qstpath, tmpfilename, ENC_STR, ENC_METHOD_192B185, strstr(qstpath, ".dat#")!=NULL,passwd); + } + + if(ret==5) //old encryption? + { + ret = decode_file_007(qstpath, tmpfilename, ENC_STR, ENC_METHOD_192B105, strstr(qstpath, ".dat#")!=NULL,passwd); + } + + if(ret==5) //old encryption? + { + ret = decode_file_007(qstpath, tmpfilename, ENC_STR, ENC_METHOD_192B104, strstr(qstpath, ".dat#")!=NULL,passwd); + } + + if(ret) + { + oldquest = true; + passwd = ""; + } + } + + f = pack_fopen_password(oldquest ? qstpath : tmpfilename, F_READ_PACKED, passwd); + + if(!f) + { + if(!oldquest&&(errno==EDOM)) + { + f = pack_fopen_password(oldquest ? qstpath : tmpfilename, F_READ, passwd); + } + + if(!f) + { + delete_file(tmpfilename); + } + + strcpy(str,"Error: Unable to open file"); +// setPackfilePassword(NULL); + return 0; + } + + ret=readheader(f, header, true); + + if(f) + { + pack_fclose(f); + } + + if(!oldquest) + { + delete_file(tmpfilename); + } + +// setPackfilePassword(NULL); + + switch(ret) + { + case 0: + break; + + case qe_invalid: + strcpy(str,"Error: Invalid quest file"); + return 0; + break; + + case qe_version: + strcpy(str,"Error: Invalid version"); + return 0; + break; + + case qe_obsolete: + strcpy(str,"Error: Obsolete version"); + return 0; + break; + } + + if(header->quest_number > 0) + { + strcpy(str, + (header->quest_number == 4) ? "Error: Not a custom quest! Clear the Second Quest with all 16 Heart Containers to play this." : + (header->quest_number == 3) ? "Error: Not a custom quest! Clear the Second Quest to play this." : + (header->quest_number > 1) ? "Error: Not a custom quest! Clear the First Quest to play this." : + "Error: Not a custom quest! Create a new save file and press Start to play the First Quest."); + return 0; + } + + strcpy(str,"Title:\n"); + strcat(str,header->title); + strcat(str,"\n\nAuthor:\n"); + strcat(str,header->author); +// setPackfilePassword(NULL); + + return 1; +} + +bool load_custom_game(int file) +{ + if(!saves[file].get_hasplayed()) + { + if(chosecustomquest) + { + clear_to_color(screen,BLACK); + saves[file].set_quest(0xFF); + char temppath[2048]; + memset(temppath, 0, 2048); + zc_make_relative_filename(temppath, qstdir, qstpath, 2047); + + if(temppath[0]==0) //can't make relative, go absolute + { + sprintf(saves[file].qstpath, "%s", qstpath); + } + else + { + sprintf(saves[file].qstpath, "%s", temppath); + } + + load_quest(saves+file); + + saves[file].set_maxlife(zinit.hc*HP_PER_HEART); + flushItemCache(); + + //messy hack to get this to work properly since game is not initialized -DD + gamedata *oldgame = game; + game = saves+file; + int maxringid = getHighestLevelOfFamily(&zinit, itemsbuf, itype_ring); + + if(maxringid != -1) + getitem(maxringid, true); + + rest(200); // Formerly 1000 -L + ringcolor(false); + load_game_icon_to_buffer(false,file); + load_game_icon(game,false,file); + game = oldgame; + chosecustomquest = false; + return true; + } + } + + return false; +} + +int custom_game(int file) +{ + zquestheader h; + char infostr[200]; + char path[2048]; + int ret=0; + + if(is_relative_filename(saves[file].qstpath)) + { + sprintf(qstpath,"%s%s",qstdir,saves[file].qstpath); + } + else + { + sprintf(qstpath,"%s", saves[file].qstpath); + } + + gamemode_dlg[0].dp2 = lfont; + gamemode_dlg[2].dp = get_filename(qstpath); + + if(get_quest_info(&h,infostr)==0) + { + gamemode_dlg[4].dp = infostr; + gamemode_dlg[5].flags = D_DISABLED; + } + else + { + gamemode_dlg[4].dp = infostr; + gamemode_dlg[5].flags = D_EXIT; + } + + gamemode_dlg[2].d1 = gamemode_dlg[4].d1 = 0; + gamemode_dlg[2].d2 = gamemode_dlg[4].d2 = 0; + system_pal(); + show_mouse(screen); + + clear_keybuf(); + + if(is_large) + large_dialog(gamemode_dlg); + + while((ret=zc_popup_dialog(gamemode_dlg,1))==1) + { + scare_mouse(); + blit(screen,tmp_scr,scrx,scry,0,0,320,240); + unscare_mouse(); + + int sel=0; + static EXT_LIST list[] = + { + { (char *)"ZC Quests (*.qst)", (char *)"qst" }, + { NULL, NULL } + }; + + strcpy(path, qstpath); + + if(jwin_file_browse_ex("Load Quest", path, list, &sel, 2048, -1, -1, lfont)) + { + // strcpy(qstpath, path); + replace_extension(qstpath,path,"qst",2047); + gamemode_dlg[2].dp = get_filename(qstpath); + + if(get_quest_info(&h,infostr)==0) + { + gamemode_dlg[4].dp = infostr; + gamemode_dlg[5].flags = D_DISABLED; + } + else + { + gamemode_dlg[4].dp = infostr; + gamemode_dlg[5].flags = D_EXIT; + } + + gamemode_dlg[2].d1 = gamemode_dlg[4].d1 = 0; + gamemode_dlg[2].d2 = gamemode_dlg[4].d2 = 0; + } + + scare_mouse(); + blit(tmp_scr,screen,0,0,scrx,scry,320,240); + unscare_mouse(); + } + + show_mouse(NULL); + game_pal(); + key[KEY_ESC]=0; + chosecustomquest = (ret==5); + return (int)chosecustomquest; +} + +static int game_details(int file) +{ + + int pos=file%3; + + if(saves[file].get_quest()==0) + return 0; + + BITMAP *info = create_bitmap_ex(8,168,32); + clear_bitmap(info); + blit(framebuf,info,40,pos*24+70,0,0,168,26); + rectfill(info,40,0,168,1,0); + rectfill(info,0,24,39,25,0); + rectfill(info,0,0,7,15,0); + rectfill(framebuf,40,64,216,192,0); + rectfill(framebuf,96,60,183,67,0); + + int i=pos*24+70; + + do + { + blit(info,framebuf,0,0,40,i,168,32); + advanceframe(true); + i-=pos+pos; + } + while(pos && i>=70); + + destroy_bitmap(info); + + textout_ex(framebuf,zfont,"GAME TYPE",40,104,3,0); + textout_ex(framebuf,zfont,"QUEST",40,112,3,0); + textout_ex(framebuf,zfont,"STATUS",40,120,3,0); + + if(saves[file].get_quest()<0xFF) + { + textout_ex(framebuf,zfont,"Normal Game",120,104,1,0); + textprintf_ex(framebuf,zfont,120,112,1,0,"%s Quest", + ordinal(saves[file].get_quest())); + } + else + { + textout_ex(framebuf,zfont,"Custom Quest",120,104,1,0); + textprintf_ex(framebuf,zfont,120,112,1,0,"%s", + get_filename(saves[file].qstpath)); + } + + if(!saves[file].get_hasplayed()) + textout_ex(framebuf,zfont,"Empty Game",120,120,1,0); + else if(!saves[file].get_timevalid()) + textout_ex(framebuf,zfont,"Time Unknown",120,120,1,0); + else + textout_ex(framebuf,zfont,time_str_med(saves[file].get_time()),120,120,1,0); + + if(saves[file].get_cheat()) + textout_ex(framebuf,zfont,"Used Cheats",120,128,1,0); + + textout_ex(framebuf,zfont,"START: PLAY GAME",56,152,1,0); + textout_ex(framebuf,zfont," B: CANCEL",56,168,1,0); + + if(!saves[file].get_hasplayed()) + textout_ex(framebuf,zfont," A: CUSTOM QUEST",56,184,1,0); + + while(!Quit) + { + advanceframe(true); + load_control_state(); + + if(rBbtn()) + { + blit(scrollbuf,framebuf,0,0,0,0,256,224); + return 0; + } + + if(rSbtn()) + { + blit(framebuf,scrollbuf,0,0,0,0,256,224); + return 1; + } + + if(rAbtn() && !saves[file].get_hasplayed()) + { + (void)custom_game(file); + } + + if(chosecustomquest && load_custom_game(file)) + { + selectscreen(); + return 0; + } + } + + return 0; +} + +static int saveslot = -1; + +int getsaveslot() +{ + if(saveslot >= 0 && (!saves[saveslot].get_quest() || saves[saveslot].get_hasplayed())) + { + return -1; + } + + return saveslot; +} + +static void select_game() +{ + if(standalone_mode) + return; + + int pos = zc_max(zc_min(currgame-listpos,3),0); + int mode = 0; + + //kill_sfx(); + + // text_mode(0); + selectscreen(); + + savecnt=0; + + while(savecnt < MAXSAVES && saves[savecnt].get_quest()>0) + ++savecnt; + + if(savecnt == 0) + pos=3; + + bool done=false; + refreshpal=true; + + do + { + load_control_state(); + sfxdat=1; + blit(scrollbuf,framebuf,0,0,0,0,256,224); + list_saves(); + draw_cursor(pos,mode); + advanceframe(true); + saveslot = pos + listpos; + + if(rSbtn()) + switch(pos) + { + case 3: + if(!register_name()) + pos = 3; + else + pos = (savecnt-1)%3; + + refreshpal=true; + break; + + case 4: + if(savecnt && savecnt((mode)?2:5)) + pos=0; + + sfx(WAV_CHIME); + } + + if(rLeft() && listpos>2) + { + listpos-=3; + sfx(WAV_CHIME); + refreshpal=true; + } + + if(rRight() && listpos+3 0) + ++savecnt; + + if(currgame > savecnt-1) + { + slot_arg = 0; + currgame = 0; + select_game(); + } + + slot_arg = 0; + //game->get_quest(&saves[currgame]); + //select_game(); + } + else + { + select_game(); + } + } + else + { + currgame = lsave-1; + + if(!saves[currgame].get_quest()) + { + select_game(); + } + } + } + + if(!Quit) + { + init_game(); + } +} + +void game_over(int type) +{ + kill_sfx(); + music_stop(); + clear_to_color(screen,BLACK); + loadfullpal(); + + if(Quit==qGAMEOVER) + jukebox(ZC_MIDI_GAMEOVER); + + Quit=0; + + clear_bitmap(framebuf); + // text_mode(-1); + textout_ex(framebuf,zfont,"CONTINUE",88,72,QMisc.colors.msgtext,-1); + + if(!type) + { + textout_ex(framebuf,zfont,"SAVE",88,96,QMisc.colors.msgtext,-1); + textout_ex(framebuf,zfont,"RETRY",88,120,QMisc.colors.msgtext,-1); + } + else + textout_ex(framebuf,zfont,"RETRY",88,96,QMisc.colors.msgtext,-1); + + int pos = 0; + int f=-1; + // int htile = QHeader.old_dat_flags[ZQ_TILES] ? 2 : 0; + int htile = 2; + bool done=false; + + do load_control_state(); + + while(rSbtn()); + + do + { + load_control_state(); + + if(f==-1) + { + if(rUp()) + { + sfx(WAV_CHINK); + pos=(pos==0)?2:pos-1; + + if(type) + { + if(pos==1) pos--; + } + } + + if(rDown()) + { + sfx(WAV_CHINK); + pos=(pos+1)%3; + + if(type) + { + if(pos==1) pos++; + } + } + + if(rSbtn()) ++f; + } + + if(f>=0) + { + if(++f == 65) + done=true; + + if(!(f&3)) + { + int c = (f&4) ? QMisc.colors.msgtext : QMisc.colors.caption; + + switch(pos) + { + case 0: + textout_ex(framebuf,zfont,"CONTINUE",88,72,c,-1); + break; + + case 1: + textout_ex(framebuf,zfont,"SAVE",88,96,c,-1); + break; + + case 2: + if(!type) + textout_ex(framebuf,zfont,"RETRY",88,120,c,-1); + else textout_ex(framebuf,zfont,"RETRY",88,96,c,-1); + + break; + } + } + } + + rectfill(framebuf,72,72,79,127,0); + puttile8(framebuf,htile,72,pos*(type?12:24)+72,1,0); + advanceframe(true); + } + while(!Quit && !done); + + reset_combo_animations(); + reset_combo_animations2(); + clear_bitmap(framebuf); + advanceframe(true); + + if(done) + { + if(pos) + { + if(standalone_mode && !skip_title) + { + Quit=qRESET; + } + else + { + Quit=qQUIT; + } + } + else + { + Quit=qCONT; + } + + //Quit = pos ? ((standalone_mode && skip_title) ? qRESET : qQUIT) : qCONT; + if(pos==1&&(!type)) + { + game->set_cheat(game->get_cheat() | cheat); + + saves[currgame]=*game; + + int ring=0; + flushItemCache(); + int maxringid = getHighestLevelOfFamily(game, itemsbuf, itype_ring); + + if(maxringid != -1) + { + ring = itemsbuf[maxringid].fam_type; + } + + ring = ring ? ring-1 : 0; + iconbuffer[currgame].ring = zc_min(ring, 3); + + load_game_icon(saves+currgame,false,currgame); + show_saving(screen); + save_savedgames(); + } + } +} + +void save_game(bool savepoint) +{ + if(savepoint) + { + game->set_continue_scrn(homescr); + game->set_continue_dmap(currdmap); + lastentrance_dmap = currdmap; + lastentrance = game->get_continue_scrn(); + } + + game->set_cheat(game->get_cheat() | cheat); + + saves[currgame]=*game; + + int ring=0; + flushItemCache(); + int maxringid = getHighestLevelOfFamily(game, itemsbuf, itype_ring); + + if(maxringid != -1) + { + ring = itemsbuf[maxringid].fam_type; + } + + ring = ring ? ring-1 : 0; + iconbuffer[currgame].ring = zc_min(ring, 3); + load_game_icon(saves+currgame,false,currgame); + show_saving(screen); + save_savedgames(); +} + +bool save_game(bool savepoint, int type) +{ + kill_sfx(); + //music_stop(); + clear_to_color(screen,BLACK); + loadfullpal(); + + // int htile = QHeader.old_dat_flags[ZQ_TILES] ? 2 : 0; + int htile = 2; + bool done=false; + bool saved=false; + + do + { + int pos = 0; + int f=-1; + bool done2=false; + clear_bitmap(framebuf); + + // text_mode(-1); + if(type) + { + textout_ex(framebuf,zfont,"SAVE AND QUIT",88,72,QMisc.colors.msgtext,-1); + } + else + { + textout_ex(framebuf,zfont,"SAVE",88,72,QMisc.colors.msgtext,-1); + } + + textout_ex(framebuf,zfont,"DON'T SAVE",88,96,QMisc.colors.msgtext,-1); + textout_ex(framebuf,zfont,"QUIT",88,120,QMisc.colors.msgtext,-1); + + do + { + load_control_state(); + + if(f==-1) + { + if(rUp()) + { + sfx(WAV_CHINK); + pos=(pos==0)?2:pos-1; + } + + if(rDown()) + { + sfx(WAV_CHINK); + pos=(pos+1)%3; + } + + if(rSbtn()) ++f; + } + + if(f>=0) + { + if(++f == 65) + done2=true; + + if(!(f&3)) + { + int c = (f&4) ? QMisc.colors.msgtext : QMisc.colors.caption; + + switch(pos) + { + case 0: + if(type) + textout_ex(framebuf,zfont,"SAVE AND QUIT",88,72,c,-1); + else textout_ex(framebuf,zfont,"SAVE",88,72,c,-1); + + break; + + case 1: + textout_ex(framebuf,zfont,"DON'T SAVE",88,96,c,-1); + break; + + case 2: + textout_ex(framebuf,zfont,"QUIT",88,120,c,-1); + break; + } + } + } + + rectfill(framebuf,72,72,79,127,0); + puttile8(framebuf,htile,72,pos*24+72,1,0); + advanceframe(true); + } + while(!Quit && !done2); + + //reset_combo_animations(); + clear_bitmap(framebuf); + //advanceframe(); + + if(done2) + { + //Quit = (pos==2) ? qQUIT : 0; + if(pos==1||pos==0) done=true; + + if(pos==0) + { + if(savepoint) + { + game->set_continue_scrn(homescr); + game->set_continue_dmap(currdmap); + lastentrance_dmap = currdmap; + lastentrance = game->get_continue_scrn(); + } + + game->set_cheat(game->get_cheat() | cheat); + + saves[currgame]=*game; + + int ring=0; + flushItemCache(); + int maxringid = getHighestLevelOfFamily(game, itemsbuf, itype_ring); + + if(maxringid != -1) + { + ring = itemsbuf[maxringid].fam_type; + } + + ring = ring ? ring-1 : 0; + iconbuffer[currgame].ring = zc_min(ring, 3); + load_game_icon(saves+currgame,false,currgame); + show_saving(screen); + save_savedgames(); + saved=true; + + if(type) + { + Quit = qQUIT; + done=true; + skipcont=1; + } + } + + if(pos==2) + { + clear_bitmap(framebuf); + // text_mode(-1); + textout_ex(framebuf,zfont,"ARE YOU SURE?",88,72,QMisc.colors.msgtext,-1); + textout_ex(framebuf,zfont,"YES",88,96,QMisc.colors.msgtext,-1); + textout_ex(framebuf,zfont,"NO",88,120,QMisc.colors.msgtext,-1); + int pos2=0; + int g=-1; + bool done3=false; + + do + { + load_control_state(); + + if(g==-1) + { + if(rUp()) + { + sfx(WAV_CHINK); + pos2=(pos2==0)?1:pos2-1; + } + + if(rDown()) + { + sfx(WAV_CHINK); + pos2=(pos2+1)%2; + } + + if(rSbtn()) ++g; + } + + if(g>=0) + { + if(++g == 65) + done3=true; + + if(!(g&3)) + { + int c = (g&4) ? QMisc.colors.msgtext : QMisc.colors.caption; + + switch(pos2) + { + case 0: + textout_ex(framebuf,zfont,"YES",88,96,c,-1); + break; + + case 1: + textout_ex(framebuf,zfont,"NO",88,120,c,-1); + break; + //case 2: textout_ex(framebuf,zfont,"QUIT",88,120,c,-1); break; + } + } + } + + + rectfill(framebuf,72,72,79,127,0); + puttile8(framebuf,htile,72,pos2*24+96,1,0); + advanceframe(true); + } + while(!Quit && !done3); + + clear_bitmap(framebuf); + + if(pos2==0) + { + Quit = qQUIT; + done=true; + skipcont=1; + } + } + } + } + while(!Quit && !done); + + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + + if(darkroom) + { + if(get_bit(quest_rules,qr_FADE)) + { + interpolatedfade(); + } + else + { + loadfadepal((DMaps[currdmap].color)*pdLEVEL+poFADE3); + } + } + + return saved; +} + + +/* +static void list_saves2() +{ + if(savecnt>3) + { + if(listpos>=3) + textout_ex(framebuf,zfont,(char *)left_arrow_str,96,60,3,0); + if(listpos+3set_maxlife( saves[listpos+i].get_maxlife()); + game->set_life( saves[listpos+i].get_maxlife()); + //boogie! + lifemeter(framebuf,144,i*24+56+((game->get_maxlife()>16*(HP_PER_HEART))?8:0),0,0); + textout_ex(framebuf,zfont,saves[listpos+i].get_name(),72,i*24+72,1,0); + + if(saves[listpos+i].get_quest()) + textprintf_ex(framebuf,zfont,72,i*24+80,1,0,"%3d",saves[listpos+i].get_deaths()); + + if(saves[listpos+i].get_quest()==2) + overtile16(framebuf,41,56,i*24+70,9,0); //put sword on second quests + + if(saves[listpos+i].get_quest()==3) + { + overtile16(framebuf,41,56,i*24+70,9,0); //put sword on second quests + overtile16(framebuf,41,41,i*24+70,9,0); //put sword on third quests + } + // maybe the triforce for the 4th quest? + textprintf_ex(framebuf,zfont,72,i*24+72,1,0,"%s",saves[listpos+i].get_name()); + } + + byte *hold = newtilebuf[0].data; + byte holdformat=newtilebuf[0].format; + newtilebuf[0].format=tf4Bit; + newtilebuf[0].data = saves[listpos+i].icon; + overtile16(framebuf,0,48,i*24+73,i+10,0); //link + newtilebuf[0].format=holdformat; + newtilebuf[0].data = hold; + + hold = colordata; + colordata = saves[listpos+i].pal; + loadpalset(i+10,0); + colordata = hold; + + textout_ex(framebuf,zfont,"-",136,i*24+72,1,0); + } + + refreshpal = r; +} + +*/ + +/*** end of title.cc ***/ + diff --git a/src/title.h b/src/title.h new file mode 100644 index 0000000000..86461f1db5 --- /dev/null +++ b/src/title.h @@ -0,0 +1,28 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// title.h +// +// Title screen and intro for zelda.cc +// Also has game loading and select screen code. +// +//-------------------------------------------------------- + +#ifndef _ZC_TITLE_H_ +#define _ZC_TITLE_H_ + +extern DIALOG gamemode_dlg[]; + +int load_savedgames(); +int save_savedgames(); +int custom_game(int file); +int getsaveslot(); +void load_game_icon(gamedata *g, bool forceDefault, int index); +void load_game_icon_to_buffer(bool forceDefault, int index); +void titlescreen(int lsave); +void game_over(int type); +void save_game(bool savepoint); +bool save_game(bool savepoint, int type); +#endif + diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000000..a2191d63b3 --- /dev/null +++ b/src/types.h @@ -0,0 +1,43 @@ +#ifndef _ZC_TYPES_H_ +#define _ZC_TYPES_H_ + +#include + +// Common data types + +typedef unsigned char byte; //0- 255 ( 8 bits) +typedef unsigned short word; //0- 65,535 (16 bits) +typedef unsigned long dword; //0- 4,294,967,295 (32 bits) +typedef unsigned long long qword; //0-18,446,744,073,709,551,616 (64 bits) + +enum dir { dir_INVALID=-1, dir_UP, dir_DOWN, dir_LEFT, dir_RIGHT }; + +// This should probably be moved into tiles.h or something +class Orientation +{ +public: + // Yes, it's horrible. I don't care. :p + // It's not as bad as it looks. The enum values just map the value + // before rotation to the value after rotation. + enum rotation + { + rot_NONE = 0x76543210, // 0->0, 1->1, 2->2, etc. + rot_90CW = 0x02137564, // 0->4, 1->6, 2->5, etc. + rot_270CCW = 0x02137564, + rot_180 = 0x45670123, + rot_270CW = 0x31204657, + rot_90CCW = 0x31204657 + }; + + Orientation(): val() {} + Orientation(int v): val(v) {} + inline void flipHorizontal() { val^=1; } + inline void flipVertical() { val^=2; } + inline void rotate(int rot) { val=(rot>>(val<<2)); } + inline operator int() const { return val; } + +private: + unsigned int val:3; +}; + +#endif diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000000..ae6c140a10 --- /dev/null +++ b/src/util.h @@ -0,0 +1,10 @@ +#ifndef _UTIL_H_ +#define _UTIL_H_ + +// Temporary! +#include "zsys.h" + +inline int clamp(int x, int low, int high) { return vbound(x, low, high); } +int wrap(int x, int low, int high); // This is in zq_misc... Does it not exist in ZC, then? + +#endif diff --git a/src/vectorset.h b/src/vectorset.h new file mode 100644 index 0000000000..f265e62486 --- /dev/null +++ b/src/vectorset.h @@ -0,0 +1,208 @@ + +#pragma once + +#include +#include +#include +#include + + +template < class Key, class Compare = std::less, class Alloc = std::allocator > +class vectorset : protected std::vector +{ +public: + typedef vectorset this_type; + typedef std::vector base_type; + typedef Key key_type; + typedef Compare key_compare; + typedef key_compare value_compare; + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::size_type size_type; + typedef typename base_type::value_type value_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + + //for convenience + typedef std::pair insert_iterator_type; + + using base_type::begin; + using base_type::end; + using base_type::rbegin; + using base_type::rend; + using base_type::size; + using base_type::max_size; + using base_type::empty; + using base_type::capacity; + using base_type::clear; + using base_type::front; + using base_type::back; + using base_type::reserve; + using base_type::swap; + using base_type::at; + using base_type::operator[]; + + explicit vectorset(const Compare& comp = Compare(), const allocator_type& alloc = allocator_type()) + : base_type(alloc), _compare(comp) + { + } + + vectorset(const this_type& v) + : base_type(v), _compare(v._compare) + { + } + + this_type& operator =(const this_type& v) + { + if(this != &v) + { + base_type::operator =(v); + _compare = v._compare; + } + + return *this; + } + + void push_back(const value_type& val) + { + insert(val); + } + + std::pair insert(const value_type& val) + { + std::pair ret(end(), false); + + iterator it = lower_bound(val); + + if(it == end() || _compare(val, *it)) + { + ret.first = base_type::insert(it, val); + ret.second = true; + } + + return ret; + } + + iterator insert(iterator it, const value_type& val) + { + return insert(val).first; + } + + template + void insert(Iter first, Iter last) + { + base_type::insert(first, last); + sort(); + } + + void erase(iterator it) + { + base_type::erase(it); + } + void erase(iterator first, iterator last) + { + base_type::erase(first, last); + } + + size_type erase(const key_type& key) + { + size_type n(0); + iterator it = find(key); + + if(it != end()) + { + erase(it); + ++n; + } + + return n; + } + + iterator find(const key_type& key) + { + iterator it = lower_bound(key); + return it; + } + + const_iterator find(const key_type& key) const + { + const_iterator it = lower_bound(key); + return it; + } + + size_type count(const key_type& key) const + { + return(find(key) != end() ? (size_type)1 : (size_type)0); + } + + key_compare key_comp() const + { + return _compare; + } + value_compare value_comp() const + { + return key_comp(); + } + + std::pair equal_range(const key_type& key) + { + iterator first = find(key); + iterator last = end(); + + if(first != end()) + last = first + 1; + + return std::pair(first, last); + } + + std::pair equal_range(const key_type& key) const + { + const_iterator first = find(key); + const_iterator last = end(); + + if(first != end()) + last = first + 1; + + return std::pair(first, last); + } + + iterator lower_bound(const key_type& key) + { + return std::lower_bound(begin(), end(), key, _compare); + } + + const_iterator lower_bound(const key_type& key) const + { + return std::lower_bound(begin(), end(), key, _compare); + } + + iterator upper_bound(const key_type& key) + { + return std::upper_bound(begin(), end(), key, _compare); + } + + const_iterator upper_bound(const key_type& key) const + { + return std::upper_bound(begin(), end(), key, _compare); + } + + void sort() + { + if(size() > (size_type)1) + { + std::sort(begin(), end(), _compare); + iterator it = std::unique(begin(), end()); + + if(it != end()) + base_type::erase(it, end()); + } + } + +protected: + key_compare _compare; +}; + + diff --git a/src/weapons.cpp b/src/weapons.cpp new file mode 100644 index 0000000000..c216cdeda8 --- /dev/null +++ b/src/weapons.cpp @@ -0,0 +1,3780 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "weapons.h" +#include "zelda.h" +#include "zc_sys.h" +#include "zsys.h" +#include "maps.h" +#include "tiles.h" +#include "pal.h" +#include "link.h" +#include "sfxManager.h" +#include "sound.h" +#include "mem_debug.h" +#include "angelscript/aszc.h" + +extern LinkClass Link; +extern zinitdata zinit; +extern int directWpn; +extern SFXManager sfxMgr; + +/**************************************/ +/*********** Weapon Class ***********/ +/**************************************/ + +byte boomframe[16] = {0,0,1,0,2,0,1,1,0,1,1,3,2,2,1,2}; +byte bszboomflip[4] = {0,2,3,1}; + +//light up the screen if there is at least one "lit" weapon +//otherwise darken the screen +void checkLightSources() +{ + for(int i=0; iisLit) + { + lighting(true); + return; + } + } + + for(int i=0; iisLit) + { + lighting(true); + return; + } + } + + lighting(false); +} + +void getdraggeditem(int j) +{ + item *it=(item*)items.spr(j); + + if(it==NULL) + return; + + it->x = LinkX(); + it->y = LinkY(); + it->z = LinkZ(); + LinkCheckItems(); +} + +void weapon::seekLink() +{ + angular = true; + angle = atan2(double(LinkY()-y),double(LinkX()-x)); + matchDirToAngle(); + + if(z>LinkZ()) z--; + else if(z=GuyCount())) + { + j=-1; + + for(int i=0; i=10) && !GuySuperman(i)) + { + mindistance=tempdistance; + j=i; + } + } + } + + if(j==-1) + { + return; + } + + angle = atan2(double(GuyY(j)-y),double(GuyX(j)-x)); + matchDirToAngle(); +} + +void weapon::matchDirToAngle() +{ + if(angle==-PI || angle==PI) + dir=left; + else if(angle==-PI/2) + dir=up; + else if(angle==PI/2) + dir=down; + else if(angle==0) + dir=right; + else if(angle<-PI/2) + dir=l_up; + else if(angle<0) + dir=r_up; + else if(angle>(PI/2)) + dir=l_down; + else + dir=r_down; +} + +void weapon::setAngle(double a) +{ + angular=true; + angle=a; + matchDirToAngle(); +} + +weapon::weapon(weapon const & other): + sprite(other), + power(other.power), + type(other.type), + dead(other.dead), + clk2(other.clk2), + misc2(other.misc2), + ignorecombo(other.ignorecombo), + isLit(other.isLit), + parentid(other.parentid), + parentitem(other.parentitem), + dragging(other.dragging), + step(other.step), + bounce(other.bounce), + ignoreLink(other.ignoreLink), + flash(other.flash), + wid(other.wid), + aframe(other.aframe), + csclk(other.csclk), + o_tile(other.o_tile), + o_cset(other.o_cset), + o_speed(other.o_speed), + o_type(other.o_type), + frames(other.frames), + o_flip(other.o_flip), + temp1(other.temp1), + behind(other.behind), + sfxLoop(other.sfxLoop), + minX(other.minX), + maxX(other.maxX), + minY(other.minY), + maxY(other.maxY), + aimedBrang(other.aimedBrang), + sparkleFunc(other.sparkleFunc) +{ + assignWeaponScript(this, "weapon"); +} + +// Let's dispose of some sound effects! +weapon::~weapon() +{ + // First, check for the existence of weapons that don't have parentitems + // but make looping sounds anyway. + if(parentitem<0 && get_bit(quest_rules, qr_MORESOUNDS)) + { + //I am reasonably confident that I fixed these expressions. ~pkmnfrk + if(id==ewBrang && Ewpns.idCount(ewBrang) > 0) + return; + + if(id==wWind && Lwpns.idCount(wWind) > 0) + return; + } + + // Check each Lwpn to see if this weapon's sound is also allocated by it. + if(parentitem>=0) + { + for(int i=0; igetUID() == getUID()) // Itself! + { + continue; + } + + int wparent = w->parentitem; + + if(wparent>=0 && (itemsbuf[wparent].family == itype_brang || itemsbuf[wparent].family == itype_nayruslove + || itemsbuf[wparent].family == itype_hookshot || itemsbuf[wparent].family == itype_cbyrna)) + { + if(itemsbuf[wparent].usesound == itemsbuf[parentitem].usesound) + return; + } + } + } + + switch(id) + { + case wBrang: + if(parentitem>=0) + { + stop_sfx(itemsbuf[parentitem].usesound); + } + + break; + + case wSSparkle: + case wFSparkle: + if(parentitem>=0 && itemsbuf[parentitem].family==itype_cbyrna) + { + stop_sfx(itemsbuf[parentitem].usesound); + } + + break; + } +} + +// This should be done elsewhere +void setScreenLimits(weapon& w) +{ + bool isDgn=isdungeon(); + int border=get_bit(quest_rules,qr_NOBORDER) ? 16 : 0; + + if(w.id>wEnemyWeapons && w.id!=ewBrang) + { + w.minY=isDgn ? 32 : (16-border); + w.maxY=isDgn ? 128 : (144+border); + w.minX=isDgn ? 32 : (16-border); + w.maxX=isDgn ? 208 : (224+border); + } + else if(w.id==wHookshot || w.id==wHSChain) + { + w.minY=isDgn ? 8 : 0; + w.maxY=isDgn ? 152 : 160; + w.minX=isDgn ? 8 : 0; + w.maxX=isDgn ? 248 : 256; + } + else + { + w.minY=isDgn ? 18 : 2; + w.maxY=isDgn ? 144 : 160; + w.minX=isDgn ? 20 : 4; + w.maxX=isDgn ? 220 : 236; + } + + if(w.id==wSSparkle || w.id==wFSparkle) + { + w.minY=0; + w.maxY=176; + w.minX=0; + w.maxX=256; + } + else if(w.id==ewFlame) + { + w.minY=isDgn ? 32 : (16-border); + w.maxY=isDgn ? 128 : (144+border); + w.minX=isDgn ? 32 : (16-border); + w.maxX=isDgn ? 208 : (224+border); + } + else if(w.id==ewFireTrail) + { + w.minY=isDgn ? 32 : (16-border); + w.maxY=isDgn ? 128 : (144+border); + w.minX=isDgn ? 32 : (16-border); + w.maxX=isDgn ? 208 : (224+border); + } + + else if(w.id==ewWind) + { + w.minY=isDgn ? 32 : (16-border); + w.maxY=isDgn ? 128 : (144+border); + w.minX=isDgn ? 32 : (16-border); + w.maxX=isDgn ? 208 : (224+border); + } +} + +weapon::weapon(fix X,fix Y,fix Z,int Id,int Type,int pow,int Dir, int Parentitem, int prntid, bool isDummy): + sprite(), + parentid(prntid), + sparkleFunc(0) +{ + /* + * Type: + * 0x01: Boss fireball + * 0x02: Seeks Link + * 0x04: Fast projectile + * 0x00-0x30: If 0x02, slants toward (type>>3)-1 + */ + + x=X; + y=Y; + z=Z; + id=Id; + type=Type; + power=pow; + parentitem=Parentitem; + dir=zc_max(Dir,0); + clk=clk2=flip=misc=misc2=0; + frames=flash=wid=aframe=csclk=0; + ignorecombo=-1; + step=0; + dead=-1; + bounce=ignoreLink=false; + yofs=playing_field_offset - 2; + dragging=-1; + hxsz=15; + hysz=15; + hzsz=8; + isLit = false; + aimedBrang=false; + setScreenLimits(*this); + + int defaultw, itemid = parentitem; + + if(id>wEnemyWeapons) + { + canfreeze=true; + + if(id!=ewBrang) + { + if(Type&2) + { + misc=(Type>>3)-1; + type &= ~2; + } + else + misc=-1; + } + } + + switch(id) + { + case wSword: // Link's sword + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_sword); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wSWORD; + + hxsz=hysz=15; + LOADGFX(defaultw); + break; + } + + case wWand: // Link's wand, as well as the Cane itself + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_wand); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wWAND; + + hxsz=15; + hysz=15; //hysz=24; + LOADGFX(defaultw); + break; + } + + case wHammer: + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_hammer); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wHAMMER; + + hxsz=15; + hysz=24; + LOADGFX(defaultw); + break; + } + + case wCByrna: // The Cane's beam + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_cbyrna); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn3; + else + defaultw = wCBYRNA; + + LOADGFX(defaultw); + int speed = parentitem>-1 ? zc_max(itemsbuf[parentitem].misc1,1) : 1; + int qty = parentitem>-1 ? zc_max(itemsbuf[parentitem].misc3,1) : 1; + clk = (int)((((2*type*PI)/qty) + // Appear on top of the cane's hook + + (dir==right? 3*PI/2 : dir==left? PI/2 : dir==down ? 0 : PI))*speed); + type = 0; + + if(parentitem>-1) + { + sfxLoop=sfxMgr.getSFX(itemsbuf[parentitem].usesound); + sfxLoop.startLooping(); + } + + break; + } + + case wWhistle: + xofs=1000; // don't show + x=y=hxofs=hyofs=0; + hxsz=hysz=255; // hit the whole screen + break; + + case wWind: + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_whistle); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wWIND; + + LOADGFX(defaultw); + + if(get_bit(quest_rules,qr_MORESOUNDS)) + { + sfxLoop=sfxMgr.getSFX(WAV_ZN1WHIRLWIND); + sfxLoop.startLooping(); + } + + clk=-14; + step=2; + break; + } + + case wBeam: + case wRefBeam: + step = 3; + + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_sword); + } + + if(itemid>-1 && id!=wRefBeam) + defaultw = itemsbuf[itemid].wpn3; + else + defaultw = ewSWORD; + + LOADGFX(defaultw); + flash = 1; + cs = 6; + + switch(dir) + { + case down: + flip=get_bit(quest_rules,qr_SWORDWANDFLIPFIX)?3:2; + + case up: + hyofs=2; + hysz=12; + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + hxofs=2; + hxsz=12; + yofs = playing_field_offset+(BSZ ? 3 : 1); + break; + } + + if(id==wRefBeam) + { + ignorecombo=(((int)y&0xF0)+((int)x>>4)); + } + + break; + + case wArrow: + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_arrow); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wARROW; + + LOADGFX(defaultw); + step=3; + + switch(dir) + { + case down: + flip=2; + + case up: + hyofs=2; + hysz=12; + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + yofs=playing_field_offset + 1; + hyofs=2; + hysz=14; + hxofs=2; + hxsz=12; + break; + } + + if(itemid >-1) + misc = itemsbuf[itemid].misc1; + + break; + + case wSSparkle: + LOADGFX(type ? type : wSSPARKLE); + step=0; + break; + + case wFSparkle: + LOADGFX(type ? type : wFSPARKLE); + step=0; + break; + + case wFire: + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_candle); + } + + switch(type) + { + case 3: // Din's Fire. This uses magicitem rather than itemid + if(magicitem >-1 && !isDummy) + defaultw = itemsbuf[magicitem].wpn5; + else defaultw = wFIRE; + + break; + + case 2: // Wand + if(itemid>-1 && !isDummy) + defaultw = itemsbuf[itemid].wpn2; + else defaultw = wFIRE; + + break; + + case 0: + case 1: // Candles + if(itemid>-1 && !isDummy) + { + defaultw = itemsbuf[itemid].wpn3; + break; + } + + default: + defaultw = wFIRE; + } + + LOADGFX(defaultw); + step = (type<2)?.5:0; + hxofs = hyofs=1; + hxsz = hysz = 14; + + if(BSZ) + yofs+=2; + + break; + + case wLitBomb: + case wBomb: + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_bomb); + } + + if(itemid >-1) + { + defaultw = itemsbuf[itemid].wpn; + misc = (id==wBomb ? 1 : itemsbuf[itemid].misc1); + } + else + { + defaultw = wBOMB; + misc = (id==wBomb ? 1 : 50); + } + + LOADGFX(defaultw); + hxofs=hyofs=4; + hxsz=hysz=8; + break; + } + + case wLitSBomb: + case wSBomb: + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_sbomb); + } + + if(parentitem>-1) + { + defaultw = itemsbuf[itemid].wpn; + misc = (id==wSBomb ? 1 : itemsbuf[itemid].misc1); + } + else + { + defaultw = wSBOMB; + misc = (id==wSBomb ? 1 : 50); + } + + LOADGFX(defaultw); + hxofs=hyofs=4; + hxsz=hysz=8; + break; + } + + case wBait: + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_bait); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wBAIT; + + LOADGFX(defaultw); + break; + + case wMagic: + { + itemid = current_item_id(itype_book); + bool book = true; + + if(itemid<0) + { + itemid = directWpn>-1 ? directWpn : current_item_id(itype_wand); + book = false; + } + + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_wand); + book = false; + } + + if(itemid >-1) + // Book Magic sprite is wpn, Wand Magic sprite is wpn3. + defaultw = book ? itemsbuf[itemid].wpn : itemsbuf[itemid].wpn3; + else + defaultw = wMAGIC; + + LOADGFX(defaultw); + step = (BSZ ? 3 : 2.5); + + switch(dir) + { + case down: + flip=2; + + case up: + hyofs=2; + hysz=12; + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + hxofs=2; + hxsz=12; + break; + } + + break; + } + + case wBrang: + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_brang); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wBRANG; + + LOADGFX(defaultw); + hxofs=4; + hxsz=7; + hyofs=2; + hysz=11; + aimedBrang=false; + break; + + case wHookshot: + hookshot_used=true; + + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_hookshot); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn; + else + defaultw = wHSHEAD; + + LOADGFX(defaultw); + step = 4; + clk2=256; + + switch(dir) + { + case down: + flip=2; + xofs+=4; + yofs+=1; + hyofs=2; + hysz=12; + break; + + case up: + yofs+=3; + xofs-=5; + hyofs=2; + hysz=12; + break; + + case left: + flip=1; /*tile=o_tile+((frames>1)?frames:1)*/update_weapon_frame(((frames>1)?frames:1),o_tile); + xofs+=2; + yofs=playing_field_offset+4; + hxofs=2; + hxsz=12; + break; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + xofs-=2; + yofs=playing_field_offset+4; + hxofs=2; + hxsz=12; + break; + } + + break; + + case wHSHandle: + step = 0; + + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_hookshot); + } + + if(itemid >-1) + defaultw = itemsbuf[itemid].wpn4; + else + defaultw = wHSHANDLE; + + LOADGFX(defaultw); + + switch(dir) + { + case down: + flip=2; + xofs+=4; + yofs+=1; + hyofs=2; + hysz=12; + break; + + case up: + yofs+=3; + xofs-=5; + hyofs=2; + hysz=12; + break; + + case left: + flip=1; /*tile=o_tile+((frames>1)?frames:1)*/update_weapon_frame(((frames>1)?frames:1),o_tile); + xofs+=2; + yofs=playing_field_offset+4; + hxofs=2; + hxsz=12; + break; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + xofs-=2; + yofs=playing_field_offset+4; + hxofs=2; + hxsz=12; + break; + } + + break; + + case wHSChain: + { + if(isDummy || itemid<0) + { + itemid = getCanonicalItemID(itemsbuf, itype_hookshot); + } + + if(itemid >-1) + defaultw = (dir1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + break; + } + + break; + + case ewLitSBomb: + case ewSBomb: + LOADGFX(ewSBOMB); + hxofs=0; + hxsz=16; + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hyofs=0; + hysz=16; + } + + if(id==ewSBomb) + misc=2; + else + step=3; + + switch(dir) + { + case down: + flip=2; + + case up: + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + break; + } + + break; + + case ewBrang: + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=0; + hxsz=16; + hyofs=0; + hysz=16; + } + else + { + hxofs=4; + hxsz=8; + } + + wid = zc_min(zc_max(current_item(itype_brang),1),3)-1+wBRANG; + LOADGFX(wid); + break; + + case ewFireball2: + if(dir < 8) + misc=dir; + else + { + misc = -1; + } + + //fallthrough + case ewFireball: + case wRefFireball: + LOADGFX(ewFIREBALL); + step=1.75; + + if(Type&2) + { + seekLink(); + } + else misc=-1; + + break; + + case ewRock: + LOADGFX(ewROCK); + + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=0; + hxsz=16; + hyofs=0; + hysz=16; + } + else + { + hxofs=4; + hxsz=8; + } + + step=3; + break; + + case ewArrow: + LOADGFX(ewARROW); + step=2; + + switch(dir) + { + case down: + flip=2; + + case up: + xofs=-4; + hxsz=8; + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + yofs=playing_field_offset+1; + break; + } + + break; + + case ewSword: + LOADGFX(ewSWORD); + + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=0; + hxsz=16; + hyofs=0; + hysz=16; + } + else + { + hxofs=4; + hxsz=8; + } + + step=3; + + switch(dir) + { + case down: + flip=2; + + case up: + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + yofs=playing_field_offset+1; + break; + } + + break; + + case wRefMagic: + case ewMagic: + LOADGFX(ewMAGIC); + + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=0; + hxsz=16; + hyofs=0; + hysz=16; + } + else + { + hxofs=4; + hxsz=8; + } + + step=3; + + switch(dir) + { + case down: + flip=2; + + case up: + break; + + case left: + flip=1; + + case right: /*tile=o_tile+((frames>1)?frames:1)*/ + update_weapon_frame(((frames>1)?frames:1),o_tile); + yofs=playing_field_offset+1; + break; + } + + if(id==wRefMagic) + { + ignorecombo=(((int)y&0xF0)+((int)x>>4)); + } + + break; + + case ewFlame: + case ewFlame2: + if(id==ewFlame) + LOADGFX(ewFLAME); + else + LOADGFX(ewFLAME2); + + if(dir==255) + { + step=2; + seekLink(); + } + else + { + /*if(Dir<0) + { + step = 0; + }*/ + if(dir>right) + { + step = .707; + } + else + { + step = 1; + } + } + + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=hyofs=0; + hxsz=hysz=16; + } + else + { + hxofs = hyofs=1; // hof of 1 means that link can use the 'half-tile trick'. + hxsz = hysz = 14; + } + + if(BSZ) + yofs+=2; + + break; + + case ewFireTrail: + LOADGFX(ewFIRETRAIL); + step=0; + dir=-1; + + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=hyofs=0; + hxsz=hysz=16; + } + else + { + hxofs = hyofs=1; // hof of 1 means that link can use the 'half-tile trick'. + hxsz = hysz = 15; + } + + if(BSZ) + yofs+=2; + + break; + + case ewWind: + if(get_bit(quest_rules, qr_OFFSETEWPNCOLLISIONFIX)) + { + hxofs=hyofs=0; + hxsz=hysz=16; + } + + LOADGFX(ewWIND); + clk=0; + step=3; + break; + + case wPhantom: + switch(type) + { + case pDINSFIREROCKET: + case pDINSFIREROCKETRETURN: + break; + + case pDINSFIREROCKETTRAIL: + LOADGFX(itemsbuf[parentitem].wpn3); + break; + + case pDINSFIREROCKETTRAILRETURN: + LOADGFX(itemsbuf[parentitem].wpn4); + break; + + case pMESSAGEMORE: + LOADGFX(iwMore); + break; + + case pNAYRUSLOVEROCKET1: + case pNAYRUSLOVEROCKETRETURN1: + case pNAYRUSLOVEROCKET2: + case pNAYRUSLOVEROCKETRETURN2: + drawstyle=itemsbuf[parentitem].flags & ITEM_FLAG2 ? 1 : 0; + break; + + case pNAYRUSLOVEROCKETTRAIL1: + LOADGFX(itemsbuf[parentitem].wpn3); + drawstyle=itemsbuf[parentitem].flags & ITEM_FLAG2 ? 1 : 0; + break; + + case pNAYRUSLOVEROCKETTRAILRETURN1: + LOADGFX(itemsbuf[parentitem].wpn4); + drawstyle=itemsbuf[parentitem].flags & ITEM_FLAG2 ? 1 : 0; + break; + + case pNAYRUSLOVEROCKETTRAIL2: + LOADGFX(itemsbuf[parentitem].wpn8); + drawstyle=itemsbuf[parentitem].flags & ITEM_FLAG2 ? 1 : 0; + break; + + case pNAYRUSLOVEROCKETTRAILRETURN2: + LOADGFX(itemsbuf[parentitem].wpn9); + drawstyle=itemsbuf[parentitem].flags & ITEM_FLAG2 ? 1 : 0; + break; + + default: + tile=0; + break; + } + + break; + + default: + LOADGFX(0); + break; + } + + if(id>wEnemyWeapons && id!=ewBrang && (Type&4)!=0) // Increase speed of Aquamentus 2 fireballs + { + step *=2; + } + + assignWeaponScript(this, "weapon"); +} + +void weapon::LOADGFX(int wpn) +{ + if(wpn<0) + return; + + wid = wpn; + flash = wpnsbuf[wid].misc&3; + tile = wpnsbuf[wid].tile; + cs = wpnsbuf[wid].csets&15; + o_tile = wpnsbuf[wid].tile; + o_cset = wpnsbuf[wid].csets; + o_flip=(wpnsbuf[wid].misc>>2)&3; + o_speed = wpnsbuf[wid].speed; + o_type = wpnsbuf[wid].type; + frames = wpnsbuf[wid].frames; + temp1 = wpnsbuf[wFIRE].tile; + behind = (wpnsbuf[wid].misc&WF_BEHIND)!=0; +} + +bool weapon::Dead() +{ + return dead!=-1; +} + +bool weapon::clip() +{ + if(xmaxX) + if(dir==right || dir==r_up || dir==r_down) + return true; + + if(ymaxY) + if(dir==down || dir==l_down || dir==r_down) + return true; + + if(id>wEnemyWeapons) + { + int border=get_bit(quest_rules,qr_NOBORDER) ? 8 : 0; + if((x<(8-border) && dir==left) || // Not checking diagonals? + (y<(8-border) && dir==up) || + (x>(232+border) && dir==right) || + (y>(168+border) && dir==down)) + return true; + } + + // This doesn't do anything useful, does it? + if(x<0||y<0||x>240||y>176) + return true; + + return false; +} + +bool weapon::blocked() +{ + return blocked(8, 8); +} + +bool weapon::blocked(int xOffset, int yOffset) +{ + int wx = x+xOffset; + int wy = y+yOffset; + + if(id == wPhantom || id == wHSHandle || id == wHSChain) // Sanity check + { + return false; + } + + if(get_bit(combo_class_buf[COMBOTYPE(wx,wy)].block_weapon,id) + || get_bit(combo_class_buf[FFCOMBOTYPE(wx,wy)].block_weapon, id)) + { + if(parentitem<0 || (combo_class_buf[COMBOTYPE(wx,wy)].block_weapon_lvl >= + itemsbuf[parentitem].fam_type)) + { + return true; + } + } + + switch(dir) + { + case up: + wy-=8; + break; + + case down: + wy+=8; + break; + + case left: + wx-=8; + break; + + case right: + wx+=8; + break; + } + + if(get_bit(combo_class_buf[COMBOTYPE(wx,wy)].block_weapon,id) + || get_bit(combo_class_buf[FFCOMBOTYPE(wx,wy)].block_weapon, id)) + { + if(parentitem<0 || (combo_class_buf[COMBOTYPE(wx,wy)].block_weapon_lvl >= + itemsbuf[parentitem].fam_type)) + { + return true; + } + } + + return false; +} + +bool weapon::animate(int) +{ + if(sparkleFunc) + sparkleFunc(*this); + + // do special timing stuff + bool hooked=false; + + // fall down + switch(id) + { + case wFire: + + // Din's Fire shouldn't fall + if(parentitem>=0 && itemsbuf[parentitem].family==itype_dinsfire && !(itemsbuf[parentitem].flags & ITEM_FLAG3)) + { + break; + } + + case wLitBomb: + case wLitSBomb: + case wBait: + case ewFlame: + case ewFireTrail: + if(tmpscr->flags7&fSIDEVIEW) + { + if(!_walkflag(x,y+16,0)) + { + y+=fall/100; + + if(fall <= (int)zinit.terminalv) + { + fall += zinit.gravity; + } + } + else + { + if(fall!=0 && !(step>0 && dir==up)) // Don't fix pos if still moving through solidness + y-=(int)y%8; // Fix position + + fall = 0; + } + + if(y>192) dead=0; // Out of bounds + } + else + { + z-=fall/100; + + if(z<=0) + { + z = fall = 0; + } + else if(fall <= (int)zinit.terminalv) + { + fall += zinit.gravity; + } + } + } + + if(id>wEnemyWeapons && id!=ewBrang && id != ewFireball2 && id != ewBomb && id != ewSBomb) + switch(misc) + { + case up: + y-=.5; + break; + + case down: + y+=.5; + break; + + case left: + x-=.5; + break; + + case right: + x+=.5; + break; + + case 4: + y-=1; + break; + + case 5: + y+=1; + break; + + case 6: + x-=1; + break; + + case 7: + x+=1; + break; + //case l_up: y-=.354; x-=.354; break; + //case r_up: y-=.354; x+=.354; break; + //case l_down:y+=.354; x-=.354; break; + //case r_down:y+=.354; x+=.354; break; + } + + switch(id) + { + // Link's weapons + case wSword: + case wWand: + case wHammer: + if(LinkAction()!=attacking && LinkAction()!=ischarging && !LinkCharged()) + { + dead=0; + } + + break; + + case wCByrna: + { + if(blocked()) + { + dead=0; + } + + int speed = parentitem>-1 ? zc_max(itemsbuf[parentitem].misc1,1) : 1; + int radius = parentitem>-1 ? zc_max(itemsbuf[parentitem].misc2,8) : 8; + double xdiff = -(sin((double)clk/speed) * radius); + double ydiff = (cos((double)clk/speed) * radius); + + double ddir=atan2(double(ydiff),double(xdiff)); + + if((ddir<=(((-5)*PI)/8))&&(ddir>(((-7)*PI)/8))) + dir=r_up; + else if((ddir<=(((-3)*PI)/8))&&(ddir>(((-5)*PI)/8))) + dir=right; + else if((ddir<=(((-1)*PI)/8))&&(ddir>(((-3)*PI)/8))) + dir=r_down; + else if((ddir<=(((1)*PI)/8))&&(ddir>(((-1)*PI)/8))) + dir=down; + else if((ddir<=(((3)*PI)/8))&&(ddir>(((1)*PI)/8))) + dir=l_down; + else if((ddir<=(((5)*PI)/8))&&(ddir>(((3)*PI)/8))) + dir=left; + else if((ddir<=(((7)*PI)/8))&&(ddir>(((5)*PI)/8))) + dir=l_up; + else + dir=up; + + x = (fix)((double)LinkX() + xdiff); + y = (fix)((double)LinkY() + ydiff); + z = LinkZ(); + + if(parentitem>-1) + sfx(itemsbuf[parentitem].usesound,pan(int(x)),true,false); + } + break; + + case wBeam: + case wRefBeam: + for(int i2=0; i2<=zc_min(type-1,3) && dead!=23; i2++) + { + if(findentrance(x,y,mfSWORDBEAM+i2,true)) dead=23; + } + + if(blocked()) + { + dead=23; + } + + case ewSword: + if(blocked()) + { + dead=0; + } + + if(get_bit(quest_rules,qr_SWORDMIRROR)) + { + int checkx=0, checky=0; + + switch(dir) + { + case up: + checkx=x+7; + checky=y+8; + break; + + case down: + checkx=x+7; + checky=y; + break; + + case left: + checkx=x+8; + checky=y+7; + break; + + case right: + checkx=x; + checky=y+7; + break; + } + + if(ignorecombo==(((int)checky&0xF0)+((int)checkx>>4))) + break; + + if(hitcombo(checkx,checky,cMIRROR)) + { + id = wRefBeam; + dir ^= 1; + + if(dir&2) + flip ^= 1; + else + flip ^= 2; + + ignoreLink=false; + ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + y=(int)y&0xF0; + x=(int)x&0xF0; + } + + if(hitcombo(checkx,checky,cMIRRORSLASH)) + { + id = wRefBeam; + dir = 3-dir; + { + if(dir==right) + flip &= ~1; // not horiz + else if(dir==left) + flip |= 1; // horiz + else if(dir==up) + flip &= ~2; // not vert + else if(dir==down) + flip |= 2; // vert + } + tile=o_tile; + + if(dir&2) + { + if(frames>1) + { + tile+=frames; + } + else + { + ++tile; + } + } + + ignoreLink=false; + ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + y=(int)y&0xF0; + x=(int)x&0xF0; + } + + if(hitcombo(checkx,checky,cMIRRORBACKSLASH)) + { + id = wRefBeam; + dir ^= 2; + { + if(dir==right) + flip &= ~1; // not horiz + else if(dir==left) + flip |= 1; // horiz + else if(dir==up) + flip &= ~2; // not vert + else if(dir==down) + flip |= 2; // vert + } + tile=o_tile; + + if(dir&2) + { + if(frames>1) + { + tile+=frames; + } + else + { + ++tile; + } + } + + ignoreLink=false; + ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + y=(int)y&0xF0; + x=(int)x&0xF0; + } + + if(hitcombo(checkx,checky,cMAGICPRISM)) + { + int newx, newy; + newy=(int)y&0xF0; + newx=(int)x&0xF0; + + for(int tdir=0; tdir<4; tdir++) + { + if(dir!=(tdir^1)) + { + weapon *w=new weapon(*this); + w->dir=tdir; + w->x=newx; + w->y=newy; + w->z=z; + w->id=wRefBeam; + w->parentid=parentid; + w->parentitem=parentitem; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + w->hyofs = w->hxofs = 0; + //also set up the magic's correct animation -DD + w->flip=0; + + switch(w->dir) + { + case down: + w->flip=2; + + case up: + w->tile = w->o_tile; + w->hyofs=2; + w->hysz=12; + break; + + case left: + w->flip=1; + + case right: + w->tile=w->o_tile+((w->frames>1)?w->frames:1); + w->hxofs=2; + w->hxsz=12; + break; + } + + Lwpns.add(w); + } + } + + dead=0; + } + + if(hitcombo(checkx,checky,cMAGICPRISM4)) + { + int newx, newy; + newy=(int)y&0xF0; + newx=(int)x&0xF0; + + for(int tdir=0; tdir<4; tdir++) + { + weapon *w=new weapon(*this); + w->dir=tdir; + w->x=newx; + w->y=newy; + w->z=z; + w->id=wRefBeam; + w->parentid=parentid; + w->parentitem=parentitem; + w->hyofs = w->hxofs = 0; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + //also set up the magic's correct animation -DD + w->flip=0; + + switch(w->dir) + { + case down: + w->flip=2; + + case up: + w->tile = w->o_tile; + w->hyofs=2; + w->hysz=12; + break; + + case left: + w->flip=1; + + case right: + w->tile=w->o_tile+((w->frames>1)?w->frames:1); + w->hxofs=2; + w->hxsz=12; + break; + } + + Lwpns.add(w); + } + + dead=0; + } + } + + break; + + case wWhistle: + if(clk) + { + dead=1; + } + + break; + + case wWind: + { + if(blocked()) + { + dead=1; + } + + int wrx; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + wrx=tmpscr->warpreturnx[0]; + else wrx=tmpscr->warparrivalx; + + int wry; + + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + wry=tmpscr->warpreturny[0]; + else wry=tmpscr->warparrivaly; + + if(type==1 && dead==-1 && x==(int)wrx && y==(int)wry) + { + dead=2; + } + else if(LinkAction() !=inwind && ((dir==right && x>=240) || (dir==down && y>=160) || (dir==left && x<=0) || (dir==up && y<=0))) + { + stop_sfx(WAV_ZN1WHIRLWIND); + dead=1; + } + else if(get_bit(quest_rules,qr_MORESOUNDS)) + sfx(WAV_ZN1WHIRLWIND,pan(int(x)),true,false); + + if(get_bit(quest_rules,qr_WHIRLWINDMIRROR)) + goto mirrors; + + break; + } + + case wFire: + { + if(blocked()) + { + dead=1; + } + + if(parentitem<0 || (parentitem>-1 && itemsbuf[parentitem].family!=itype_book)) + { + if(clk==32) + { + step=0; + + if(parentitem<0 || !(itemsbuf[parentitem].flags & ITEM_FLAG2)) + { + isLit = true; + checkLightSources(); + } + } + + if(clk==94) + { + dead=1; + + if((parentitem<0 || !(itemsbuf[parentitem].flags & ITEM_FLAG2)) && + get_bit(quest_rules,qr_TEMPCANDLELIGHT) && + (Lwpns.idCount(wFire) + Ewpns.idCount(ewFlame))==1) + { + isLit = false; + checkLightSources(); + } + } + + if(clk==94 || get_bit(quest_rules,qr_INSTABURNFLAGS)) + { + findentrance(x,y,mfBCANDLE,true); + + if(type>0) + { + findentrance(x,y,mfRCANDLE,true); + } + + if(type>2) + { + findentrance(x,y,mfDINSFIRE,true); + } + } + } //wand fire + else + { + if(clk==1) + { + isLit = true; + checkLightSources(); + } + + if(clk==80) + { + dead=1; + findentrance(x,y,mfBCANDLE,true); + findentrance(x,y,mfRCANDLE,true); + findentrance(x,y,mfWANDFIRE,true); + + if(get_bit(quest_rules,qr_TEMPCANDLELIGHT) && (Lwpns.idCount(wFire) + Ewpns.idCount(ewFlame))==1) + { + isLit=false; + checkLightSources(); + } + } + } + + // Killed by script? + if(dead==0 && get_bit(quest_rules,qr_TEMPCANDLELIGHT) && (Lwpns.idCount(wFire) + Ewpns.idCount(ewFlame))==1) + { + isLit=false; + checkLightSources(); + } + + break; + } + + case wLitBomb: + case wBomb: + case ewLitBomb: + case ewBomb: + case ewLitSBomb: + case ewSBomb: + case wLitSBomb: + case wSBomb: + { + if(!misc) + { + break; + } + + // Naaah. + /*if (blocked()) + { + dead=1; + }*/ + if(clk==(misc-2) && step==0) + { + id = (id>wEnemyWeapons ? (id==ewLitSBomb||id==ewSBomb ? ewSBomb : ewBomb) + : parentitem>-1 ? ((itemsbuf[parentitem].family==itype_sbomb) ? wSBomb:wBomb) + : (id==wLitSBomb||id==wSBomb ? wSBomb : wBomb)); + hxofs=2000; + } + + if(clk==(misc-1) && step==0) + { + sfx((id>=wEnemyWeapons || parentitem<0) ? WAV_BOMB : + itemsbuf[parentitem].usesound,pan(int(x))); + + if(id==wSBomb || id==wLitSBomb || id==ewSBomb || id==ewLitSBomb) + { + hxofs=hyofs=-16; + hxsz=hysz=48; + } + else + { + hxofs=hyofs=-8; + hxsz=hysz=32; + } + + hzsz=16; + } + + int boomend = (misc+(((id == wBomb || id == wSBomb || id == wLitBomb || id == wLitSBomb) && + (parentitem>-1 && itemsbuf[parentitem].flags & ITEM_FLAG1)) ? 35 : 31)); + + if(clk==boomend && step==0) + { + hxofs=2000; + } + + if(idflags7&fSIDEVIEW?2:-3),mfBOMB,true); + + if(id==wSBomb || id==wLitSBomb) + { + findentrance(x+tx,y+ty+(tmpscr->flags7&fSIDEVIEW?2:-3),mfSBOMB,true); + } + + findentrance(x+tx,y+ty+(tmpscr->flags7&fSIDEVIEW?2:-3),mfSTRIKE,true); + } + } + } + + if(!get_bit(quest_rules,qr_NOBOMBPALFLASH)) + { + if(!usebombpal) + { + if(clk==misc || clk==misc+5) + { + + usebombpal=true; + memcpy(tempbombpal, RAMpal, PAL_SIZE*sizeof(RGB)); + + //grayscale entire screen + if(get_bit(quest_rules,qr_FADE)) + { + for(int i=CSET(0); i < CSET(15); i++) + { + int g = zc_min((RAMpal[i].r*42 + RAMpal[i].g*75 + RAMpal[i].b*14) >> 7, 63); + g = (g >> 1) + 32; + RAMpal[i] = _RGB(g,g,g); + } + + } + else + { + // this is awkward. NES Z1 converts colors based on the global + // NES palette. Something like RAMpal[i] = NESpal( reverse_NESpal(RAMpal[i]) & 0x30 ); + for(int i=CSET(0); i < CSET(15); i++) + { + RAMpal[i] = NESpal(reverse_NESpal(RAMpal[i]) & 0x30); + } + } + + refreshpal = true; + } + } + + if((clk==misc+4 || clk==misc+9) && usebombpal) + { + // undo grayscale + usebombpal=false; + memcpy(RAMpal, tempbombpal, PAL_SIZE*sizeof(RGB)); + refreshpal = true; + } + } + + if(clk==misc+30) + { + bombdoor(x,y); + } + } + + if(clk==misc+34) + { + if(step==0) + { + dead=1; + } + } + + break; + } + + case wArrow: + { + if(dead>0) + { + break; + } + + if(misc>0 && clk > misc) + { + dead=4; + } + + if(findentrance(x,y,mfSTRIKE,true)) + { + dead=4; + } + + if(findentrance(x,y,mfARROW,true)) + { + dead=4; + } + + if(current_item(itype_arrow)>1) + { + if(findentrance(x,y,mfSARROW,true)) + { + dead=4; + } + } + + if(current_item(itype_arrow)>=3) + { + if(findentrance(x,y,mfGARROW,true)) + { + dead=4; + } + } + + if(blocked()) + { + dead=4; + } + + break; + } + + case wSSparkle: + if(blocked()) //no spakle area? + { + dead=1; + } + + if(clk>=frames*o_speed-1) //(((wpnsbuf[wSSPARKLE].frames) * (wpnsbuf[wSSPARKLE].speed))-1)) + { + dead=1; + } + + break; + + case wFSparkle: + if(blocked()) //no sparkle area? + { + dead=1; + } + + if(clk>=frames*o_speed-1) //(((wpnsbuf[wFSPARKLE].frames) * (wpnsbuf[wFSPARKLE].speed))-1)) + { + dead=1; + } + + break; + + case wBait: + if(blocked()) //no bait area? + { + dead=23; + } + + if(parentitem>-1 && clk>=itemsbuf[parentitem].misc1) + { + dead=1; + } + + break; + + case wBrang: + { + if(dead==0) // Set by ZScript + { + stop_sfx(itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_brang)].usesound); + break; + } + + else if(dead==1) // Set by ZScript + { + onhit(false); + } + + int deadval=(itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_brang)].flags & ITEM_FLAG3)?-2:1; + + for(int i=0; i-1 ? parentitem : current_item_id(itype_brang)].misc1; + + if(range && clk2>=range) + { + if(deadval==1) + { + misc=1; + } + else + { + dead=deadval; + } + } + + if(range && clk2>range-18 && clk2-1 ? parentitem : current_item_id(itype_brang)].usesound,pan(int(x)),true); + return false; + } + + if(clk==1) // then check directional input + { + if(Up()) + { + dir=up; + + if(Left()) dir=l_up; + + if(Right()) dir=r_up; + } + else if(Down()) + { + dir=down; + + if(Left()) dir=l_down; + + if(Right()) dir=r_down; + } + else if(Left()) + { + dir=left; + } + else if(Right()) + { + dir=right; + } + } + + if(dead==1) + { + dead=-1; + misc=1; + } + + if(dead==-2) + { + misc=1; + } + + if(misc==1) // returning + { + if((abs(LinkY()-y)<7 && abs(LinkX()-x)<7)||dead==-2) + { + if(dead!=-2) + { + CatchBrang(); + } + + if(Lwpns.idCount(wBrang)<=1 && (!get_bit(quest_rules, qr_MORESOUNDS) || !Ewpns.idCount(ewBrang))) + stop_sfx(itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_brang)].usesound); + + if(dragging!=-1) + { + getdraggeditem(dragging); + } + + return true; + } + + seekLink(); + } + + sfx(itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_brang)].usesound,pan(int(x)),true,false); + + break; + } + + case wHookshot: + { + if(dead==0) // Set by ZScript + { + hookshot_used = false; + + for(int i=0; i-1 ? 16*itemsbuf[parentitem].misc1 : 0; + + if((abs(LinkX()-x)>maxlength)||(abs(LinkY()-y)>maxlength)) + { + dead=1; + } + + if(findentrance(x,y,mfSTRIKE,true)) dead=1; + + if(findentrance(x,y,mfHOOKSHOT,true)) dead=1; + + if(dir==up) + { + if((combobuf[MAPCOMBO(x+2,y+7)].type==cHSGRAB)) + { + hooked=true; + } + + if(get_bit(quest_rules, qr_HOOKSHOTLAYERFIX)) + hooked = hooked || (combobuf[MAPCOMBO2(0,x+2,y+7)].type==cHSGRAB) || (combobuf[MAPCOMBO2(1,x+2,y+7)].type==cHSGRAB); + + if(!hooked && _walkflag(x+2,y+7,1) && !ishookshottable((int)x+2,(int)y+7)) + { + dead=1; + } + } + + if(dir==down) + { + if((combobuf[MAPCOMBO(x+12,y+12)].type==cHSGRAB)) + { + hooked=true; + } + + if(get_bit(quest_rules, qr_HOOKSHOTLAYERFIX)) + hooked = hooked || (combobuf[MAPCOMBO2(0,x+12,y+12)].type==cHSGRAB) || (combobuf[MAPCOMBO2(1,x+12,y+12)].type==cHSGRAB); + + if(!hooked && _walkflag(x+12,y+12,1) && !ishookshottable((int)x+12,(int)y+12)) + { + dead=1; + } + } + + if(dir==left) + { + if(get_bit(quest_rules, qr_OLDHOOKSHOTGRAB)) + { + if(combobuf[MAPCOMBO(x+6,y+7)].type==cHSGRAB) + { + hooked=true; + } + } + else if(combobuf[MAPCOMBO(x+6,y+13)].type==cHSGRAB) + { + hooked=true; + } + + if(get_bit(quest_rules, qr_HOOKSHOTLAYERFIX)) + hooked = hooked || (combobuf[MAPCOMBO2(0,x+6,y+13)].type==cHSGRAB) || (combobuf[MAPCOMBO2(1,x+6,y+13)].type==cHSGRAB); + + if(!hooked && _walkflag(x+6,y+13,1) && !ishookshottable((int)x+6,(int)y+13)) + { + dead=1; + } + } + + if(dir==right) + { + if(get_bit(quest_rules, qr_OLDHOOKSHOTGRAB)) + { + if(combobuf[MAPCOMBO(x+9,y+7)].type==cHSGRAB) + { + hooked=true; + } + } + else if((combobuf[MAPCOMBO(x+9,y+13)].type==cHSGRAB)) + { + hooked=true; + } + + if(get_bit(quest_rules, qr_HOOKSHOTLAYERFIX)) + hooked = hooked || (combobuf[MAPCOMBO2(0,x+9,y+13)].type==cHSGRAB) || (combobuf[MAPCOMBO2(1,x+9,y+13)].type==cHSGRAB); + + if(!hooked && _walkflag(x+9,y+13,1) && !ishookshottable((int)x+9,(int)y+13)) + { + dead=1; + } + } + } + + if(hooked==true) + { + misc=1; + pull_link=true; + step=0; + } + + ++clk2; + + if(clk==0) // delay a frame + { + ++clk; + + if(parentitem>-1) + { + sfx(itemsbuf[parentitem].usesound,pan(int(x)),true); + } + + return false; + } + + if(dead==1) + { + dead=-1; + + if(step > 0) + step = -step; + + misc=1; + } + + if(misc==1) // returning + { + if((dir= left && abs(LinkX()-x)<9)) + { + hookshot_used=false; + + if(pull_link) + { + hs_fix=true; + } + + pull_link=false; + chainlinks.clear(); + CatchBrang(); + + if(parentitem>-1) + { + stop_sfx(itemsbuf[parentitem].usesound); + } + + if(dragging!=-1) + { + getdraggeditem(dragging); + } + + return true; + } + } + + if(parentitem>-1) + { + sfx(itemsbuf[parentitem].usesound,pan(int(x)),true,false); + } + + if(blocked()) + { + //not on the return!! -DD + if(dead != -1) + dead=1; + } + } + break; + + case wHSHandle: + if(hookshot_used==false) + { + dead=0; + } + + if(blocked()) //no hookshot handle area? + { + hookshot_used=false; + dead=0; + } + + break; + + case wPhantom: + switch(type) + { + case pDINSFIREROCKET: + case pDINSFIREROCKETRETURN: + case pNAYRUSLOVEROCKETRETURN1: + case pNAYRUSLOVEROCKETRETURN2: + break; + + case pDINSFIREROCKETTRAIL: + if(clk>=(((wpnsbuf[wDINSFIRES1A].frames) * (wpnsbuf[wDINSFIRES1A].speed))-1)) + { + dead=0; + } + + break; + + case pDINSFIREROCKETTRAILRETURN: + if(clk>=(((wpnsbuf[wDINSFIRES1B].frames) * (wpnsbuf[wDINSFIRES1B].speed))-1)) + { + dead=0; + } + + break; + + case pNAYRUSLOVEROCKETTRAIL1: + if(clk>=(((wpnsbuf[wNAYRUSLOVES1A].frames) * (wpnsbuf[wNAYRUSLOVES1A].speed))-1)) + { + dead=0; + } + + break; + + case pNAYRUSLOVEROCKETTRAILRETURN1: + if(clk>=(((wpnsbuf[wNAYRUSLOVES1B].frames) * (wpnsbuf[wNAYRUSLOVES1B].speed))-1)) + { + dead=0; + } + + break; + + case pNAYRUSLOVEROCKETTRAIL2: + if(clk>=(((wpnsbuf[wNAYRUSLOVES2A].frames) * (wpnsbuf[wNAYRUSLOVES2A].speed))-1)) + { + dead=0; + } + + break; + + case pNAYRUSLOVEROCKETTRAILRETURN2: + if(clk>=(((wpnsbuf[wNAYRUSLOVES2B].frames) * (wpnsbuf[wNAYRUSLOVES2B].speed))-1)) + { + dead=0; + } + + break; + + } + + if(blocked()) //not really sure this is needed + { + dead=1; + } + + break; + + case wRefMagic: + case wMagic: + case ewMagic: + { + if((id==wMagic)&&(findentrance(x,y,mfWANDMAGIC,true))) dead=0; + + if((id==wRefMagic)&&(findentrance(x,y,mfREFMAGIC,true))) dead=0; + + if((id!=ewMagic)&&(findentrance(x,y,mfSTRIKE,true))) dead=0; + + if((id==wMagic && current_item(itype_book) && + itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_book)].flags&ITEM_FLAG1) && get_bit(quest_rules,qr_INSTABURNFLAGS)) + { + findentrance(x,y,mfBCANDLE,true); + findentrance(x,y,mfRCANDLE,true); + findentrance(x,y,mfWANDFIRE,true); + } + +mirrors: + int checkx=0, checky=0; + + switch(dir) + { + case up: + checkx=x+7; + checky=y+8; + break; + + case down: + checkx=x+7; + checky=y; + break; + + case left: + checkx=x+8; + checky=y+7; + break; + + case right: + checkx=x; + checky=y+7; + break; + } + + if(ignorecombo!=(((int)checky&0xF0)+((int)checkx>>4))) + { + if(hitcombo(checkx,checky,cMIRROR)) + { + weapon *w=new weapon(*this); + + if(id==ewMagic) + { + Lwpns.add(w); + dead=0; + } + else + { + w=this; + } + + + w->dir ^= 1; + + if(w->id != wWind) + { + w->id = wRefMagic; + + if(w->dir&2) + w->flip ^= 1; + else + w->flip ^= 2; + } + + w->ignoreLink=false; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + w->y=checky&0xF0; + w->x=checkx&0xF0; + } + + if(hitcombo(checkx,checky,cMIRRORSLASH)) + { + weapon *w=new weapon(*this); + + if(id==ewMagic) + { + Lwpns.add(w); + dead=0; + } + else + { + w=this; + } + + w->dir = 3-w->dir; + + if(w->id != wWind) + { + w->id = wRefMagic; + + if((w->dir==1)||(w->dir==2)) + w->flip ^= 3; + } + + w->tile=w->o_tile; + + if(w->dir&2) + { + if(w->frames>1) + { + w->tile+=w->frames; + } + else + { + ++w->tile; + } + } + + w->ignoreLink=false; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + w->y=checky&0xF0; + w->x=checkx&0xF0; + } + + if(hitcombo(checkx,checky,cMIRRORBACKSLASH)) + { + weapon *w=new weapon(*this); + + if(id==ewMagic) + { + Lwpns.add(w); + dead=0; + } + else + { + w=this; + } + + w->dir ^= 2; + + if(w->id != wWind) + { + w->id = wRefMagic; + + if(w->dir&1) + w->flip ^= 2; + else + w->flip ^= 1; + } + + w->tile=w->o_tile; + + if(w->dir&2) + { + if(w->frames>1) + { + w->tile+=w->frames; + } + else + { + ++w->tile; + } + } + + w->ignoreLink=false; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + w->y=checky&0xF0; + w->x=checkx&0xF0; + } + + if(hitcombo(checkx,checky,cMAGICPRISM) && (id != wWind)) + { + int newx, newy; + newy=checky&0xF0; + newx=checkx&0xF0; + + for(int tdir=0; tdir<4; tdir++) + { + if(dir!=(tdir^1)) + { + weapon *w=new weapon(*this); + w->dir=tdir; + w->x=newx; + w->y=newy; + w->z=z; + w->id=wRefMagic; + w->parentid=parentid; + w->parentitem=parentitem; + w->flip = 0; + w->ignoreLink = false; + w->hyofs = w->hxofs = 0; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + + //also set up the magic's correct animation -DD + switch(w->dir) + { + case down: + w->flip=2; + + case up: + w->tile = w->o_tile; + w->hyofs=2; + w->hysz=12; + break; + + case left: + w->flip=1; + + case right: + w->tile=w->o_tile+((w->frames>1)?w->frames:1); + w->hxofs=2; + w->hxsz=12; + break; + } + + Lwpns.add(w); + } + } + + dead=0; + } + + if(hitcombo(checkx,checky,cMAGICPRISM4) && (id != wWind)) + { + int newx, newy; + newy=checky&0xF0; + newx=checkx&0xF0; + + for(int tdir=0; tdir<4; tdir++) + { + weapon *w=new weapon(*this); + w->dir=tdir; + w->x=newx; + w->y=newy; + w->z=z; + w->id=wRefMagic; + w->parentid=parentid; + w->parentitem=parentitem; + w->flip = 0; + w->ignoreLink = false; + w->hyofs = w->hxofs = 0; + w->ignorecombo=(((int)checky&0xF0)+((int)checkx>>4)); + + //also set up the magic's correct animation -DD + switch(w->dir) + { + case down: + w->flip=2; + + case up: + w->tile = w->o_tile; + w->hyofs=2; + w->hysz=12; + break; + + case left: + w->flip=1; + + case right: + w->tile=w->o_tile+((w->frames>1)?w->frames:1); + w->hxofs=2; + w->hxsz=12; + break; + } + + Lwpns.add(w); + } + + dead=0; + } + + if(blocked(0, 0)) + { + dead=0; + } + } + } + break; + + // enemy weapons + case ewFireball2: + switch(misc) + { + case up: + y-=.5; + break; + + case down: + y+=.5; + break; + + case left: + x-=.5; + break; + + case right: + x+=.5; + break; + + case l_up: + y-=.354; + x-=.354; + break; + + case r_up: + y-=.354; + x+=.354; + break; + + case l_down: + y+=.354; + x-=.354; + break; + + case r_down: + y+=.354; + x+=.354; + break; + } + + //fallthrough + case wRefFireball: + case ewFireball: + { + if((id==wRefFireball)&&(findentrance(x,y,mfREFFIREBALL,true))) dead=0; + + if((id==wRefFireball)&&(findentrance(x,y,mfSTRIKE,true))) dead=0; + + if(blocked()) + { + dead=0; + } + + if(clk<16) + { + ++clk; + + if(dead>0) + --dead; + + return dead==0; + } + + break; + } + + case ewFlame: + { + if(clk==32) + { + step=0; + misc = -1; // Don't drift diagonally anymore + isLit=true; + checkLightSources(); + } + + if(clk==126) + { + dead=1; + + if(get_bit(quest_rules,qr_TEMPCANDLELIGHT)) + { + isLit=false; + checkLightSources(); + } + } + + if(blocked()) + { + dead=1; + } + + // Killed by script? + if(dead==0 && get_bit(quest_rules,qr_TEMPCANDLELIGHT) && (Lwpns.idCount(wFire) + Ewpns.idCount(ewFlame))==1) + { + isLit=false; + checkLightSources(); + } + + break; + } + + case ewFireTrail: + { + if(clk==32) + { + step=0; //should already be 0, but still... + isLit=true; + checkLightSources(); + } + + if(clk==640) + { + dead=1; + + if(get_bit(quest_rules,qr_TEMPCANDLELIGHT)) + { + isLit=false; + checkLightSources(); + } + } + + if(blocked()) + { + dead=1; + } + + break; + } + + case ewBrang: + { + if(clk==0) + { + misc2=(dir27 && clk2<61) + { + step=1; + } + else if(misc) + { + step=2; + } + else + { + step=3; + } + } + + bool killrang = false; + + if(misc==1) // returning + { + if(aimedBrang) + { + //no parent + if(parentid < 0) + return true; + + //find parent + int index = -1; + + for(int i=0; igetUID()==parentid) + { + index = i; + break; + } + + //parent is not a guy + if(index < 0) + return true; + + seekEnemy(index); + + if((abs(x-GuyX(index))<7)&&(abs(y-GuyY(index))<7)) + { + if(get_bit(quest_rules,qr_MORESOUNDS) && !Lwpns.idCount(wBrang) && Ewpns.idCount(ewBrang)<=1) + { + stop_sfx(WAV_BRANG); + } + + return true; + } + } + else + { + switch(dir) + { + case up: + if(ymisc2) killrang=true; + + break; + + case left: + if(xmisc2) killrang=true; + + break; + } + } + } + else if(blocked()) + { + //only obey block flags before the bounce + dead=1; + } + + //if the boomerang is not on its way home, it bounces + if(dead==1 && misc != 1) + { + dead=-1; + misc=1; + dir^=1; + clk2=zc_max(46,90-clk2); + } + + //otherwise it disappears + if(killrang || dead==1) + { + if(get_bit(quest_rules,qr_MORESOUNDS) && !Lwpns.idCount(wBrang) && Ewpns.idCount(ewBrang)<=1) + { + stop_sfx(WAV_BRANG); + } + + dead = 1; + } + } + } + + // move sprite, check clipping + if(dead==-1 && clk>=0) + { + move(step); + + if(clip()) + { + onhit(true); + } + else if(id==ewRock) + { + if(_walkflag(x,y,2) || _walkflag(x,y+8,2)) + { + onhit(true); + } + } + } + else if(dead==-10) // Scripting hack thing related to weapon->DeadState + { + if(clip()) + { + onhit(true); + } + } + + if(bounce) + { + switch(dir) + { + case up: + x-=1; + y+=2; + break; + + case down: + x+=1; + y-=2; + break; + + case left: + x+=2; + y-=1; + break; + + case right: + x-=2; + y-=1; + break; + } + } + + // update clocks + ++clk; + + if(dead>0) + { + --dead; + } + + return dead==0; +} + +void weapon::onhit(bool clipped) +{ + onhit(clipped, 0, -1); +} + +void weapon::onhit(bool clipped, int special, int linkdir) +{ + if((scriptcoldet&1) == 0) + { + // These won't hit anything, but they can still go too far offscreen... + // Unless the compatibility rule is set. + if(get_bit(quest_rules, qr_OFFSCREENWEAPONS) || !clipped) + return; + goto offscreenCheck; + } + + if(special==2) // hit Link's mirror shield + { + switch(id) + { + case ewFireball2: + case ewFireball: + id = wRefFireball; + ignoreLink=true; + goto reflect; + + case ewRock: + case ewSword: + case wRefBeam: + case ewMagic: + case wRefMagic: + //otherwise he can get hit by the newly-created projectile if he's walking into it fast enough -DD + ignoreLink=true; + id = ((id==ewMagic || id==wRefMagic) ? wRefMagic : id==ewRock ? wRefRock : wRefBeam); + goto reflect; + + case wScript1: + case wScript2: + case wScript3: + case wScript4: + case wScript5: + case wScript6: + case wScript7: + case wScript8: + case wScript9: + case wScript10: + // If this isn't set, the weapon may reflect repeatedly + ignoreLink=true; +reflect: + + if(angular) switch(linkdir) + { + case up: + angle += (PI - angle) * 2.0; + break; + + case down: + angle = -angle; + break; + + case left: + angle += ((-PI/2) - angle) * 2.0; + break; + + case right: + angle += ((PI/2) - angle) * 2.0; + break; + + default: + angle += PI; + break; + } + else + { + dir ^= 1; + + if(dir&2) + flip ^= 1; + else + flip ^= 2; + } + + return; + } + } + + if(special>=1) // hit Link's shield + { + switch(id) + { + case ewRock: + case ewMagic: + case ewArrow: + case ewSword: + bounce=true; + dead=16; + return; + + case ewBrang: + if(misc==0) + { + clk2=256; + misc=1; + dir^=1; + } + + return; + } + } + +offscreenCheck: + switch(id) + { + case wSword: + case wWand: + case wHammer: + break; + + case ewBomb: + step=0; + break; + + case ewLitBomb: + step=0; + misc=50; + clk=misc-3; + hxofs=hyofs=-7; + hxsz=hysz=30; + break; + + case ewSBomb: + step=0; + break; + + case ewLitSBomb: + step=0; + misc=50; + clk=misc-3; + hxofs=hyofs=-16; + hxsz=hysz=48; + break; + + case wLitBomb: + if(!clipped) dead=1; + + case wLitSBomb: + if(!clipped) dead=1; + + case wWhistle: + case wBomb: + case wSBomb: + case wBait: + case wFire: + case wHSHandle: + case wPhantom: + break; // don't worry about clipping or hits with these + + case ewFireTrail: + if(!clipped) dead=1; + + break; + + case ewFlame: + if(!clipped) dead=1; + + break; + + case wRefBeam: + case wBeam: + dead=23; + break; + + case wArrow: + dead=4; + break; //findentrance(x,y,mfARROW,true); break; + + case ewArrow: + dead=clipped?4:1; + break; + + case wCByrna: + + // byrna keeps going + if(parentitem<0 || !(itemsbuf[parentitem].flags&ITEM_FLAG1)) + dead=0; + + break; + + case wWind: + if(x>=240) + dead=2; + + break; + + case wBrang: + if(misc==0) + { + clk2=256; + int deadval=(itemsbuf[parentitem>-1 ? parentitem : current_item_id(itype_brang)].flags & ITEM_FLAG3)?-2:4; + + if(clipped) + { + dead=deadval; + } + else + { + if(deadval==-2) + { + dead=deadval; + } + + misc=1; + } + } + + break; + + case wHookshot: + if(misc==0) + { + clk2=256; + + if(clipped) + dead=4; + else + dead=1; + } + + break; + + case ewBrang: + if(misc==0) + { + clk2=256; + dead=4; + } + + break; + + case wRefMagic: + case wMagic: + dead=1; //remove the dead part to make the wand only die when clipped + + if(((id==wMagic && current_item(itype_book) && + (itemsbuf[current_item_id(itype_book)].flags&ITEM_FLAG1))) && Lwpns.idCount(wFire)<2) + { + Lwpns.add(new weapon(x,y,z,wFire,2,1*DAMAGE_MULTIPLIER,0,current_item_id(itype_book),-1)); + sfx(WAV_FIRE,pan(x)); + } + + break; + + case ewWind: + if(clipped) + { + if(misc==999) // in enemy wind + { + ewind_restart=true; + } + + dead=1; + } + + break; + + default: + dead=1; + } +} + +// override hit detection to check for invicibility, etc +bool weapon::hit(sprite *s) +{ + if(!(scriptcoldet&1)) return false; + + if(id==ewBrang && misc) + return false; + + return (dead!=-1&&dead!=-10) ? false : sprite::hit(s); +} + +bool weapon::hit(int tx,int ty,int tz,int txsz2,int tysz2,int tzsz2) +{ + if(!(scriptcoldet&1)) return false; + + if(id==ewBrang && misc) + return false; + + return (dead!=-1&&dead!=-10) ? false : sprite::hit(tx,ty,tz,txsz2,tysz2,tzsz2); +} + +void weapon::update_weapon_frame(int change, int orig) +{ + if(extend > 2) + { + byte extra_rows=(tysz-1)*(((orig%TILES_PER_ROW)+(txsz*change))/TILES_PER_ROW); + tile=orig+(txsz*change)+(extra_rows*TILES_PER_ROW); + } + else + tile=orig+change; +} + +void weapon::draw(BITMAP *dest) +{ + if(flash==1) + { + if(!BSZ) + { + cs = (id==wBeam || id==wRefBeam) ? 6 : o_cset&15; + cs += frame&3; + } + else + { + if(id==wBeam || id==wRefBeam) + cs = ((frame>>2)&1)+7; + else + { + cs = o_cset&15; + + if(++csclk >= 12) + csclk = 0; + + cs += csclk>>2; + } + } + } + + if(flash>1) + { + if(++csclk >= (o_speed<<1)) + csclk = 0; + + cs = o_cset&15; + + if(csclk >= o_speed) + cs = o_cset>>4; + } + + if(frames) + { + if(id!=wBrang && id!=ewBrang) // Brangs use clk2 for adjusting boomerang's flight range. + { + if(++clk2 >= o_speed) + { + clk2 = 0; + + if(frames>1 && ++aframe >= frames) + { + aframe = 0; + } + } + } + else + { + if((clk2 % zc_max(1, o_speed))==0) + { + if(frames>1 && ++aframe >= frames) + { + aframe = 0; + } + } + } + + //tile = o_tile+aframe; + update_weapon_frame(aframe,o_tile); + } + + // do special case stuff + switch(id) + { + case wSword: + case wHammer: + if(get_bit(quest_rules,qr_LINKFLICKER)&&((getClock()||LinkHClk())&&(frame&1)) || + Link.getDontDraw() || tmpscr->flags3&fINVISLINK) + return; + + case wBeam: + case wRefBeam: + { + if(dead==-1) break; + + // draw the beam shards + int ofs=23-dead; + int f = frame&3; + int type2 = o_type; + //tile = o_tile+((frames?frames:1)*2); + update_weapon_frame(((frames?frames:1)*2),o_tile); + + if(type2) + cs = o_cset>>4; + + if(type2==3 && (f&2)) + ++tile; + + if(!type2 || f==0 || (type2>1 && f==3)) overtile16(dest,tile,x-2-ofs,y+playing_field_offset-2-ofs-(z+zofs),cs,0); + + if(!type2 || f==2 || (type2>1 && f==1)) overtile16(dest,tile,x+2+ofs,y+playing_field_offset-2-ofs-(z+zofs),cs,1); + + if(!type2 || f==1 || (type2>1 && f==2)) overtile16(dest,tile,x-2-ofs,y+playing_field_offset+2+ofs-(z+zofs),cs,2); + + if(!type2 || f==3 || (type2>1 && f==0)) overtile16(dest,tile,x+2+ofs,y+playing_field_offset+2+ofs-(z+zofs),cs,3); + } + + return; // don't draw sword + + case wBomb: + case wSBomb: + case ewBomb: + case ewSBomb: + { + if(!misc || clk-1) + { + id2=itemsbuf[parentitem].wpn2; + } + + break; + } + + case wSBomb: + { + id2=wSBOOM; + + if(parentitem>-1) + { + id2=itemsbuf[parentitem].wpn2; + } + + break; + } + + case ewBomb: + id2=ewBOOM; + break; + + case ewSBomb: + id2=ewSBOOM; + break; + } + + tile = wpnsbuf[id2].tile; + cs = wpnsbuf[id2].csets&15; + boomframes = wpnsbuf[id2].frames; + + if(boomframes != 0) + { + //equally divide up the explosion time among the frames + int perframe = (boomframes >= 34 ? 1 : (boomframes + 34)/boomframes); + + if(clk > misc) + tile += (clk-misc)/perframe; + + //update_weapon_frame((clk-misc)/perframe,tile); + } + else if(clk>misc+22) + { + ++tile; + //update_weapon_frame(1,tile); + } + + overtile16(dest,tile,x+((clk&1)?7:-7),y+yofs-13-(z+zofs),cs,0); + overtile16(dest,tile,x,y+yofs-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?-14:14),y+yofs-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?-7:7),y+yofs+14-(z+zofs),cs,0); + + if(id==wSBomb||id==ewSBomb) + { + overtile16(dest,tile,x+((clk&1)?7:-7),y+yofs-27-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?-21:21),y+yofs-13-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?-28:28),y+yofs-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?21:-21),y+yofs+14-(z+zofs),cs,0); + overtile16(dest,tile,x+((clk&1)?-7:7),y+yofs+28-(z+zofs),cs,0); + } + else + { + ; + } + + if(get_debug() && key[KEY_O]) + rectfill(dest,x+hxofs,y+hyofs+yofs-(z+zofs), + x+hxofs+hxsz-1,y+hyofs+hysz-1+yofs,vc(id)); + + return; // don't draw bomb + } + + case wArrow: + case ewArrow: + if(dead>0 && !bounce) + { + cs=7; + tile=54; + flip=0; + } + + break; + + case ewFireTrail: + case ewFlame: + case wFire: + + //if no animation, flip tile + if(frames==0) + flip = o_flip & (clk>>2); + + break; + + case ewBrang: + case wBrang: + cs = o_cset&15; + + if(parentitem<0 || !(itemsbuf[parentitem].flags & ITEM_FLAG1)) + { + tile = o_tile; + + if(BSZ) + flip = bszboomflip[(clk>>2)&3]; + else + { + //tile = boomframe[clk&0xE] + o_tile; + update_weapon_frame(boomframe[clk&0xE],o_tile); + flip = boomframe[(clk&0xE)+1]; + } + + if(parentitem>=0 && itemsbuf[parentitem].flags & ITEM_FLAG2) + { + update_weapon_frame((BSZ?1:4)*dir,tile); + } + } + else + { + if(parentitem>=0 && itemsbuf[parentitem].flags & ITEM_FLAG2) + { + update_weapon_frame(zc_max(frames,1)*dir,tile); + } + } + + if(dead>0) + { + if(parentitem>=0 && itemsbuf[parentitem].flags & ITEM_FLAG1) + { + tile=o_tile+(frames*(itemsbuf[parentitem].flags & ITEM_FLAG2)?8:1); + } + else + { + cs=7; + tile=54; + flip=0; + } + } + + break; + + case wHookshot: + break; + + case wWind: + if(frames==0) + flip ^= o_flip; + + if((dead!=-1) && !BSZ) + tile = temp1;//wpnsbuf[wFIRE].tile; + + break; + + case ewWind: + /* + if(wpnsbuf[wid].frames==0) + flip ^= (wpnsbuf[wid].misc>>2)&3; + */ + break; + + case wPhantom: + switch(type) + { + case pNAYRUSLOVEROCKET1: + case pNAYRUSLOVEROCKETRETURN1: + case pNAYRUSLOVEROCKETTRAIL1: + case pNAYRUSLOVEROCKETTRAILRETURN1: + case pNAYRUSLOVEROCKET2: + case pNAYRUSLOVEROCKETRETURN2: + case pNAYRUSLOVEROCKETTRAIL2: + case pNAYRUSLOVEROCKETTRAILRETURN2: + if(parentitem>=0 && (itemsbuf[parentitem].flags & ITEM_FLAG1 ? 1 : 0)&&!(frame&1)) + { + return; + } + + break; + } + + break; + } + + // draw it + sprite::draw(dest); +} + +void weapon::activateRemoteBomb() +{ + misc=50; + clk=47; + id=(id==wLitBomb) ? wBomb : wLitSBomb; +} + +void weapon::adjustDraggedItem(int removed) +{ + if(dragging==removed) + dragging=-1; + else if(dragging>removed) + dragging--; +} + +// Uses putweapon() to draw a misc. sprite. I'm not certain it's exactly right. +// And it should really be moved... +void putMiscSprite(BITMAP *dest, int spr, int x, int y) +{ + if(wpnsbuf[spr].tile!=0) + putweapon(dest, x, y, wPhantom, 4, up, lens_hint_weapon[wPhantom][0], lens_hint_weapon[wPhantom][1], -1); +} + +void putweapon(BITMAP *dest,int x,int y,int weapon_id, int type, int dir, int &aclk, int &aframe, int parentid) +{ + weapon temp((fix)x,(fix)y,(fix)0,weapon_id,type,0,dir,-1,parentid,true); + temp.ignorecombo=((dir==up?y+8:y)&0xF0)+((dir==left?x+8:x)>>4); // Lens hints can sometimes create real weapons without this + temp.ignoreLink=true; + temp.yofs=0; + temp.clk2=aclk; + temp.aframe=aframe; + temp.animate(0); + temp.draw(dest); + aclk=temp.clk2; + aframe=temp.aframe; +} + +/*** end of weapons.cpp ***/ + diff --git a/src/weapons.h b/src/weapons.h new file mode 100644 index 0000000000..e1d1e9cea6 --- /dev/null +++ b/src/weapons.h @@ -0,0 +1,101 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- + +#ifndef _WEAPONS_H_ +#define _WEAPONS_H_ + +#include "zdefs.h" +#include "sprite.h" +#include "sfxClass.h" + +/**************************************/ +/*********** Weapon Class ***********/ +/**************************************/ + +extern byte boomframe[16]; +extern byte bszboomflip[4]; + +class weapon : public sprite +{ +private: + void seekLink(); + void seekEnemy(int j); + +public: + int power,type,dead,clk2,misc2,ignorecombo; + bool isLit; //if true, this weapon is providing light to the current screen + int parentid, //Enemy who created it + parentitem; //Item which created it + int dragging; + fix step; + bool bounce, ignoreLink; + word flash,wid,aframe,csclk; + int o_tile, o_cset, o_speed, o_type, frames, o_flip; + int temp1; + bool behind; + bool aimedBrang; + + weapon(weapon const & other); + weapon(fix X,fix Y,fix Z,int Id,int Type,int pow,int Dir, int Parentid, int prntid, bool isDummy=false); + virtual ~weapon(); + void LOADGFX(int wpn); + bool Dead(); + bool clip(); + bool blocked(); + virtual bool blocked(int xOffset, int yOffset); + virtual bool animate(int index); + virtual void onhit(bool clipped); + virtual void onhit(bool clipped, int special, int linkdir); + // override hit detection to check for invicibility, etc + virtual bool hit(sprite *s); + virtual bool hit(int tx,int ty,int tz,int txsz,int tysz,int tzsz); + virtual void draw(BITMAP *dest); + virtual void update_weapon_frame(int change, int orig); + void setAngle(double angle); + + // Bombs only + void activateRemoteBomb(); + + // Boomerangs and hookshots only + // Shift dragged item index after an item with a lower index is collected + void adjustDraggedItem(int removed); + + // Wind only + inline void pickUpLink() { misc=999; } + inline bool hasLink() { return misc==999; } + + inline void setSparkleFunc(void (*sf)(const weapon&)) { sparkleFunc=sf; } + +private: + SFX sfxLoop; + + // How close the weapon can get to the edge of the screen before + // being deleted (or bouncing, in the case of boomerangs) + int minX, maxX, minY, maxY; + + // If set, this function will be called every frame to add sparkles. + void (*sparkleFunc)(const weapon&); + + // Set dir to the appropriate value for angle. + void matchDirToAngle(); + + friend void setScreenLimits(weapon&); +}; + +void putMiscSprite(BITMAP *dest, int spr, int x, int y); +void putweapon(BITMAP *dest,int x,int y,int weapon_id, int type, int dir, int &aclk, int &aframe, + int parentid); +#endif +/*** end of sprite.cc ***/ + diff --git a/src/win32.cpp b/src/win32.cpp new file mode 100644 index 0000000000..a4744cef56 --- /dev/null +++ b/src/win32.cpp @@ -0,0 +1,273 @@ + +#include "precompiled.h" //always first + + +#ifdef _WIN32 + +#include +#include +#include + +#include "win32.h" + + +bool is_only_instance(const char* name) +{ + HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, name); + + if (!hMutex) + { + hMutex = CreateMutex(0, 0, name); + return true; + } + else + return false; +} + + +Win32Data win32data; +WNDPROC hAllegroProc = 0; + + +#define FATAL_ERROR(message) \ + set_gfx_mode(GFX_TEXT,0,0,0,0); \ + allegro_message(message); \ + exit(1) + + +/* + These are unfinished, though the windows stuff is here if it is needed. + This might work, but most likely will crash for most cases so I don't even bother + with it anymore. + NOTE : None of the code below is actually used by zc by default and needs to be + removed as soon as allegro version can be updated to 4.4. +*/ + + +#define Z_WIN32NOUPDATE + + +void Win32Data::Update(int frameskip) +{ + if(!win32data.isValid) + return; + + if(frameskip > 0) + { + } + + while(!win32data.hasFocus) + { + rest(17); + } +} + + +// Should be called from winmain, and alleg-event threads. +int Win32Data::zqSetDefaultThreadPriority(HANDLE _thread) +{ + (void*)_thread; + /* + if(!_thread) + _thread = ::GetCurrentThread(); + + DWORD priority = ::GetThreadPriority( _thread ); + if( priority != THREAD_PRIORITY_NORMAL ) + { + printf("Thread Priority (%ld) set to normal.\n", priority); + priority = THREAD_PRIORITY_NORMAL; + + if( !::SetThreadPriority(_thread, priority) ) + { + printf("Error: Thread Priority not changed.\n"); + return 1; + } + } + */ + + return 0; +} + + +int Win32Data::zqSetCustomCallbackProc(HWND hWnd) +{ + Win32Mutex mutex; + mutex.Lock(); + + memset((void*)&win32data, 0, sizeof(Win32Data)); + win32data.hasFocus = true; + + win32data.hWnd = hWnd; + + if(win32data.hWnd) + win32data.isValid = true; + else return -1; + + hAllegroProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC); + + if(!hAllegroProc) + { + win32data.isValid = false; + return -1; + } + + win32data.hInstance = ::GetWindowLongPtr(hWnd, GWLP_HINSTANCE); + + if(!win32data.hInstance) + { + win32data.isValid = false; + return -1; + } + + win32data.hId = ::GetWindowLongPtr(hWnd, GWLP_ID); + + //assign a new callback + LONG_PTR pcb = ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)Win32Data::zqWindowsProc); + + if(!pcb) + { + al_trace("Error: Cannot Set Windows Procedure."); + win32data.isValid = false; + return -1; + } + + return 0; +} + + + +LRESULT CALLBACK Win32Data::zqWindowsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + assert(win32data.isValid && "ZQuest-Windows Fatal Error: Set \"zq_win_proc_fix = 0\" in config file."); + + static bool initPriority = false; + + if(!initPriority) + { + //sets the allegro worker threads' priority + zqSetDefaultThreadPriority(0); + } + + switch(uMsg) + { + case WM_SETFOCUS: + { + win32data.hasFocus = true; + } + break; + + case WM_KILLFOCUS: + { + win32data.hasFocus = false; + } + break; + } + + //ship the rest for allegro to handle + return hAllegroProc(hwnd, uMsg, wParam, lParam); +} + + + + + + +int Win32Data::zcSetCustomCallbackProc(HWND hWnd) +{ + Win32Mutex mutex; + mutex.Lock(); + + memset((void*)&win32data, 0, sizeof(Win32Data)); + win32data.hasFocus = true; + + win32data.hWnd = hWnd; + + if(win32data.hWnd) + win32data.isValid = true; + else return -1; + + hAllegroProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC); + + if(!hAllegroProc) + { + win32data.isValid = false; + return -1; + } + + win32data.hInstance = ::GetWindowLongPtr(hWnd, GWLP_HINSTANCE); + + if(!win32data.hInstance) + { + win32data.isValid = false; + return -1; + } + + win32data.hId = ::GetWindowLongPtr(hWnd, GWLP_ID); + + //assign a new callback + LONG_PTR pcb = ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)Win32Data::zcWindowsProc); + + if(!pcb) + { + al_trace("Error: Cannot Set Windows Procedure."); + win32data.isValid = false; + return -1; + } + + return 0; +} + + + +LRESULT CALLBACK Win32Data::zcWindowsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + assert(win32data.isValid && "ZC-Win32 Fatal Error: Set \"zc_win_proc_fix = 0\" in config file."); + + /* + HWND tmp_hwnd = win_get_window(); + if( win32data.hWnd != hwnd || win32data.hWnd != tmp_hwnd ) + { + win32data.hWnd = hwnd; //happens at shutdown + } + */ + + switch(uMsg) + { + case WM_SETFOCUS: + { + win32data.hasFocus = true; + } + break; + + case WM_KILLFOCUS: + { + win32data.hasFocus = false; + } + break; + + case WM_SYSCOMMAND: + { + switch(wParam) + { + // *Don't let the monitor enter screen-save mode.* + // -this is actually an annoying bug on my laptop: what happens is if allegro + // is running and we go into powersave, (joystick input is not considered activity), + // the damn thing locks up sometimes and I have to enter stand-by mode... :/ -Gleeok + case SC_SCREENSAVE: + case SC_MONITORPOWER: + //fall through + return 0; + } + + break; + } + } + + //ship the rest for allegro to handle + LRESULT result = hAllegroProc(hwnd, uMsg, wParam, lParam); + + return result; +} + + +#endif //_WIN32 diff --git a/src/win32.h b/src/win32.h new file mode 100644 index 0000000000..45823b3ea8 --- /dev/null +++ b/src/win32.h @@ -0,0 +1,90 @@ + +#pragma once + +#ifdef _WIN32 + + +#define WIN32_LEAN_AND_MEAN +#define WIN32_EXTRA_LEAN +#include +#include + + + +class Win32Data +{ +public: + volatile HWND hWnd; + volatile LONG_PTR hInstance; + volatile LONG_PTR hId; + + static LRESULT CALLBACK zqWindowsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static int zqSetDefaultThreadPriority(HANDLE _thread); + static int zqSetCustomCallbackProc(HWND hWnd); + + static LRESULT CALLBACK zcWindowsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static int zcSetCustomCallbackProc(HWND hWnd); + + volatile bool hasFocus; + volatile bool isValid; + + //call from main thread. + void Update(int frameskip); +}; +extern Win32Data win32data; + + + +class Win32Mutex +{ +public: + Win32Mutex(bool lock = false) : m_locked(false) + { + ::InitializeCriticalSection(&m_criticalSection); + + if(lock) + Lock(); + } + + ~Win32Mutex() + { + Unlock(); + ::DeleteCriticalSection(&m_criticalSection); + } + + void Lock() + { + if(!m_locked) + { + m_locked = true; + ::EnterCriticalSection(&m_criticalSection); + } + } + + void Unlock() + { + if(m_locked) + { + m_locked = false; + ::LeaveCriticalSection(&m_criticalSection); + } + } + +protected: + CRITICAL_SECTION m_criticalSection; + bool m_locked; +}; + + + + + + + + + + + + + +#endif //_WIN32 diff --git a/src/zc_alleg.h b/src/zc_alleg.h new file mode 100644 index 0000000000..d8c6072ae4 --- /dev/null +++ b/src/zc_alleg.h @@ -0,0 +1,75 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zc_alleg.h +// +// For debugging... +// +//-------------------------------------------------------- + +#ifndef _ZC_ALLEG_H_ +#define _ZC_ALLEG_H_ + +#define DEBUGMODE +#define ALLEGRO_NO_COMPATIBILITY +#include +#include + +#ifdef __cplusplus +INLINE fix abs(fix f) +{ + fix t; + + if(f < 0) + { + t.v = -f.v; + } + else + { + t.v = f.v; + } + + return t; +} +#endif + +#ifdef _ZQUEST_SCALE_ +#undef SCREEN_W +#undef SCREEN_H +#define SCREEN_W (screen ? screen->w : 0) +#define SCREEN_H (screen ? screen->h : 0) +#define popup_dialog popup_zqdialog +#define do_dialog do_zqdialog +#endif + +#ifdef ALLEGRO_WINDOWS +#include +#define YIELD() Sleep(10) +#else +#if defined(ALLEGRO_UNIX)||defined(ALLEGRO_LINUX)||defined(ALLEGRO_MACOSX) +#include +INLINE void YIELD(void) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); +} +#else +#define YIELD() yield_timeslice() +#endif +#endif + +#if !defined(ALLEGRO_MACOSX) +#define KEY_ZC_LCONTROL KEY_LCONTROL +#define KEY_ZC_RCONTROL KEY_RCONTROL +#else +#define KEY_ZC_LCONTROL KEY_COMMAND +#define KEY_ZC_RCONTROL KEY_COMMAND + +#endif + +#endif + + diff --git a/src/zc_array.h b/src/zc_array.h new file mode 100644 index 0000000000..bddd60d997 --- /dev/null +++ b/src/zc_array.h @@ -0,0 +1,492 @@ +/* + * - Visual Studio "autoexp.dat" info. -Gleeok + * +;------------------------------------------------------------------------------ +; Array +;------------------------------------------------------------------------------ +Array<*>{ + children + ( + #array + ( + expr : ($e._ptr)[$i], + size : $e._size + ) + ) + preview + ( + #( + "[", $e._size, "](", + #array + ( + expr : ($e._ptr)[$i], + size : $e._size + ), + ")" + ) + ) +} +*/ +#if defined (_MSC_VER) && defined (USING_ARRAY) +#define ZCArray Array +#define ZCArrayIterator ArrayIterator +#endif + +// ZScript arrays were planned on having multi-dimensional support at one time, but +// were never finished, hence the x,y,z components. +// TODO: Should either finish them or make array dimensions use templates. +#include "zdefs.h" + +#ifndef __zc_array_h_ +#define __zc_array_h_ + +//#define _DEBUGZCARRAY + + +template +class ZCArray +{ +public: + typedef const T* const_iterator; + typedef T* iterator; + typedef unsigned int size_type; + typedef const T& const_reference; + typedef const T* const_pointer; + typedef const T const_type; + typedef T& reference; + typedef T* pointer; + typedef T type; + + ZCArray() : _ptr(NULL), _size(0) + { + for(int i = 0; i < 4; i++) + _dim[i] = 0; + } + + ZCArray(size_type _Size) : _ptr(NULL) + { + _SetDimensions(0, 0, _Size); + _Alloc(_size); + } + + ZCArray(size_type _Y, size_type _X) : _ptr(NULL) + { + _SetDimensions(0, _Y, _X); + _Alloc(_size); + } + + ZCArray(size_type _Z, size_type _Y, size_type _X) : _ptr(NULL) + { + _SetDimensions(_Z, _Y, _X); + _Alloc(_size); + } + + ZCArray(const ZCArray &_Array) : _ptr(NULL), _size(0) + { + for(int i = 0; i < 4; i++) _dim[i] = 0; + + Copy(_Array); + } + + ~ZCArray() + { + _Delete(); + } + + const ZCArray &operator = (const ZCArray &_Array) + { + if(this != &_Array) + Copy(_Array); + + return *this; + } + + bool operator == (const ZCArray &_Array) const + { + if(_size != _Array._size) + return false; + + for(size_type i(0); i < _size; i++) + if(*(_ptr + i) != *(_Array._ptr + i)) + return false; + + return true; + } + + bool operator != (const ZCArray &right) const + { + return !(*this == right); + } + + reference operator()(size_type _X) + { + return _ptr[ _X ]; + } + reference operator()(size_type _Y, size_type _X) + { + return _ptr[ _X + _Y * _dim[0] ]; + } + reference operator()(size_type _Z, size_type _Y, size_type _X) + { + return _ptr[ _X + _Y * _dim[0] + _Z * _dim[3] ]; + } + + const_reference operator()(size_type _X) const + { + return _ptr[ _X ]; + } + const_reference operator()(size_type _Y, size_type _X) const + { + return _ptr[ _X + _Y * _dim[0] ]; + } + const_reference operator()(size_type _Z, size_type _Y, size_type _X) const + { + return _ptr[ _X + _Y * _dim[0] + _Z * _dim[3] ]; + } + + + pointer operator ->() + { + return &(*_ptr); + } + const_pointer operator ->() const + { + return &(*_ptr); + } + type operator * () + { + return *_ptr; + } + const_type operator * () const + { + return *_ptr; + } + reference operator [](const size_type& i) + { + return _ptr[i]; + } + const_reference operator [](const size_type& i) const + { + return _ptr[i]; + } + + reference At(size_type _X) + { + if(!_Bounds(_X)) + return _ptr[ 0 ]; //Must be a better way of returning an invalied element in a template than this... + + return _ptr[ _X ]; + } + reference At(const size_type& _Y, const size_type& _X) + { + if(!_Bounds(_X,_Y)) + return _ptr[ 0 ]; + + return _ptr[ Offset(_Y, _X) ]; + } + reference At(const size_type& _Z, const size_type& _Y, const size_type& _X) + { + if(!_BoundsExp(_X,_Y,_Z)) + return _ptr[ 0 ]; + + return _ptr[ Offset(_Z, _Y, _X) ]; + } + + reference StrictAt(size_type _X) + { + _BoundsExp(_X); + return _ptr[ _X ]; + } + reference StrictAt(size_type _Y, size_type _X) + { + _BoundsExp(_X,_Y); + return _ptr[ Offset(_Y, _X) ]; + } + reference StrictAt(size_type _Z, size_type _Y, size_type _X) + { + _BoundsExp(_X,_Y,_Z); + return _ptr[ Offset(_Z, _Y, _X) ]; + } + + reference Front() + { + return *_ptr; + } + reference Back() + { + return _ptr[ _size - 1 ]; + } + const_reference Front() const + { + return *_ptr; + } + const_reference Back() const + { + return _ptr[ _size - 1 ]; + } + + size_type Offset(const size_type& _Z, const size_type& _Y, const size_type& _X) const + { + return (_X + _Y * _dim[0] + _Z * _dim[3]); + } + size_type Offset(const size_type& _Y, const size_type& _X) const + { + return (_X + _Y * _dim[0]); + } + + iterator Begin() + { + return iterator(_ptr); + } + iterator End() + { + return iterator(_ptr + _size); + } + const_iterator Begin() const + { + return const_iterator(_ptr); + } + const_iterator End() const + { + return const_iterator(_ptr + _size); + } + + size_type Size() const + { + return _size; + } + bool Empty() const + { + return (_size == 0); + } + + size_type Offset(const size_type _Z, const size_type _Y, const size_type _X) const + { + return (_X + _Y * _dim[0] + _Z * _dim[3]); + } + size_type Offset(const size_type _Y, const size_type _X) const + { + return (_X + _Y * _dim[0]); + } + + void Assign(const size_type _Begin, const size_type _End, const type& _Val = type()) + { + for(size_type i(_Begin); i < _End; i++) + _ptr[ i ] = _Val; + } + + void Resize(const size_type _Size) + { + Resize(0, 0, _Size); + } + void Resize(const size_type _Y, const size_type _X) + { + Resize(0, _Y, _X); + } + void Resize(const size_type _Z, const size_type _Y, const size_type _X) + { + const size_type _OldSize = _size; + const size_type _NewSize = _GetSize(_Z, _Y, _X); + + _SetDimensions(_Z, _Y, _X); + + if(_NewSize == 0) + { + _Delete(); + _size = _NewSize; + } + else if(_OldSize != _NewSize) + _ReAssign(_OldSize, _NewSize); + } + + void Copy(const ZCArray &_Array) + { + if(_Array.Empty()) + { + Clear(); + return; + } + +#ifdef _DEBUGZCARRAY + + // _size should always be 0 if _ptr is null...so this shouldn't ever happen + if((!_ptr && _size > 0) || (!_Array._ptr && _Array._size > 0)) + { + al_trace("ZCArray copy op error!!!: -lhs p: %p -size: %u -rhs p: %p -size: %u\n", + (void*)_ptr, _size, (void*)_Array._ptr, _Array._size); + _size = _Array.Size() + 1; + } + +#endif + + if(_size != _Array.Size()) + _Alloc(_Array.Size()); + + for(int i = 0; i < 4; i++) + _dim[ i ] = _Array._dim[ i ]; + + for(size_type i(0); i < _size; i++) + _ptr[ i ] = _Array._ptr[ i ]; + } + + void GetDimensions(size_type _4dim[]) const + { + _4dim[0] = _dim[0]; + _4dim[1] = _dim[1]; + _4dim[2] = _dim[2]; + _4dim[3] = _dim[3]; + } + + void Clear() + { + Resize(0); + } + + +protected: + + void _Alloc(size_type size) + { + +#ifdef _DEBUGZCARRAY + al_trace("Memory to allocate: %i\n", size); +#endif + + if(_ptr) + _Delete(); + + if(size == 0) + { + al_trace("Tried to allocate zero sized array\n"); +#ifdef _DEBUGZCARRAY + throw("Cannot allocate a zero sized array."); +#else + size = 1; +#endif + } + + _ptr = new type[ size ]; + _size = size; + } + + void _ReAssign(const size_type _OldSize, const size_type _NewSize) + { + pointer _oldPtr = _ptr; + _ptr = new type[ _NewSize ]; + + const size_type _copyRange = (_OldSize < _NewSize ? _OldSize : _NewSize); + + for(size_type i(0); i < _copyRange; i++) + _ptr[ i ] = _oldPtr[ i ]; + + _Delete(_oldPtr); + _size = _NewSize; + } + + void _Delete() + { + if(_ptr) + delete [] _ptr; + + _ptr = NULL; + + _size = 0; + } + + void _Delete(pointer _Ptr) + { + if(_Ptr) + delete [] _Ptr; + + _Ptr = NULL; + } + + void _SetDimensions(size_type _Z, size_type _Y, size_type _X) + { + _dim[0] = _X; + _dim[1] = _Y; + _dim[2] = _Z; + _dim[3] = (_X * _Y); + + _size = _GetSize(_X, _Y, _Z); + } + + size_type _GetSize(size_type _Z, size_type _Y, size_type _X) const + { + if(_Z > 0) + return (_X * _Y * _Z); + else if(_Y > 0) + return (_X * _Y); + + return (_X); + } + + void _BoundsExp(size_type _X) + { + if(_X >= _size) + { + al_trace("Array indices out of range.\n"); + throw("Array indices out of range."); + } + } + + void _BoundsExp(size_type _X, size_type _Y) const + { + if(Offset(_Y, _X) >= _size) + { + al_trace("Array indices out of range.\n"); + throw("Array indices out of range."); + } + } + + void _BoundsExp(size_type _X, size_type _Y, size_type _Z) const + { + if(Offset(_Z, _Y, _X) >= _size) + { + al_trace("Array indices out of range.\n"); + throw("Array indices out of range."); + } + } + + bool _Bounds(size_type _X) + { + if(_X >= _size) + { + al_trace("Array index (%i) out of range (%i).\n", _X, _size); + return false; + } + + return true; + } + + bool _Bounds(size_type _X, size_type _Y) const + { + if(Offset(_Y, _X) >= _size) + { + al_trace("Array indices out of range.\n"); + return false; + } + + return true; + } + + bool _Bounds(size_type _X, size_type _Y, size_type _Z) const + { + if(Offset(_Z, _Y, _X) >= _size) + { + al_trace("Array indices out of range.\n"); + return false; + } + + return true; + } + +private: + pointer _ptr; + size_type _size; + size_type _dim[ 4 ]; + +}; + +#endif + diff --git a/src/zc_custom.cpp b/src/zc_custom.cpp new file mode 100644 index 0000000000..a28bfc0573 --- /dev/null +++ b/src/zc_custom.cpp @@ -0,0 +1,573 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zc_custom.cc +// +// Custom item, enemy, etc. for Zelda. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include "zc_custom.h" +#include "zelda.h" +#include "zdefs.h" + +//extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; + +int old_floatspr, old_slashspr, linkspr; +int walkspr[4][3]; //dir, tile/flip/extend +int stabspr[4][3]; //dir, tile/flip/extend +int slashspr[4][3]; //dir, tile/flip/extend +int floatspr[4][3]; //dir, tile/flip/extend +int swimspr[4][3]; //dir, tile/flip/extend +int divespr[4][3]; //dir, tile/flip/extend +int poundspr[4][3]; //dir, tile/flip/extend +int jumpspr[4][3]; //dir, tile/flip/extend +int chargespr[4][3]; //dir, tile/flip/extend +int castingspr[3]; // tile/flip/extend +int holdspr[2][2][3]; // land/water, hands. tile/flip/extend +//int fallspr[3]; // tile/flip/extend + +void linktile(int *tile, int *flip, int *extend, int state, int dir, int style) +{ + switch(state) + { + case ls_float: + *extend=floatspr[dir][spr_extend]; + break; + + case ls_swim: + *extend=swimspr[dir][spr_extend]; + break; + + case ls_dive: + *extend=divespr[dir][spr_extend]; + break; + + case ls_slash: + *extend=slashspr[dir][spr_extend]; + break; + + case ls_walk: + *extend=walkspr[dir][spr_extend]; + break; + + case ls_jump: + *extend=jumpspr[dir][spr_extend]; + break; + + case ls_charge: + *extend=chargespr[dir][spr_extend]; + break; + + case ls_stab: + *extend=stabspr[dir][spr_extend]; + break; + + case ls_pound: + *extend=poundspr[dir][spr_extend]; + break; + + case ls_cast: + *extend=castingspr[spr_extend]; + break; + + case ls_landhold1: + *extend=holdspr[spr_landhold][spr_hold1][spr_extend]; + break; + + case ls_landhold2: + *extend=holdspr[spr_landhold][spr_hold2][spr_extend]; + break; + + case ls_waterhold1: + *extend=holdspr[spr_waterhold][spr_hold1][spr_extend]; + break; + + case ls_waterhold2: + *extend=holdspr[spr_waterhold][spr_hold2][spr_extend]; + break; + + default: + *tile=0; + *flip=0; + *extend=0; + return; + } + + linktile(tile, flip, state, dir, style); +} +void setlinktile(int tile, int flip, int extend, int state, int dir) +{ + switch(state) + { + case ls_float: + floatspr[dir][spr_tile] = tile; + floatspr[dir][spr_flip] = flip; + floatspr[dir][spr_extend] = extend; + break; + + case ls_swim: + swimspr[dir][spr_tile] = tile; + swimspr[dir][spr_flip] = flip; + swimspr[dir][spr_extend] = extend; + break; + + case ls_dive: + divespr[dir][spr_tile] = tile; + divespr[dir][spr_flip] = flip; + divespr[dir][spr_extend] = extend; + break; + + case ls_slash: + slashspr[dir][spr_tile] = tile; + slashspr[dir][spr_flip] = flip; + slashspr[dir][spr_extend] = extend; + break; + + case ls_walk: + walkspr[dir][spr_tile] = tile; + walkspr[dir][spr_flip] = flip; + walkspr[dir][spr_extend] = extend; + break; + + case ls_stab: + stabspr[dir][spr_tile] = tile; + stabspr[dir][spr_flip] = flip; + stabspr[dir][spr_extend] = extend; + break; + + case ls_pound: + poundspr[dir][spr_tile] = tile; + poundspr[dir][spr_flip] = flip; + poundspr[dir][spr_extend] = extend; + break; + + case ls_jump: + jumpspr[dir][spr_tile] = tile; + jumpspr[dir][spr_flip] = flip; + jumpspr[dir][spr_extend] = extend; + break; + + case ls_charge: + chargespr[dir][spr_tile] = tile; + chargespr[dir][spr_flip] = flip; + chargespr[dir][spr_extend] = extend; + break; + + case ls_cast: + castingspr[spr_tile] = tile; + castingspr[spr_flip] = flip; + castingspr[spr_extend] = extend; + break; + + case ls_landhold1: + holdspr[spr_landhold][spr_hold1][spr_tile] = tile; + holdspr[spr_landhold][spr_hold1][spr_flip] = flip; + holdspr[spr_landhold][spr_hold1][spr_extend] = extend; + break; + + case ls_landhold2: + holdspr[spr_landhold][spr_hold2][spr_tile] = tile; + holdspr[spr_landhold][spr_hold2][spr_flip] = flip; + holdspr[spr_landhold][spr_hold2][spr_extend] = extend; + break; + + case ls_waterhold1: + holdspr[spr_waterhold][spr_hold1][spr_tile] = tile; + holdspr[spr_waterhold][spr_hold1][spr_flip] = flip; + holdspr[spr_waterhold][spr_hold1][spr_extend] = extend; + break; + + case ls_waterhold2: + holdspr[spr_waterhold][spr_hold2][spr_tile] = tile; + holdspr[spr_waterhold][spr_hold2][spr_flip] = flip; + holdspr[spr_waterhold][spr_hold2][spr_extend] = extend; + break; + + default: + break; + } +} + +void linktile(int *tile, int *flip, int state, int dir, int) +{ + switch(state) + { + case ls_float: + *tile=floatspr[dir][spr_tile]; + *flip=floatspr[dir][spr_flip]; + break; + + case ls_swim: + *tile=swimspr[dir][spr_tile]; + *flip=swimspr[dir][spr_flip]; + break; + + case ls_dive: + *tile=divespr[dir][spr_tile]; + *flip=divespr[dir][spr_flip]; + break; + + case ls_slash: + *tile=slashspr[dir][spr_tile]; + *flip=slashspr[dir][spr_flip]; + break; + + case ls_walk: + *tile=walkspr[dir][spr_tile]; + *flip=walkspr[dir][spr_flip]; + break; + + case ls_stab: + *tile=stabspr[dir][spr_tile]; + *flip=stabspr[dir][spr_flip]; + break; + + case ls_pound: + *tile=poundspr[dir][spr_tile]; + *flip=poundspr[dir][spr_flip]; + break; + + case ls_jump: + *tile=jumpspr[dir][spr_tile]; + *flip=jumpspr[dir][spr_flip]; + break; + + case ls_charge: + *tile=chargespr[dir][spr_tile]; + *flip=chargespr[dir][spr_flip]; + break; + + case ls_cast: + *tile=castingspr[spr_tile]; + *flip=castingspr[spr_flip]; + break; + + case ls_landhold1: + *tile=holdspr[spr_landhold][spr_hold1][spr_tile]; + *flip=holdspr[spr_landhold][spr_hold1][spr_flip]; + break; + + case ls_landhold2: + *tile=holdspr[spr_landhold][spr_hold2][spr_tile]; + *flip=holdspr[spr_landhold][spr_hold2][spr_flip]; + break; + + case ls_waterhold1: + *tile=holdspr[spr_waterhold][spr_hold1][spr_tile]; + *flip=holdspr[spr_waterhold][spr_hold1][spr_flip]; + break; + + case ls_waterhold2: + *tile=holdspr[spr_waterhold][spr_hold2][spr_tile]; + *flip=holdspr[spr_waterhold][spr_hold2][spr_flip]; + break; + + default: + *tile=0; + *flip=0; + break; + } +} + +void setuplinktiles(int style) +{ + old_floatspr = wpnsbuf[iwSwim].tile; + old_slashspr = wpnsbuf[iwLinkSlash].tile; + linkspr = 4; + + switch(style) + { + case 0: //normal + walkspr[up][spr_tile]=linkspr+20; + walkspr[up][spr_flip]=0; + walkspr[up][spr_extend]=0; + walkspr[down][spr_tile]=linkspr+18; + walkspr[down][spr_flip]=0; + walkspr[down][spr_extend]=0; + walkspr[left][spr_tile]=linkspr+16; + walkspr[left][spr_flip]=1; + walkspr[left][spr_extend]=0; + walkspr[right][spr_tile]=linkspr+16; + walkspr[right][spr_flip]=0; + walkspr[right][spr_extend]=0; + + stabspr[up][spr_tile]=linkspr+23; + stabspr[up][spr_flip]=0; + stabspr[up][spr_extend]=0; + stabspr[down][spr_tile]=linkspr+22; + stabspr[down][spr_flip]=0; + stabspr[down][spr_extend]=0; + stabspr[left][spr_tile]=linkspr+21; + stabspr[left][spr_flip]=1; + stabspr[left][spr_extend]=0; + stabspr[right][spr_tile]=linkspr+21; + stabspr[right][spr_flip]=0; + stabspr[right][spr_extend]=0; + + slashspr[up][spr_tile]=old_slashspr; + slashspr[up][spr_flip]=0; + slashspr[up][spr_extend]=0; + slashspr[down][spr_tile]=old_slashspr+1; + slashspr[down][spr_flip]=0; + slashspr[down][spr_extend]=0; + slashspr[left][spr_tile]=old_slashspr+2; + slashspr[left][spr_flip]=0; + slashspr[left][spr_extend]=0; + slashspr[right][spr_tile]=old_slashspr+3; + slashspr[right][spr_flip]=0; + slashspr[right][spr_extend]=0; + + floatspr[up][spr_tile]=old_floatspr + 4; + floatspr[up][spr_flip]=0; + floatspr[up][spr_extend]=0; + floatspr[down][spr_tile]=old_floatspr + 2; + floatspr[down][spr_flip]=0; + floatspr[down][spr_extend]=0; + floatspr[left][spr_tile]=old_floatspr; + floatspr[left][spr_flip]=1; + floatspr[left][spr_extend]=0; + floatspr[right][spr_tile]=old_floatspr; + floatspr[right][spr_flip]=0; + floatspr[right][spr_extend]=0; + + swimspr[up][spr_tile]=old_floatspr + 4; + swimspr[up][spr_flip]=0; + swimspr[up][spr_extend]=0; + swimspr[down][spr_tile]=old_floatspr + 2; + swimspr[down][spr_flip]=0; + swimspr[down][spr_extend]=0; + swimspr[left][spr_tile]=old_floatspr; + swimspr[left][spr_flip]=1; + swimspr[left][spr_extend]=0; + swimspr[right][spr_tile]=old_floatspr; + swimspr[right][spr_flip]=0; + swimspr[right][spr_extend]=0; + + divespr[up][spr_tile]=old_floatspr + 8; + divespr[up][spr_flip]=0; + divespr[up][spr_extend]=0; + divespr[down][spr_tile]=old_floatspr + 8; + divespr[down][spr_flip]=0; + divespr[down][spr_extend]=0; + divespr[left][spr_tile]=old_floatspr + 8; + divespr[left][spr_flip]=0; + divespr[left][spr_extend]=0; + divespr[right][spr_tile]=old_floatspr + 8; + divespr[right][spr_flip]=0; + divespr[right][spr_extend]=0; + + poundspr[up][spr_tile]=linkspr+3; + poundspr[up][spr_flip]=0; + poundspr[up][spr_extend]=0; + poundspr[down][spr_tile]=linkspr+2; + poundspr[down][spr_flip]=0; + poundspr[down][spr_extend]=0; + poundspr[left][spr_tile]=linkspr+1; + poundspr[left][spr_flip]=1; + poundspr[left][spr_extend]=0; + poundspr[right][spr_tile]=linkspr+1; + poundspr[right][spr_flip]=0; + poundspr[right][spr_extend]=0; + +// Alter these when default sprites are created. + jumpspr[up][spr_tile]=linkspr+24; + jumpspr[up][spr_flip]=0; + jumpspr[up][spr_extend]=0; + jumpspr[down][spr_tile]=linkspr+19; + jumpspr[down][spr_flip]=0; + jumpspr[down][spr_extend]=0; + jumpspr[left][spr_tile]=linkspr+16; + jumpspr[left][spr_flip]=1; + jumpspr[left][spr_extend]=0; + jumpspr[right][spr_tile]=linkspr+16; + jumpspr[right][spr_flip]=0; + jumpspr[right][spr_extend]=0; + +// Alter these when default sprites are created. + chargespr[up][spr_tile]=linkspr+24; + chargespr[up][spr_flip]=0; + chargespr[up][spr_extend]=0; + chargespr[down][spr_tile]=linkspr+19; + chargespr[down][spr_flip]=0; + chargespr[down][spr_extend]=0; + chargespr[left][spr_tile]=linkspr+16; + chargespr[left][spr_flip]=1; + chargespr[left][spr_extend]=0; + chargespr[right][spr_tile]=linkspr+16; + chargespr[right][spr_flip]=0; + chargespr[right][spr_extend]=0; + + castingspr[spr_tile]=linkspr; + castingspr[spr_flip]=0; + castingspr[spr_extend]=0; + + holdspr[spr_landhold][spr_hold1][spr_tile]=linkspr+30; + holdspr[spr_landhold][spr_hold1][spr_flip]=0; + holdspr[spr_landhold][spr_hold1][spr_extend]=0; + holdspr[spr_landhold][spr_hold2][spr_tile]=linkspr+25; + holdspr[spr_landhold][spr_hold2][spr_flip]=0; + holdspr[spr_landhold][spr_hold2][spr_extend]=0; + + holdspr[spr_waterhold][spr_hold1][spr_tile]=old_floatspr+7; + holdspr[spr_waterhold][spr_hold1][spr_flip]=0; + holdspr[spr_waterhold][spr_hold1][spr_extend]=0; + holdspr[spr_waterhold][spr_hold2][spr_tile]=old_floatspr+6; + holdspr[spr_waterhold][spr_hold2][spr_flip]=0; + holdspr[spr_waterhold][spr_hold2][spr_extend]=0; + break; + + case 1: //BS + walkspr[up][spr_tile]=linkspr+24; + walkspr[up][spr_flip]=0; + walkspr[up][spr_extend]=0; + walkspr[down][spr_tile]=linkspr+19; + walkspr[down][spr_flip]=0; + walkspr[down][spr_extend]=0; + walkspr[left][spr_tile]=linkspr+16; + walkspr[left][spr_flip]=1; + walkspr[left][spr_extend]=0; + walkspr[right][spr_tile]=linkspr+16; + walkspr[right][spr_flip]=0; + walkspr[right][spr_extend]=0; + + stabspr[up][spr_tile]=linkspr+27; + stabspr[up][spr_flip]=0; + stabspr[up][spr_extend]=0; + stabspr[down][spr_tile]=linkspr+23; + stabspr[down][spr_flip]=0; + stabspr[down][spr_extend]=0; + stabspr[left][spr_tile]=linkspr+22; + stabspr[left][spr_flip]=1; + stabspr[left][spr_extend]=0; + stabspr[right][spr_tile]=linkspr+22; + stabspr[right][spr_flip]=0; + stabspr[right][spr_extend]=0; + + slashspr[up][spr_tile]=old_slashspr; + slashspr[up][spr_flip]=0; + slashspr[up][spr_extend]=0; + slashspr[down][spr_tile]=old_slashspr+1; + slashspr[down][spr_flip]=0; + slashspr[down][spr_extend]=0; + slashspr[left][spr_tile]=old_slashspr+2; + slashspr[left][spr_flip]=0; + slashspr[left][spr_extend]=0; + slashspr[right][spr_tile]=old_slashspr+3; + slashspr[right][spr_flip]=0; + slashspr[right][spr_extend]=0; + + floatspr[up][spr_tile]=old_floatspr+6; + floatspr[up][spr_flip]=0; + floatspr[up][spr_extend]=0; + floatspr[down][spr_tile]=old_floatspr+3; + floatspr[down][spr_flip]=0; + floatspr[down][spr_extend]=0; + floatspr[left][spr_tile]=old_floatspr; + floatspr[left][spr_flip]=1; + floatspr[left][spr_extend]=0; + floatspr[right][spr_tile]=old_floatspr; + floatspr[right][spr_flip]=0; + floatspr[right][spr_extend]=0; + + swimspr[up][spr_tile]=old_floatspr+6; + swimspr[up][spr_flip]=0; + swimspr[up][spr_extend]=0; + swimspr[down][spr_tile]=old_floatspr+3; + swimspr[down][spr_flip]=0; + swimspr[down][spr_extend]=0; + swimspr[left][spr_tile]=old_floatspr; + swimspr[left][spr_flip]=1; + swimspr[left][spr_extend]=0; + swimspr[right][spr_tile]=old_floatspr; + swimspr[right][spr_flip]=0; + swimspr[right][spr_extend]=0; + + divespr[up][spr_tile]=old_floatspr + 11; + divespr[up][spr_flip]=0; + divespr[up][spr_extend]=0; + divespr[down][spr_tile]=old_floatspr + 11; + divespr[down][spr_flip]=0; + divespr[down][spr_extend]=0; + divespr[left][spr_tile]=old_floatspr + 11; + divespr[left][spr_flip]=0; + divespr[left][spr_extend]=0; + divespr[right][spr_tile]=old_floatspr + 11; + divespr[right][spr_flip]=0; + divespr[right][spr_extend]=0; + + poundspr[up][spr_tile]=linkspr+3; + poundspr[up][spr_flip]=0; + poundspr[up][spr_extend]=0; + poundspr[down][spr_tile]=linkspr+2; + poundspr[down][spr_flip]=0; + poundspr[down][spr_extend]=0; + poundspr[left][spr_tile]=linkspr+1; + poundspr[left][spr_flip]=1; + poundspr[left][spr_extend]=0; + poundspr[right][spr_tile]=linkspr+1; + poundspr[right][spr_flip]=0; + poundspr[right][spr_extend]=0; + +// Alter these when default sprites are created. + jumpspr[up][spr_tile]=linkspr+24; + jumpspr[up][spr_flip]=0; + jumpspr[up][spr_extend]=0; + jumpspr[down][spr_tile]=linkspr+19; + jumpspr[down][spr_flip]=0; + jumpspr[down][spr_extend]=0; + jumpspr[left][spr_tile]=linkspr+16; + jumpspr[left][spr_flip]=1; + jumpspr[left][spr_extend]=0; + jumpspr[right][spr_tile]=linkspr+16; + jumpspr[right][spr_flip]=0; + jumpspr[right][spr_extend]=0; + +// Alter these when default sprites are created. + chargespr[up][spr_tile]=linkspr+24; + chargespr[up][spr_flip]=0; + chargespr[up][spr_extend]=0; + chargespr[down][spr_tile]=linkspr+19; + chargespr[down][spr_flip]=0; + chargespr[down][spr_extend]=0; + chargespr[left][spr_tile]=linkspr+16; + chargespr[left][spr_flip]=1; + chargespr[left][spr_extend]=0; + chargespr[right][spr_tile]=linkspr+16; + chargespr[right][spr_flip]=0; + chargespr[right][spr_extend]=0; + + castingspr[spr_tile]=linkspr; + castingspr[spr_flip]=0; + castingspr[spr_extend]=0; + + holdspr[spr_landhold][spr_hold1][spr_tile]=linkspr+29; + holdspr[spr_landhold][spr_hold1][spr_flip]=0; + holdspr[spr_landhold][spr_hold1][spr_extend]=0; + holdspr[spr_landhold][spr_hold2][spr_tile]=linkspr+28; + holdspr[spr_landhold][spr_hold2][spr_flip]=0; + holdspr[spr_landhold][spr_hold2][spr_extend]=0; + + holdspr[spr_waterhold][spr_hold1][spr_tile]=old_floatspr+10; + holdspr[spr_waterhold][spr_hold1][spr_flip]=0; + holdspr[spr_waterhold][spr_hold1][spr_extend]=0; + holdspr[spr_waterhold][spr_hold2][spr_tile]=old_floatspr+9; + holdspr[spr_waterhold][spr_hold2][spr_flip]=0; + holdspr[spr_waterhold][spr_hold2][spr_extend]=0; + break; + + default: + break; + } +} diff --git a/src/zc_custom.h b/src/zc_custom.h new file mode 100644 index 0000000000..647855f2bd --- /dev/null +++ b/src/zc_custom.h @@ -0,0 +1,44 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zc_custom.cc +// +// Custom item, enemy, etc. for Zelda. +// +//-------------------------------------------------------- + +#ifndef _ZC_CUSTOM_H_ +#define _ZC_CUSTOM_H_ + +enum +{ + ls_walk, ls_slash, ls_stab, ls_pound, ls_float, ls_dive, + ls_landhold1, ls_landhold2, ls_waterhold1, ls_waterhold2, ls_cast, + ls_swim, ls_jump, ls_charge, ls_max +}; +enum {spr_tile, spr_flip, spr_extend}; +//enum {cst_tile, cst_extend}; +enum {spr_landhold, spr_waterhold}; +enum {spr_hold1, spr_hold2}; +enum { las_original, las_bszelda, las_zelda3, las_zelda3slow, las_max }; + +extern int old_floatspr, old_slashspr, linkspr; +extern int walkspr[4][3]; //dir, tile/flip/extend +extern int stabspr[4][3]; //dir, tile/flip/extend +extern int slashspr[4][3]; //dir, tile/flip/extend +extern int floatspr[4][3]; //dir, tile/flip/extend +extern int swimspr[4][3]; //dir, tile/flip/extend +extern int divespr[4][3]; //dir, tile/flip/extend +extern int poundspr[4][3]; //dir, tile/flip/extend +extern int jumpspr[4][3]; //dir, tile/flip/extend +extern int chargespr[4][3]; //dir, tile/flip/extend +extern int castingspr[3]; // tile/flip/extend +extern int holdspr[2][2][3]; // land/water, hands. tile/flip/extend + +void linktile(int *tile, int *flip, int state, int dir, int style); +void linktile(int *tile, int *flip, int *extend, int state, int dir, int style); +void setuplinktiles(int style); +void setlinktile(int tile, int flip, int extend, int state, int dir); +#endif + diff --git a/src/zc_init.cpp b/src/zc_init.cpp new file mode 100644 index 0000000000..b117192cca --- /dev/null +++ b/src/zc_init.cpp @@ -0,0 +1,141 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +/* + #include "zq_custom.h" + */ +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "gui.h" +#include "init.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "jwin.h" +#include "zq_init.h" +#include "zsys.h" +#include "zquest.h" +#include "gamedata.h" +#include "link.h" +#include "zelda.h" +#include "zc_init.h" + +int onCheatConsole() +{ + char init_title[80]; + sprintf(init_title, "Current Data"); + init_dlg[0].dp=init_title; + zinitdata *zinit2 = copyIntoZinit(game); + //modify some entries + init_dlg[1655].dp = (void *)""; + init_dlg[1658].dp = (void *)"Current HP (hearts):"; + init_dlg[1658].flags |= D_DISABLED; + init_dlg[1659].flags |= D_DISABLED; + init_dlg[1663].flags |= D_DISABLED; + init_dlg[1664].flags |= D_DISABLED; + init_dlg[1664].dp = (void *)""; + init_dlg[1670].flags |= D_DISABLED; + init_dlg[1671].flags |= D_DISABLED; + init_dlg[1667].flags |= D_DISABLED; + init_dlg[1698].flags |= D_DISABLED; + init_dlg[1699].flags |= D_DISABLED; + init_dlg[1703].flags |= D_DISABLED; + init_dlg[1704].flags |= D_DISABLED; + init_dlg[1705].flags |= D_DISABLED; +// the following statement has no effect, as the D_DISABLED flag is ignored by the jwin_tab_proc +// init_tabs[4].flags |= D_DISABLED; + int rval = doInit(zinit2); + resetItems(game, zinit2, false); + delete zinit2; + ringcolor(false); + return rval; +} + + +void center_zc_init_dialog() +{ + jwin_center_dialog(init_dlg); +} + +void onInitOK() +{ +} + +// copyIntoZinit: worst kludge in all of ZC history? I've seen worse. ;) -Gleeok +zinitdata *copyIntoZinit(gamedata *gdata) +{ + zinitdata *zinit2 = new zinitdata; + //populate it + zinit2->gravity=zinit.gravity; + zinit2->terminalv=zinit.terminalv; + zinit2->jump_link_layer_threshold=zinit.jump_link_layer_threshold; + zinit2->hc = gdata->get_maxlife()/HP_PER_HEART; + zinit2->bombs = gdata->get_bombs(); + zinit2->keys = gdata->get_keys(); + zinit2->max_bombs = gdata->get_maxbombs(); + zinit2->super_bombs = gdata->get_sbombs(); + zinit2->bomb_ratio = zinit.bomb_ratio; + zinit2->hcp = gdata->get_HCpieces(); + zinit2->rupies = gdata->get_rupies(); + + for(int i=0; imap, i, (gdata->lvlitems[i] & liMAP) ? 1 : 0); + set_bit(zinit2->compass, i, (gdata->lvlitems[i] & liCOMPASS) ? 1 : 0); + set_bit(zinit2->boss_key, i, (gdata->lvlitems[i] & liBOSSKEY) ? 1 : 0); + zinit2->level_keys[i] = gdata->lvlkeys[i]; + } + + for(int i=0; i<8; i++) + { + set_bit(&zinit2->triforce,i,(gdata->lvlitems[i+1]&liTRIFORCE) ? 1 : 0); + } + + zinit2->max_magic = gdata->get_maxmagic(); + zinit2->magic = gdata->get_magic(); + + int drain = vbound(2-gdata->get_magicdrainrate(), 0, 1); + set_bit(zinit2->misc, idM_DOUBLEMAGIC, drain); + set_bit(zinit2->misc, idM_CANSLASH, gdata->get_canslash()); + + zinit2->arrows = gdata->get_arrows(); + zinit2->max_arrows = gdata->get_maxarrows(); + + zinit2->max_rupees = gdata->get_maxcounter(1); + zinit2->max_keys = gdata->get_maxcounter(5); + + zinit2->start_heart = gdata->get_life()/HP_PER_HEART; + zinit2->cont_heart = gdata->get_cont_hearts(); + zinit2->hcp_per_hc = gdata->get_hcp_per_hc(); + set_bit(zinit2->misc,idM_CONTPERCENT,gdata->get_cont_percent() ? 1 : 0); + + //now set up the items! + for(int i=0; iitems[i] = gdata->get_item(i); + } + + return zinit2; +} + +void resetItems(gamedata *gamed) +{ + zinitdata *z = copyIntoZinit(gamed); + resetItems(gamed, z, false); + delete z; +} + diff --git a/src/zc_init.h b/src/zc_init.h new file mode 100644 index 0000000000..6d0622764f --- /dev/null +++ b/src/zc_init.h @@ -0,0 +1,19 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- + +#ifndef _ZC_INIT_H_ +#define _ZC_INIT_H_ + +int onCheatConsole(); +void center_zc_init_dialog(); +zinitdata *copyIntoZinit(gamedata *src); +void resetItems(gamedata *game); +#endif + diff --git a/src/zc_items.cpp b/src/zc_items.cpp new file mode 100644 index 0000000000..cccfb1a878 --- /dev/null +++ b/src/zc_items.cpp @@ -0,0 +1,204 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------+ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +/**********************************/ +/********** Item Class **********/ +/**********************************/ + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first +#include "items.h" + +#include "guys.h" +#include "link.h" +#include "maps.h" +#include "zdefs.h" +#include "zelda.h" +#include "zc_sys.h" +#include + +extern sprite_list guys; +extern sprite_list items; + + +inline bool hasEnoughHearts(int id) +{ + return game->get_maxlife()>=itemsbuf[id].pickup_hearts*HP_PER_HEART; +} + +bool item::canPickUp(LinkClass* link) +{ + if((pickup&ipTIMER)!=0 && clk2<32 && id!=iFairyMoving) + // Recently dropped non-fairy; still flashing + return false; + + if((pickup&ipENEMY)!=0) // item was being carried by enemy + if(more_carried_items()<=1) // I don't know what's going on here... + hasitem&=~2; + + if((pickup&ipDUMMY)!=0) // Dummy item; can't be picked up + { + // But it may still do something. + // This should be moved, but it'll have to wait... + if((pickup&ipMONEY)!=0) + { + // if(onGetDummyMoney) + // onGetDummyMoney(); + } + + return false; + } + + const itemdata& data=itemsbuf[id]; + + if(data.pickup_hearts>0) + { + if((get_bit(quest_rules,qr_HEARTSREQUIREDFIX) || (pickup&ipSPECIAL)) && + !hasEnoughHearts(id)) + return false; + } + + if(game->get_spendable_rupies()data.fam_type) + { + if(nextItem==-1 || + itemsbuf[i].fam_type<=itemsbuf[nextItem].fam_type) + nextItem=i; + } + } + } + + return nextItem; +} + +bool addfairy(fix x, fix y, int misc3, int id) +{ + addenemy(x,y,eITEMFAIRY,id); + ((enemy*)guys.spr(guys.Count()-1))->dstep=misc3; + ((enemy*)guys.spr(guys.Count()-1))->step=(misc3/100.0); + movefairy(x,y,id); + return true; +} + +bool can_drop(fix x, fix y) +{ + return !_walkflag(x,y+16,0); +} + +int select_dropitem(int item_set, int x, int y) +{ + int total_chance=0; + + for(int k=0; k<11; ++k) + { + int current_chance=item_drop_sets[item_set].chance[k]; + + if(k>0) + { + int current_item=item_drop_sets[item_set].item[k-1]; + + if((!get_bit(quest_rules,qr_ENABLEMAGIC)||(game->get_maxmagic()<=0))&&(itemsbuf[current_item].family == itype_magic)) + { + current_chance=0; + } + + if((!get_bit(quest_rules,qr_TRUEARROWS))&&(itemsbuf[current_item].family == itype_arrowammo)) + { + current_chance=0; + } + } + + total_chance+=current_chance; + } + + if(total_chance==0) + return -1; + + int item_chance=(rand()%total_chance)+1; + + int drop_item=-1; + + for(int k=10; k>=0; --k) + { + + int current_chance=item_drop_sets[item_set].chance[k]; + int current_item=(k==0 ? -1 : item_drop_sets[item_set].item[k-1]); + + if((!get_bit(quest_rules,qr_ENABLEMAGIC)||(game->get_maxmagic()<=0))&&(current_item>=0&&itemsbuf[current_item].family == itype_magic)) + { + current_chance=0; + } + + if((!get_bit(quest_rules,qr_TRUEARROWS))&&(current_item>=0&&itemsbuf[current_item].family == itype_arrowammo)) + { + current_chance=0; + } + + if(current_chance>0&&item_chance<=current_chance) + { + drop_item=current_item; + break; + } + else + { + item_chance-=current_chance; + } + } + + if(drop_item>=0 && itemsbuf[drop_item].family==itype_fairy) + { + for(int j=0; jid].family==itype_fairy)&&((abs(items.spr(j)->x-x)<32)||(abs(items.spr(j)->y-y)<32))) + { + drop_item=-1; + break; + } + } + } + + return drop_item; +} + +bool is_side_view() +{ + return (tmpscr->flags7&fSIDEVIEW)!=0; +} +/*** end of sprite.cc ***/ + diff --git a/src/zc_malloc.h b/src/zc_malloc.h new file mode 100644 index 0000000000..f212479ecb --- /dev/null +++ b/src/zc_malloc.h @@ -0,0 +1,44 @@ + +#pragma once + +#ifndef _zc_malloc_h +#define _zc_malloc_h + +#include +#include + +// This should catch the following: +// -double deletions, +// -calls to free on unallocated memory, +// -memory leaks from malloc calls. +// -unanswered prayers to babylonian gods. + + +#define ZC_DEBUG_MALLOC_ENABLED 0 + + +#if defined(NDEBUG) && (ZC_DEBUG_MALLOC_ENABLED) +#define ZC_MALLOC_ALWAYS_ASSERT(x) assert(x), __zc_always_assert(x, #x, __FILE__, __LINE__) +#else +#define ZC_MALLOC_ALWAYS_ASSERT(x) assert(x) +#endif + + +extern void *__zc_debug_malloc(size_t numBytes, const char* file, int line); +extern void __zc_debug_free(void* p, const char* file, int line); +extern void __zc_debug_malloc_free_print_memory_leaks(); + +#if (ZC_DEBUG_MALLOC_ENABLED != 0) +#define zc_malloc(x) __zc_debug_malloc(x, __FILE__, __LINE__) +#define zc_free(x) __zc_debug_free(x, __FILE__, __LINE__) +#else +#define zc_malloc malloc +#define zc_free free +#endif + + +void __zc_always_assert(bool e, const char* expression, const char* file, int line); + +#endif + + diff --git a/src/zc_math.h b/src/zc_math.h new file mode 100644 index 0000000000..a877fe7c3d --- /dev/null +++ b/src/zc_math.h @@ -0,0 +1,90 @@ +#ifndef __zc_math_h_ +#define __zc_math_h_ + +#include + +namespace zc +{ + + +namespace math +{ + + +inline bool IsPowerOfTwo(unsigned int x) +{ + return (x != 0 && !((x-1) & x)); +} + +inline unsigned int NextPowerOfTwo(unsigned int x) +{ + unsigned int y(1); + + while(y < x) y <<= 1; + + return y; +} + +inline float ToDegrees(float radians) +{ + return (radians * 57.29578f); +} + +inline float ToRadians(float degrees) +{ + return (degrees * 0.0174533f); +} + +inline float Round(float x) +{ + return floorf(x + 0.5f); +} + +inline float Lerp(float a, float b, float t) +{ + return (a + (b - a) * t); +} + +inline float CalculateBezier(const float p1, const float t1, const float p2, float t) +{ + const float a = 1.0f - t; + const float A = a * a; + const float B = 2.0f * a * t; + const float C = t * t; + + return ((p1 * A) + (t1 * B) + (p2 * C)); +} + +inline float CalculateBezier(const float p1, const float t1, const float t2, const float p2, float t) +{ + const float a = 1.0f - t; + const float A = a * a * a; + const float B = 3.0f * a * a * t; + const float C = 3.0f * a * t * t; + const float D = t * t * t; + + return ((p1 * A) + (t1 * B) + (t2 * C) + (p2 * D)); +} + +inline float CalculateBezier(const float p1, const float t1, const float t2, const float t3, const float p2, float t) +{ + const float a = 1.0f - t, b = a * a, c = t * t, d = (1.0f - t) * t; + const float A = b * b; + const float B = 4.0f * b * d; + const float C = 6.0f * b * c; + const float D = 4.0f * d * c; + const float E = c * c; + + return ((p1 * A) + (t1 * B) + (t2 * C) + (t3 * D) + (p2 * E)); +} + + + + + +} //namespace math + + +} //namespace zc + +#endif diff --git a/src/zc_sprite.cpp b/src/zc_sprite.cpp new file mode 100644 index 0000000000..a18a9d006e --- /dev/null +++ b/src/zc_sprite.cpp @@ -0,0 +1,257 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "sprite.h" +#include "zelda.h" +#include "maps.h" +#include "tiles.h" +#include "sound.h" + +/* +void sprite::check_conveyor() +{ + if (conveyclk<=0) + { + int ctype=(combobuf[MAPCOMBO(x+8,y+8)].type); + if((ctype>=cOLD_CVUP) && (ctype<=cOLD_CVRIGHT)) + { + switch (ctype-cOLD_CVUP) + { + case up: + if(!_walkflag(x,y+8-2,2)) + { + y=y-2; + } + break; + case down: + if(!_walkflag(x,y+15+2,2)) + { + y=y+2; + } + break; + case left: + if(!_walkflag(x-2,y+8,1)) + { + x=x-2; + } + break; + case right: + if(!_walkflag(x+15+2,y+8,1)) + { + x=x+2; + } + break; + } + } + } +} +*/ + +void sprite::check_conveyor() +{ + int deltax=0; + int deltay=0; + + if(conveyclk<=0 && (z==0 || (tmpscr->flags2&fAIRCOMBOS))) + { + int ctype=(combobuf[MAPCOMBO(x+8,y+8)].type); + deltax=combo_class_buf[ctype].conveyor_x_speed; + deltay=combo_class_buf[ctype].conveyor_y_speed; + + if(deltax!=0||deltay!=0) + { + if(deltay<0&&!_walkflag(x,y+8-2,2)) + { + y=y-abs(deltay); + } + else if(deltay>0&&!_walkflag(x,y+15+2,2)) + { + y=y+abs(deltay); + } + + if(deltax<0&&!_walkflag(x-2,y+8,1)) + { + x=x-abs(deltax); + } + else if(deltax>0&&!_walkflag(x+15+2,y+8,1)) + { + x=x+abs(deltax); + } + } + } +} + +void movingblock::push(fix bx,fix by,int d2,int f) +{ + trigger=false; + endx=x=bx; + endy=y=by; + dir=d2; + oldflag=f; + word *di = &(tmpscr->data[(int(y)&0xF0)+(int(x)>>4)]); + byte *ci = &(tmpscr->cset[(int(y)&0xF0)+(int(x)>>4)]); + // bcombo = ((*di)&0xFF)+(tmpscr->cpage<<8); + bcombo = tmpscr->data[(int(y)&0xF0)+(int(x)>>4)]; + oldcset = tmpscr->cset[(int(y)&0xF0)+(int(x)>>4)]; + cs = (isdungeon() && !get_bit(quest_rules, qr_PUSHBLOCKCSETFIX)) ? 9 : oldcset; + tile = combobuf[bcombo].tile; + flip = combobuf[bcombo].flip; + // cs = ((*di)&0x700)>>8; + *di = tmpscr->undercombo; + *ci = tmpscr->undercset; + putcombo(scrollbuf,x,y,*di,*ci); + clk=32; + blockmoving=true; +} + +bool movingblock::animate(int index) +{ + //these are here to bypass compiler warnings about unused arguments + index=index; + + if(clk<=0) + return false; + + move((fix)0.5); + + if(--clk==0) + { + bool bhole=false; + blockmoving=false; + int f1 = tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]; + int f2 = MAPCOMBOFLAG(x,y); + + tmpscr->data[(int(y)&0xF0)+(int(x)>>4)]=bcombo; + tmpscr->cset[(int(y)&0xF0)+(int(x)>>4)]=oldcset; + + if((f1==mfBLOCKTRIGGER)||f2==mfBLOCKTRIGGER) + { + trigger=true; + tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]=mfPUSHED; + //the above line used to be in the following if statement. + //However, it caused inherent-flag pushblocks to not lock into + //block trigger combos unless the block trigger is also an + //inherent flag + /* + if(f2==mfBLOCKTRIGGER) + { + tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]=mfPUSHED; + } + */ + } + + if((f1==mfBLOCKHOLE)||f2==mfBLOCKHOLE) + { + tmpscr->data[(int(y)&0xF0)+(int(x)>>4)]+=1; + bhole=true; + //tmpscr->cset[(int(y)&0xF0)+(int(x)>>4)]=; + } + + if(bhole) + { + tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]=mfNONE; + } + else + { + f2 = MAPCOMBOFLAG(x,y); + + if(!((f2==mfPUSHUDINS && dir<=down) || + (f2==mfPUSHLRINS && dir>=left) || + (f2==mfPUSHUINS && dir==up) || + (f2==mfPUSHDINS && dir==down) || + (f2==mfPUSHLINS && dir==left) || + (f2==mfPUSHRINS && dir==right) || + (f2==mfPUSH4INS))) + { + tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]=mfPUSHED; + } + } + + if(oldflag>=mfPUSHUDINS&&oldflag&&!trigger&&!bhole) + { + tmpscr->sflag[(int(y)&0xF0)+(int(x)>>4)]=oldflag; + } + + for(int i=0; i<176; i++) + { + if(tmpscr->sflag[i]==mfBLOCKTRIGGER||combobuf[tmpscr->data[i]].flag==mfBLOCKTRIGGER) + { + trigger=false; + } + } + + //triggers a secret + f2 = MAPCOMBOFLAG(x,y); + + if((oldflag==mfPUSH4 || + (oldflag==mfPUSHUD && dir<=down) || + (oldflag==mfPUSHLR && dir>=left) || + (oldflag==mfPUSHU && dir==up) || + (oldflag==mfPUSHD && dir==down) || + (oldflag==mfPUSHL && dir==left) || + (oldflag==mfPUSHR && dir==right) || + f2==mfPUSH4 || + (f2==mfPUSHUD && dir<=down) || + (f2==mfPUSHLR && dir>=left) || + (f2==mfPUSHU && dir==up) || + (f2==mfPUSHD && dir==down) || + (f2==mfPUSHL && dir==left) || + (f2==mfPUSHR && dir==right)) || + trigger) + //if(oldflagsecretsfx); + } + else + { + hidden_entrance(0,true,true); + + if((combobuf[bcombo].type == cPUSH_WAIT) || + (combobuf[bcombo].type == cPUSH_HW) || + (combobuf[bcombo].type == cPUSH_HW2) || trigger) + { + sfx(tmpscr->secretsfx); + } + } + + if(isdungeon() && tmpscr->flags&fSHUTTERS) + { + opendoors=8; + } + + if(!isdungeon()) + { + if(combobuf[bcombo].type==cPUSH_HEAVY || combobuf[bcombo].type==cPUSH_HW + || combobuf[bcombo].type==cPUSH_HEAVY2 || combobuf[bcombo].type==cPUSH_HW2) + { + if(!(tmpscr->flags5&fTEMPSECRETS)) setmapflag(mSECRET); + } + } + } + + putcombo(scrollbuf,x,y,bcombo,cs); + } + + return false; +} + +/*** end of sprite.cc ***/ + diff --git a/src/zc_subscr.cpp b/src/zc_subscr.cpp new file mode 100644 index 0000000000..c6c8ff5885 --- /dev/null +++ b/src/zc_subscr.cpp @@ -0,0 +1,314 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// subscr.cc +// +// Subscreen code for zelda.cc +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "zelda.h" +#include "zc_sys.h" +#include "subscr.h" +#include "zc_subscr.h" +#include "link.h" +#include "gamedata.h" +#include "guys.h" +#include "sound.h" + +extern LinkClass Link; +extern int directItem; +extern int directItemA; +extern int directItemB; + +//DIALOG *sso_properties_dlg; + +void put_active_subscr(miscQdata *misc, int y, int pos) +{ + //Don't call Sitems.animate() - that gets called somewhere else, somehow. -L + animate_selectors(); + bool showtime = game->get_timevalid() && !game->get_cheat() && get_bit(quest_rules,qr_TIME); + show_custom_subscreen(framebuf, misc, current_subscreen_active, 0, 6-y, showtime, pos); +} + +void dosubscr(miscQdata *misc) +{ + PALETTE temppal; + + if(tmpscr->flags3&fNOSUBSCR) + { + return; + } + + if(usebombpal) + { + memcpy(temppal, RAMpal, PAL_SIZE*sizeof(RGB)); + memcpy(RAMpal, tempbombpal, PAL_SIZE*sizeof(RGB)); + refreshpal=true; + } + + int miny; + bool showtime = game->get_timevalid() && !game->get_cheat() && get_bit(quest_rules,qr_TIME); + load_Sitems(misc); + + pause_sfx(WAV_BRANG); + + if(current_item_id(itype_brang)>=0) + pause_sfx(itemsbuf[current_item_id(itype_brang)].usesound); + + if(current_item_id(itype_hookshot)>=0) + pause_sfx(itemsbuf[current_item_id(itype_hookshot)].usesound); + + adjust_sfx(WAV_ER,128,false); + adjust_sfx(WAV_MSG,128,false); + + set_clip_rect(scrollbuf, 0, 0, scrollbuf->w, scrollbuf->h); + set_clip_rect(framebuf, 0, 0, framebuf->w, framebuf->h); + + //make a copy of the blank playing field on the right side of scrollbuf + blit(scrollbuf,scrollbuf,0,playing_field_offset,256,0,256,176); + //make a copy of the complete playing field on the bottom of scrollbuf + blit(framebuf,scrollbuf,0,playing_field_offset,0,176,256,176); + miny = 6; + + //Set the selector to the correct position before bringing up the subscreen -DD + if(get_bit(quest_rules,qr_SELECTAWPN)) + { + if(Bwpn==0 && Awpn!=0) + Bpos = zc_max(game->awpn,0); + else + Bpos = zc_max(game->bwpn,0); + } + else + Bpos = zc_max(game->bwpn,0); + + for(int y=176-2; y>=6; y-=3) + { + do_dcounters(); + Link.refill(); + //fill in the screen with black to prevent the hall of mirrors effect + rectfill(framebuf, 0, 0, 255, 223, 0); + + if(COOLSCROLL) + { + //copy the playing field back onto the screen + blit(scrollbuf,framebuf,0,176,0,passive_subscreen_height,256,176); + } + else + { + //scroll the playing field (copy the copy we made) + blit(scrollbuf,framebuf,256,0,0,176-2-y+passive_subscreen_height,256,y); + } + + //throw the passive subscreen onto the screen + put_passive_subscr(framebuf,misc,0,176-2-y,showtime,sspSCROLLING); + //put the active subscreen above the passive subscreen + put_active_subscr(misc,y,sspSCROLLING); + advanceframe(false); + + if(Quit) + return; + } + + bool done=false; + + do + { + load_control_state(); + int pos = Bpos; + + if(rUp()) Bpos = selectWpn_new(SEL_UP, pos); + else if(rDown()) Bpos = selectWpn_new(SEL_DOWN, pos); + else if(rLeft()) Bpos = selectWpn_new(SEL_LEFT, pos); + else if(rRight()) Bpos = selectWpn_new(SEL_RIGHT, pos); + else if(rLbtn()) Bpos = selectWpn_new(SEL_LEFT, pos); + else if(rRbtn()) Bpos = selectWpn_new(SEL_RIGHT, pos); + + if(get_bit(quest_rules,qr_SELECTAWPN)) + { + if(rBbtn()) + { + if(Awpn == Bweapon(Bpos)) + { + Awpn = Bwpn; + game->awpn = game->bwpn; + directItemA = directItemB; + } + + Bwpn = Bweapon(Bpos); + sfx(WAV_PLACE); + + game->bwpn = Bpos; + directItemB = directItem; + } + else if(rAbtn()) + { + if(Bwpn == Bweapon(Bpos)) + { + Bwpn = Awpn; + game->bwpn = game->awpn; + directItemB = directItemA; + } + + Awpn = Bweapon(Bpos); + sfx(WAV_PLACE); + game->awpn = Bpos; + directItemA = directItem; + } + } + else + { + Bwpn = Bweapon(Bpos); + game->bwpn = Bpos; + directItemB = directItem; + } + + if(pos!=Bpos) + sfx(WAV_CHIME); + + do_dcounters(); + Link.refill(); + + //put_passive_subscr(framebuf,misc,0,174-miny,showtime,true); + //blit(scrollbuf,framebuf,0,6,0,6-miny,256,168); + //put_active_subscr(misc,miny,true); + + //fill in the screen with black to prevent the hall of mirrors effect + rectfill(framebuf, 0, 0, 255, 223, 0); + + if(COOLSCROLL) + { + //copy the playing field back onto the screen + blit(scrollbuf,framebuf,0,176,0,passive_subscreen_height,256,176); + } + else + { + //nothing to do; the playing field has scrolled off the screen + } + + //throw the passive subscreen onto the screen + put_passive_subscr(framebuf,misc,0,176-2-miny,showtime,sspDOWN); + //put the active subscreen above the passive subscreen + put_active_subscr(misc,miny,sspDOWN); + + advanceframe(false); + + if(NESquit && Up() && cAbtn() && cBbtn()) + { + Udown=true; + Quit=qQUIT; + } + + if(Quit) + return; + + if(rSbtn()) + done=true; + } + while(!done); + + for(int y=6; y<=174; y+=3) + { + do_dcounters(); + Link.refill(); + //fill in the screen with black to prevent the hall of mirrors effect + rectfill(framebuf, 0, 0, 255, 223, 0); + + if(COOLSCROLL) + { + //copy the playing field back onto the screen + blit(scrollbuf,framebuf,0,176,0,passive_subscreen_height,256,176); + } + else + { + //scroll the playing field (copy the copy we made) + blit(scrollbuf,framebuf,256,0,0,176-2-y+passive_subscreen_height,256,y); + } + + //throw the passive subscreen onto the screen + put_passive_subscr(framebuf,misc,0,176-2-y,showtime,sspSCROLLING); + //put the active subscreen above the passive subscreen + put_active_subscr(misc,y,sspSCROLLING); + advanceframe(false); + + if(Quit) + return; + } + + // Sitems.clear(); + if(usebombpal) + { + memcpy(RAMpal, temppal, PAL_SIZE*sizeof(RGB)); + } + + resume_sfx(WAV_BRANG); +} + +void markBmap(int dir, int sc) +{ + /* + if((DMaps[get_currdmap()].type&dmfTYPE)==dmOVERW) + return; + */ + if(sc>=128) + { + return; + } + + byte drow = DMaps[get_currdmap()].grid[sc>>4]; + byte mask = 1 << (7-((sc&15)-DMaps[get_currdmap()].xoff)); + int di = ((get_currdmap()-1)<<6) + ((sc>>4)<<3) + ((sc&15)-DMaps[get_currdmap()].xoff); + int code = 0; + + + switch((DMaps[get_currdmap()].type&dmfTYPE)) + { + case dmDNGN: + + // check dmap + if((drow&mask)==0) + return; + + // calculate code + for(int i=3; i>=0; i--) + { + code <<= 1; + code += tmpscr->door[i]&1; + } + + // mark the map + game->bmaps[di] = code|128; + break; + + case dmOVERW: + break; + + default: + game->bmaps[di] |= 128; + + if(dir>=0) + game->bmaps[di] |= (1<. +// + + +// to prevent from generating errors +#define __GTHREAD_HIDE_WIN32API 1 + +#include "precompiled.h" //always first + +#include +#include +#include +#include +#include +#include +#include "zc_alleg.h" +#include "gamedata.h" +#include "zc_init.h" +#include "zquest.h" +#include "init.h" + +#ifdef ALLEGRO_DOS +#include +#endif + +#include "zdefs.h" +#include "zelda.h" +#include "tiles.h" +#include "colors.h" +#include "pal.h" +#include "zsys.h" +#include "qst.h" +#include "zc_sys.h" +#include "debug.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "gui.h" +#include "midi.h" +#include "subscr.h" +#include "maps.h" +#include "sprite.h" +#include "guys.h" +#include "link.h" +#include "title.h" +#include "particles.h" +#include "screenWipe.h" +#include "sound.h" +#include "mem_debug.h" + +int d_stringloader(int msg,DIALOG *d,int c); + +extern FONT *lfont; +extern LinkClass Link; +extern sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations, particles; +extern int loadlast; +byte disable_direct_updating; +byte use_dwm_flush; +byte use_save_indicator; +byte midi_patch_fix; + +//extern movingblock mblock2; //mblock[4]? +//extern int db; + +static const char *ZC_str = "Zelda Classic"; +#ifdef ALLEGRO_DOS +static const char *qst_dir_name = "dos_qst_dir"; +#elif defined(ALLEGRO_WINDOWS) +static const char *qst_dir_name = "win_qst_dir"; +#elif defined(ALLEGRO_LINUX) +static const char *qst_dir_name = "linux_qst_dir"; +#elif defined(ALLEGRO_MACOSX) +static const char *qst_dir_name = "macosx_qst_dir"; +#endif +#ifdef ALLEGRO_LINUX +static const char *samplepath = "samplesoundset/patches.dat"; +#endif + +#ifdef _MSC_VER +#define getcwd _getcwd +#endif + +bool rF12(); +bool rF5(); +bool rF11(); +bool rI(); +bool rQ(); +bool zc_key_pressed(); + +#ifdef _WIN32 + +// This should only be necessary for MinGW, since it doesn't have a dwmapi.h. Add another #ifdef if you like. +extern "C" +{ + typedef HRESULT(WINAPI *t_DwmFlush)(); + typedef HRESULT(WINAPI *t_DwmIsCompositionEnabled)(BOOL *pfEnabled); +} + +void do_DwmFlush() +{ + static HMODULE shell = LoadLibrary("dwmapi.dll"); + + if(!shell) + return; + + static t_DwmFlush flush=reinterpret_cast(GetProcAddress(shell, "DwmFlush")); + static t_DwmIsCompositionEnabled isEnabled=reinterpret_cast(GetProcAddress(shell, "DwmIsCompositionEnabled")); + + BOOL enabled; + isEnabled(&enabled); + + if(isEnabled) + flush(); +} + +#endif // _WIN32 + +// Dialogue largening +void large_dialog(DIALOG *d) +{ + large_dialog(d, 1.5); +} + +void large_dialog(DIALOG *d, float RESIZE_AMT) +{ + if(!d[0].d1) + { + d[0].d1 = 1; + int oldwidth = d[0].w; + int oldheight = d[0].h; + int oldx = d[0].x; + int oldy = d[0].y; + d[0].x -= int(d[0].w/RESIZE_AMT); + d[0].y -= int(d[0].h/RESIZE_AMT); + d[0].w = int(d[0].w*RESIZE_AMT); + d[0].h = int(d[0].h*RESIZE_AMT); + + for(int i=1; d[i].proc !=NULL; i++) + { + // Place elements horizontally + double xpc = ((double)(d[i].x - oldx) / (double)oldwidth); + d[i].x = int(d[0].x + (xpc*d[0].w)); + + if(d[i].proc != d_stringloader) + { + if(d[i].proc==d_bitmap_proc) + { + d[i].w *= 2; + } + else d[i].w = int(d[i].w*RESIZE_AMT); + } + + // Place elements vertically + double ypc = ((double)(d[i].y - oldy) / (double)oldheight); + d[i].y = int(d[0].y + (ypc*d[0].h)); + + // Vertically resize elements + if(d[i].proc == jwin_edit_proc || d[i].proc == jwin_check_proc || d[i].proc == jwin_checkfont_proc) + { + d[i].h = int((double)d[i].h*1.5); + } + else if(d[i].proc == jwin_droplist_proc) + { + d[i].y += int((double)d[i].h*0.25); + d[i].h = int((double)d[i].h*1.25); + } + else if(d[i].proc==d_bitmap_proc) + { + d[i].h *= 2; + } + else d[i].h = int(d[i].h*RESIZE_AMT); + + // Fix frames + if(d[i].proc == jwin_frame_proc) + { + d[i].x++; + d[i].y++; + d[i].w-=4; + d[i].h-=4; + } + } + } + + for(int i=1; d[i].proc!=NULL; i++) + { + if(d[i].proc==jwin_slider_proc) + continue; + + // Bigger font + bool bigfontproc = (d[i].proc != jwin_initlist_proc && d[i].proc != d_midilist_proc && d[i].proc != jwin_droplist_proc && d[i].proc != jwin_abclist_proc && d[i].proc != jwin_list_proc); + + if(!d[i].dp2 && bigfontproc) + { + //d[i].dp2 = (d[i].proc == jwin_edit_proc) ? sfont3 : lfont_l; + d[i].dp2 = lfont_l; + } + else if(!bigfontproc) + { +// ((ListData *)d[i].dp)->font = &sfont3; + ((ListData *)d[i].dp)->font = &lfont_l; + } + + // Make checkboxes work + if(d[i].proc == jwin_check_proc) + d[i].proc = jwin_checkfont_proc; + else if(d[i].proc == jwin_radio_proc) + d[i].proc = jwin_radiofont_proc; + } + + jwin_center_dialog(d); +} + + +/**********************************/ +/******** System functions ********/ +/**********************************/ + +static char cfg_sect[] = "zeldadx"; + +int d_dummy_proc(int msg,DIALOG *d,int c) +{ + msg=msg; + d=d; + c=c; /*these are here to bypass compiler warnings about unused arguments*/ return D_O_K; +} + +void load_game_configs() +{ + joystick_index = get_config_int(cfg_sect,"joystick_index",0); + + if((unsigned int)joystick_index > 4) + joystick_index = 0; // 4 is the max number supported by allegro + + Akey = get_config_int(cfg_sect,"key_a",KEY_ALT); + Bkey = get_config_int(cfg_sect,"key_b",KEY_ZC_LCONTROL); + Skey = get_config_int(cfg_sect,"key_s",KEY_ENTER); + Lkey = get_config_int(cfg_sect,"key_l",KEY_Z); + Rkey = get_config_int(cfg_sect,"key_r",KEY_X); + Pkey = get_config_int(cfg_sect,"key_p",KEY_SPACE); + Exkey1 = get_config_int(cfg_sect,"key_ex1",KEY_Q); + Exkey2 = get_config_int(cfg_sect,"key_ex2",KEY_W); + Exkey3 = get_config_int(cfg_sect,"key_ex3",KEY_A); + Exkey4 = get_config_int(cfg_sect,"key_ex4",KEY_S); + + DUkey = get_config_int(cfg_sect,"key_up", KEY_UP); + DDkey = get_config_int(cfg_sect,"key_down", KEY_DOWN); + DLkey = get_config_int(cfg_sect,"key_left", KEY_LEFT); + DRkey = get_config_int(cfg_sect,"key_right",KEY_RIGHT); + + Abtn = get_config_int(cfg_sect,"btn_a",2); + Bbtn = get_config_int(cfg_sect,"btn_b",1); + Sbtn = get_config_int(cfg_sect,"btn_s",10); + Mbtn = get_config_int(cfg_sect,"btn_m",9); + Lbtn = get_config_int(cfg_sect,"btn_l",5); + Rbtn = get_config_int(cfg_sect,"btn_r",6); + Pbtn = get_config_int(cfg_sect,"btn_p",12); + Exbtn1 = get_config_int(cfg_sect,"btn_ex1",7); + Exbtn2 = get_config_int(cfg_sect,"btn_ex2",8); + Exbtn3 = get_config_int(cfg_sect,"btn_ex3",4); + Exbtn4 = get_config_int(cfg_sect,"btn_ex4",3); + + digi_volume = get_config_int(cfg_sect,"digi",248); + midi_volume = get_config_int(cfg_sect,"midi",255); + sfx_volume = get_config_int(cfg_sect,"sfx",248); + emusic_volume = get_config_int(cfg_sect,"emusic",248); + pan_style = get_config_int(cfg_sect,"pan",1); + // 1 <= zcmusic_bufsz <= 128 + zcmusic_bufsz = vbound(get_config_int(cfg_sect,"zcmusic_bufsz",64),1,128); + volkeys = get_config_int(cfg_sect,"volkeys",0)!=0; + zc_vsync = get_config_int(cfg_sect,"vsync",0); + Throttlefps = get_config_int(cfg_sect,"throttlefps",1)!=0; + TransLayers = get_config_int(cfg_sect,"translayers",1)!=0; + SnapshotFormat = get_config_int(cfg_sect,"snapshot_format",3); + NameEntryMode = get_config_int(cfg_sect,"name_entry_mode",0); + ShowFPS = get_config_int(cfg_sect,"showfps",0)!=0; + NESquit = get_config_int(cfg_sect,"fastquit",0)!=0; + ClickToFreeze = get_config_int(cfg_sect,"clicktofreeze",1)!=0; + title_version = get_config_int(cfg_sect,"title",2); + + //default - scale x2, 640 x 480 + resx = get_config_int(cfg_sect,"resx",640); + resy = get_config_int(cfg_sect,"resy",480); + //screen_scale = get_config_int(cfg_sect,"screen_scale",2); + + scanlines = get_config_int(cfg_sect,"scanlines",0)!=0; + loadlast = get_config_int(cfg_sect,"load_last",0); + fullscreen = get_config_int(cfg_sect,"fullscreen",1); + disable_triplebuffer = (byte) get_config_int(cfg_sect,"doublebuffer",0); + can_triplebuffer_in_windowed_mode = (byte) get_config_int(cfg_sect,"triplebuffer",0); + + zc_color_depth = (byte) get_config_int(cfg_sect,"color_depth",8); + + //workaround for the 100% CPU bug. -Gleeok +#ifdef ALLEGRO_MACOSX //IIRC rest(0) was a mac issue fix. + frame_rest_suggest = (byte) get_config_int(cfg_sect,"frame_rest_suggest",0); +#else + frame_rest_suggest = (byte) get_config_int(cfg_sect,"frame_rest_suggest",1); +#endif + frame_rest_suggest = zc_min(2, frame_rest_suggest); + + forceExit = (byte) get_config_int(cfg_sect,"force_exit",0); + +#ifdef _WIN32 + use_debug_console = (byte) get_config_int(cfg_sect,"debug_console",0); + //use_win7_keyboard_fix = (byte) get_config_int(cfg_sect,"use_win7_key_fix",0); + use_win32_proc = (byte) get_config_int(cfg_sect,"zc_win_proc_fix",0); //buggy + + // This seems to fix some problems on Windows 7 + disable_direct_updating = (byte) get_config_int("graphics","disable_direct_updating",1); + + // This one's for Aero + use_dwm_flush = (byte) get_config_int("zeldadx","use_dwm_flush",0); + + // And this one fixes patches unloading on some MIDI setups + midi_patch_fix = (byte) get_config_int("zeldadx","midi_patch_fix",0); +#endif + +#ifdef ALLEGRO_MACOSX + const char *default_path="../../../"; +#else + const char *default_path=""; +#endif + strcpy(qstdir,get_config_string(cfg_sect,qst_dir_name,default_path)); + + if(strlen(qstdir)==0) + { + getcwd(qstdir,2048); + fix_filename_case(qstdir); + fix_filename_slashes(qstdir); + put_backslash(qstdir); + } + else + { + chop_path(qstdir); + } + + strcpy(qstpath,qstdir); //qstpath is the local (for this run of ZC) quest path, qstdir is the universal quest dir. + ss_enable = get_config_int(cfg_sect,"ss_enable",1) ? 1 : 0; + ss_after = vbound(get_config_int(cfg_sect,"ss_after",14), 0, 14); + ss_speed = vbound(get_config_int(cfg_sect,"ss_speed",2), 0, 6); + ss_density = vbound(get_config_int(cfg_sect,"ss_density",3), 0, 6); + heart_beep = get_config_int(cfg_sect,"heart_beep",1)!=0; + gui_colorset = get_config_int(cfg_sect,"gui_colorset",0); + sfxdat = get_config_int(cfg_sect,"use_sfx_dat",1); + fullscreen = get_config_int(cfg_sect,"fullscreen",1); + use_save_indicator = get_config_int(cfg_sect,"save_indicator",0); +} + +void save_game_configs() +{ + set_config_int(cfg_sect,"joystick_index",joystick_index); + set_config_int(cfg_sect,"key_a",Akey); + set_config_int(cfg_sect,"key_b",Bkey); + set_config_int(cfg_sect,"key_s",Skey); + set_config_int(cfg_sect,"key_l",Lkey); + set_config_int(cfg_sect,"key_r",Rkey); + set_config_int(cfg_sect,"key_p",Pkey); + set_config_int(cfg_sect,"key_ex1",Exkey1); + set_config_int(cfg_sect,"key_ex2",Exkey2); + set_config_int(cfg_sect,"key_ex3",Exkey3); + set_config_int(cfg_sect,"key_ex4",Exkey4); + + set_config_int(cfg_sect,"key_up", DUkey); + set_config_int(cfg_sect,"key_down", DDkey); + set_config_int(cfg_sect,"key_left", DLkey); + set_config_int(cfg_sect,"key_right",DRkey); + + set_config_int(cfg_sect,"btn_a",Abtn); + set_config_int(cfg_sect,"btn_b",Bbtn); + set_config_int(cfg_sect,"btn_s",Sbtn); + set_config_int(cfg_sect,"btn_m",Mbtn); + set_config_int(cfg_sect,"btn_l",Lbtn); + set_config_int(cfg_sect,"btn_r",Rbtn); + set_config_int(cfg_sect,"btn_p",Pbtn); + set_config_int(cfg_sect,"btn_ex1",Exbtn1); + set_config_int(cfg_sect,"btn_ex2",Exbtn2); + set_config_int(cfg_sect,"btn_ex3",Exbtn3); + set_config_int(cfg_sect,"btn_ex4",Exbtn4); + + set_config_int(cfg_sect,"digi",digi_volume); + set_config_int(cfg_sect,"midi",midi_volume); + set_config_int(cfg_sect,"sfx",sfx_volume); + set_config_int(cfg_sect,"emusic",emusic_volume); + set_config_int(cfg_sect,"pan",pan_style); + set_config_int(cfg_sect,"zcmusic_bufsz",zcmusic_bufsz); + set_config_int(cfg_sect,"volkeys",(int)volkeys); + set_config_int(cfg_sect,"vsync",zc_vsync); + set_config_int(cfg_sect,"throttlefps", (int)Throttlefps); + set_config_int(cfg_sect,"translayers",(int)TransLayers); + set_config_int(cfg_sect,"snapshot_format",SnapshotFormat); + set_config_int(cfg_sect,"name_entry_mode",NameEntryMode); + set_config_int(cfg_sect,"showfps",(int)ShowFPS); + set_config_int(cfg_sect,"fastquit",(int)NESquit); + set_config_int(cfg_sect,"clicktofreeze", (int)ClickToFreeze); + set_config_int(cfg_sect,"title",title_version); + + set_config_int(cfg_sect,"resx",resx); + set_config_int(cfg_sect,"resy",resy); + + //sbig depricated as of 2.5 RC3. handled exclusively by resx, resy now. + //set_config_int(cfg_sect,"screen_scale",screen_scale); + //set_config_int(cfg_sect,"sbig",sbig); + //set_config_int(cfg_sect,"sbig2",sbig2); + + set_config_int(cfg_sect,"scanlines",scanlines); + set_config_int(cfg_sect,"load_last",loadlast); + chop_path(qstdir); + set_config_string(cfg_sect,qst_dir_name,qstdir); + set_config_int(cfg_sect,"ss_enable",ss_enable); + set_config_int(cfg_sect,"ss_after",ss_after); + set_config_int(cfg_sect,"ss_speed",ss_speed); + set_config_int(cfg_sect,"ss_density",ss_density); + set_config_int(cfg_sect,"heart_beep",heart_beep); + set_config_int(cfg_sect,"gui_colorset",gui_colorset); + set_config_int(cfg_sect,"use_sfx_dat",sfxdat); + set_config_int(cfg_sect,"fullscreen",fullscreen); + set_config_int(cfg_sect,"doublebuffer",disable_triplebuffer); + set_config_int(cfg_sect,"triplebuffer",can_triplebuffer_in_windowed_mode); + set_config_int(cfg_sect,"color_depth",zc_color_depth); + set_config_int(cfg_sect,"frame_rest_suggest",frame_rest_suggest); + set_config_int(cfg_sect,"force_exit",forceExit); + +#ifdef _WIN32 + set_config_int(cfg_sect,"debug_console",use_debug_console); + //set_config_int(cfg_sect,"use_win7_key_fix",use_win7_keyboard_fix); + set_config_int(cfg_sect,"zc_win_proc_fix",use_win32_proc); + set_config_int("graphics","disable_direct_updating",disable_direct_updating); + set_config_int("zeldadx","use_dwm_flush",use_dwm_flush); + set_config_int("zeldadx","midi_patch_fix",midi_patch_fix); +#endif + +#ifdef ALLEGRO_LINUX + set_config_string("sound","patches",samplepath); // set to sample sound path set for DIGMIDI driver in Linux ~ Takuya +#endif + + set_config_int(cfg_sect,"save_indicator",use_save_indicator); + + flush_config_file(); +} + +//---------------------------------------------------------------- + +// Timers + +void fps_callback() +{ + lastfps=framecnt; + dword tempsecs = fps_secs; + ++tempsecs; + //avgfps=((long double)avgfps*fps_secs+lastfps)/(++fps_secs); // DJGPP doesn't like this + avgfps=((long double)avgfps*fps_secs+lastfps)/(tempsecs); + ++fps_secs; + framecnt=0; +} + +END_OF_FUNCTION(fps_callback) + +int Z_init_timers() +{ + static bool didit = false; + const static char *err_str = "Couldn't allocate timer"; + err_str = err_str; //Unused variable warning + + if(didit) + return 1; + + didit = true; + + LOCK_VARIABLE(lastfps); + LOCK_VARIABLE(framecnt); + LOCK_FUNCTION(fps_callback); + + if(install_int_ex(fps_callback,SECS_TO_TIMER(1))) + return 0; + + return 1; +} + +void Z_remove_timers() +{ + remove_int(fps_callback); +} + +//---------------------------------------------------------------- + +void go() +{ + scare_mouse(); + blit(screen,tmp_scr,scrx,scry,0,0,screen->w,screen->h); + unscare_mouse(); +} + +void comeback() +{ + scare_mouse(); + blit(tmp_scr,screen,0,0,scrx,scry,screen->w,screen->h); + unscare_mouse(); +} + +void dump_pal(BITMAP *dest) +{ + for(int i=0; i<256; i++) + rectfill(dest,(i&63)<<2,(i&0xFC0)>>4,((i&63)<<2)+3,((i&0xFC0)>>4)+3,i); +} + +void show_paused(BITMAP *target) +{ + // return; + char buf[7] = "PAUSED"; + + for(int i=0; buf[i]!=0; i++) + buf[i]+=0x60; + + // text_mode(-1); + if(sbig) + { + int x = scrx+40-((screen_scale-1)*120); + int y = scry+224+((screen_scale-1)*104); + textout_ex(target,zfont,buf,x,y,-1,-1); + } + else + textout_ex(target,zfont,buf,scrx+40,scry+224,-1,-1); +} + +void show_fps(BITMAP *target) +{ + char buf[50]; + + // text_mode(-1); + sprintf(buf,"%2d/60",lastfps); + + // sprintf(buf,"%d/%u/%f/%u",lastfps,int(avgfps),avgfps,fps_secs); + for(int i=0; buf[i]!=0; i++) + if(buf[i]!=' ') + buf[i]+=0x60; + + if(sbig) + { + int x = scrx+40-((screen_scale-1)*120); + int y = scry+216+((screen_scale-1)*104); + textout_ex(target,zfont,buf,x,y,-1,-1); + // textout_ex(target,zfont,buf,scrx+40-120,scry+216+104,-1,-1); + } + else + { + textout_ex(target,zfont,buf,scrx+40,scry+216,-1,-1); + } +} + +void show_saving(BITMAP *target) +{ + if(!use_save_indicator) + return; + + char buf[10] = "SAVING..."; + + for(int i=0; buf[i]!=0; i++) + buf[i]+=0x60; + + if(sbig) + { + int x = scrx+200+((screen_scale-1)*120); + int y = scry+224+((screen_scale-1)*104); + textout_ex(target,zfont,buf,x,y,-1,-1); + } + else + textout_ex(target,zfont,buf,scrx+200,scry+224,-1,-1); +} + +//---------------------------------------------------------------- + +// sets the video mode and initializes the palette and mouse sprite +bool game_vid_mode(int mode,int wait) +{ + if(set_gfx_mode(mode,resx,resy,0,0)!=0) + { + return false; + } + + scrx = (resx-320)>>1; + scry = (resy-240)>>1; + + set_mouse_sprite((BITMAP*)data[BMP_MOUSE].dat); + + for(int i=240; i<256; i++) + RAMpal[i]=((RGB*)data[PAL_GUI].dat)[i]; + + set_palette(RAMpal); + clear_to_color(screen,BLACK); + + rest(wait); + return true; +} + +void init_NES_mode() +{ + // qst.dat may not load correctly without this... + QHeader.templatepath[0]='\0'; + + if(!init_colordata(true, &QHeader, &QMisc)) + { + return; + } + + loadfullpal(); + init_tiles(false, &QHeader); +} + +//---------------------------------------------------------------- + +bool item_disabled(int item) //is this item disabled? +{ + return (item>=0 && game->items_off[item] != 0); +} + +bool can_use_item(int item_type, int item) //can Link use this item? +{ + if(current_item(item_type, true) >=item) + { + return true; + } + + return false; +} + +bool has_item(int item_type, int it) //does Link possess this item? +{ + switch(item_type) + { + case itype_bomb: + case itype_sbomb: + { + int itemid = getItemID(itemsbuf, item_type, it); + + if(itemid == -1) + return false; + + return (game->get_item(itemid)); + } + + case itype_clock: + return Link.getClock()?1:0; + + case itype_key: + return (game->get_keys()>0); + + case itype_magiccontainer: + return (game->get_maxmagic()>=MAGICPERBLOCK); + + case itype_triforcepiece: //it: -2=any, -1=current level, other=that level + { + switch(it) + { + case -2: + { + for(int i=0; ilvlitems[i]&liTRIFORCE) + { + return true; + } + } + + return false; + break; + } + + case -1: + return (game->lvlitems[dlevel]&liTRIFORCE); + break; + + default: + if(it>=0&&itlvlitems[it]&liTRIFORCE); + } + + break; + } + + return 0; + } + + case itype_map: //it: -2=any, -1=current level, other=that level + { + switch(it) + { + case -2: + { + for(int i=0; ilvlitems[i]&liMAP) + { + return true; + } + } + + return false; + } + break; + + case -1: + return (game->lvlitems[dlevel]&liMAP)!=0; + break; + + default: + if(it>=0&&itlvlitems[it]&liMAP)!=0; + } + + break; + } + + return 0; + } + + case itype_compass: //it: -2=any, -1=current level, other=that level + { + switch(it) + { + case -2: + { + for(int i=0; ilvlitems[i]&liCOMPASS) + { + return true; + } + } + + return false; + break; + } + + case -1: + return (game->lvlitems[dlevel]&liCOMPASS)!=0; + break; + + default: + if(it>=0&&itlvlitems[it]&liCOMPASS)!=0; + } + + break; + } + + return 0; + } + + case itype_bosskey: //it: -2=any, -1=current level, other=that level + { + switch(it) + { + case -2: + { + for(int i=0; ilvlitems[i]&liBOSSKEY) + { + return true; + } + } + + return false; + break; + } + + case -1: + return (game->lvlitems[dlevel]&liBOSSKEY)?1:0; + break; + + default: + if(it>=0&&itlvlitems[it]&liBOSSKEY)?1:0; + } + + break; + } + + return 0; + } + + default: + int itemid = getItemID(itemsbuf, item_type, it); + + if(itemid == -1) + return false; + + return game->get_item(itemid); + break; + } +} + + +int current_item(int item_type, bool checkenabled) //item currently being used +{ + switch(item_type) + { + case itype_clock: + return has_item(itype_clock,1) ? 1 : 0; + break; + + case itype_key: + return game->get_keys(); + + case itype_lkey: + return game->lvlkeys[get_dlevel()]; + + case itype_magiccontainer: + return game->get_maxmagic()/MAGICPERBLOCK; + + case itype_triforcepiece: + { + int count=0; + + for(int i=0; ilvlitems[i]&liTRIFORCE)?1:0; + } + + return count; + break; + } + + case itype_map: + { + int count=0; + + for(int i=0; ilvlitems[i]&liMAP)?1:0; + } + + return count; + break; + } + + case itype_compass: + { + int count=0; + + for(int i=0; ilvlitems[i]&liCOMPASS)?1:0; + } + + return count; + break; + } + + case itype_bosskey: + { + int count=0; + + for(int i=0; ilvlitems[i]&liBOSSKEY)?1:0; + } + + return count; + break; + } + + default: + int maxid = getHighestLevelOfFamily(game, itemsbuf, item_type, checkenabled); + + if(maxid == -1) + return 0; + + return itemsbuf[maxid].fam_type; + break; + } +} + +int current_item(int item_type) //item currently being used +{ + return current_item(item_type, true); +} + +std::map itemcache; + +void flushItemCache() +{ + itemcache.clear(); + + //also fix the active subscreen if items were deleted -DD + if(game != NULL) + { + verifyBothWeapons(); + load_Sitems(&QMisc); + } +} + +// This is used often, so it should be as direct as possible. +int current_item_id(int itemtype, bool checkmagic) +{ + if(itemtype!=itype_ring) // Rings must always be checked. + { + std::map::iterator res = itemcache.find(itemtype); + + if(res != itemcache.end()) + return res->second; + } + + int result = -1; + int highestlevel = -1; + + for(int i=0; iget_item(i) && itemsbuf[i].family==itemtype && !item_disabled(i)) + { + if((checkmagic || itemtype == itype_ring) && itemtype != itype_magicring) + { + //printf("Checkmagic for %d: %d (%d %d)\n",i,checkmagiccost(i),itemsbuf[i].magic*game->get_magicdrainrate(),game->get_magic()); + if(!checkmagiccost(i)) + { + continue; + } + } + + if(itemsbuf[i].fam_type >= highestlevel) + { + highestlevel = itemsbuf[i].fam_type; + result=i; + } + } + } + + itemcache[itemtype] = result; + return result; +} + +int current_item_power(int itemtype) +{ + int result = current_item_id(itemtype,true); + return (result<0) ? 0 : itemsbuf[result].power; +} + +int item_tile_mod(bool) +{ + long tile=0; + int ret=0; + + ret=game->get_bombs(); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + if(current_item_id(itype_bomb,false)>=0) + ret=itemsbuf[current_item_id(itype_bomb,false)].ltm; + else + ret=0; + + break; + + } + + tile+=ret; + + ret=game->get_sbombs(); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + if(current_item_id(itype_sbomb,false)>=0) + ret=itemsbuf[current_item_id(itype_sbomb,false)].ltm; + else + ret=0; + + break; + } + + tile+=ret; + + ret=current_item(itype_clock); + + switch(ret) + { + case 1: + ret=itemsbuf[iClock].ltm; + break; + + default: + ret=0; + break; + } + + tile+=ret; + + ret=current_item(itype_key); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iKey].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_lkey); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iLevelKey].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_map); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iMap].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_compass); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iCompass].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_bosskey); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iBossKey].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_magiccontainer); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iMagicC].ltm; + break; + } + + tile+=ret; + + ret=current_item(itype_triforcepiece); + + switch(ret) + { + case 0: + ret=0; + break; + + default: + ret=itemsbuf[iTriforce].ltm; + break; + } + + tile+=ret; + + for(int i=0; i= 0) + tile+=itemsbuf[ret].ltm; + } + + return tile; +} + +int dmap_tile_mod() +{ + return 0; +} + +// Hints are drawn on a separate layer to combo reveals. +void draw_lens_under(BITMAP *dest, bool layer) +{ + bool hints = (layer && get_bit(quest_rules,qr_LENSHINTS)); + + int strike_hint_table[11]= + { + mfARROW, mfBOMB, mfBRANG, mfWANDMAGIC, + mfSWORD, mfREFMAGIC, mfHOOKSHOT, + mfREFFIREBALL, mfHAMMER, mfSWORDBEAM, mfWAND + }; + + // int page = tmpscr->cpage; + { + int blink_rate=1; + // int temptimer=0; + int tempitem, tempweapon=0; + strike_hint=strike_hint_table[strike_hint_counter]; + + if(strike_hint_timer>32) + { + strike_hint_timer=0; + strike_hint_counter=((strike_hint_counter+1)%11); + } + + ++strike_hint_timer; + + for(int i=0; i<176; i++) + { + int x = (i & 15) << 4; + int y = (i & 0xF0) + playing_field_offset; + int tempitemx=-16, tempitemy=-16; + int tempweaponx=-16, tempweapony=-16; + + for(int iter=0; iter<2; ++iter) + { + int checkflag=0; + + if(iter==0) + { + checkflag=combobuf[tmpscr->data[i]].flag; + } + else + { + checkflag=tmpscr->sflag[i]; + } + + if(checkflag==mfSTRIKE) + { + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSTRIKE],tmpscr->secretcset[sSTRIKE]); + else + { + checkflag = strike_hint; + } + } + + switch(checkflag) + { + case 0: + case mfZELDA: + case mfPUSHED: + case mfENEMY0: + case mfENEMY1: + case mfENEMY2: + case mfENEMY3: + case mfENEMY4: + case mfENEMY5: + case mfENEMY6: + case mfENEMY7: + case mfENEMY8: + case mfENEMY9: + case mfSINGLE: + case mfSINGLE16: + case mfNOENEMY: + case mfTRAP_H: + case mfTRAP_V: + case mfTRAP_4: + case mfTRAP_LR: + case mfTRAP_UD: + case mfNOGROUNDENEMY: + case mfNOBLOCKS: + case mfSCRIPT1: + case mfSCRIPT2: + case mfSCRIPT3: + case mfSCRIPT4: + case mfSCRIPT5: + break; + + case mfPUSHUD: + case mfPUSHLR: + case mfPUSH4: + case mfPUSHU: + case mfPUSHD: + case mfPUSHL: + case mfPUSHR: + case mfPUSHUDNS: + case mfPUSHLRNS: + case mfPUSH4NS: + case mfPUSHUNS: + case mfPUSHDNS: + case mfPUSHLNS: + case mfPUSHRNS: + case mfPUSHUDINS: + case mfPUSHLRINS: + case mfPUSH4INS: + case mfPUSHUINS: + case mfPUSHDINS: + case mfPUSHLINS: + case mfPUSHRINS: + if(!hints && ((!(get_debug() && key[KEY_N]) && (lensclk&16)) + || ((get_debug() && key[KEY_N]) && (frame&16)))) + { + putcombo(dest,x,y,tmpscr->undercombo,tmpscr->undercset); + } + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + if(hints) + { + switch(combobuf[tmpscr->data[i]].type) + { + case cPUSH_HEAVY: + case cPUSH_HW: + tempitem=getItemIDPower(itemsbuf,itype_bracelet,1); + tempitemx=x, tempitemy=y; + + if(tempitem>-1) + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + + break; + + case cPUSH_HEAVY2: + case cPUSH_HW2: + tempitem=getItemIDPower(itemsbuf,itype_bracelet,2); + tempitemx=x, tempitemy=y; + + if(tempitem>-1) + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + + break; + } + } + } + + break; + + case mfWHISTLE: + if(hints) + { + tempitem=getItemID(itemsbuf,itype_whistle,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + //Why is this here? + case mfFAIRY: + case mfMAGICFAIRY: + case mfALLFAIRY: + if(hints) + { + tempitem=getItemID(itemsbuf, itype_fairy,1);//iFairyMoving; + + if(tempitem < 0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfBCANDLE: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sBCANDLE],tmpscr->secretcset[sBCANDLE]); + else + { + tempitem=getItemID(itemsbuf,itype_candle,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfRCANDLE: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sRCANDLE],tmpscr->secretcset[sRCANDLE]); + else + { + tempitem=getItemID(itemsbuf,itype_candle,2); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfWANDFIRE: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sWANDFIRE],tmpscr->secretcset[sWANDFIRE]); + else + { + tempitem=getItemID(itemsbuf,itype_wand,1); + + if(tempitem<0) break; + + tempweapon=wFire; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + else + { + tempweaponx=x; + tempweapony=y; + } + + putweapon(dest,tempweaponx,tempweapony,tempweapon, 0, up, lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfDINSFIRE: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sDINSFIRE],tmpscr->secretcset[sDINSFIRE]); + else + { + tempitem=getItemID(itemsbuf,itype_dinsfire,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfARROW: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sARROW],tmpscr->secretcset[sARROW]); + else + { + tempitem=getItemID(itemsbuf,itype_arrow,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfSARROW: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSARROW],tmpscr->secretcset[sSARROW]); + else + { + tempitem=getItemID(itemsbuf,itype_arrow,2); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfGARROW: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sGARROW],tmpscr->secretcset[sGARROW]); + else + { + tempitem=getItemID(itemsbuf,itype_arrow,3); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfBOMB: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sBOMB],tmpscr->secretcset[sBOMB]); + else + { + //tempitem=getItemID(itemsbuf,itype_bomb,1); + tempweapon = wLitBomb; + + //if (tempitem<0) break; + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempweaponx=x; + tempweapony=y; + } + + putweapon(dest,tempweaponx,tempweapony+lens_hint_weapon[tempweapon][4],tempweapon, 0, up, lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + } + + break; + + case mfSBOMB: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSBOMB],tmpscr->secretcset[sSBOMB]); + else + { + //tempitem=getItemID(itemsbuf,itype_sbomb,1); + //if (tempitem<0) break; + tempweapon = wLitSBomb; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempweaponx=x; + tempweapony=y; + } + + putweapon(dest,tempweaponx,tempweapony+lens_hint_weapon[tempweapon][4],tempweapon, 0, up, lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + } + + break; + + case mfARMOS_SECRET: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSTAIRS],tmpscr->secretcset[sSTAIRS]); + + break; + + case mfBRANG: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sBRANG],tmpscr->secretcset[sBRANG]); + else + { + tempitem=getItemID(itemsbuf,itype_brang,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfMBRANG: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sMBRANG],tmpscr->secretcset[sMBRANG]); + else + { + tempitem=getItemID(itemsbuf,itype_brang,2); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfFBRANG: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sFBRANG],tmpscr->secretcset[sFBRANG]); + else + { + tempitem=getItemID(itemsbuf,itype_brang,3); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfWANDMAGIC: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sWANDMAGIC],tmpscr->secretcset[sWANDMAGIC]); + else + { + tempitem=getItemID(itemsbuf,itype_wand,1); + + if(tempitem<0) break; + + tempweapon=itemsbuf[tempitem].wpn3; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + else + { + tempweaponx=x; + tempweapony=y; + --lens_hint_weapon[wMagic][4]; + + if(lens_hint_weapon[wMagic][4]<-8) + { + lens_hint_weapon[wMagic][4]=8; + } + } + + putweapon(dest,tempweaponx,tempweapony+lens_hint_weapon[tempweapon][4],tempweapon, 0, up, lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfREFMAGIC: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sREFMAGIC],tmpscr->secretcset[sREFMAGIC]); + else + { + tempitem=getItemID(itemsbuf,itype_shield,3); + + if(tempitem<0) break; + + tempweapon=ewMagic; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + else + { + tempweaponx=x; + tempweapony=y; + + if(lens_hint_weapon[ewMagic][2]==up) + { + --lens_hint_weapon[ewMagic][4]; + } + else + { + ++lens_hint_weapon[ewMagic][4]; + } + + if(lens_hint_weapon[ewMagic][4]>8) + { + lens_hint_weapon[ewMagic][2]=up; + } + + if(lens_hint_weapon[ewMagic][4]<=0) + { + lens_hint_weapon[ewMagic][2]=down; + } + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + putweapon(dest,tempweaponx,tempweapony+lens_hint_weapon[tempweapon][4],tempweapon, 0, lens_hint_weapon[ewMagic][2], lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + } + + break; + + case mfREFFIREBALL: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sREFFIREBALL],tmpscr->secretcset[sREFFIREBALL]); + else + { + tempitem=getItemID(itemsbuf,itype_shield,3); + + if(tempitem<0) break; + + tempweapon=ewFireball; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + tempweaponx=x; + tempweapony=y; + ++lens_hint_weapon[ewFireball][3]; + + if(lens_hint_weapon[ewFireball][3]>8) + { + lens_hint_weapon[ewFireball][3]=-8; + lens_hint_weapon[ewFireball][4]=8; + } + + if(lens_hint_weapon[ewFireball][3]>0) + { + ++lens_hint_weapon[ewFireball][4]; + } + else + { + --lens_hint_weapon[ewFireball][4]; + } + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + putweapon(dest,tempweaponx+lens_hint_weapon[tempweapon][3],tempweapony+lens_hint_weapon[ewFireball][4],tempweapon, 0, up, lens_hint_weapon[tempweapon][0], lens_hint_weapon[tempweapon][1],-1); + } + + break; + + case mfSWORD: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSWORD],tmpscr->secretcset[sSWORD]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfWSWORD: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sWSWORD],tmpscr->secretcset[sWSWORD]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,2); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfMSWORD: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sMSWORD],tmpscr->secretcset[sMSWORD]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,3); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfXSWORD: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sXSWORD],tmpscr->secretcset[sXSWORD]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,4); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfSWORDBEAM: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sSWORDBEAM],tmpscr->secretcset[sSWORDBEAM]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 1); + } + + break; + + case mfWSWORDBEAM: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sWSWORDBEAM],tmpscr->secretcset[sWSWORDBEAM]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,2); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 2); + } + + break; + + case mfMSWORDBEAM: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sMSWORDBEAM],tmpscr->secretcset[sMSWORDBEAM]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,3); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 3); + } + + break; + + case mfXSWORDBEAM: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sXSWORDBEAM],tmpscr->secretcset[sXSWORDBEAM]); + else + { + tempitem=getItemID(itemsbuf,itype_sword,4); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 4); + } + + break; + + case mfHOOKSHOT: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sHOOKSHOT],tmpscr->secretcset[sHOOKSHOT]); + else + { + tempitem=getItemID(itemsbuf,itype_hookshot,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfWAND: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sWAND],tmpscr->secretcset[sWAND]); + else + { + tempitem=getItemID(itemsbuf,itype_wand,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfHAMMER: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[sHAMMER],tmpscr->secretcset[sHAMMER]); + else + { + tempitem=getItemID(itemsbuf,itype_hammer,1); + + if(tempitem<0) break; + + if((!(get_debug() && key[KEY_N]) && (lensclk&blink_rate)) + || ((get_debug() && key[KEY_N]) && (frame&blink_rate))) + { + tempitemx=x; + tempitemy=y; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + + break; + + case mfARMOS_ITEM: + case mfDIVE_ITEM: + if(!getmapflag()) + // putitem2(dest,x,y,tmpscr->catchall); + putitem2(dest,x,y,tmpscr->catchall, lens_hint_item[tmpscr->catchall][0], lens_hint_item[tmpscr->catchall][1], 0); + + break; + + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + if(!hints) + putcombo(dest,x,y,tmpscr->secretcombo[checkflag-16+4], + tmpscr->secretcset[checkflag-16+4]); + + break; + + default: + if(layer && ((checkflag!=mfRAFT && checkflag!=mfRAFT_BRANCH&& checkflag!=mfRAFT_BOUNCE) || get_bit(quest_rules,qr_RAFTLENS))) + { + if((!(get_debug() && key[KEY_N]) && (lensclk&1)) || ((get_debug() && key[KEY_N]) && (frame&1))) + { + rectfill(dest,x,y,x+15,y+15,WHITE); + } + } + + break; + } + } + } + + if(layer) + { + if(tmpscr->door[0]==dWALK) + rectfill(dest, 120, 16+playing_field_offset, 135, 31+playing_field_offset, WHITE); + + if(tmpscr->door[1]==dWALK) + rectfill(dest, 120, 144+playing_field_offset, 135, 159+playing_field_offset, WHITE); + + if(tmpscr->door[2]==dWALK) + rectfill(dest, 16, 80+playing_field_offset, 31, 95+playing_field_offset, WHITE); + + if(tmpscr->door[3]==dWALK) + rectfill(dest, 224, 80+playing_field_offset, 239, 95+playing_field_offset, WHITE); + + if(tmpscr->door[0]==dBOMB) + { + showbombeddoor(dest, 0); + } + + if(tmpscr->door[1]==dBOMB) + { + showbombeddoor(dest, 1); + } + + if(tmpscr->door[2]==dBOMB) + { + showbombeddoor(dest, 2); + } + + if(tmpscr->door[3]==dBOMB) + { + showbombeddoor(dest, 3); + } + } + + if(tmpscr->stairx + tmpscr->stairy) + { + if(!hints) + putcombo(dest,tmpscr->stairx,tmpscr->stairy+playing_field_offset,tmpscr->secretcombo[sSTAIRS],tmpscr->secretcset[sSTAIRS]); + else + { + if(tmpscr->flags&fWHISTLE) + { + tempitem=getItemID(itemsbuf,itype_whistle,1); + int tempitemx=-16; + int tempitemy=-16; + + if((!(get_debug() && key[KEY_N]) && (lensclk&(blink_rate/4))) + || ((get_debug() && key[KEY_N]) && (frame&(blink_rate/4)))) + { + tempitemx=tmpscr->stairx; + tempitemy=tmpscr->stairy+playing_field_offset; + } + + putitem2(dest,tempitemx,tempitemy,tempitem, lens_hint_item[tempitem][0], lens_hint_item[tempitem][1], 0); + } + } + } + } +} + +BITMAP *lens_scr_d; // The "d" is for "destructible"! + +void draw_lens_over() +{ + // Oh, what the heck. + static BITMAP *lens_scr = NULL; + static int last_width = -1; + int width = itemsbuf[current_item_id(itype_lens,true)].misc1; + + // Only redraw the circle if the size has changed + if(width != last_width) + { + if(lens_scr == NULL) + { + lens_scr = create_bitmap_ex(8,2*288,2*(240-playing_field_offset)); + } + + clear_to_color(lens_scr, BLACK); + circlefill(lens_scr, 288, 240-playing_field_offset, width, 0); + circle(lens_scr, 288, 240-playing_field_offset, width+2, 0); + circle(lens_scr, 288, 240-playing_field_offset, width+5, 0); + last_width=width; + } + + masked_blit(lens_scr, framebuf, 288-(LinkX()+8), 240-playing_field_offset-(LinkY()+8), 0, playing_field_offset, 256, 168); +} + +//---------------------------------------------------------------- + +void draw_wavy(BITMAP *source, BITMAP *target, int amplitude, bool interpol) +{ + //recreating a big bitmap every frame is highly sluggish. + static BITMAP *wavebuf = create_bitmap_ex(8,288,240-original_playing_field_offset); + + clear_to_color(wavebuf,0); + blit(source,wavebuf,0,original_playing_field_offset,16,0,256,224-original_playing_field_offset); + + int ofs; + // int amplitude=8; + // int wavelength=4; + amplitude = zc_min(2048,amplitude); // some arbitrary limit to prevent crashing + int amp2=168; + int i=frame%amp2; + + for(int j=0; j<168; j++) + { + if(j&1 && interpol) + { + ofs=int(sin((double(i+j)*2*PI/amp2))*amplitude); + } + else + { + ofs=-int(sin((double(i+j)*2*PI/amp2))*amplitude); + } + + if(ofs) + { + for(int k=0; k<256; k++) + { + target->line[j+original_playing_field_offset][k]=wavebuf->line[j][k+ofs+16]; + } + } + } +} + +void draw_fuzzy(int fuzz) +// draws from right half of scrollbuf to framebuf +{ + int firstx, firsty, xstep, ystep, i, y, dx, dy; + byte *start, *si, *di; + + if(fuzz<1) + fuzz = 1; + + xstep = 128%fuzz; + + if(xstep > 0) + xstep = fuzz-xstep; + + ystep = 112%fuzz; + + if(ystep > 0) + ystep = fuzz-ystep; + + firsty = 1; + + for(y=0; y<224;) + { + start = &(scrollbuf->line[y][256]); + + for(dy=0; dyline[y+dy][0]); + i = xstep; + firstx = 1; + + for(dx=0; dx<256; dx++) + { + *(di++) = *si; + + if(++i >= fuzz) + { + if(!firstx) + si += fuzz; + else + { + si += fuzz-xstep; + firstx = 0; + } + + i = 0; + } + } + } + + if(!firsty) + y += fuzz; + else + { + y += ystep; + ystep = fuzz; + firsty = 0; + } + } +} + +void updatescr(bool allowwavy) +{ + static BITMAP *wavybuf = create_bitmap_ex(8,256,224); + static BITMAP *panorama = create_bitmap_ex(8,256,224); + + if(toogam) + { + textout_ex(framebuf,font,"no walls",8,216,1,-1); + } + + if(Showpal) + dump_pal(framebuf); + + if(!Playing) + abortScreenWipe(); + + if(screenWipeIsActive()) + updateScreenWipe(Advance || !Paused); + + if(refreshpal) + { + refreshpal=false; + RAMpal[253] = _RGB(0,0,0); + RAMpal[254] = _RGB(63,63,63); + set_palette_range(RAMpal,0,255,false); + + create_rgb_table(&rgb_table, RAMpal, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; qflags3&fNOSUBSCR && !(tmpscr->flags3&fNOSUBSCROFFSET)); + + if(nosubscr) + { + rectfill(panorama,0,0,255,passive_subscreen_height/2,0); + rectfill(panorama,0,168+passive_subscreen_height/2,255,168+passive_subscreen_height-1,0); + blit(wavybuf,panorama,0,playing_field_offset,0,passive_subscreen_height/2,256,224-passive_subscreen_height); + } + + BITMAP *source = nosubscr ? panorama : wavybuf; + BITMAP *target = NULL; + + bool dontusetb = triplebuffer_not_available || + !(Throttlefps ^ (true && key[KEY_TILDE])); + + if(dontusetb) + target=screen; + else + target=tb_page[curr_tb_page]; + +// static BITMAP *tempscreen=NULL; + static BITMAP *scanlinesbmp=NULL; + + if(resx != SCREEN_W || resy != SCREEN_H) + { + Z_message("Conflicting variables warning: screen_scale %i, resx %i, resy %i, w %i, h %i\n", screen_scale, resx, resy, SCREEN_W, SCREEN_H); + resx = SCREEN_W; + resy = SCREEN_H; + screen_scale = zc_max(zc_min(resx / 320, resy / 240), 1); + } + + if(!sbig && screen_scale > 1) + sbig = true; + + const int sx = 256 * screen_scale; + const int sy = 224 * screen_scale; + const int scale_mul = screen_scale - 1; + const int mx = scale_mul * 128; + const int my = scale_mul * 112; + + if(sbig) + { + if(scanlines) + { + if(!scanlinesbmp) + scanlinesbmp = create_bitmap_ex(8, sx, sy); + + stretch_blit(source, scanlinesbmp, 0, 0, 256, 224, 0, 0, sx, sy); + + for(int i=0; i<224; ++i) + _allegro_hline(scanlinesbmp, 0, (i*screen_scale)+1, sx, BLACK); + + blit(scanlinesbmp, target, 0, 0, scrx+32-mx, scry+8-my, sx, sy); + } + else + { + stretch_blit(source, target, 0, 0, 256, 224, scrx+32-mx, scry+8-my, sx, sy); + } + + if(quakeclk>0) + rectfill(target, // I don't know if these are right... + scrx+32 - mx, //x1 + scry+8 - my + sy, //y1 + scrx+32 - mx + sx, //x2 + scry+8 - my + sy + (16 * scale_mul), //y2 + 0); + + //stretch_blit(nosubscr?panorama:wavybuf,target,0,0,256,224,scrx+32-128,scry+8-112,512,448); + //if(quakeclk>0) rectfill(target,scrx+32-128,scry+8-112+448,scrx+32-128+512,scry+8-112+456,0); + } + else + { + blit(source,target,0,0,scrx+32,scry+8,256,224); + + if(quakeclk>0) rectfill(target,scrx+32,scry+8+224,scrx+32+256,scry+8+232,0); + } + + if(ShowFPS) + show_fps(target); + + if(Paused) + show_paused(target); + + if(details) + { + textprintf_ex(target,font,0,SCREEN_H-8,254,BLACK,"%-6d (%s)", idle_count, time_str_long(idle_count)); + } + + if(!dontusetb) + { + if(!poll_scroll()) + { + request_video_bitmap(tb_page[curr_tb_page]); + curr_tb_page=(curr_tb_page+1)%3; + clear_to_color(tb_page[curr_tb_page],BLACK); + } + } + + //if(panorama!=NULL) destroy_bitmap(panorama); + + ++framecnt; +} + +//---------------------------------------------------------------- + +PALETTE sys_pal; + +int onGUISnapshot() +{ + char buf[20]; + int num=0; + + do + { +#ifdef ALLEGRO_MACOSX + sprintf(buf, "../../../zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#else + sprintf(buf, "zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#endif + } + while(num<999 && exists(buf)); + + BITMAP *b = create_bitmap_ex(8,resx,resy); + + if(b) + { + blit(screen,b,0,0,0,0,resx,resy); + save_bmp(buf,b,sys_pal); + destroy_bitmap(b); + } + + return D_O_K; +} + +int onNonGUISnapshot() +{ + PALETTE temppal; + get_palette(temppal); + bool realpal=(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]); + + char buf[20]; + int num=0; + + do + { + sprintf(buf, "zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); + } + while(num<999 && exists(buf)); + + BITMAP *panorama = create_bitmap_ex(8,256,168); + + if(tmpscr->flags3&fNOSUBSCR) + { + clear_to_color(panorama,0); + blit(framebuf,panorama,0,playing_field_offset,0,0,256,168); + save_bitmap(buf,panorama,realpal?temppal:RAMpal); + } + else + { + save_bitmap(buf,framebuf,realpal?temppal:RAMpal); + } + + destroy_bitmap(panorama); + return D_O_K; +} + +int onSnapshot() +{ + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + onGUISnapshot(); + } + else + { + onNonGUISnapshot(); + } + + return D_O_K; +} + +int onSaveMapPic() +{ + BITMAP* mappic = NULL; + int mapres2 = 0; + char buf[20]; + int num=0; + set_clip_state(temp_buf,1); + set_clip_rect(temp_buf,0,0,temp_buf->w, temp_buf->h); + + do + { +#ifdef ALLEGRO_MACOSX + sprintf(buf, "../../../zelda%03d.png", ++num); +#else + sprintf(buf, "zelda%03d.png", ++num); +#endif + } + while(num<999 && exists(buf)); + + // if(!mappic) { + mappic = create_bitmap_ex(8,(256*16)>>mapres2,(176*8)>>mapres2); + + if(!mappic) + { + system_pal(); + jwin_alert("Save Map Picture","Not enough memory.",NULL,NULL,"OK",NULL,13,27,lfont); + game_pal(); + return D_O_K; + } + + // } + + int layermap, layerscreen; + int x2=0; + + // draw the map + for(int y=0; y<8; y++) + { + for(int x=0; x<16; x++) + { + int s = (y<<4) + x; + + if(!displayOnMap(x, y)) + { + rectfill(temp_buf, 0, 0, 255, 223, WHITE); + } + else + { + loadscr(1,currdmap,s,-1,false); + putscr(temp_buf, 0, 0, tmpscr+1); + + for(int k=0; k<4; k++) + { + if(k==2) + { + putscrdoors(temp_buf, 0, 0, tmpscr+1); + } + + layermap=TheMaps[currmap*MAPSCRS+s].layermap[k]-1; + + if(layermap>-1) + { + layerscreen=layermap*MAPSCRS+TheMaps[currmap*MAPSCRS+s].layerscreen[k]; + + if(TheMaps[currmap*MAPSCRS+s].layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + overcombo(temp_buf,((i&15)<<4)+x2,(i&0xF0),TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(temp_buf,((i&15)<<4)+x2,(i&0xF0),TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],TheMaps[currmap*MAPSCRS+s].layeropacity[k]); + } + } + } + } + + for(int i=0; i<176; i++) + { +// if (COMBOTYPE((i&15)<<4,i&0xF0)==cOLD_OVERHEAD) + if(combo_class_buf[COMBOTYPE((i&15)<<4,i&0xF0)].overhead) + { + overcombo(temp_buf,((i&15)<<4)+x2,(i&0xF0),MAPCOMBO((i&15)<<4,i&0xF0),MAPCSET((i&15)<<4,i&0xF0)); + } + } + + for(int k=4; k<6; k++) + { + layermap=TheMaps[currmap*MAPSCRS+s].layermap[k]-1; + + if(layermap>-1) + { + layerscreen=layermap*MAPSCRS+TheMaps[currmap*MAPSCRS+s].layerscreen[k]; + + if(TheMaps[currmap*MAPSCRS+s].layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + overcombo(temp_buf,((i&15)<<4)+x2,(i&0xF0),TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(temp_buf,((i&15)<<4)+x2,(i&0xF0),TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],TheMaps[currmap*MAPSCRS+s].layeropacity[k]); + } + } + } + } + } + + stretch_blit(temp_buf, mappic, 0, 0, 256, 176, + x<<(8-mapres2), (y*176)>>mapres2, 256>>mapres2, 176>>mapres2); + } + + } + + save_bitmap(buf,mappic,RAMpal); + destroy_bitmap(mappic); + return D_O_K; +} + +void f_Quit(int type) +{ + if(type==qQUIT && !Playing) + return; + + music_pause(); + pause_all_sfx(); + system_pal(); + clear_keybuf(); + + switch(type) + { + case qQUIT: + onQuit(); + break; + + case qRESET: + onReset(); + break; + + case qEXIT: + onExit(); + break; + } + + if(Quit) + { + kill_sfx(); + music_stop(); + clear_to_color(screen,BLACK); + } + else + { + game_pal(); + music_resume(); + resume_all_sfx(); + } + + eat_buttons(); + + if(key[KEY_ESC]) + key[KEY_ESC]=0; + + if(key[KEY_ENTER]) + key[KEY_ENTER]=0; +} + +//---------------------------------------------------------------- + +int onNoWalls() +{ + toogam = !toogam; + + if(toogam) + { + cheat_superman=true; + setClock(true); + } + + return D_O_K; +} + +int input_idle(bool checkmouse) +{ + static int mx, my, mz, mb; + + if(keypressed() || zc_key_pressed() || + (checkmouse && (mx != gui_mouse_x() || my != gui_mouse_y() || mz != gui_mouse_z() || mb != gui_mouse_b()))) + { + idle_count = 0; + + if(active_count < MAX_ACTIVE) + { + ++active_count; + } + } + else if(idle_count < MAX_IDLE) + { + ++idle_count; + active_count = 0; + } + + mx = gui_mouse_x(); + my = gui_mouse_y(); + mz = gui_mouse_z(); + mb = gui_mouse_b(); + + return idle_count; +} + +int onGoFast() +{ + gofast=gofast?false:true; + return D_O_K; +} + +int onKillCheat() +{ + for(int i=0; iflags & guy_doesntcount))((enemy*)guys.spr(i))->kickbucket(); + } + + return D_O_K; +} + +int onShowLayer0() +{ + show_layer_0 = !show_layer_0; + return D_O_K; +} +int onShowLayer1() +{ + show_layer_1 = !show_layer_1; + return D_O_K; +} +int onShowLayer2() +{ + show_layer_2 = !show_layer_2; + return D_O_K; +} +int onShowLayer3() +{ + show_layer_3 = !show_layer_3; + return D_O_K; +} +int onShowLayer4() +{ + show_layer_4 = !show_layer_4; + return D_O_K; +} +int onShowLayer5() +{ + show_layer_5 = !show_layer_5; + return D_O_K; +} +int onShowLayer6() +{ + show_layer_6 = !show_layer_6; + return D_O_K; +} +int onShowLayerO() +{ + show_layer_over=!show_layer_over; + return D_O_K; +} +int onShowLayerP() +{ + show_layer_push=!show_layer_push; + return D_O_K; +} +int onShowLayerS() +{ + show_sprites=!show_sprites; + return D_O_K; +} +int onShowLayerF() +{ + show_ffcs=!show_ffcs; + return D_O_K; +} +int onShowLayerW() +{ + show_walkflags=!show_walkflags; + return D_O_K; +} +int onShowFFScripts() +{ + show_ff_scripts=!show_ff_scripts; + return D_O_K; +} +int onShowHitboxes() +{ + show_hitboxes=!show_hitboxes; + return D_O_K; +} + +int onLightSwitch() +{ + do_cheat_light=true; + return D_O_K; +} + +int onGoTo(); +int onGoToComplete(); + +void syskeys() +{ + int oldtitle_version; + + if(close_button_quit) + { + close_button_quit=false; + f_Quit(qEXIT); + } + + poll_joystick(); + + if(rMbtn() || (gui_mouse_b() && !mouse_down && ClickToFreeze &&!disableClickToFreeze)) + { + oldtitle_version=title_version; + System(); + } + + mouse_down=gui_mouse_b(); + + if(ReadKey(KEY_F1)) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + halt=!halt; + //zinit.subscreen=(zinit.subscreen+1)%ssdtMAX; + } + else + { + Throttlefps=!Throttlefps; + logic_counter=0; + } + } + + // if(ReadKey(KEY_F1)) Vsync=!Vsync; + /* + if(ReadKey(KEY_F1)) set_bit(QHeader.rules4,qr4_NEWENEMYTILES, + 1-((get_bit(QHeader.rules4,qr4_NEWENEMYTILES)))); + */ + + if(ReadKey(KEY_OPENBRACE)) if(frame_rest_suggest > 0) frame_rest_suggest--; + + if(ReadKey(KEY_CLOSEBRACE)) if(frame_rest_suggest <= 2) frame_rest_suggest++; + + if(ReadKey(KEY_F2)) ShowFPS=!ShowFPS; + + if(ReadKey(KEY_F3) && Playing) Paused=!Paused; + + if(ReadKey(KEY_F4) && Playing) + { + Paused=true; + Advance=true; + } + + if(ReadKey(KEY_F6)) if(!get_bit(quest_rules, qr_NOCONTINUE)) f_Quit(qQUIT); + +#ifndef ALLEGRO_MACOSX + if(ReadKey(KEY_F9)) f_Quit(qRESET); + + if(ReadKey(KEY_F10)) f_Quit(qEXIT); +#else + if(ReadKey(KEY_F7)) f_Quit(qRESET); + + if(ReadKey(KEY_F8)) f_Quit(qEXIT); +#endif + if(rF5()&&(Playing && currscr<128 && DMaps[currdmap].flags&dmfVIEWMAP)) onSaveMapPic(); + + if(rF12()) + { + onSnapshot(); + } + + if(debug_enabled && ReadKey(KEY_TAB)) + set_debug(!get_debug()); + + if(get_debug() || cheat>=1) + { + if(ReadKey(KEY_ASTERISK) || ReadKey(KEY_H)) game->set_life(game->get_maxlife()); + + if(ReadKey(KEY_SLASH_PAD) || ReadKey(KEY_M)) game->set_magic(game->get_maxmagic()); + + if(ReadKey(KEY_R)) game->set_drupy(999); + + if(ReadKey(KEY_B)) + { + onCheatBombs(); + } + + if(ReadKey(KEY_A)) + { + onCheatArrows(); + } + } + + if(get_debug() || cheat>=2) + { + if(rI()) + { + setClock(!getClock()); + cheat_superman=getClock(); + } + } + + if(get_debug() || cheat>=4) + { + if(rF11()) + { + onNoWalls(); + } + + if(rQ()) + { + onGoFast(); + } + + if(ReadKey(KEY_F)) + { + if(Link.getAction()==freeze) + { + Link.unfreeze(); + } + else + { + Link.Freeze(); + } + } + + if(ReadKey(KEY_G)) onGoToComplete(); + + if(ReadKey(KEY_0)) onShowLayer0(); + + if(ReadKey(KEY_1)) onShowLayer1(); + + if(ReadKey(KEY_2)) onShowLayer2(); + + if(ReadKey(KEY_3)) onShowLayer3(); + + if(ReadKey(KEY_4)) onShowLayer4(); + + if(ReadKey(KEY_5)) onShowLayer5(); + + if(ReadKey(KEY_6)) onShowLayer6(); + + //if(ReadKey(KEY_7)) onShowLayerO(); + if(ReadKey(KEY_7)) onShowLayerF(); + + if(ReadKey(KEY_8)) onShowLayerS(); + + if(ReadKey(KEY_W)) onShowLayerW(); + + if(ReadKey(KEY_L)) onLightSwitch(); + } + + if(volkeys) + { + if(ReadKey(KEY_PGUP)) master_volume(-1,midi_volume+8); + + if(ReadKey(KEY_PGDN)) master_volume(-1,midi_volume==255?248:midi_volume-8); + + if(ReadKey(KEY_HOME)) master_volume(digi_volume+8,-1); + + if(ReadKey(KEY_END)) master_volume(digi_volume==255?248:digi_volume-8,-1); + } + + if(!get_debug() || !SystemKeys) + goto bottom; + + if(ReadKey(KEY_D)) + { + details = !details; + rectfill(screen,0,0,319,7,BLACK); + rectfill(screen,0,8,31,239,BLACK); + rectfill(screen,288,8,319,239,BLACK); + rectfill(screen,32,232,287,239,BLACK); + } + + if(ReadKey(KEY_V)) + { + Throttlefps=!Throttlefps; + /* + remove_int(fps_callback); + + install_int_ex(fps_callback,SECS_TO_TIMER(1)); + */ + avgfps=fps_secs=framecnt=0; + logic_counter = 0; + } + + if(ReadKey(KEY_P)) Paused=!Paused; + + if(ReadKey(KEY_A)) + { + Paused=true; + Advance=true; + } + + if(ReadKey(KEY_G)) db=(db==999)?0:999; +#ifndef ALLEGRO_MACOSX + if(ReadKey(KEY_F8)) Showpal=!Showpal; + + if(ReadKey(KEY_F7)) + { + Matrix(ss_speed, ss_density, 0); + game_pal(); + } +#else + // The reason these are different on Mac in the first place is that + // the OS doesn't let us use F9 and F10... + if(ReadKey(KEY_F10)) Showpal=!Showpal; + + if(ReadKey(KEY_F9)) + { + Matrix(ss_speed, ss_density, 0); + game_pal(); + } +#endif + if(ReadKey(KEY_PLUS_PAD) || ReadKey(KEY_EQUALS)) + { + //change containers + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + //magic containers + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + game->set_maxmagic(zc_min(game->get_maxmagic()+MAGICPERBLOCK,MAGICPERBLOCK*8)); + } + else + { + game->set_maxlife(zc_min(game->get_maxlife()+HP_PER_HEART,HP_PER_HEART*24)); + } + } + else + { + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + game->set_magic(zc_min(game->get_magic()+1,game->get_maxmagic())); + } + else + { + game->set_life(zc_min(game->get_life()+1,game->get_maxlife())); + } + } + } + + if(ReadKey(KEY_MINUS_PAD) || ReadKey(KEY_MINUS)) + { + //change containers + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + //magic containers + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + game->set_maxmagic(zc_max(game->get_maxmagic()-MAGICPERBLOCK,0)); + game->set_magic(zc_min(game->get_maxmagic(), game->get_magic())); + //heart containers + } + else + { + game->set_maxlife(zc_max(game->get_maxlife()-HP_PER_HEART,HP_PER_HEART)); + game->set_life(zc_min(game->get_maxlife(), game->get_life())); + } + } + else + { + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + game->set_magic(zc_max(game->get_magic()-1,0)); + } + else + { + game->set_life(zc_max(game->get_life()-1,0)); + } + } + } + + if(ReadKey(KEY_COMMA)) jukebox(currmidi-1); + + if(ReadKey(KEY_STOP)) jukebox(currmidi+1); + + /* + if(ReadKey(KEY_TILDE)) { + wavyout(); + zinit.subscreen=(zinit.subscreen+1)%3; + wavyin(); + } + */ + + verifyBothWeapons(); + +bottom: + + if(input_idle(true) > after_time()) + { + Matrix(ss_speed, ss_density, 0); + game_pal(); + } + + //while(Playing && keypressed()) + //readkey(); + // What's the Playing check for? + clear_keybuf(); +} + +// 99*360 + 59*60 +#define MAXTIME 21405240 + +void advanceframe(bool allowwavy, bool sfxcleanup) +{ + if(zcmusic!=NULL) + { + zcmusic_poll(); + } + + while(Paused && !Advance && !Quit) + { + // have to call this, otherwise we'll get an infinite loop + syskeys(); + // to keep fps constant + updatescr(allowwavy); + throttleFPS(); + +#ifdef _WIN32 + + if(use_dwm_flush) + { + do_DwmFlush(); + } + +#endif + + // to keep music playing + if(zcmusic!=NULL) + { + zcmusic_poll(); + } + } + + if(Quit && Quit!=qGAMEOVER) + return; + + if(Playing && game->get_time()change_time(1); + + Advance=false; + ++frame; + + syskeys(); + // Someday... maybe install a Turbo button here? + updatescr(allowwavy); + throttleFPS(); + +#ifdef _WIN32 + + if(use_dwm_flush) + { + do_DwmFlush(); + } + +#endif + + //textprintf_ex(screen,font,0,72,254,BLACK,"%d %d", lastentrance, lastentrance_dmap); + if(sfxcleanup) + sfx_cleanup(); +} + +void zapout() +{ + set_clip_rect(scrollbuf, 0, 0, scrollbuf->w, scrollbuf->h); + blit(framebuf,scrollbuf,0,0,256,0,256,224); + + script_drawing_commands.Clear(); + + // zap out + for(int i=1; i<=24; i++) + { + draw_fuzzy(i); + syskeys(); + advanceframe(true); + + if(Quit) + { + break; + } + } +} + +void zapin() +{ + draw_screen(tmpscr); + set_clip_rect(scrollbuf, 0, 0, scrollbuf->w, scrollbuf->h); + put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + blit(framebuf,scrollbuf,0,0,256,0,256,224); + + // zap out + for(int i=24; i>=1; i--) + { + draw_fuzzy(i); + syskeys(); + advanceframe(true); + + if(Quit) + { + break; + } + } +} + + +void wavyout(bool showlink) +{ + draw_screen(tmpscr, showlink); + put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + + BITMAP *wavebuf = create_bitmap_ex(8,288,224); + clear_to_color(wavebuf,0); + blit(framebuf,wavebuf,0,0,16,0,256,224); + + PALETTE wavepal; + + int ofs; + int amplitude=8; + + int wavelength=4; + double palpos=0, palstep=4, palstop=126; + + for(int i=0; i<168; i+=wavelength) + { + for(int l=0; l<256; l++) + { + wavepal[l].r=vbound(int(RAMpal[l].r+((palpos/palstop)*(63-RAMpal[l].r))),0,63); + wavepal[l].g=vbound(int(RAMpal[l].g+((palpos/palstop)*(63-RAMpal[l].g))),0,63); + wavepal[l].b=vbound(int(RAMpal[l].b+((palpos/palstop)*(63-RAMpal[l].b))),0,63); + } + + palpos+=palstep; + + if(palpos>=0) + { + set_palette(wavepal); + } + else + { + set_palette(RAMpal); + } + + for(int j=0; j+playing_field_offset<224; j++) + { + for(int k=0; k<256; k++) + { + ofs=0; + + if((jline[j+playing_field_offset][k]=wavebuf->line[j+playing_field_offset][k+ofs+16]; + } + } + + syskeys(); + advanceframe(true); + + // animate_combos(); + if(Quit) + break; + } + + destroy_bitmap(wavebuf); +} + +void wavyin() +{ + draw_screen(tmpscr); + put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + + BITMAP *wavebuf = create_bitmap_ex(8,288,224); + clear_to_color(wavebuf,0); + blit(framebuf,wavebuf,0,0,16,0,256,224); + + PALETTE wavepal; + + //Breaks dark rooms. + //In any case I don't think we need this, since palette is already loaded in doWarp() (famous last words...) -DD + /* + loadfullpal(); + loadlvlpal(DMaps[currdmap].color); + ringcolor(false); + */ + refreshpal=false; + int ofs; + int amplitude=8; + int wavelength=4; + double palpos=168, palstep=4, palstop=126; + + for(int i=0; i<168; i+=wavelength) + { + for(int l=0; l<256; l++) + { + wavepal[l].r=vbound(int(RAMpal[l].r+((palpos/palstop)*(63-RAMpal[l].r))),0,63); + wavepal[l].g=vbound(int(RAMpal[l].g+((palpos/palstop)*(63-RAMpal[l].g))),0,63); + wavepal[l].b=vbound(int(RAMpal[l].b+((palpos/palstop)*(63-RAMpal[l].b))),0,63); + } + + palpos-=palstep; + + if(palpos>=0) + { + set_palette(wavepal); + } + else + { + set_palette(RAMpal); + } + + for(int j=0; j+playing_field_offset<224; j++) + { + for(int k=0; k<256; k++) + { + ofs=0; + + if((j<(167-i))&&(j&1)) + { + ofs=int(sin((double(i+j)*2*PI/168.0))*amplitude); + } + + framebuf->line[j+playing_field_offset][k]=wavebuf->line[j+playing_field_offset][k+ofs+16]; + } + } + + syskeys(); + advanceframe(true); + // animate_combos(); + + if(Quit) + break; + } + + destroy_bitmap(wavebuf); +} + +void blackscr(int fcnt,bool showsubscr) +{ + reset_pal_cycling(); + script_drawing_commands.Clear(); + + while(fcnt>0) + { + clear_bitmap(framebuf); + + if(showsubscr) + { + put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + } + + syskeys(); + advanceframe(true); + + if(Quit) + break; + + --fcnt; + } +} + +void openscreen() +{ + reset_pal_cycling(); + abortScreenWipe(); + + if(COOLSCROLL) + { + beginScreenWipeIn(LinkX()+8, (LinkY()-LinkZ())+8+playing_field_offset); + while(screenWipeIsActive()) + { + draw_screen(tmpscr); + put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + syskeys(); + advanceframe(true); + + if(Quit) + { + // Abort wipe? Probably doesn't matter. + break; + } + } + return; + } + else + { + Link.setDontDraw(true); + show_subscreen_dmap_dots=false; + show_subscreen_numbers=false; + // show_subscreen_items=false; + show_subscreen_life=false; + } + + int x=128; + + for(int i=0; i<80; i++) + { + draw_screen(tmpscr); + //? draw_screen already draws the subscreen -DD + //put_passive_subscr(framebuf,&QMisc,0,passive_subscreen_offset,false,sspUP); + x=128-(((i*128/80)/8)*8); + + if(x>0) + { + rectfill(framebuf,0,playing_field_offset,x,167+playing_field_offset,0); + rectfill(framebuf,256-x,playing_field_offset,255,167+playing_field_offset,0); + } + + // x=((80-i)/2)*4; + /* + --x; + switch(++c) + { + case 5: c=0; + case 0: + case 2: + case 3: --x; break; + } + */ + syskeys(); + advanceframe(true); + + if(Quit) + { + break; + } + } + + Link.setDontDraw(false); + show_subscreen_items=true; + show_subscreen_dmap_dots=true; +} + +int TriforceCount() +{ + int c=0; + + for(int i=1; i<=8; i++) + if(game->lvlitems[i]&liTRIFORCE) + ++c; + + return c; +} + +int onCustomGame() +{ + int file = getsaveslot(); + + if(file < 0) + return D_O_K; + + bool ret = (custom_game(file)!=0); + return ret ? D_CLOSE : D_O_K; +} + +int onContinue() +{ + return D_CLOSE; +} + +int onEsc() // Unused?? -L +{ + return key[KEY_ESC]?D_CLOSE:D_O_K; +} + +int onVsync() +{ + Throttlefps = !Throttlefps; + return D_O_K; +} + +int onClickToFreeze() +{ + ClickToFreeze = !ClickToFreeze; + return D_O_K; +} + +int onFrameSkip() +{ + FrameSkip = !FrameSkip; + return D_O_K; +} + +int onTransLayers() +{ + TransLayers = !TransLayers; + return D_O_K; +} + +int onNESquit() +{ + NESquit = !NESquit; + return D_O_K; +} + +int onVolKeys() +{ + volkeys = !volkeys; + return D_O_K; +} + +int onShowFPS() +{ + ShowFPS = !ShowFPS; + scare_mouse(); + + if(ShowFPS) + show_fps(screen); + + if(sbig) + stretch_blit(fps_undo,screen,0,0,64,16,scrx+40-120,scry+216+96,128,32); + else + blit(fps_undo,screen,0,0,scrx+40,scry+216,64,16); + + if(Paused) + show_paused(screen); + + unscare_mouse(); + return D_O_K; +} + +bool is_Fkey(int k) +{ + switch(k) + { + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + return true; + } + + return false; +} + +void kb_getkey(DIALOG *d) +{ + d->flags|=D_SELECTED; + + scare_mouse(); + jwin_button_proc(MSG_DRAW,d,0); + jwin_draw_win(screen, (resx-160)/2, (resy-48)/2, 160, 48, FR_WIN); + // text_mode(vc(11)); + textout_centre_ex(screen, font, "Press a key", resx/2, resy/2 - 8, jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_centre_ex(screen, font, "ESC to cancel", resx/2, resy/2, jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + unscare_mouse(); + + clear_keybuf(); + int k = next_press_key(); + clear_keybuf(); + + //shnarf + //47=f1 + //59=esc + if(k>0 && k<123 && !((k>46)&&(k<60))) + *((int*)d->dp3) = k; + + + d->flags&=~D_SELECTED; +} + +int d_kbutton_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_KEY: + case MSG_CLICK: + + kb_getkey(d); + + while(gui_mouse_b()) + clear_keybuf(); + + return D_REDRAW; + } + + return jwin_button_proc(msg,d,c); +} + +void j_getbtn(DIALOG *d) +{ + d->flags|=D_SELECTED; + scare_mouse(); + jwin_button_proc(MSG_DRAW,d,0); + jwin_draw_win(screen, (resx-160)/2, (resy-48)/2, 160, 48, FR_WIN); + // text_mode(vc(11)); + int y = resy/2 - 12; + textout_centre_ex(screen, font, "Press a button", resx/2, y, jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_centre_ex(screen, font, "ESC to cancel", resx/2, y+8, jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_centre_ex(screen, font, "SPACE to disable", resx/2, y+16, jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + unscare_mouse(); + + int b = next_press_btn(); + + if(b>=0) + *((int*)d->dp3) = b; + + d->flags&=~D_SELECTED; + + if(!player) //safety first... + player = init_dialog(d,-1); + + player->joy_on = TRUE; +} + +int d_jbutton_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_KEY: + case MSG_CLICK: + + j_getbtn(d); + + while(gui_mouse_b()) + clear_keybuf(); + + return D_REDRAW; + } + + return jwin_button_proc(msg,d,c); +} + +//shnarf +const char *key_str[] = +{ + "(none)", "a", "b", "c", + "d", "e", "f", "g", + "h", "i", "j", "k", + "l", "m", "n", "o", + "p", "q", "r", "s", + "t", "u", "v", "w", + "x", "y", "z", "0", + "1", "2", "3", "4", + "5", "6", "7", "8", + "9", "num 0", "num 1", "num 2", + "num 3", "num 4", "num 5", "num 6", + "num 7", "num 8", "num 9", "f1", + "f2", "f3", "f4", "f5", + "f6", "f7", "f8", "f9", + "f10", "f11", "f12", "esc", + "~", "-", "=", "backspace", + "tab", "{", "}", "enter", + ":", "quote", "\\", "\\ (2)", + ",", ".", "/", "space", + "insert", "delete", "home", "end", + "page up", "page down", "left", "right", + "up", "down", "num /", "num *", + "num -", "num +", "num delete", "num enter", + "print screen", "pause", "abnt c1", "yen", + "kana", "convert", "no convert", "at", + "circumflex", ": (2)", "kanji", "num =", + "back quote", ";", "command", "unknown (0)", + "unknown (1)", "unknown (2)", "unknown (3)", "unknown (4)", + "unknown (5)", "unknown (6)", "unknown (7)", "left shift", + "right shift", "left control", "right control", "alt", + "alt gr", "left win", "right win", "menu", + "scroll lock", "number lock", "caps lock", "MAX" +}; + +const char *pan_str[4] = { "MONO", " 1/2", " 3/4", "FULL" }; +//extern int zcmusic_bufsz; + +static char str_a[80],str_b[80],str_s[80],str_m[16],str_l[16],str_r[16],str_p[16],str_ex1[16],str_ex2[16],str_ex3[16],str_ex4[16]; + +int d_stringloader(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg==MSG_DRAW) + { + switch(d->w) + { + case 0: + sprintf(str_a,"%d\n%s",Akey,key_str[Akey]); + sprintf(str_b,"%d\n%s",Bkey,key_str[Bkey]); + sprintf(str_s,"%d\n%s",Skey,key_str[Skey]); + sprintf(str_l,"%d\n%s",Lkey,key_str[Lkey]); + sprintf(str_r,"%d\n%s",Rkey,key_str[Rkey]); + sprintf(str_p,"%d\n%s",Pkey,key_str[Pkey]); + sprintf(str_ex1,"%d\n%s",Pkey,key_str[Exkey1]); + sprintf(str_ex2,"%d\n%s",Pkey,key_str[Exkey2]); + sprintf(str_ex3,"%d\n%s",Pkey,key_str[Exkey3]); + sprintf(str_ex4,"%d\n%s",Pkey,key_str[Exkey4]); + break; + + case 1: + sprintf(str_a,"%d\n%s",DUkey,key_str[DUkey]); + sprintf(str_b,"%d\n%s",DDkey,key_str[DDkey]); + sprintf(str_l,"%d\n%s",DLkey,key_str[DLkey]); + sprintf(str_r,"%d\n%s",DRkey,key_str[DRkey]); + break; + + case 2: + sprintf(str_a,"%d",Abtn); + sprintf(str_b,"%d",Bbtn); + sprintf(str_s,"%d",Sbtn); + sprintf(str_l,"%d",Lbtn); + sprintf(str_r,"%d",Rbtn); + sprintf(str_m,"%d",Mbtn); + sprintf(str_p,"%d",Pbtn); + break; + + case 3: + sprintf(str_a,"%3d",midi_volume); + sprintf(str_b,"%3d",digi_volume); + sprintf(str_l,"%3d",emusic_volume); + sprintf(str_m,"%3dKB",zcmusic_bufsz); + sprintf(str_r,"%3d",sfx_volume); + strcpy(str_s,pan_str[pan_style]); + break; + + case 4: + sprintf(str_ex1,"%d",Exbtn1); + sprintf(str_ex2,"%d",Exbtn2); + sprintf(str_ex3,"%d",Exbtn3); + sprintf(str_ex4,"%d",Exbtn4); + } + } + + return D_O_K; +} + +int set_vol(void *dp3, int d2) +{ + switch(((int*)dp3)[0]) + { + case 0: + midi_volume = zc_min(d2<<3,255); + break; + + case 1: + digi_volume = zc_min(d2<<3,255); + break; + + case 2: + emusic_volume = zc_min(d2<<3,255); + break; + + case 3: + sfx_volume = zc_min(d2<<3,255); + break; + } + + scare_mouse(); + // text_mode(vc(11)); + textprintf_right_ex(screen,is_large ? lfont_l : font, ((int*)dp3)[1],((int*)dp3)[2],jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%3d",zc_min(d2<<3,255)); + unscare_mouse(); + return D_O_K; +} + +int set_pan(void *dp3, int d2) +{ + pan_style = vbound(d2,0,3); + scare_mouse(); + // text_mode(vc(11)); + textout_right_ex(screen,is_large ? lfont_l : font, pan_str[pan_style],((int*)dp3)[1],((int*)dp3)[2],jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + unscare_mouse(); + return D_O_K; +} + +int set_buf(void *dp3, int d2) +{ + scare_mouse(); + // text_mode(vc(11)); + zcmusic_bufsz = d2 + 1; + textprintf_right_ex(screen,is_large ? lfont_l : font, ((int*)dp3)[1],((int*)dp3)[2],jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%3dKB",zcmusic_bufsz); + unscare_mouse(); + return D_O_K; +} + +static DIALOG key_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 8, 44, 304, 228, 0, 0, 0, D_EXIT, 0, 0, (void *) "Keyboard Buttons", NULL, NULL }, + { d_stringloader, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 14, 70, 148, 105, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_frame_proc, 158, 70, 148, 105, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_frame_proc, 14, 171, 292, 67, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_text_proc, 30, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Standard", NULL, NULL }, + { jwin_text_proc, 175, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Extended", NULL, NULL }, + + { jwin_text_proc, 92, 92, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_a, NULL, NULL }, + { jwin_text_proc, 92, 120, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_b, NULL, NULL }, + { jwin_text_proc, 92, 148, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_s, NULL, NULL }, + { jwin_text_proc, 92, 180, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex1, NULL, NULL }, + { jwin_text_proc, 92, 212, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex3, NULL, NULL }, + { jwin_text_proc, 237, 92, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_l, NULL, NULL }, + { jwin_text_proc, 237, 120, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_r, NULL, NULL }, + { jwin_text_proc, 237, 148, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_p, NULL, NULL }, + { jwin_text_proc, 237, 180, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex2, NULL, NULL }, + { jwin_text_proc, 237, 212, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex4, NULL, NULL }, + + { d_kbutton_proc, 22, 90, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "A", NULL, &Akey}, + { d_kbutton_proc, 22, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "B", NULL, &Bkey}, + { d_kbutton_proc, 22, 146, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Start", NULL, &Skey}, + { d_kbutton_proc, 22, 178, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX1", NULL, &Exkey1}, + { d_kbutton_proc, 22, 210, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX3", NULL, &Exkey3}, + { d_kbutton_proc, 167, 90, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "L", NULL, &Lkey}, + { d_kbutton_proc, 167, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "R", NULL, &Rkey}, + { d_kbutton_proc, 167, 146, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Map", NULL, &Pkey}, + { d_kbutton_proc, 167, 178, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX2", NULL, &Exkey2}, + { d_kbutton_proc, 167, 210, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX4", NULL, &Exkey4}, + + { jwin_button_proc, 90, 240, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 240, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; +static DIALOG keydir_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 8, 44, 304, 172, 0, 0, 0, D_EXIT, 0, 0, (void *) "Keyboard Directions", NULL, NULL }, + { d_stringloader, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 14, 70, 147, 104, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_frame_proc, 159, 70, 147, 104, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_text_proc, 30, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Vertical", NULL, NULL }, + { jwin_text_proc, 175, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Horizontal", NULL, NULL }, + + { jwin_text_proc, 92, 92, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_a, NULL, NULL }, + { jwin_text_proc, 92, 120, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_b, NULL, NULL }, + { jwin_text_proc, 237, 92, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_l, NULL, NULL }, + { jwin_text_proc, 237, 120, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_r, NULL, NULL }, + + { d_kbutton_proc, 22, 90, 61, 21, vc(14), vc(11), 0, 0, 0, 0, (void *) "Up", NULL, &DUkey}, + { d_kbutton_proc, 22, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Down", NULL, &DDkey}, + { d_kbutton_proc, 167, 90, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Left", NULL, &DLkey}, + { d_kbutton_proc, 167, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Right", NULL, &DRkey}, + // 14 + { jwin_button_proc, 90, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG btn_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 8, 44, 304, 172, 0, 0, 0, D_EXIT, 0, 0, (void *) "Joystick/Gamepad Buttons", NULL, NULL }, + { d_stringloader, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 159, 70, 147, 104, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_frame_proc, 14, 70, 147, 132, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_ctext_proc, 22+31, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Button", NULL, NULL }, + { jwin_ctext_proc, 167+31, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Button", NULL, NULL }, + + { jwin_ctext_proc, 100+20, 96, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_a, NULL, NULL }, + { jwin_ctext_proc, 100+20, 124, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_b, NULL, NULL }, + { jwin_ctext_proc, 100+20, 152, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_s, NULL, NULL }, + { jwin_ctext_proc, 100+20, 180, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_m, NULL, NULL }, + { jwin_ctext_proc, 245+20, 96, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_l, NULL, NULL }, + { jwin_ctext_proc, 245+20, 124, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_r, NULL, NULL }, + { jwin_ctext_proc, 245+20, 152, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_p, NULL, NULL }, + // 13 + { d_jbutton_proc, 22, 90, 61, 21, vc(14), vc(11), 0, 0, 0, 0, (void *) "A", NULL, &Abtn}, + { d_jbutton_proc, 22, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "B", NULL, &Bbtn}, + { d_jbutton_proc, 22, 146, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Start", NULL, &Sbtn}, + { d_jbutton_proc, 22, 174, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Menu", NULL, &Mbtn}, + { d_jbutton_proc, 167, 90, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "L", NULL, &Lbtn}, + { d_jbutton_proc, 167, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "R", NULL, &Rbtn}, + { d_jbutton_proc, 167, 146, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "Map", NULL, &Pbtn}, + // 20 + { jwin_button_proc, 170, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 240, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_ctext_proc, 100+20, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Stick/Pad", NULL, NULL }, + { jwin_ctext_proc, 245+20, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Stick/Pad", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG exbtn_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 8, 44, 304, 172, 0, 0, 0, D_EXIT, 0, 0, (void *) "Extra Joystick/Gamepad Buttons", NULL, NULL }, + { d_stringloader, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 159, 70, 147, 104, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_frame_proc, 14, 70, 147, 132, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_ctext_proc, 22+31, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Button", NULL, NULL }, + { jwin_ctext_proc, 167+31, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Button", NULL, NULL }, + + { jwin_ctext_proc, 100+20, 96, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex1, NULL, NULL }, + { jwin_ctext_proc, 100+20, 124, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex3, NULL, NULL }, + { jwin_ctext_proc, 245+20, 96, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex2, NULL, NULL }, + { jwin_ctext_proc, 245+20, 124, 60, 8, vc(7), vc(11), 0, 0, 0, 0, str_ex4, NULL, NULL }, + // 13 + { d_jbutton_proc, 22, 90, 61, 21, vc(14), vc(11), 0, 0, 0, 0, (void *) "EX1", NULL, &Exbtn1}, + { d_jbutton_proc, 22, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX3", NULL, &Exbtn3}, + { d_jbutton_proc, 167, 90, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX2", NULL, &Exbtn2}, + { d_jbutton_proc, 167, 118, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) "EX4", NULL, &Exbtn4}, + // 20 + { jwin_button_proc, 170, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 240, 184, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_ctext_proc, 100+20, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Stick/Pad", NULL, NULL }, + { jwin_ctext_proc, 245+20, 76, 160, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Stick/Pad", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +/* +int midi_dp[3] = {0,147,104}; +int digi_dp[3] = {1,147,120}; +int pan_dp[3] = {0,147,136}; +int buf_dp[3] = {0,147,152}; +*/ +int midi_dp[3] = {0,0,0}; +int digi_dp[3] = {1,0,0}; +int emus_dp[3] = {2,0,0}; +int buf_dp[3] = {0,0,0}; +int sfx_dp[3] = {3,0,0}; +int pan_dp[3] = {0,0,0}; + +static DIALOG sound_dlg[] = +{ + //(dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 320, 178, 0, 0, 0, D_EXIT, 0, 0, (void *) "Sound Settings", NULL, NULL }, + { d_stringloader, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 58, 148, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 138, 148, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 10, 28, 300, 112, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 190, 40, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_a, NULL, NULL }, + { jwin_rtext_proc, 190, 56, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_b, NULL, NULL }, + { jwin_rtext_proc, 190, 72, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_l, NULL, NULL }, + { jwin_rtext_proc, 190, 88, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_m, NULL, NULL }, + // 10 + { jwin_rtext_proc, 190, 104, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_r, NULL, NULL }, + { jwin_rtext_proc, 190, 120, 40, 8, vc(7), vc(11), 0, 0, 0, 0, (void *) str_s, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_slider_proc, 196, 40, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 32, 0, NULL, (void *) set_vol, midi_dp }, + { jwin_slider_proc, 196, 56, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 32, 0, NULL, (void *) set_vol, digi_dp }, + { jwin_slider_proc, 196, 72, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 32, 0, NULL, (void *) set_vol, emus_dp }, + { jwin_slider_proc, 196, 88, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 127, 0, NULL, (void *) set_buf, buf_dp }, + { jwin_slider_proc, 196, 104, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 32, 0, NULL, (void *) set_vol, sfx_dp }, + //20 + { jwin_slider_proc, 196, 120, 96, 8, vc(0), jwin_pal[jcBOX], 0, 0, 3, 0, NULL, (void *) set_pan, pan_dp }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 17, 40, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Master MIDI Volume", NULL, NULL }, + { jwin_text_proc, 17, 56, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Master Digi Volume", NULL, NULL }, + { jwin_text_proc, 17, 72, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Enhanced Music Volume", NULL, NULL }, + { jwin_text_proc, 17, 88, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Enhanced Music Buffer", NULL, NULL }, + { jwin_text_proc, 17, 104, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "SFX Volume", NULL, NULL }, + { jwin_text_proc, 17, 120, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "SFX Pan", NULL, NULL }, + //30 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, +}; + +static DIALOG about_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 68, 52, 184, 154, 0, 0, 0, D_EXIT, 0, 0, (void *) "About", NULL, NULL }, + { jwin_button_proc, 140, 176, 41, 21, vc(14), 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_ctext_proc, 160, 84, 0, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Zelda Classic", NULL, NULL }, + { jwin_ctext_proc, 160, 92, 0, 8, vc(0) , vc(11), 0, 0, 0, 0, str_s, NULL, NULL }, + { jwin_ctext_proc, 160, 100, 0, 8, vc(0) , vc(11), 0, 0, 0, 0, (void *) DATE_STR, NULL, NULL }, + { jwin_text_proc, 88, 124, 140, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Coded by:", NULL, NULL }, + { jwin_text_proc, 88, 132, 140, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) " Phantom Menace", NULL, NULL }, + { jwin_text_proc, 88, 144, 140, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Produced by:", NULL, NULL }, + { jwin_text_proc, 88, 152, 140, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) " Armageddon Games", NULL, NULL }, + { jwin_frame_proc, 80, 117, 160, 50, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG quest_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 68, 25, 184, 190, 0, 0, 0, D_EXIT, 0, 0, (void *) "Quest Info", NULL, NULL }, + { jwin_edit_proc, 84, 54, 152, 16, 0, 0, 0, D_READONLY, 100, 0, NULL, NULL, NULL }, + { jwin_text_proc, 89, 84, 141, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Number:", NULL, NULL }, + { jwin_text_proc, 152, 84, 24, 8, vc(7), vc(11), 0, 0, 0, 0, str_a, NULL, NULL }, + { jwin_text_proc, 89, 94, 141, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Version:", NULL, NULL }, + { jwin_text_proc, 160, 94, 64, 8, vc(7), vc(11), 0, 0, 0, 0, QHeader.version, NULL, NULL }, + { jwin_text_proc, 89, 104, 141, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "ZQ Version:", NULL, NULL }, + { jwin_text_proc, 184, 104, 64, 8, vc(7), vc(11), 0, 0, 0, 0, str_s, NULL, NULL }, + { jwin_text_proc, 84, 126, 80, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Title:", NULL, NULL }, + { jwin_textbox_proc, 84, 136, 152, 24, 0, 0, 0, 0, 0, 0, QHeader.title, NULL, NULL }, + { jwin_text_proc, 84, 168, 80, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Author:", NULL, NULL }, + { jwin_textbox_proc, 84, 178, 152, 24, 0, 0, 0, 0, 0, 0, QHeader.author, NULL, NULL }, + { jwin_frame_proc, 84, 79, 152, 38, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG triforce_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 64, 177, 105, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Triforce Pieces", NULL, NULL }, + // 1 + { jwin_check_proc, 129, 94, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "1", NULL, NULL }, + { jwin_check_proc, 129, 104, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "2", NULL, NULL }, + { jwin_check_proc, 129, 114, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "3", NULL, NULL }, + { jwin_check_proc, 129, 124, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "4", NULL, NULL }, + { jwin_check_proc, 172, 94, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "5", NULL, NULL }, + { jwin_check_proc, 172, 104, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "6", NULL, NULL }, + { jwin_check_proc, 172, 114, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "7", NULL, NULL }, + { jwin_check_proc, 172, 124, 24, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "8", NULL, NULL }, + // 9 + { jwin_button_proc, 90, 144, 61, 21, vc(0), vc(11), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 144, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +/*static DIALOG equip_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 16, 18, 289, 215, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Equipment", NULL, NULL }, + // 1 + { jwin_button_proc, 90, 206, 61, 21, vc(0), vc(11), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 206, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 3 + { jwin_frame_proc, 25, 45, 77, 50, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 29, 42, 40, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Sword", NULL, NULL }, + { jwin_check_proc, 33, 52, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Wooden", NULL, NULL }, + { jwin_check_proc, 33, 62, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "White", NULL, NULL }, + { jwin_check_proc, 33, 72, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Magic", NULL, NULL }, + { jwin_check_proc, 33, 82, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Master", NULL, NULL }, + // 9 + { jwin_frame_proc, 25, 99, 77, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 29, 96, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Shield", NULL, NULL }, + { jwin_check_proc, 33, 106, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Small", NULL, NULL }, + { jwin_check_proc, 33, 116, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Magic", NULL, NULL }, + { jwin_check_proc, 33, 126, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Mirror", NULL, NULL }, + // 14 + { jwin_frame_proc, 25, 143, 61, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 29, 140, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Ring", NULL, NULL }, + { jwin_check_proc, 33, 150, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Blue", NULL, NULL }, + { jwin_check_proc, 33, 160, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Red", NULL, NULL }, + { jwin_check_proc, 33, 170, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Gold", NULL, NULL }, + // 19 + { jwin_frame_proc, 110, 45, 85, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 114, 42, 64, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Bracelet", NULL, NULL }, + { jwin_check_proc, 118, 52, 72, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Level 1", NULL, NULL }, + { jwin_check_proc, 118, 62, 72, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Level 2", NULL, NULL }, + // 23 + { jwin_frame_proc, 110, 79, 85, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 114, 76, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Amulet", NULL, NULL }, + { jwin_check_proc, 118, 86, 72, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Level 1", NULL, NULL }, + { jwin_check_proc, 118, 96, 72, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Level 2", NULL, NULL }, + // 27 + { jwin_frame_proc, 110, 113, 69, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 114, 110, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Wallet", NULL, NULL }, + { jwin_check_proc, 118, 120, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Small", NULL, NULL }, + { jwin_check_proc, 118, 130, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Large", NULL, NULL }, + // 31 + { jwin_frame_proc, 110, 147, 69, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 114, 144, 24, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Bow", NULL, NULL }, + { jwin_check_proc, 118, 154, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Small", NULL, NULL }, + { jwin_check_proc, 118, 164, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Large", NULL, NULL }, + // 35 + { jwin_frame_proc, 203, 45, 93, 70, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 207, 42, 40, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Other", NULL, NULL }, + { jwin_check_proc, 211, 52, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Raft", NULL, NULL }, + { jwin_check_proc, 211, 62, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Ladder", NULL, NULL }, + { jwin_check_proc, 211, 72, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Book", NULL, NULL }, + { jwin_check_proc, 211, 82, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Magic Key", NULL, NULL }, + { jwin_check_proc, 211, 92, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Flippers", NULL, NULL }, + { jwin_check_proc, 211, 102, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Boots", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG items_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 16, 18, 289, 215, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Items", NULL, NULL }, + //1 + { jwin_button_proc, 90, 206, 61, 21, vc(0), vc(11), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 206, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 3 + { jwin_frame_proc, 27, 45, 77, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 31, 42, 64, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Boomerang", NULL, NULL }, + { jwin_check_proc, 35, 52, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Wooden", NULL, NULL }, + { jwin_check_proc, 35, 62, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Magic", NULL, NULL }, + { jwin_check_proc, 35, 72, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Fire", NULL, NULL }, + // 8 + { jwin_frame_proc, 27, 89, 77, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 31, 86, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Arrow", NULL, NULL }, + { jwin_check_proc, 35, 96, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Wooden", NULL, NULL }, + { jwin_check_proc, 35, 106, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Silver", NULL, NULL }, + { jwin_check_proc, 35, 116, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Golden", NULL, NULL }, + // 13 + { jwin_frame_proc, 27, 133, 63, 40, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 31, 130, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Potion", NULL, NULL }, + { jwin_radio_proc, 35, 140, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "None", NULL, NULL }, + { jwin_radio_proc, 35, 150, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Blue", NULL, NULL }, + { jwin_radio_proc, 35, 160, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Red", NULL, NULL }, + // 18 + { jwin_frame_proc, 114, 45, 93, 20, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 118, 42, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Whistle", NULL, NULL }, + { jwin_check_proc, 122, 52, 80, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Recorder", NULL, NULL }, + // 21 + { jwin_frame_proc, 114, 69, 86, 20, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 118, 66, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Hammer", NULL, NULL }, + { jwin_check_proc, 122, 76, 72, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Level 1", NULL, NULL }, + // 24 + { jwin_frame_proc, 114, 93, 69, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 118, 90, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Hookshot", NULL, NULL }, + { jwin_check_proc, 122, 100, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Short", NULL, NULL }, + { jwin_check_proc, 122, 110, 56, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Long", NULL, NULL }, + // 28 + { jwin_frame_proc, 114, 127, 60, 30, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 118, 124, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Candle", NULL, NULL }, + { jwin_check_proc, 122, 134, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Blue", NULL, NULL }, + { jwin_check_proc, 122, 144, 48, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Red", NULL, NULL }, + // 32 + { jwin_frame_proc, 217, 45, 77, 138, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 221, 42, 80, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Other", NULL, NULL }, + { jwin_check_proc, 225, 52, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Bait", NULL, NULL }, + { jwin_check_proc, 225, 62, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Letter", NULL, NULL }, + { jwin_check_proc, 225, 72, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Wand", NULL, NULL }, + { jwin_check_proc, 225, 82, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Lens", NULL, NULL }, + { jwin_check_proc, 225, 92, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Din's Fire", NULL, NULL }, + { jwin_check_proc, 225, 102, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Farore's Wind", NULL, NULL }, + { jwin_check_proc, 225, 112, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Nayru's Love", NULL, NULL }, + { jwin_text_proc, 225, 132, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "Bombs:", NULL, NULL }, + { jwin_edit_proc, 229, 142, 40, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_text_proc, 225, 162, 48, 9, vc(0), vc(11), 0, 0, 0, 0, (void *) "S-Bombs:", NULL, NULL }, + { jwin_edit_proc, 229, 162, 40, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_check_proc, 225, 122, 64, 9, vc(0), vc(11), 0, 0, 1, 0, (void *) "Cane of Byrna", NULL, NULL }, + //45 + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +};*/ + +static DIALOG credits_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 40, 38, 241, 173, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Zelda Classic Credits", NULL, NULL }, + { jwin_frame_proc, 47, 65, 227, 115, vc(15), vc(1), 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_bitmap_proc, 49, 67, 222, 110, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 140, 184, 41, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static ListData dmap_list(dmaplist, &font); + +static DIALOG goto_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 48, 25, 205, 100, 0, 0, 0, D_EXIT, 0, 0, (void *) "Goto Location", NULL, NULL }, + { jwin_button_proc, 90, 176-78, 61, 21, vc(14), 0, 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 176-78, 61, 21, vc(14), 0, 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 55, 129-75, 80, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_droplist_proc, 88, 126-75, 160, 16, 0, 0, 0, 0, 0, 0, (void *) &dmap_list, NULL, NULL }, + { jwin_text_proc, 55, 149-75, 80, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_edit_proc, 132, 146-75, 91, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int xtoi(char *hexstr) +{ + int val=0; + + while(isxdigit(*hexstr)) + { + val<<=4; + + if(*hexstr<='9') + val += *hexstr-'0'; + else val+= ((*hexstr)|0x20)-'a'+10; + + ++hexstr; + } + + return val; +} + +int onGoTo() +{ + bool music = false; + music = music; + sprintf(cheat_goto_screen_str,"%X",cheat_goto_screen); + + goto_dlg[0].dp2=lfont; + goto_dlg[4].d2=cheat_goto_dmap; + goto_dlg[6].dp=cheat_goto_screen_str; + + clear_keybuf(); + + if(is_large) + large_dialog(goto_dlg); + + if(zc_popup_dialog(goto_dlg,4)==1) + { + cheat_goto_dmap=goto_dlg[4].d2; + cheat_goto_screen=zc_min(xtoi(cheat_goto_screen_str),0x7F); + do_cheat_goto=true; + }; + + return D_O_K; +} + +int onGoToComplete() +{ + if(!Playing) + { + return D_O_K; + } + + system_pal(); + music_pause(); + pause_all_sfx(); + show_mouse(screen); + onGoTo(); + eat_buttons(); + + if(key[KEY_ESC]) + key[KEY_ESC]=0; + + show_mouse(NULL); + game_pal(); + music_resume(); + resume_all_sfx(); + return D_O_K; +} + +int onCredits() +{ + go(); + + BITMAP *win = create_bitmap_ex(8,222,110); + + if(!win) + return D_O_K; + + int c=0; + int l=0; + int ol=-1; + RLE_SPRITE *rle = (RLE_SPRITE*)(data[RLE_CREDITS].dat); + RGB *pal = (RGB*)(data[PAL_CREDITS].dat); + PALETTE tmppal; + + clear_bitmap(win); + draw_rle_sprite(win,rle,0,0); + credits_dlg[0].dp2=lfont; + credits_dlg[1].fg = gui_mg_color; + credits_dlg[2].dp = win; + set_palette_range(black_palette,0,127,false); + + DIALOG_PLAYER *p = init_dialog(credits_dlg,3); + + while(update_dialog(p)) + { + throttleFPS(); + ++c; + l = zc_max((c>>1)-30,0); + + if(l > rle->h) + l = c = 0; + + if(l > rle->h - 112) + l = rle->h - 112; + + clear_bitmap(win); + draw_rle_sprite(win,rle,0,0-l); + + if(c<=64) + fade_interpolate(black_palette,pal,tmppal,c,0,127); + + set_palette_range(tmppal,0,127,false); + + if(l!=ol) + { + scare_mouse(); + d_bitmap_proc(MSG_DRAW,credits_dlg+2,0); + unscare_mouse(); + SCRFIX(); + ol=l; + } + } + + shutdown_dialog(p); + destroy_bitmap(win); + comeback(); + return D_O_K; +} + +const char *midilist(int index, int *list_size) +{ + if(index<0) + { + *list_size=0; + + for(int i=0; id2; + int ret = jwin_droplist_proc(msg,d,c); + + if(d2!=d->d2) + { + get_info(d->d2); + } + + return ret; +} + +int d_listen_proc(int msg,DIALOG *d,int c) +{ + /* 'd->d1' is offset from 'd' in DIALOG array to midilist proc */ + + int ret = jwin_button_proc(msg,d,c); + + if(ret == D_CLOSE) + { + // get current midi index + int index = (d+(d->d1))->d2; + int i=0, m=0; + + while(m<=index && i<=MAXMIDIS) + { + if(tunes[i].data) + ++m; + + ++i; + } + + --i; + jukebox(i); + listening = true; + ret = D_O_K; + } + + return ret; +} + +int d_savemidi_proc(int msg,DIALOG *d,int c) +{ + /* 'd->d1' is offset from 'd' in DIALOG array to midilist proc */ + + int ret = jwin_button_proc(msg,d,c); + + if(ret == D_CLOSE) + { + // get current midi index + int index = (d+(d->d1))->d2; + int i=0, m=0; + + while(m<=index && i<=MAXMIDIS) + { + if(tunes[i].data) + ++m; + + ++i; + } + + --i; + + // get file name + + int sel=0; + //struct ffblk f; + char title[40] = "Save MIDI: "; + static char fname[2048] = ""; + static EXT_LIST list[] = + { + { (char *)"MIDI files (*.mid)", (char *)"mid" }, + { (char *)"HTML files (*.html, *.html)", (char *)"htm html" }, + { NULL, NULL } + }; + + strcpy(title+11, tunes[i].title); + + if(jwin_file_browse_ex(title, fname, list, &sel, 2048, -1, -1, lfont)==0) + goto done; + + if(exists(fname)) + { + if(jwin_alert(title, fname, "already exists.", "Overwrite it?", "&Yes","&No",'y','n',lfont)==2) + goto done; + } + + // save midi i + + if(save_midi(fname, (MIDI*)tunes[i].data) != 0) + jwin_alert(title, "Error saving MIDI to", fname, NULL, "Darn", NULL,13,27,lfont); + +done: + chop_path(fname); + ret = D_REDRAW; + } + + return ret; +} + +static ListData midi_list(midilist, &font); + +static DIALOG midi_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 8, 28, 304, 184, 0, 0, 0, D_EXIT, 0, 0, (void *) "MIDI Info", NULL, NULL }, + { jwin_text_proc, 32, 60, 40, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Tune:", NULL, NULL }, + { d_midilist_proc, 80, 56, 192, 16, 0, 0, 0, 0, 0, 0, (void *) &midi_list, NULL, NULL }, + { jwin_textbox_proc, 15, 80, 290, 96, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_listen_proc, 24, 183, 72, 21, 0, 0, 'l', D_EXIT, -2, 0, (void *) "&Listen", NULL, NULL }, + { d_savemidi_proc, 108, 183, 72, 21, 0, 0, 's', D_EXIT, -3, 0, (void *) "&Save", NULL, NULL }, + { jwin_button_proc, 236, 183, 61, 21, 0, 0, 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void get_info(int index) +{ + int i=0, m=0; + + while(m<=index && i<=MAXMIDIS) + { + if(tunes[i].data) + ++m; + + ++i; + } + + --i; + + if(i==MAXMIDIS && m= 0) ? D_DISABLED : D_EXIT; + midi_dlg[5].flags = (tunes[midi_dlg[2].d1].flags&tfDISABLESAVE) ? D_DISABLED : D_EXIT; + + listening = false; + dialog_running=false; + get_info(0); + + dialog_running=true; + + if(is_large) + large_dialog(midi_dlg); + + zc_popup_dialog(midi_dlg,0); + dialog_running=false; + + if(listening) + music_stop(); + + zc_free(text); + zc_free(zmi); + return D_O_K; +} + +int onAbout() +{ + switch(IS_BETA) + { + case 1: + sprintf(str_s,"%s Beta Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case -1: + sprintf(str_s,"%s Alpha Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case 0: + default: + sprintf(str_s,"%s Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + } + + // sprintf(str_s,"%s",VerStr(ZELDA_VERSION)); + about_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(about_dlg); + + zc_popup_dialog(about_dlg,1); + return D_O_K; +} + +int onQuest() +{ + char fname[100]; + strcpy(fname, get_filename(qstpath)); + quest_dlg[0].dp2=lfont; + quest_dlg[1].dp = fname; + + if(QHeader.quest_number==0) + sprintf(str_a,"Custom"); + else + sprintf(str_a,"%d",QHeader.quest_number); + + sprintf(str_s,"%s",VerStr(QHeader.zelda_version)); + + quest_dlg[11].d1 = quest_dlg[9].d1 = 0; + quest_dlg[11].d2 = quest_dlg[9].d2 = 0; + + if(is_large) + large_dialog(quest_dlg); + + zc_popup_dialog(quest_dlg, 0); + return D_O_K; +} + +int onVidMode() +{ + int VidMode=gfx_driver->id; +#ifdef ALLEGRO_DOS + + switch(VidMode) + { + case GFX_MODEX: + sprintf(str_a,"VGA Mode X"); + break; + + case GFX_VESA1: + sprintf(str_a,"VESA 1.x"); + break; + + case GFX_VESA2B: + sprintf(str_a,"VESA2 Banked"); + break; + + case GFX_VESA2L: + sprintf(str_a,"VESA2 Linear"); + break; + + case GFX_VESA3: + sprintf(str_a,"VESA3"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_WINDOWS) + + switch(VidMode) + { + case GFX_DIRECTX: + sprintf(str_a,"DirectX Hardware Accelerated"); + break; + + case GFX_DIRECTX_SOFT: + sprintf(str_a,"DirectX Software Accelerated"); + break; + + case GFX_DIRECTX_SAFE: + sprintf(str_a,"DirectX Safe"); + break; + + case GFX_DIRECTX_WIN: + sprintf(str_a,"DirectX Windowed"); + break; + + case GFX_GDI: + sprintf(str_a,"GDI"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_MACOSX) + + switch(VidMode) + { + case GFX_SAFE: + sprintf(str_a,"MacOS X Safe"); + break; + + case GFX_QUARTZ_FULLSCREEN: + sprintf(str_a,"MacOS X Fullscreen Quartz"); + break; + + case GFX_QUARTZ_WINDOW: + sprintf(str_a,"MacOS X Windowed Quartz"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_LINUX) + + switch(VidMode) + { + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#endif + + sprintf(str_b,"%dx%d 8-bit",resx,resy); + jwin_alert("Video Mode",str_a,str_b,NULL,"OK",NULL,13,27,lfont); + return D_O_K; +} + +#define addToHash(c,b,h) if(h->find(c ## key) == h->end()) \ +{(*h)[c ## key]=true;} else {b = false;} + +int onKeyboard() +{ + int a = Akey; + int b = Bkey; + int s = Skey; + int l = Lkey; + int r = Rkey; + int p = Pkey; + int ex1 = Exkey1; + int ex2 = Exkey2; + int ex3 = Exkey3; + int ex4 = Exkey4; + bool done=false; + int ret; + + key_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(key_dlg); + + while(!done) + { + ret = zc_popup_dialog(key_dlg,27); + + if(ret==27) // OK + { + std::map *keyhash = new std::map(); + bool unique = true; + addToHash(A,unique,keyhash); + addToHash(B,unique,keyhash); + addToHash(S,unique,keyhash); + addToHash(L,unique,keyhash); + addToHash(R,unique,keyhash); + addToHash(P,unique,keyhash); + addToHash(DU,unique,keyhash); + addToHash(DD,unique,keyhash); + addToHash(DL,unique,keyhash); + addToHash(DR,unique,keyhash); + + if(keyhash->find(Exkey1) == keyhash->end()) + { + (*keyhash)[Exkey1]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey2) == keyhash->end()) + { + (*keyhash)[Exkey2]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey3) == keyhash->end()) + { + (*keyhash)[Exkey3]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey4) == keyhash->end()) + { + (*keyhash)[Exkey4]=true; + } + else + { + unique = false; + } + + delete keyhash; + + if(unique) + done=true; + else + jwin_alert("Error", "Key bindings must be unique!", "", "", "OK",NULL,'o',0,lfont); + } + else // Cancel + { + Akey = a; + Bkey = b; + Skey = s; + Lkey = l; + Rkey = r; + Pkey = p; + Exkey1 = ex1; + Exkey2 = ex2; + Exkey3 = ex3; + Exkey4 = ex4; + done=true; + } + } + + save_game_configs(); + return D_O_K; +} + +int onKeyboardDir() +{ + int u = DUkey; + int d = DDkey; + int l = DLkey; + int r = DRkey; + + keydir_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(keydir_dlg); + + bool done=false; + int ret; + + key_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(key_dlg); + + while(!done) + { + ret = zc_popup_dialog(keydir_dlg,14); + + if(ret==14) // OK + { + std::map *keyhash = new std::map(); + bool unique = true; + addToHash(A,unique,keyhash); + addToHash(B,unique,keyhash); + addToHash(S,unique,keyhash); + addToHash(L,unique,keyhash); + addToHash(R,unique,keyhash); + addToHash(P,unique,keyhash); + addToHash(DU,unique,keyhash); + addToHash(DD,unique,keyhash); + addToHash(DL,unique,keyhash); + addToHash(DR,unique,keyhash); + + if(keyhash->find(Exkey1) == keyhash->end()) + { + (*keyhash)[Exkey1]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey2) == keyhash->end()) + { + (*keyhash)[Exkey2]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey3) == keyhash->end()) + { + (*keyhash)[Exkey3]=true; + } + else + { + unique = false; + } + + if(keyhash->find(Exkey4) == keyhash->end()) + { + (*keyhash)[Exkey4]=true; + } + else + { + unique = false; + } + + delete keyhash; + + if(unique) + done=true; + else + jwin_alert("Error", "Key bindings must be unique!", "", "", "OK",NULL,'o',0,lfont); + } + else // Cancel + { + DUkey = u; + DDkey = d; + DLkey = l; + DRkey = r; + done=true; + } + } + + save_game_configs(); + return D_O_K; +} + +int onJoystick() +{ + int a = Abtn; + int b = Bbtn; + int s = Sbtn; + int l = Lbtn; + int r = Rbtn; + int m = Mbtn; + int p = Pbtn; + + btn_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(btn_dlg); + + int ret = zc_popup_dialog(btn_dlg,20); + + // not OK'd + if(ret != 20) + { + Abtn = a; + Bbtn = b; + Sbtn = s; + Lbtn = l; + Rbtn = r; + Mbtn = m; + Pbtn = p; + } + + save_game_configs(); + return D_O_K; +} + +int onEXJoystick() +{ + int ex1 = Exbtn1; + int ex2 = Exbtn2; + int ex3 = Exbtn3; + int ex4 = Exbtn4; + + exbtn_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(exbtn_dlg); + + int ret = zc_popup_dialog(exbtn_dlg,14); + + // not OK'd + if(ret != 14) + { + Exbtn1 = ex1; + Exbtn2 = ex2; + Exbtn3 = ex3; + Exbtn4 = ex4; + } + + save_game_configs(); + return D_O_K; +} + +int onSound() +{ + int m = midi_volume; + int d = digi_volume; + int e = emusic_volume; + int b = zcmusic_bufsz; + int s = sfx_volume; + int p = pan_style; + pan_style = vbound(pan_style,0,3); + + sound_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(sound_dlg); + + midi_dp[1] = sound_dlg[6].x; + midi_dp[2] = sound_dlg[6].y; + digi_dp[1] = sound_dlg[7].x; + digi_dp[2] = sound_dlg[7].y; + emus_dp[1] = sound_dlg[8].x; + emus_dp[2] = sound_dlg[8].y; + buf_dp[1] = sound_dlg[9].x; + buf_dp[2] = sound_dlg[9].y; + sfx_dp[1] = sound_dlg[10].x; + sfx_dp[2] = sound_dlg[10].y; + pan_dp[1] = sound_dlg[11].x; + pan_dp[2] = sound_dlg[11].y; + sound_dlg[15].d2 = (midi_volume==255) ? 32 : midi_volume>>3; + sound_dlg[16].d2 = (digi_volume==255) ? 32 : digi_volume>>3; + sound_dlg[17].d2 = (emusic_volume==255) ? 32 : emusic_volume>>3; + sound_dlg[18].d2 = zcmusic_bufsz; + sound_dlg[19].d2 = (sfx_volume==255) ? 32 : sfx_volume>>3; + sound_dlg[20].d2 = pan_style; + + int ret = zc_popup_dialog(sound_dlg,1); + + if(ret==2) + { + master_volume(digi_volume,midi_volume); + set_all_voice_volume(sfx_volume); + } + else + { + midi_volume = m; + digi_volume = d; + emusic_volume = e; + zcmusic_bufsz = b; + sfx_volume = s; + pan_style = p; + } + + return D_O_K; +} + +int queding(const char *s1,char *s2,char *s3) +{ + return jwin_alert(ZC_str,s1,s2,s3,"&Yes","&No",'y','n',lfont); +} + +int onQuit() +{ + if(Playing) + { + int ret=0; + + if(get_bit(quest_rules, qr_NOCONTINUE)) + { + if(standalone_mode) + { + ret=queding("End current game?", + "The continue screen is disabled; the game", + "will be reloaded from the last save."); + } + else + { + ret=queding("End current game?", + "The continue screen is disabled. You will", + "be returned to the file select screen."); + } + } + else + ret=queding("End current game?",NULL,NULL); + + if(ret==1) + { + disableClickToFreeze=false; + Quit=qQUIT; + return D_CLOSE; + } + } + + return D_O_K; +} + +int onReset() +{ + if(queding(" Reset system? ",NULL,NULL)==1) + { + disableClickToFreeze=false; + Quit=qRESET; + return D_CLOSE; + } + + return D_O_K; +} + +int onExit() +{ + if(queding(" Quit Zelda Classic? ",NULL,NULL)==1) + { + Quit=qEXIT; + return D_CLOSE; + } + + return D_O_K; +} + +int onTitle_NES() +{ + title_version=0; + return D_O_K; +} +int onTitle_DX() +{ + title_version=1; + return D_O_K; +} +int onTitle_25() +{ + title_version=2; + return D_O_K; +} + +int onDebug() +{ + if(debug_enabled) + set_debug(!get_debug()); + + return D_O_K; +} + +int onHeartBeep() +{ + heart_beep=!heart_beep; + return D_O_K; +} + +int onSaveIndicator() +{ + use_save_indicator=!use_save_indicator; + return D_O_K; +} + +int onTriforce() +{ + for(int i=0; ilvlitems[i] & liTRIFORCE) ? D_SELECTED : 0; + + if(zc_popup_dialog (triforce_dlg,-1)==9) + { + for(int i=1; i<=8; i++) + { + game->lvlitems[i] &= ~liTRIFORCE; + game->lvlitems[i] |= (triforce_dlg[i].flags & D_SELECTED) ? liTRIFORCE : 0; + } + } + return D_O_K;*/ +} + +bool rc = false; +/* +int onEquipment() +{ + for (int i=0; iset_life(vbound(getnumber("Life",game->get_life()),1,game->get_maxlife())); + return D_O_K; +} + +int onHeartC() +{ + game->set_maxlife(vbound(getnumber("Heart Containers",game->get_maxlife()/HP_PER_HEART),1,4096) * HP_PER_HEART); + game->set_life(vbound(getnumber("Life",game->get_life()/HP_PER_HEART),1,game->get_maxlife()/HP_PER_HEART)*HP_PER_HEART); + return D_O_K; +} + +int onMagicC() +{ + game->set_maxmagic(vbound(getnumber("Magic Containers",game->get_maxmagic()/MAGICPERBLOCK),0,4096) * MAGICPERBLOCK); + game->set_magic(vbound(getnumber("Magic",game->get_magic()/MAGICPERBLOCK),0,game->get_maxmagic()/MAGICPERBLOCK)*MAGICPERBLOCK); + return D_O_K; +} + +int onRupies() +{ + game->set_rupies(vbound(getnumber("Rupees",game->get_rupies()),0,game->get_maxcounter(1))); + return D_O_K; +} + +int onMaxBombs() +{ + game->set_maxbombs(vbound(getnumber("Max Bombs",game->get_maxbombs()),8,99)); + game->set_bombs(game->get_maxbombs()); + return D_O_K; +} + +int onRefillLife() +{ + game->set_life(game->get_maxlife()); + return D_O_K; +} +int onRefillMagic() +{ + game->set_magic(game->get_maxmagic()); + return D_O_K; +} +int onClock() +{ + setClock(!getClock()); + return D_O_K; +} + +int onQstPath() +{ + char path[2048]; + + chop_path(qstdir); + strcpy(path,qstdir); + + go(); + + if(jwin_dfile_select_ex("Quest File Directory", path, "qst", 2048, -1, -1, lfont)) + { + chop_path(path); + fix_filename_case(path); + fix_filename_slashes(path); + strcpy(qstdir,path); + strcpy(qstpath,qstdir); + } + + comeback(); + return D_O_K; +} + +static DIALOG cheat_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 72, 176, 96, 0, 0, 0, D_EXIT, 0, 0, (void *) "Enter cheat code", NULL, NULL }, + { jwin_edit_proc, 88, 104, 144, 16, 0, 0, 0, 0, 40, 0, NULL, NULL, NULL }, + { jwin_button_proc, 130, 136, 61, 21, 0, 0, 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onCheat() +{ + if(!zcheats.flags && !get_debug()) + return D_O_K; + + str_a[0]=0; + cheat_dlg[0].dp2=lfont; + cheat_dlg[1].dp=str_a; + + if(is_large) + large_dialog(cheat_dlg); + + int ret=zc_popup_dialog(cheat_dlg,1); + + if((ret==2) && strlen(str_a)) + { + char str[80]; + + for(int i=0; i<4; i++) + { + if(!strcmp(str_a, zcheats.codes[i])) + { + cheat = i + 1; + game->set_cheat(game->get_cheat() | cheat); + sprintf(str, "Cheat level %d enabled", i+1); + jwin_alert("Cheats enabled",NULL,str,NULL,"OK",NULL,13,27,lfont); + goto done; + } + } + + jwin_alert("ZQuest",NULL,"Invalid cheat code",NULL,"OK",NULL,13,27,lfont); + } + +done: + return D_O_K; +} + +int onCheatRupies() +{ + game->set_drupy(game->get_maxcounter(1)); + return D_O_K; +} + +int onCheatArrows() +{ + game->set_arrows(game->get_maxarrows()); + return D_O_K; +} + +int onCheatBombs() +{ + //getitem(iBombs,true); + for(int i=0; iset_bombs(game->get_maxbombs()); + game->set_sbombs(game->get_maxcounter(6)); + return D_O_K; +} + +// *** screen saver + +int after_time() +{ + if(ss_enable == 0) + return INT_MAX; + + if(ss_after <= 0) + return 5 * 60; + + if(ss_after <= 3) + return ss_after * 15 * 60; + + if(ss_after <= 13) + return (ss_after - 3) * 60 * 60; + + return MAX_IDLE + 1; +} + +static const char *after_str[15] = +{ + " 5 sec", "15 sec", "30 sec", "45 sec", " 1 min", " 2 min", " 3 min", + " 4 min", " 5 min", " 6 min", " 7 min", " 8 min", " 9 min", "10 min", + "Never" +}; + +const char *after_list(int index, int *list_size) +{ + if(index < 0) + { + *list_size = 15; + return NULL; + } + + return after_str[index]; +} + +static ListData after__list(after_list, &font); + +static DIALOG scrsaver_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) */ + { jwin_win_proc, 32, 64, 256, 136, 0, 0, 0, D_EXIT, 0, 0, (void *) "Screen Saver Settings", NULL, NULL }, + { jwin_frame_proc, 42, 92, 236, 70, 0, 0, 0, 0, FR_ETCHED,0, NULL, NULL, NULL }, + { jwin_text_proc, 60, 104, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Run After", NULL, NULL }, + { jwin_text_proc, 60, 128, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Speed", NULL, NULL }, + { jwin_text_proc, 60, 144, 48, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) "Density", NULL, NULL }, + { jwin_droplist_proc, 144, 100, 96, 16, 0, 0, 0, 0, 0, 0, (void *) &after__list, NULL, NULL }, + { jwin_slider_proc, 144, 128, 116, 8, vc(0), jwin_pal[jcBOX], 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_slider_proc, 144, 144, 116, 8, vc(0), jwin_pal[jcBOX], 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_button_proc, 42, 170, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 124, 170, 72, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Preview", NULL, NULL }, + { jwin_button_proc, 218, 170, 61, 21, 0, 0, 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onScreenSaver() +{ + scrsaver_dlg[0].dp2=lfont; + scrsaver_dlg[5].d1 = scrsaver_dlg[5].d2 = ss_after; + scrsaver_dlg[6].d2 = ss_speed; + scrsaver_dlg[7].d2 = ss_density; + + if(is_large) + large_dialog(scrsaver_dlg); + + int ret = zc_popup_dialog(scrsaver_dlg,-1); + + if(ret == 8 || ret == 9) + { + ss_after = scrsaver_dlg[5].d1; + ss_speed = scrsaver_dlg[6].d2; + ss_density = scrsaver_dlg[7].d2; + } + + if(ret == 9) + // preview Screen Saver + { + clear_keybuf(); + scare_mouse(); + Matrix(ss_speed, ss_density, 30); + system_pal(); + unscare_mouse(); + } + + return D_O_K; +} + +/***** Menus *****/ + +static MENU game_menu[] = +{ + { (char *)"&Continue\tESC", onContinue, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"L&oad Quest...", onCustomGame, NULL, 0, NULL }, + { (char *)"&End Game\tF6", onQuit, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, +#ifndef ALLEGRO_MACOSX + { (char *)"&Reset\tF9", onReset, NULL, 0, NULL }, + { (char *)"&Quit\tF10", onExit, NULL, 0, NULL }, +#else + { (char *)"&Reset\tF7", onReset, NULL, 0, NULL }, + { (char *)"&Quit\tF8", onExit, NULL, 0, NULL }, +#endif + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU title_menu[] = +{ + { (char *)"&Original", onTitle_NES, NULL, 0, NULL }, + { (char *)"&Zelda Classic", onTitle_DX, NULL, 0, NULL }, + { (char *)"Zelda Classic &2.50", onTitle_25, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU snapshot_format_menu[] = +{ + { (char *)"&BMP", onSetSnapshotFormat, NULL, 0, NULL }, + { (char *)"&GIF", onSetSnapshotFormat, NULL, 0, NULL }, + { (char *)"&JPG", onSetSnapshotFormat, NULL, 0, NULL }, + { (char *)"&PNG", onSetSnapshotFormat, NULL, 0, NULL }, + { (char *)"PC&X", onSetSnapshotFormat, NULL, 0, NULL }, + { (char *)"&TGA", onSetSnapshotFormat, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU controls_menu[] = +{ + { (char *)"Key &Buttons...", onKeyboard, NULL, 0, NULL }, + { (char *)"Key &Directions...", onKeyboardDir, NULL, 0, NULL }, + { (char *)"&Joystick/Gamepad...", onJoystick, NULL, 0, NULL }, + { (char *)"&Extra Joystick/Gamepad...", onEXJoystick, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU name_entry_mode_menu[] = +{ + { (char *)"&Keyboard", onKeyboardEntry, NULL, 0, NULL }, + { (char *)"&Letter Grid", onLetterGridEntry, NULL, 0, NULL }, + { (char *)"&Extended Letter Grid", onExtLetterGridEntry, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU settings_menu[] = +{ + { (char *)"C&ontrols", NULL, controls_menu, 0, NULL }, + { (char *)"&Sound...", onSound, NULL, 0, NULL }, + { (char *)"&Title Screen", NULL, title_menu, 0, NULL }, + { (char *)"Name &Entry Mode", NULL, name_entry_mode_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Cap FPS\tF1", onVsync, NULL, 0, NULL }, + { (char *)"Show &FPS\tF2", onShowFPS, NULL, 0, NULL }, + { (char *)"Show Trans. &Layers", onTransLayers, NULL, 0, NULL }, + { (char *)"Up+A+B To &Quit", onNESquit, NULL, 0, NULL }, + { (char *)"Click to Freeze", onClickToFreeze, NULL, 0, NULL }, + { (char *)"Volume &Keys", onVolKeys, NULL, 0, NULL }, + { (char *)"Cont. &Heart Beep", onHeartBeep, NULL, 0, NULL }, + { (char *)"Sa&ve Indicator", onSaveIndicator, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"S&napshot Format", NULL, snapshot_format_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Debu&g", onDebug, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU misc_menu[] = +{ + { (char *)"&About...", onAbout, NULL, 0, NULL }, + { (char *)"&Credits...", onCredits, NULL, 0, NULL }, + { (char *)"&Fullscreen", onFullscreenMenu, NULL, 0, NULL }, + { (char *)"&Video Mode...", onVidMode, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Quest Info...", onQuest, NULL, 0, NULL }, + { (char *)"Quest &MIDI Info...", onMIDICredits, NULL, 0, NULL }, + { (char *)"Quest &Directory...", onQstPath, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Take &Snapshot\tF12", onSnapshot, NULL, 0, NULL }, + { (char *)"Sc&reen Saver...", onScreenSaver, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU refill_menu[] = +{ + { (char *)"&Life\t*, H", onRefillLife, NULL, 0, NULL }, + { (char *)"&Magic\t/, M", onRefillMagic, NULL, 0, NULL }, + { (char *)"&Bombs\tb", onCheatBombs, NULL, 0, NULL }, + { (char *)"&Rupees\tr", onCheatRupies, NULL, 0, NULL }, + { (char *)"&Arrows\ta", onCheatArrows, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU show_menu[] = +{ + { (char *)"Combos\t0", onShowLayer0, NULL, 0, NULL }, + { (char *)"Layer 1\t1", onShowLayer1, NULL, 0, NULL }, + { (char *)"Layer 2\t2", onShowLayer2, NULL, 0, NULL }, + { (char *)"Layer 3\t3", onShowLayer3, NULL, 0, NULL }, + { (char *)"Layer 4\t4", onShowLayer4, NULL, 0, NULL }, + { (char *)"Layer 5\t5", onShowLayer5, NULL, 0, NULL }, + { (char *)"Layer 6\t6", onShowLayer6, NULL, 0, NULL }, + { (char *)"Overhead Combos", onShowLayerO, NULL, 0, NULL }, + { (char *)"Push Blocks", onShowLayerP, NULL, 0, NULL }, + { (char *)"Freeform Combos\t7", onShowLayerF, NULL, 0, NULL }, + { (char *)"Sprites\t8", onShowLayerS, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Walkability\tw", onShowLayerW, NULL, 0, NULL }, + { (char *)"Current FFC Scripts", onShowFFScripts, NULL, 0, NULL }, + { (char *)"Hitboxes", onShowHitboxes, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU cheat_menu[] = +{ + { (char *)"&Enter code...", onCheat, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Re&fill", NULL, refill_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Clock\ti", onClock, NULL, 0, NULL }, + { (char *)"Ma&x Bombs...", onMaxBombs, NULL, 0, NULL }, + { (char *)"&Heart Containers...", onHeartC, NULL, 0, NULL }, + { (char *)"&Magic Containers...", onMagicC, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Link Data...", onCheatConsole, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Walk Through &Walls\tF11", onNoWalls, NULL, 0, NULL }, + { (char *)"&Quick Movement\tq", onGoFast, NULL, 0, NULL }, + { (char *)"&Kill All Enemies", onKillCheat, NULL, 0, NULL }, + { (char *)"Show/Hide Layer", NULL, show_menu, 0, NULL }, + { (char *)"Toggle Light\tl", onLightSwitch, NULL, 0, NULL }, + { (char *)"&Goto Location...\tg", onGoTo, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +MENU the_menu[] = +{ + { (char *)"&Game", NULL, game_menu, 0, NULL }, + { (char *)"&Settings", NULL, settings_menu, 0, NULL }, + { (char *)"&Cheat", NULL, cheat_menu, 0, NULL }, + { (char *)"&Misc", NULL, misc_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +MENU the_menu2[] = +{ + { (char *)"&Game", NULL, game_menu, 0, NULL }, + { (char *)"&Settings", NULL, settings_menu, 0, NULL }, + { (char *)"&Misc", NULL, misc_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +int onKeyboardEntry() +{ + NameEntryMode=0; + return D_O_K; +} + +int onLetterGridEntry() +{ + NameEntryMode=1; + return D_O_K; +} + +int onExtLetterGridEntry() +{ + NameEntryMode=2; + return D_O_K; +} + +int onFullscreenMenu() +{ + onFullscreen(); + misc_menu[2].flags =(isFullScreen()==1)?D_SELECTED:0; + return D_O_K; +} + +void fix_menu() +{ + if(!debug_enabled) + settings_menu[15].text = NULL; +} + +static DIALOG system_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_menu_proc, 0, 0, 0, 0, 0, 0, 0, D_USER, 0, 0, (void *) the_menu, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onVsync, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F2, 0, (void *) onShowFPS, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F6, 0, (void *) onQuit, NULL, NULL }, +#ifndef ALLEGRO_MACOSX + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F9, 0, (void *) onReset, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F10, 0, (void *) onExit, NULL, NULL }, +#else + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F7, 0, (void *) onReset, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F8, 0, (void *) onExit, NULL, NULL }, +#endif + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, 0, (void *) onSnapshot, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_TAB, 0, (void *) onDebug, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG system_dlg2[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_menu_proc, 0, 0, 0, 0, 0, 0, 0, D_USER, 0, 0, (void *) the_menu2, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onVsync, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F2, 0, (void *) onShowFPS, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F6, 0, (void *) onQuit, NULL, NULL }, +#ifndef ALLEGRO_MACOSX + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F9, 0, (void *) onReset, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F10, 0, (void *) onExit, NULL, NULL }, +#else + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F7, 0, (void *) onReset, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F8, 0, (void *) onExit, NULL, NULL }, +#endif + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, 0, (void *) onSnapshot, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_TAB, 0, (void *) onDebug, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void reset_snapshot_format_menu() +{ + for(int i=0; itext[1]) + { + case 'B': //"&BMP" + SnapshotFormat=0; + break; + + case 'G': //"&GIF" + SnapshotFormat=1; + break; + + case 'J': //"&JPG" + SnapshotFormat=2; + break; + + case 'P': //"&PNG" + SnapshotFormat=3; + break; + + case 'C': //"PC&X" + SnapshotFormat=4; + break; + + case 'T': //"&TGA" + SnapshotFormat=5; + break; + + case 'L': //"&LBM" + SnapshotFormat=6; + break; + } + + snapshot_format_menu[SnapshotFormat].flags=D_SELECTED; + return D_O_K; +} + + +void color_layer(RGB *src,RGB *dest,char r,char g,char b,char pos,int from,int to) +{ + PALETTE tmp; + + for(int i=0; i<256; i++) + { + tmp[i].r=r; + tmp[i].g=g; + tmp[i].b=b; + } + + fade_interpolate(src,tmp,dest,pos,from,to); +} + + +void system_pal() +{ + PALETTE pal; + copy_pal((RGB*)data[PAL_GUI].dat, pal); + + // set up the grayscale palette + for(int i=128; i<192; i++) + { + pal[i].r = i-128; + pal[i].g = i-128; + pal[i].b = i-128; + } + + + switch(gui_colorset) + { + /* + enum + { + jcBOX, jcLIGHT, jcMEDLT, jcMEDDARK, jcDARK, jcBOXFG, + jcTITLEL, jcTITLER, jcTITLEFG, jcTEXTBG, jcTEXTFG, jcSELBG, jcSELFG, + jcMAX + }; + */ + case 1: //Windows 98 + { + pal[dvc(1)] = _RGB(0*63/255, 0*63/255, 0*63/255); + pal[dvc(2)] = _RGB(128*63/255, 128*63/255, 128*63/255); + pal[dvc(3)] = _RGB(192*63/255, 192*63/255, 192*63/255); + pal[dvc(4)] = _RGB(223*63/255, 223*63/255, 223*63/255); + pal[dvc(5)] = _RGB(255*63/255, 255*63/255, 255*63/255); + pal[dvc(6)] = _RGB(255*63/255, 255*63/255, 225*63/255); + pal[dvc(7)] = _RGB(255*63/255, 225*63/255, 160*63/255); + pal[dvc(8)] = _RGB(0*63/255, 0*63/255, 80*63/255); + + byte palrstart= 0*63/255, palrend=166*63/255, + palgstart= 0*63/255, palgend=202*63/255, + palbstart=128*63/255, palbend=240*63/255, + paldivs=7; + + for(int i=0; i>3)+2; + int c = (i>>3)+192; + pal[c] = _RGB(v,v,v+(v>>1)); + /* + if(i<240) + { + _allegro_hline(tmp_scr,0,i,319,c); + _allegro_hline(tmp_scr,0,i+1,319,c); + } + */ + } + + // draw the vertical screen gradient + for(int i=0; i<240; ++i) + { + _allegro_hline(tmp_scr,0,i,319,192+(i*31/239)); + } + + /* + palrstart= 10*63/255; palrend=166*63/255; + palgstart= 36*63/255; palgend=202*63/255; + palbstart=106*63/255; palbend=240*63/255; + paldivs=32; + for(int i=0; iflags3&fNOSUBSCR && !(tmpscr->flags3&fNOSUBSCROFFSET)) + { + clear_to_color(panorama,0); + blit(framebuf,panorama,0,playing_field_offset,0,28,256,224-passive_subscreen_height); + ts_height=224-passive_subscreen_height; + ts_start=28; + } + else + { + blit(framebuf,panorama,0,0,0,0,256,224); + ts_height=224; + ts_start=0; + } + + // gray scale the current frame + for(int y=0; yline[y+ts_start][x]; + int gray = zc_min((RAMpal[c].r*42 + RAMpal[c].g*75 + RAMpal[c].b*14) >> 7, 63); + tmp_scr->line[y+8+ts_start][x+32] = gray+128; + } + } + + destroy_bitmap(panorama); + + // save the fps_undo section + blit(tmp_scr,fps_undo,40,216,0,0,64,16); + + // display everything + vsync(); + set_palette_range(pal,0,255,false); + + if(sbig) + stretch_blit(tmp_scr,screen,0,0,320,240,scrx-(160*(screen_scale-1)),scry-(120*(screen_scale-1)),screen_scale*320,screen_scale*240); + else + blit(tmp_scr,screen,0,0,scrx,scry,320,240); + + if(ShowFPS) + show_fps(screen); + + if(Paused) + show_paused(screen); + + // sys_pal = pal; + memcpy(sys_pal,pal,sizeof(pal)); +} + + +void system_pal2() +{ + PALETTE RAMpal2; + copy_pal((RGB*)data[PAL_GUI].dat, RAMpal2); + + /* Windows 2000 colors + RAMpal2[dvc(1)] = _RGB( 0*63/255, 0*63/255, 0*63/255); + RAMpal2[dvc(2)] = _RGB( 66*63/255, 65*63/255, 66*63/255); + RAMpal2[dvc(3)] = _RGB(132*63/255, 130*63/255, 132*63/255); + RAMpal2[dvc(4)] = _RGB(212*63/255, 208*63/255, 200*63/255); + RAMpal2[dvc(5)] = _RGB(255*63/255, 255*63/255, 255*63/255); + RAMpal2[dvc(6)] = _RGB(255*63/255, 255*63/255, 225*63/255); + RAMpal2[dvc(7)] = _RGB(255*63/255, 225*63/255, 160*63/255); + RAMpal2[dvc(8)] = _RGB( 0*63/255, 0*63/255, 80*63/255); + + byte palrstart= 10*63/255, palrend=166*63/255, + palgstart= 36*63/255, palgend=202*63/255, + palbstart=106*63/255, palbend=240*63/255, + paldivs=7; + for(int i=0; i>3)+2; + int c = (i>>3)+192; + RAMpal2[c] = _RGB(v,v,v+(v>>1)); + + /* + if(i<240) + { + _allegro_hline(tmp_scr,0,i,319,c); + _allegro_hline(tmp_scr,0,i+1,319,c); + } + */ + } + + set_palette(RAMpal2); + + for(int i=0; i<240; ++i) + { + _allegro_hline(tmp_scr,0,i,319,192+(i*31/239)); + } + + /* + byte palrstart= 10*63/255, palrend=166*63/255, + palgstart= 36*63/255, palgend=202*63/255, + palbstart=106*63/255, palbend=240*63/255, + paldivs=32; + for(int i=0; iflags3&fNOSUBSCR && !(tmpscr->flags3&fNOSUBSCROFFSET)) + { + clear_to_color(panorama,0); + blit(framebuf,panorama,0,playing_field_offset,0,28,256,224-passive_subscreen_height); + ts_height=224-passive_subscreen_height; + ts_start=28; + } + else + { + blit(framebuf,panorama,0,0,0,0,256,224); + ts_height=224; + ts_start=0; + } + + // gray scale the current frame + for(int y=0; yline[y+ts_start][x]; + int gray = zc_min((RAMpal2[c].r*42 + RAMpal2[c].g*75 + RAMpal2[c].b*14) >> 7, 63); + tmp_scr->line[y+8+ts_start][x+32] = gray+128; + } + } + + destroy_bitmap(panorama); + + // save the fps_undo section + blit(tmp_scr,fps_undo,40,216,0,0,64,16); + + // display everything + vsync(); + set_palette_range(RAMpal2,0,255,false); + + if(sbig) + //stretch_blit(tmp_scr,screen,0,0,320,240,scrx-160,scry-120,640,480); + stretch_blit(tmp_scr,screen,0,0,320,240,scrx-(160*(screen_scale-1)),scry-(120*(screen_scale-1)),screen_scale*320,screen_scale*240); + else + blit(tmp_scr,screen,0,0,scrx,scry,320,240); + + if(ShowFPS) + show_fps(screen); + + if(Paused) + show_paused(screen); + + // sys_pal = pal; + memcpy(sys_pal,RAMpal2,sizeof(RAMpal2)); +} + +#ifdef _WIN32 +void switch_out_callback() +{ + if(midi_patch_fix==0 || currmidi==0) + return; + + bool was_paused=get_midi_paused(); + long pos=midi_pos; + int digi_vol, midi_vol; + + get_volume(&digi_vol, &midi_vol); + stop_midi(); + jukebox(currmidi); + set_volume(digi_vol, midi_vol); + midi_seek(pos); + + if(was_paused) + { + midi_pause(); + set_midi_paused(true); + } +} + +void switch_in_callback() +{ + if(midi_patch_fix==0 || currmidi==0) + return; + + bool was_paused=get_midi_paused(); + long pos=midi_pos; + int digi_vol, midi_vol; + + get_volume(&digi_vol, &midi_vol); + stop_midi(); + jukebox(currmidi); + set_volume(digi_vol, midi_vol); + midi_seek(pos); + + if(was_paused) + { + midi_pause(); + set_midi_paused(true); + } +} +#else // Not Windows +void switch_out_callback() +{ +} + +void switch_in_callback() +{ +} +#endif + +void game_pal() +{ + clear_to_color(screen,BLACK); + set_palette_range(RAMpal,0,255,false); +} + +static char bar_str[] = ""; + +void System() +{ + mouse_down=gui_mouse_b(); + music_pause(); + pause_all_sfx(); + + system_pal(); + // FONT *oldfont=font; + // font=tfont; + + misc_menu[2].flags =(isFullScreen()==1)?D_SELECTED:0; + + game_menu[2].flags = getsaveslot() > -1 ? 0 : D_DISABLED; + game_menu[3].flags = + misc_menu[5].flags = Playing ? 0 : D_DISABLED; + misc_menu[7].flags = !Playing ? 0 : D_DISABLED; + + clear_keybuf(); + show_mouse(screen); + + DIALOG_PLAYER *p; + + if(!Playing || (!zcheats.flags && !get_debug())) + { + p = init_dialog(system_dlg2,-1); + } + else + { + p = init_dialog(system_dlg,-1); + } + + // drop the menu on startup if menu button pressed + if(joybtn(Mbtn)||key[KEY_ESC]) + simulate_keypress(KEY_G << 8); + + do + { + rest(17); + + if(mouse_down && !gui_mouse_b()) + mouse_down=0; + + title_menu[0].flags = (title_version==0) ? D_SELECTED : 0; + title_menu[1].flags = (title_version==1) ? D_SELECTED : 0; + title_menu[2].flags = (title_version==2) ? D_SELECTED : 0; + + settings_menu[5].flags = Throttlefps?D_SELECTED:0; + settings_menu[6].flags = ShowFPS?D_SELECTED:0; + settings_menu[7].flags = TransLayers?D_SELECTED:0; + settings_menu[8].flags = NESquit?D_SELECTED:0; + settings_menu[9].flags = ClickToFreeze?D_SELECTED:0; + settings_menu[10].flags = volkeys?D_SELECTED:0; + + name_entry_mode_menu[0].flags = (NameEntryMode==0)?D_SELECTED:0; + name_entry_mode_menu[1].flags = (NameEntryMode==1)?D_SELECTED:0; + name_entry_mode_menu[2].flags = (NameEntryMode==2)?D_SELECTED:0; + + /* + if(!Playing || (!zcheats.flags && !debug)) + { + cheat_menu[0].flags = D_DISABLED; + cheat_menu[1].text = NULL; + } + else */ + { + cheat_menu[0].flags = 0; + refill_menu[4].flags = get_bit(quest_rules, qr_TRUEARROWS) ? 0 : D_DISABLED; + cheat_menu[1].text = (cheat >= 1) || get_debug() ? bar_str : NULL; + cheat_menu[3].text = (cheat >= 2) || get_debug() ? bar_str : NULL; + cheat_menu[8].text = (cheat >= 3) || get_debug() ? bar_str : NULL; + cheat_menu[10].text = (cheat >= 4) || get_debug() ? bar_str : NULL; + cheat_menu[4].flags = getClock() ? D_SELECTED : 0; + cheat_menu[11].flags = toogam ? D_SELECTED : 0; + cheat_menu[12].flags = gofast ? D_SELECTED : 0; + + show_menu[0].flags = show_layer_0 ? D_SELECTED : 0; + show_menu[1].flags = show_layer_1 ? D_SELECTED : 0; + show_menu[2].flags = show_layer_2 ? D_SELECTED : 0; + show_menu[3].flags = show_layer_3 ? D_SELECTED : 0; + show_menu[4].flags = show_layer_4 ? D_SELECTED : 0; + show_menu[5].flags = show_layer_5 ? D_SELECTED : 0; + show_menu[6].flags = show_layer_6 ? D_SELECTED : 0; + show_menu[7].flags = show_layer_over ? D_SELECTED : 0; + show_menu[8].flags = show_layer_push ? D_SELECTED : 0; + show_menu[9].flags = show_sprites ? D_SELECTED : 0; + show_menu[10].flags = show_ffcs ? D_SELECTED : 0; + show_menu[12].flags = show_walkflags ? D_SELECTED : 0; + show_menu[13].flags = show_ff_scripts ? D_SELECTED : 0; + show_menu[14].flags = show_hitboxes ? D_SELECTED : 0; + } + + settings_menu[11].flags = heart_beep ? D_SELECTED : 0; + settings_menu[12].flags = use_save_indicator ? D_SELECTED : 0; + reset_snapshot_format_menu(); + snapshot_format_menu[SnapshotFormat].flags = D_SELECTED; + + if(debug_enabled) + { + settings_menu[16].flags = get_debug() ? D_SELECTED : 0; + } + + if(gui_mouse_b() && !mouse_down) + break; + + // press menu to drop the menu + if(rMbtn()) + simulate_keypress(KEY_G << 8); + + { + if(input_idle(true) > after_time()) + // run Screeen Saver + { + // Screen saver enabled for now. + clear_keybuf(); + scare_mouse(); + Matrix(ss_speed, ss_density, 0); + system_pal(); + unscare_mouse(); + broadcast_dialog_message(MSG_DRAW, 0); + } + } + + } + while(update_dialog(p)); + + // font=oldfont; + mouse_down=gui_mouse_b(); + shutdown_dialog(p); + show_mouse(NULL); + + if(Quit) + { + kill_sfx(); + music_stop(); + clear_to_color(screen,BLACK); + } + else + { + game_pal(); + music_resume(); + resume_all_sfx(); + + if(rc) + ringcolor(false); + } + + eat_buttons(); + + rc=false; + clear_keybuf(); + // text_mode(0); +} + +void fix_dialog(DIALOG *d) +{ + for(; d->proc != NULL; d++) + { + d->x += scrx; + d->y += scry; + } +} + +void fix_dialogs() +{ + /* + int x = scrx-(sbig?160:0); + int y = scry-(sbig?120:0); + if(x>0) x+=3; + if(y>0) y+=3; + if(x<0) x=0; + if(y<0) y=0; + + system_dlg[0].x = x; + system_dlg[0].y = y; + system_dlg2[0].x = x; + system_dlg2[0].y = y; + */ + + jwin_center_dialog(about_dlg); + jwin_center_dialog(btn_dlg); + jwin_center_dialog(exbtn_dlg); + jwin_center_dialog(cheat_dlg); + jwin_center_dialog(credits_dlg); + jwin_center_dialog(gamemode_dlg); + jwin_center_dialog(getnum_dlg); + jwin_center_dialog(goto_dlg); + center_zc_init_dialog(); + jwin_center_dialog(key_dlg); + jwin_center_dialog(keydir_dlg); + jwin_center_dialog(midi_dlg); + jwin_center_dialog(quest_dlg); + jwin_center_dialog(scrsaver_dlg); + jwin_center_dialog(sound_dlg); + jwin_center_dialog(triforce_dlg); + + digi_dp[1] += scrx; + digi_dp[2] += scry; + midi_dp[1] += scrx; + midi_dp[2] += scry; + pan_dp[1] += scrx; + pan_dp[2] += scry; + emus_dp[1] += scrx; + emus_dp[2] += scry; + buf_dp[1] += scrx; + buf_dp[2] += scry; + sfx_dp[1] += scrx; + sfx_dp[2] += scry; +} + + +/*******************************/ +/******* Input Handlers ********/ +/*******************************/ + +#define MAX_BUTTONS_CHK 13 // button range 0 - 12 + +bool joybtn(int b) +{ + if(b == 0) + return false; + + return joy[joystick_index].button[b-1].b !=0; +} + +int next_press_key() +{ + char k[128]; + + for(int i=0; i<128; i++) + k[i]=key[i]; + + for(;;) + { + for(int i=0; i<128; i++) + if(key[i]!=k[i]) + return i; + } + + // return (readkey()>>8); +} + +int next_press_btn() +{ + clear_keybuf(); + bool b[MAX_BUTTONS_CHK]; + + for(int i=1; i>8) + { + case KEY_ESC: + return -1; + + case KEY_SPACE: + return 0; + } + } + + poll_joystick(); + bool done = true; + + for(int i=1; i>8) + { + case KEY_ESC: + return -1; + + case KEY_SPACE: + return 0; + } + } + + poll_joystick(); + + for(int i=1; i STICK_PRECISION; + control_state[2]=key[DLkey]||joy[joystick_index].stick[0].axis[0].d1||joy[joystick_index].stick[0].axis[0].pos< -STICK_PRECISION; + control_state[3]=key[DRkey]||joy[joystick_index].stick[0].axis[0].d2||joy[joystick_index].stick[0].axis[0].pos > STICK_PRECISION; + control_state[4]=key[Akey]||joybtn(Abtn); + control_state[5]=key[Bkey]||joybtn(Bbtn); + control_state[6]=key[Skey]||joybtn(Sbtn); + control_state[7]=key[Lkey]||joybtn(Lbtn); + control_state[8]=key[Rkey]||joybtn(Rbtn); + control_state[9]=key[Pkey]||joybtn(Pbtn); + control_state[10]=key[Exkey1]||joybtn(Exbtn1); + control_state[11]=key[Exkey2]||joybtn(Exbtn2); + control_state[12]=key[Exkey3]||joybtn(Exbtn3); + control_state[13]=key[Exkey4]||joybtn(Exbtn4); + + if(num_joysticks != 0) + { + //this is a workaround to a really stupid allegro bug. + control_state[14]= joy[joystick_index].stick[1].axis[0].pos - 128 < -STICK_PRECISION; + control_state[15]= joy[joystick_index].stick[1].axis[0].pos - 128 > STICK_PRECISION; + control_state[16]= joy[joystick_index].stick[0].axis[2].pos < -STICK_PRECISION; + control_state[17]= joy[joystick_index].stick[0].axis[2].pos > STICK_PRECISION; + } + + button_press[0]=rButton(Up,button_hold[0]); + button_press[1]=rButton(Down,button_hold[1]); + button_press[2]=rButton(Left,button_hold[2]); + button_press[3]=rButton(Right,button_hold[3]); + button_press[4]=rButton(cAbtn,button_hold[4]); + button_press[5]=rButton(cBbtn,button_hold[5]); + button_press[6]=rButton(cSbtn,button_hold[6]); + button_press[7]=rButton(cLbtn,button_hold[7]); + button_press[8]=rButton(cRbtn,button_hold[8]); + button_press[9]=rButton(cPbtn,button_hold[9]); + button_press[10]=rButton(cEx1btn,button_hold[10]); + button_press[11]=rButton(cEx2btn,button_hold[11]); + button_press[12]=rButton(cEx3btn,button_hold[12]); + button_press[13]=rButton(cEx4btn,button_hold[13]); + button_press[14]=rButton(AxisUp,button_hold[14]); + button_press[15]=rButton(AxisDown,button_hold[15]); + button_press[16]=rButton(AxisLeft,button_hold[16]); + button_press[17]=rButton(AxisRight,button_hold[17]); + +} + +// Returns true if any game key is pressed. This is needed because keypressed() +// doesn't detect modifier keys and control_state[] can be modified by scripts. +bool zc_key_pressed() +{ + if((key[DUkey]||joy[joystick_index].stick[0].axis[1].d1||joy[joystick_index].stick[0].axis[1].pos< -STICK_PRECISION) || + (key[DDkey]||joy[joystick_index].stick[0].axis[1].d2||joy[joystick_index].stick[0].axis[1].pos > STICK_PRECISION) || + (key[DLkey]||joy[joystick_index].stick[0].axis[0].d1||joy[joystick_index].stick[0].axis[0].pos< -STICK_PRECISION) || + (key[DRkey]||joy[joystick_index].stick[0].axis[0].d2||joy[joystick_index].stick[0].axis[0].pos > STICK_PRECISION) || + (key[Akey]||joybtn(Abtn)) || + (key[Bkey]||joybtn(Bbtn)) || + (key[Skey]||joybtn(Sbtn)) || + (key[Lkey]||joybtn(Lbtn)) || + (key[Rkey]||joybtn(Rbtn)) || + (key[Pkey]||joybtn(Pbtn)) || + (key[Exkey1]||joybtn(Exbtn1)) || + (key[Exkey2]||joybtn(Exbtn2)) || + (key[Exkey3]||joybtn(Exbtn3)) || + (key[Exkey4]||joybtn(Exbtn4))) // Skipping joystick axes + return true; + + return false; +} + +bool Up() +{ + return control_state[0]; +} +bool Down() +{ + return control_state[1]; +} +bool Left() +{ + return control_state[2]; +} +bool Right() +{ + return control_state[3]; +} +bool cAbtn() +{ + return control_state[4]; +} +bool cBbtn() +{ + return control_state[5]; +} +bool cSbtn() +{ + return control_state[6]; +} +bool cLbtn() +{ + return control_state[7]; +} +bool cRbtn() +{ + return control_state[8]; +} +bool cPbtn() +{ + return control_state[9]; +} +bool cEx1btn() +{ + return control_state[10]; +} +bool cEx2btn() +{ + return control_state[11]; +} +bool cEx3btn() +{ + return control_state[12]; +} +bool cEx4btn() +{ + return control_state[13]; +} +bool AxisUp() +{ + return control_state[14]; +} +bool AxisDown() +{ + return control_state[15]; +} +bool AxisLeft() +{ + return control_state[16]; +} +bool AxisRight() +{ + return control_state[17]; +} + +bool cMbtn() +{ + return key[KEY_ESC]||joybtn(Mbtn); +} +bool cF12() +{ + return key[KEY_F12] != 0; +} +bool cF11() +{ + return key[KEY_F11] != 0; +} +bool cF5() +{ + return key[KEY_F5] != 0; +} +bool cQ() +{ + return key[KEY_Q] != 0; +} +bool cI() +{ + return key[KEY_I] != 0; +} + +bool rUp() +{ + return rButton(Up,Udown); +} +bool rDown() +{ + return rButton(Down,Ddown); +} +bool rLeft() +{ + return rButton(Left,Ldown); +} +bool rRight() +{ + return rButton(Right,Rdown); +} +bool rAbtn() +{ + return rButton(cAbtn,Adown); +} +bool rBbtn() +{ + return rButton(cBbtn,Bdown); +} +bool rSbtn() +{ + return rButton(cSbtn,Sdown); +} +bool rMbtn() +{ + return rButton(cMbtn,Mdown); +} +bool rLbtn() +{ + return rButton(cLbtn,LBdown); +} +bool rRbtn() +{ + return rButton(cRbtn,RBdown); +} +bool rPbtn() +{ + return rButton(cPbtn,Pdown); +} +bool rEx1btn() +{ + return rButton(cEx1btn,Ex1down); +} +bool rEx2btn() +{ + return rButton(cEx2btn,Ex2down); +} +bool rEx3btn() +{ + return rButton(cEx3btn,Ex3down); +} +bool rEx4btn() +{ + return rButton(cEx4btn,Ex4down); +} +bool rAxisUp() +{ + return rButton(AxisUp,AUdown); +} +bool rAxisDown() +{ + return rButton(AxisDown,ADdown); +} +bool rAxisLeft() +{ + return rButton(AxisLeft,ALdown); +} +bool rAxisRight() +{ + return rButton(AxisRight,ARdown); +} + +bool rF12() +{ + return rButton(cF12, F12); +} +bool rF11() +{ + return rButton(cF11, F11); +} +bool rF5() +{ + return rButton(cF5, F5); +} +bool rQ() +{ + return rButton(cQ, keyQ); +} +bool rI() +{ + return rButton(cI, keyI); +} + +bool drunk() +{ + return ((!(frame%((rand()%100)+1)))&&(rand()%MAXDRUNKCLOCK. +// + +/* Zelda Classic Music Library */ +/* ------------------------------------*/ +/* Wrapper for transparently extending */ +/* supported music file formats. */ + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +//#include "precompiled.h" //always first + + +#include "zc_alleg.h" // Has to be there or else OS X Universal 10.4 complains of fix overload - Taku +#include +#include +#include +#include + +#include "zsys.h" +#include "zcmusic.h" +#include "zc_malloc.h" +#include "mutex.h" + +#undef int8_t +#undef uint8_t +#undef int16_t +#undef uint16_t +#undef int32_t +#undef uint32_t +//short of fixing gme, these warnings will always be there... +#pragma warning(disable:4512) //assignment operator could not be generated +#pragma warning(disable:4100) //unreferenced formal parameter +#include "gme/Nsf_Emu.h" +#include "gme/Gbs_Emu.h" +#include "gme/Spc_Emu.h" +#include "gme/Vgm_Emu.h" +#include "gme/Gym_Emu.h" +#pragma warning(default:4100) +#pragma warning(default:4512) +#define int8_t signed char +#define uint8_t unsigned char +#define int16_t signed short +#define uint16_t unsigned short +#define int32_t signed int +#define uint32_t unsigned int + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +// might consider replacing the following with user defined values from the +// 'sound' dialog in the player. This way, each person could tune it as needed. +#define DUH_CHANNELS 2 // stereo +#define DUH_SAMPLES 44100 //Hz +#define DUH_RESAMPLE 1 + +int zcmusic_bufsz = 64; +static int zcmusic_bufsz_private = 64; + +mutex playlistmutex; + +typedef struct DUHFILE : public ZCMUSICBASE +{ + DUH *s; + AL_DUH_PLAYER *p; +} DUHFILE; + +typedef struct OGGFILE : public ZCMUSICBASE +{ + ALOGG_OGGSTREAM *s; + PACKFILE *f; + char *fname; + int vol; +} OGGFILE; + +typedef struct MP3FILE : public ZCMUSICBASE +{ + ALMP3_MP3STREAM *s; + PACKFILE *f; + char *fname; + int vol; +} MP3FILE; + +typedef struct GMEFILE : public ZCMUSICBASE +{ + AUDIOSTREAM *stream; + class Music_Emu* emu; + int samples; +} GMEFILE; + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h +#include +static std::vector playlist; //yeah, I'm too lazy to do it myself +static int libflags = 0; + +// forward declarations +OGGFILE *load_ogg_file(char *filename); +int poll_ogg_file(OGGFILE *ogg); +void unload_ogg_file(OGGFILE *ogg); +bool ogg_pause(OGGFILE *ogg); +bool ogg_resume(OGGFILE *ogg); +bool ogg_reset(OGGFILE *ogg); +void ogg_stop(OGGFILE *ogg); + +MP3FILE *load_mp3_file(char *filename); +int poll_mp3_file(MP3FILE *mp3); +void unload_mp3_file(MP3FILE *mp3); +bool mp3_pause(MP3FILE *mp3); +bool mp3_resume(MP3FILE *mp3); +bool mp3_reset(MP3FILE *mp3); +void mp3_stop(MP3FILE *mp3); + +Music_Emu* gme_load_file(char* filename, char* ext); +int poll_gme_file(GMEFILE *gme); +int unload_gme_file(GMEFILE* gme); +int gme_play(GMEFILE *gme, int vol); + + +extern "C" +{ + void zcm_extract_name(char *path,char *name,int type) + { + int l=(int)strlen(path); + int i=l; + + while(i>0 && path[i-1]!='/' && path[i-1]!='\\') + --i; + + int n=0; + + if(type==FILENAME8__) + { + while(i::iterator b = playlist.begin(); + + while(b != playlist.end()) + { + switch((*b)->playing) + { + case ZCM_STOPPED: + // if it has stopped, remove it from playlist; + b = playlist.erase(b); + break; + + case ZCM_PLAYING: + (*b)->position++; + + switch((*b)->type & flags & libflags) // only poll those specified by 'flags' + { + case ZCMF_DUH: + if(((DUHFILE*)*b)->p) + al_poll_duh(((DUHFILE*)*b)->p); + + break; + + case ZCMF_OGG: + poll_ogg_file((OGGFILE*)*b); + break; + + case ZCMF_MP3: + poll_mp3_file((MP3FILE*)*b); + break; + + case ZCMF_GME: + if(((GMEFILE*)*b)->emu) + poll_gme_file((GMEFILE*)*b); + + break; + } + + case ZCM_PAUSED: + b++; + } + } + + mutex_unlock(&playlistmutex); +// setPackfilePassword(oldpwd); +// if(oldpwd != NULL) +// delete[] oldpwd; + return true; + } + + void zcmusic_exit() + { + //lock mutex + mutex_lock(&playlistmutex); + std::vector::iterator b = playlist.begin(); + + while(b != playlist.end()) + { + zcmusic_unload_file(*b); + b = playlist.erase(b); + } + + playlist.clear(); + mutex_unlock(&playlistmutex); + + if(libflags & ZCMF_DUH) + { + dumb_exit(); + libflags ^= ZCMF_DUH; + } + + if(libflags & ZCMF_OGG) + { + libflags ^= ZCMF_OGG; + } + + if(libflags & ZCMF_MP3) + { + libflags ^= ZCMF_MP3; + } + + if(libflags & ZCMF_GME) + { + libflags ^= ZCMF_GME; + } + } + + ZCMUSIC const * zcmusic_load_file(char *filename) + { + if(filename == NULL) + { + return NULL; + } + + al_trace("Trying to load %s\n", filename); + + if(strlen(filename)>255) + { + al_trace("Music file '%s' not loaded: filename too long\n", filename); + return NULL; + } + + char *ext=get_extension(filename); + + if((stricmp(ext,"ogg")==0) && (libflags & ZCMF_OGG)) + { + OGGFILE *p = load_ogg_file(filename); + + if(!p) + { + al_trace("OGG file '%s' not loaded.\n",filename); + goto error; + } + + p->fname = (char*)zc_malloc(strlen(filename)+1); + + if(!p->fname) + { + unload_ogg_file(p); + goto error; + } + + strcpy(p->fname, filename); + p->type = ZCMF_OGG; + p->playing = ZCM_STOPPED; + ZCMUSIC *music=(ZCMUSIC*)p; + zcm_extract_name(filename, music->filename, FILENAMEALL); + music->filename[255]='\0'; + music->track=0; + return music; + } + + if((stricmp(ext,"mp3")==0) && (libflags & ZCMF_MP3)) + { + MP3FILE *p = load_mp3_file(filename); + + if(!p) + { + al_trace("MP3 file '%s' not found.\n",filename); + goto error; + } + + p->fname = (char*)zc_malloc(strlen(filename)+1); + + if(!p->fname) + { + unload_mp3_file(p); + goto error; + } + + strcpy(p->fname, filename); + p->type = ZCMF_MP3; + p->playing = ZCM_STOPPED; + ZCMUSIC *music=(ZCMUSIC*)p; + zcm_extract_name(filename, music->filename, FILENAMEALL); + music->filename[255]='\0'; + music->track=0; + return music; + } + + if(libflags & ZCMF_DUH) + { + DUH* d = NULL; + + if(stricmp(ext,"it")==0) + { + d = dumb_load_it(filename); + + if(!d) al_trace("IT file '%s' not found.\n",filename); + } + else if(stricmp(ext,"xm")==0) + { + d = dumb_load_xm(filename); + + if(!d) al_trace("XM file '%s' not found.\n",filename); + } + else if(stricmp(ext,"s3m")==0) + { + d = dumb_load_s3m(filename); + + if(!d) al_trace("S3M file '%s' not found.\n",filename); + } + else if(stricmp(ext,"mod")==0) + { + d = dumb_load_mod(filename); + + if(!d) al_trace("MOD file '%s' not found.\n",filename); + } + + if(d) + { + DUHFILE *p = (DUHFILE*)zc_malloc(sizeof(DUHFILE)); + + if(!p) + { + unload_duh(d); + goto error; + } + + p->type = ZCMF_DUH; + p->playing = ZCM_STOPPED; + p->s = d; + p->p = NULL; + ZCMUSIC *music=(ZCMUSIC*)p; + zcm_extract_name(filename, music->filename, FILENAMEALL); + music->filename[255]='\0'; + music->track=0; + return music; + } + } + + if((libflags & ZCMF_GME)) + { + if((stricmp(ext,"spc")==0) || (stricmp(ext,"gbs")==0) || (stricmp(ext,"vgm")==0)|| (stricmp(ext,"gym")==0)|| (stricmp(ext,"nsf")==0)) + { + + Music_Emu *emu; + + emu=gme_load_file(filename, ext); + + if(emu) + { + GMEFILE *p=(GMEFILE*)zc_malloc(sizeof(GMEFILE)); + + if(!p) return NULL; + + p->type = ZCMF_GME; + p->playing = ZCM_STOPPED; + p->emu = emu; + ZCMUSIC *music=(ZCMUSIC*)p; + zcm_extract_name(filename, music->filename, FILENAMEALL); + music->filename[255]='\0'; + music->track=0; + return music; + } + else al_trace("%s file '%s' not found.\n",ext,filename); + + } + } + +error: + return NULL; + } + + bool zcmusic_play(ZCMUSIC* zcm, int vol) /* = FALSE */ + { + // the libraries require polling + // of individual streams, so here we must keep + // record of each file which is + // playing, so we can iterate over all of them + // when zcmusic_poll() is called. + // + // In addition, any music library which actually + // has a 'play' function or similar will be + // called from here. + + if(zcm == NULL) return FALSE; + + int ret = TRUE; + + if(zcm->playing != ZCM_STOPPED) // adjust volume + { + switch(zcm->type & libflags) + { + case ZCMF_DUH: + if(((DUHFILE*)zcm)->p != NULL) + al_duh_set_volume(((DUHFILE*)zcm)->p, (float)vol / (float)255); + + break; + + case ZCMF_OGG: + if(((OGGFILE*)zcm)->s != NULL) + { + /*pan*/ + alogg_adjust_oggstream(((OGGFILE*)zcm)->s, vol, 128, 1000/*speed*/); + ((OGGFILE*)zcm)->vol = vol; + } + + break; + + case ZCMF_MP3: + if(((MP3FILE*)zcm)->s != NULL) + { + /*pan*/ + almp3_adjust_mp3stream(((MP3FILE*)zcm)->s, vol, 128, 1000/*speed*/); + ((MP3FILE*)zcm)->vol = vol; + } + + break; + + case ZCMF_GME: + // need to figure out volume switch + break; + } + } + else + { + switch(zcm->type & libflags) + { + case ZCMF_DUH: + if(((DUHFILE*)zcm)->s != NULL) + { + ((DUHFILE*)zcm)->p = al_start_duh(((DUHFILE*)zcm)->s, DUH_CHANNELS, 0/*pos*/, ((float)vol) / (float)255, (zcmusic_bufsz_private*1024)/*bufsize*/, DUH_SAMPLES); + ret = (((DUHFILE*)zcm)->p != NULL) ? TRUE : FALSE; + } + + break; + + case ZCMF_OGG: + if(((OGGFILE*)zcm)->s != NULL) + { + if(alogg_play_oggstream(((OGGFILE*)zcm)->s, (zcmusic_bufsz_private*1024), vol, 128) != ALOGG_OK) + ret = FALSE; + + ((OGGFILE*)zcm)->vol = vol; + } + else + { + ret = FALSE; + } + + break; + + case ZCMF_MP3: + if(((MP3FILE*)zcm)->s != NULL) + { + if(almp3_play_mp3stream(((MP3FILE*)zcm)->s, (zcmusic_bufsz_private*1024), vol, 128) != ALMP3_OK) + ret = FALSE; + + ((MP3FILE*)zcm)->vol = vol; + } + else + { + ret = FALSE; + } + + break; + + case ZCMF_GME: + if(((GMEFILE*)zcm)->emu != NULL) + { + gme_play((GMEFILE*) zcm, vol); + } + + break; + } + + if(ret != FALSE) + { + zcm->position=0; + zcm->playing = ZCM_PLAYING; + mutex_lock(&playlistmutex); + playlist.push_back(zcm); + mutex_unlock(&playlistmutex); + } + } + + return ret!=0; + } + + bool zcmusic_pause(ZCMUSIC* zcm, int pause = -1) + { + // This function suspends play of the music indicated + // by 'zcm'. Passing 0 for pause will resume; passing + // -1 (or if the default argument is invoked) will + // toggle the current state; passing 1 will pause. + if(zcm == NULL) return FALSE; + + mutex_lock(&playlistmutex); + + if(zcm->playing != ZCM_STOPPED) + { + int p = ZCM_PLAYING; + + switch(pause) + { + case ZCM_TOGGLE: + p = (zcm->playing == ZCM_PAUSED) ? ZCM_PLAYING : ZCM_PAUSED; + break; + + case ZCM_RESUME: + p = ZCM_PLAYING; + break; + + case ZCM_PAUSE: + p = ZCM_PAUSED; + break; + } + + if(p != zcm->playing) // if the state has actually changed + { + zcm->playing = p; + + switch(zcm->type & libflags) + { + case ZCMF_DUH: + if(((DUHFILE*)zcm)->p != NULL) + { + if(p == ZCM_PAUSED) + al_pause_duh(((DUHFILE*)zcm)->p); + else + al_resume_duh(((DUHFILE*)zcm)->p); + + break; + } + + case ZCMF_OGG: + if(p == ZCM_PAUSED) + ogg_pause((OGGFILE*)zcm); + else + ogg_resume((OGGFILE*)zcm); + + break; + + case ZCMF_MP3: + if(p == ZCM_PAUSED) + mp3_pause((MP3FILE*)zcm); + else + mp3_resume((MP3FILE*)zcm); + + break; + + case ZCMF_GME: + if(((GMEFILE*)zcm)->emu != NULL) + { + if(p == ZCM_PAUSED) + { + voice_stop(((GMEFILE*)zcm)->stream->voice); + } + else + { + voice_start(((GMEFILE*)zcm)->stream->voice); + } + + break; + } + + } + } + } + + mutex_unlock(&playlistmutex); + return TRUE; + } + + bool zcmusic_stop(ZCMUSIC* zcm) + { + // this function will stop playback of 'zcm' and reset + // the stream position to the beginning. + if(zcm == NULL) return FALSE; + + mutex_lock(&playlistmutex); + + switch(zcm->type & libflags) + { + case ZCMF_DUH: + if(((DUHFILE*)zcm)->p != NULL) + { + al_stop_duh(((DUHFILE*)zcm)->p); + ((DUHFILE*)zcm)->p = NULL; + zcm->playing = ZCM_STOPPED; + } + + break; + + case ZCMF_OGG: + ogg_stop((OGGFILE*)zcm); + break; + + case ZCMF_MP3: + mp3_stop((MP3FILE*)zcm); + break; + + case ZCMF_GME: + if(((GMEFILE*)zcm)->emu != NULL) + { + if(zcm->playing != ZCM_STOPPED) stop_audio_stream(((GMEFILE*)zcm)->stream); + + zcm->playing = ZCM_STOPPED; + } + + break; + + } + + mutex_unlock(&playlistmutex); + return TRUE; + } + + void zcmusic_unload_file(ZCMUSIC* &zcm) + { + // this will unload and destroy all of the data/etc. + // associated with 'zcm'. Also sets the pointer to + // NULL so you don't try to use it later. + if(zcm == NULL) return; + + // explicitly remove it from the playlist since we're + // freeing the memory which holds the ZCM struct. + // don't want to leave an soon-to-be invalid pointers + // lying around to cause crashes. + { + mutex_lock(&playlistmutex); + std::vector::iterator b = playlist.begin(); + + while(b != playlist.end()) + { + if(*b == zcm) + { + b = playlist.erase(b); + } + else + { + b++; + } + } + + mutex_unlock(&playlistmutex); + } + + switch(zcm->type & libflags) + { + case ZCMF_DUH: + if(((DUHFILE*)zcm)->p != NULL) + { + zcmusic_stop(zcm); + ((DUHFILE*)zcm)->p = NULL; + } + + if(((DUHFILE*)zcm)->s != NULL) + { + unload_duh(((DUHFILE*)zcm)->s); + ((DUHFILE*)zcm)->s = NULL; + zc_free(zcm); + } + + break; + + case ZCMF_OGG: + unload_ogg_file((OGGFILE*)zcm); + break; + + case ZCMF_MP3: + unload_mp3_file((MP3FILE*)zcm); + break; + + case ZCMF_GME: + unload_gme_file((GMEFILE*)zcm); + break; + } + + zcm = NULL; + return; + } + + int zcmusic_get_tracks(ZCMUSIC* zcm) + { + if(zcm == NULL) return 0; + + switch(zcm->type & libflags) + { + case ZCMF_DUH: + case ZCMF_OGG: + case ZCMF_MP3: + return 0; + break; + + case ZCMF_GME: + if(((GMEFILE*)zcm)->emu != NULL) + { + int t=((GMEFILE*)zcm)->emu->track_count(); + return (t>1)?t:0; + } + else + { + return 0; + } + + break; + } + + return 0; + } + + int zcmusic_change_track(ZCMUSIC* zcm, int tracknum) + { + if(zcm == NULL) return -1; + + switch(zcm->type & libflags) + { + case ZCMF_DUH: + case ZCMF_OGG: + case ZCMF_MP3: + return -1; + break; + + case ZCMF_GME: + if(((GMEFILE*)zcm)->emu != NULL) + { + mutex_lock(&playlistmutex); + int t=((GMEFILE*)zcm)->emu->track_count(); + + if(tracknum<0 || tracknum>=t) + { + tracknum=0; + } + + ((GMEFILE*)zcm)->emu->start_track(tracknum); + zcm->track=tracknum; + mutex_unlock(&playlistmutex); + return tracknum; + } + else + { + return -1; + } + + break; + } + + return 0; + } + +} // extern "C" + +MP3FILE *load_mp3_file(char *filename) +{ + MP3FILE *p = NULL; + PACKFILE *f = NULL; + ALMP3_MP3STREAM *s = NULL; + char *data = new char[(zcmusic_bufsz_private*512)]; + int len; + + if((p = (MP3FILE *)zc_malloc(sizeof(MP3FILE)))==NULL) + goto error; + + if((f = pack_fopen_password(filename, F_READ,""))==NULL) + goto error; + + // ID3 tags sometimes cause problems with almp3, so try to skip them + if((len = pack_fread(data, 10, f)) <= 0) + goto error; + + if(strncmp(data, "ID3", 3)==0) + { + int id3Size=10; + + id3Size=((data[6]&0x7F)<<21)|((data[7]&0x7F)<<14)|((data[8]&0x7F)<<7)|(data[9]&0x7F); + pack_fseek(f, id3Size-10); + if((len = pack_fread(data, (zcmusic_bufsz_private*512), f)) <= 0) + goto error; + } + else // no ID3 + { + if((len = pack_fread(data+10, (zcmusic_bufsz_private*512)-10, f)) <= 0) + goto error; + } + + if(len < (zcmusic_bufsz_private*512)) + { + if((s = almp3_create_mp3stream(data, len, TRUE))==NULL) + goto error; + } + else + { + if((s = almp3_create_mp3stream(data, (zcmusic_bufsz_private*512), FALSE))==NULL) + goto error; + } + + p->f = f; + p->s = s; + delete[] data; + return p; + +error: + + if(f) + pack_fclose(f); + + if(p) + zc_free(p); + + delete[] data; + return NULL; +} + +int poll_mp3_file(MP3FILE *mp3) +{ + if(mp3 == NULL) return ALMP3_POLL_NOTPLAYING; + + if(mp3->s == NULL) return ALMP3_POLL_NOTPLAYING; + + char *data = (char *)almp3_get_mp3stream_buffer(mp3->s); + + if(data) + { + long len = pack_fread(data, (zcmusic_bufsz_private*512), mp3->f); + + if(len < (zcmusic_bufsz_private*512)) + almp3_free_mp3stream_buffer(mp3->s, len); + else + almp3_free_mp3stream_buffer(mp3->s, -1); + } + + int ret = almp3_poll_mp3stream(mp3->s); + + if(ret != ALMP3_OK) + { + mp3_reset(mp3); + almp3_play_mp3stream(mp3->s, (zcmusic_bufsz_private*1024), mp3->vol, 128); + mp3->playing = ZCM_PLAYING; + } + + return ret; +} + +void unload_mp3_file(MP3FILE *mp3) +{ + if(mp3 != NULL) + { + if(mp3->f != NULL) + { + pack_fclose(mp3->f); + mp3->f = NULL; + } + + if(mp3->s != NULL) + { + AUDIOSTREAM* a = almp3_get_audiostream_mp3stream(mp3->s); + + if(a != NULL) + voice_stop(a->voice); + + almp3_destroy_mp3stream(mp3->s); + mp3->s = NULL; + } + + if(mp3->fname != NULL) + { + zc_free(mp3->fname); + zc_free(mp3); + } + } +} + +bool mp3_pause(MP3FILE *mp3) +{ + AUDIOSTREAM* a = NULL; + + if(mp3->s != NULL) + a = almp3_get_audiostream_mp3stream(mp3->s); + + if(a != NULL) + { + voice_stop(a->voice); + return true; + } + + return false; +} + +bool mp3_resume(MP3FILE *mp3) +{ + AUDIOSTREAM* a = NULL; + + if(mp3->s != NULL) + a = almp3_get_audiostream_mp3stream(mp3->s); + + if(a != NULL) + { + voice_start(a->voice); + return true; + } + + return false; +} + +bool mp3_reset(MP3FILE *mp3) +{ + if(mp3->fname != NULL) + { + if(mp3->f != NULL) + { + pack_fclose(mp3->f); + mp3->f = NULL; + } + + if(mp3->s != NULL) + { + AUDIOSTREAM* a = almp3_get_audiostream_mp3stream(mp3->s); + + if(a != NULL) + voice_stop(a->voice); + + almp3_destroy_mp3stream(mp3->s); + mp3->s = NULL; + } + + MP3FILE* tmp3 = load_mp3_file(mp3->fname); + + if(tmp3 != NULL) + { + mp3->playing = ZCM_STOPPED; + mp3->s = tmp3->s; + mp3->f = tmp3->f; + zc_free(tmp3); + return true; + } + } + + return false; +} + +void mp3_stop(MP3FILE *mp3) +{ + if(mp3->fname != NULL) + { + if(mp3->f != NULL) + { + pack_fclose(mp3->f); + mp3->f = NULL; + } + + if(mp3->s != NULL) + { + AUDIOSTREAM* a = almp3_get_audiostream_mp3stream(mp3->s); + + if(a != NULL) + voice_stop(a->voice); + + almp3_destroy_mp3stream(mp3->s); + mp3->s = NULL; + } + } +} + +OGGFILE *load_ogg_file(char *filename) +{ + OGGFILE *p = NULL; + PACKFILE *f = NULL; + ALOGG_OGGSTREAM *s = NULL; + char *data = new char[(zcmusic_bufsz_private*512)]; + int len; + + if((p = (OGGFILE *)zc_malloc(sizeof(OGGFILE)))==NULL) + { + goto error; + } + + if((f = pack_fopen_password(filename, F_READ,""))==NULL) + { + goto error; + } + + if((len = pack_fread(data, (zcmusic_bufsz_private*512), f)) <= 0) + { + goto error; + } + + if(len < (zcmusic_bufsz_private*512)) + { + if((s = alogg_create_oggstream(data, len, TRUE))==NULL) + { + goto error; + } + } + else + { + if((s = alogg_create_oggstream(data, (zcmusic_bufsz_private*512), FALSE))==NULL) + { + goto error; + } + } + + p->f = f; + p->s = s; + delete[] data; + return p; + +error: + + if(f) + pack_fclose(f); + + if(p) + zc_free(p); + + delete[] data; + return NULL; +} + +int poll_ogg_file(OGGFILE *ogg) +{ + if(ogg == NULL) return ALOGG_POLL_NOTPLAYING; + + if(ogg->s == NULL) return ALOGG_POLL_NOTPLAYING; + + char *data = (char *)alogg_get_oggstream_buffer(ogg->s); + + if(data) + { + long len = pack_fread(data, (zcmusic_bufsz_private*512), ogg->f); + + if(len < (zcmusic_bufsz_private*512)) + alogg_free_oggstream_buffer(ogg->s, len); + else + alogg_free_oggstream_buffer(ogg->s, -1); + } + + int ret = alogg_poll_oggstream(ogg->s); + + if(ret != ALOGG_OK) + { + ogg_reset(ogg); + alogg_play_oggstream(ogg->s, (zcmusic_bufsz_private*1024), ogg->vol, 128); + ogg->playing = ZCM_PLAYING; + } + + return ret; +} + +void unload_ogg_file(OGGFILE *ogg) +{ + if(ogg != NULL) + { + if(ogg->f != NULL) + { + pack_fclose(ogg->f); + ogg->f = NULL; + } + + if(ogg->s != NULL) + { + AUDIOSTREAM* a = alogg_get_audiostream_oggstream(ogg->s); + + if(a != NULL) + voice_stop(a->voice); + + alogg_destroy_oggstream(ogg->s); + ogg->s = NULL; + } + + if(ogg->fname != NULL) + { + zc_free(ogg->fname); + zc_free(ogg); + } + } +} + +bool ogg_pause(OGGFILE *ogg) +{ + AUDIOSTREAM* a = NULL; + + if(ogg->s != NULL) + a = alogg_get_audiostream_oggstream(ogg->s); + + if(a != NULL) + { + voice_stop(a->voice); + return true; + } + + return false; +} + +bool ogg_resume(OGGFILE *ogg) +{ + AUDIOSTREAM* a = NULL; + + if(ogg->s != NULL) + a = alogg_get_audiostream_oggstream(ogg->s); + + if(a != NULL) + { + voice_start(a->voice); + return true; + } + + return false; +} + +bool ogg_reset(OGGFILE *ogg) +{ + if(ogg->fname != NULL) + { + if(ogg->f != NULL) + { + pack_fclose(ogg->f); + ogg->f = NULL; + } + + if(ogg->s != NULL) + { + AUDIOSTREAM* a = alogg_get_audiostream_oggstream(ogg->s); + + if(a != NULL) + voice_stop(a->voice); + + alogg_destroy_oggstream(ogg->s); + ogg->s = NULL; + } + + OGGFILE* togg = load_ogg_file(ogg->fname); + + if(togg != NULL) + { + ogg->playing = ZCM_STOPPED; + ogg->s = togg->s; + ogg->f = togg->f; + zc_free(togg); + return true; + } + } + + return false; +} + +void ogg_stop(OGGFILE *ogg) +{ + if(ogg->fname != NULL) + { + if(ogg->f != NULL) + { + pack_fclose(ogg->f); + ogg->f = NULL; + } + + if(ogg->s != NULL) + { + AUDIOSTREAM* a = alogg_get_audiostream_oggstream(ogg->s); + + if(a != NULL) + voice_stop(a->voice); + + alogg_destroy_oggstream(ogg->s); + ogg->s = NULL; + } + } +} + +int poll_gme_file(GMEFILE* gme) +{ + unsigned char *p; + p = (unsigned char*) get_audio_stream_buffer(gme->stream); + + if(p) + { + int samples=gme->samples; + memset(p,0,4*samples); + unsigned short *q=(unsigned short*) p; + gme->emu->play((long) 2*samples,(short*)p); + + // Allegro only uses UNSIGNED samples ... + for(int j=0; j<2*samples; ++j) + { + *q ^= 0x8000; + q++; + } + + free_audio_stream_buffer(gme->stream); + return true; + } + + return false; +} + + +Music_Emu* gme_load_file(char* filename, char* ext) +{ + Music_Emu* emu=NULL; + + if(stricmp(ext,"spc")==0) emu = new Spc_Emu; + + if(stricmp(ext,"gbs")==0) emu = new Gbs_Emu; + + if(stricmp(ext,"vgm")==0) emu = new Vgm_Emu; + + if(stricmp(ext,"nsf")==0) emu = new Nsf_Emu; + + if(stricmp(ext,"gym")==0) emu = new Gym_Emu; + + if(!emu) return NULL; + + Std_File_Reader in; + + const char* err = emu->set_sample_rate(DUH_SAMPLES); + + if(!err) err = in.open(filename); + + if(!err) err = emu->load(in); + + if(err) + { + delete emu; + return NULL; + } + + return emu; +} + +int gme_play(GMEFILE *gme, int vol) +{ + gme->emu->start_track(0); + int samples=512; + int buf_size=2*DUH_SAMPLES/50; + + while(samples < buf_size) samples *= 2; + + gme->samples=samples; + + if(gme->playing != ZCM_STOPPED) stop_audio_stream(gme->stream); + + gme->stream = play_audio_stream(samples, 16, TRUE, DUH_SAMPLES, vol, 128); + return true; +} + +int unload_gme_file(GMEFILE* gme) +{ + if(gme!=NULL) + { + if(gme->emu != NULL) + { + zcmusic_stop(gme); + delete gme->emu; + gme->emu=NULL; + zc_free(gme); + } + } + + return true; +} + diff --git a/src/zcmusic.h b/src/zcmusic.h new file mode 100644 index 0000000000..abba02fdf9 --- /dev/null +++ b/src/zcmusic.h @@ -0,0 +1,65 @@ +/* Zelda Classic Music Library */ +/* ------------------------------------ */ +/* Wrapper for transparently extending */ +/* supported music file formats. */ + +#ifndef _ZCMUSIC_H_ +#define _ZCMUSIC_H_ + +#if defined ZCM_DLL +#define ZCM_EXTERN extern __declspec(dllexport) +#elif defined ZCM_DLL_IMPORT +#define ZCM_EXTERN extern __declspec(dllimport) +#else +#define ZCM_EXTERN extern +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define ZCMF_DUH 0x00000001 +#define ZCMF_OGG 0x00000002 +#define ZCMF_MP3 0x00000004 +#define ZCMF_GME 0x00000008 + +#define ZCM_PLAYING 1 +#define ZCM_STOPPED 0 +#define ZCM_PAUSED -1 + +#define ZCM_PAUSE 1 +#define ZCM_RESUME 0 +#define ZCM_TOGGLE -1 + +ZCM_EXTERN char const * zcmusic_types; +ZCM_EXTERN int zcmusic_bufsz; + +ZCM_EXTERN bool zcmusic_init(int flags = -1); +ZCM_EXTERN bool zcmusic_poll(int flags = -1); +ZCM_EXTERN void zcmusic_exit(); + +typedef struct ZCMUSICBASE +{ + int type; // uses ZCMF defines + int playing; // -1 = paused, 0 = stopped, 1 = playing + int position; // Only needed to sync Triforce jingle + char filename[256]; + int track; +} ZCMUSIC; + +ZCM_EXTERN ZCMUSIC const * zcmusic_load_file(char *filename); +ZCM_EXTERN bool zcmusic_play(ZCMUSIC* zcm, int vol); +ZCM_EXTERN bool zcmusic_pause(ZCMUSIC* zcm, int pause); +ZCM_EXTERN bool zcmusic_stop(ZCMUSIC* zcm); +ZCM_EXTERN void zcmusic_unload_file(ZCMUSIC* &zcm); +ZCM_EXTERN int zcmusic_get_tracks(ZCMUSIC* zcm); +ZCM_EXTERN int zcmusic_change_track(ZCMUSIC* zcm, int tracknum); + +#ifdef __cplusplus +} // extern "C" +#endif + +#undef ZCM_EXTERN +#endif + diff --git a/src/zcmusicd.cpp b/src/zcmusicd.cpp new file mode 100644 index 0000000000..986e8a513f --- /dev/null +++ b/src/zcmusicd.cpp @@ -0,0 +1,23 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +/* Zelda Classic Music Library */ +/* ------------------------------------ */ +/* Wrapper for transparently extending */ +/* supported music file formats. */ + +#include "precompiled.h" //always first + +#include "zcmusic.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +char const * zcmusic_types = "it;mod;mp3;ogg;s3m;spc;gym;nsf;gbs;vgm;xm"; + +#ifdef __cplusplus +} +#endif + diff --git a/src/zconsole.h b/src/zconsole.h new file mode 100644 index 0000000000..33801eec30 --- /dev/null +++ b/src/zconsole.h @@ -0,0 +1,115 @@ +#ifndef _zc_win_console_h_ +#define _zc_win_console_h_ + + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#define WIN32_EXTRA_LEAN +#include +#include +#include +#include +#include +#include + + +#ifdef _MSC_VER +#pragma warning ( disable : 4996 ) +#endif + + + +class DebugConsole //Really half-ass singleton class. Do not instantiate this object. +{ +private: + bool isOpen; + static DebugConsole singleton; +public: + DebugConsole() : isOpen(false) + { + } + + ~DebugConsole() + { + Close(); + } + + static void Close() + { + if(singleton.isOpen) + ::FreeConsole(); + + singleton.isOpen = false; + } + + static void Open() + { + if(singleton.isOpen) + return; + + singleton.isOpen = true; + + const int MAX_CONSOLE_LINES = 512; + + CONSOLE_SCREEN_BUFFER_INFO console_info; + int hConHandle; + long lStdHandle; + + ::AllocConsole(); + ::SetConsoleTitle("zconsole"); + + + // set the screen buffer to be big enough to scroll text + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &console_info); + console_info.dwSize.Y = MAX_CONSOLE_LINES; + SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), console_info.dwSize); + + + // redirect unbuffered STDOUT to the console + lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + *stdout = *_fdopen(hConHandle, "w"); + setvbuf(stdout, NULL, _IONBF, 0); + + + // redirect unbuffered STDIN to the console + lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + *stdin = *_fdopen(hConHandle, "r"); + setvbuf(stdin, NULL, _IONBF, 0); + + + // redirect unbuffered STDERR to the console + lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); + hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); + *stderr = *_fdopen(hConHandle, "w"); + setvbuf(stderr, NULL, _IONBF, 0); + + + //for cout, wcout, cin, wcin, wcerr, cerr, wclog and clog + std::ios::sync_with_stdio(); + } + +}; + + +#ifdef _MSC_VER +#pragma warning ( default : 4996 ) +#endif + + +#else // _WIN32 + +class DebugConsole +{ +public: + static void Open() {} + static void Close() {} + static DebugConsole singleton; +}; + +#endif // not _WIN32 + +#endif + diff --git a/src/zdefs.h b/src/zdefs.h new file mode 100644 index 0000000000..5c1062ab34 --- /dev/null +++ b/src/zdefs.h @@ -0,0 +1,2915 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zdefs.h +// +// Data formats, definitions, and a few small functions +// for zelda.cc and zquest.cc +// +//-------------------------------------------------------- + +#ifndef _ZDEFS_H_ +#define _ZDEFS_H_ + +//Conditional Debugging Compilation +//Script related +#define _FFDEBUG +//#define _SCRIPT_COUNTER +//#define _FFDISSASSEMBLY +//#define _FFONESCRIPTDISSASSEMBLY + +//Other +//#define _SKIPPASSWORDCHECK + + +/* + //DOS Graphics Modes + GFX_TEXT + GFX_AUTODETECT + GFX_AUTODETECT_FULLSCREEN + GFX_AUTODETECT_WINDOWED + GFX_SAFE + GFX_VGA + GFX_MODEX + GFX_VESA1 + GFX_VESA2B + GFX_VESA2L + GFX_VESA3 + GFX_VBEAF + + //Windows Graphics Modes + GFX_TEXT + GFX_AUTODETECT + GFX_AUTODETECT_FULLSCREEN + GFX_AUTODETECT_WINDOWED + GFX_SAFE + GFX_DIRECTX + GFX_DIRECTX_ACCEL + GFX_DIRECTX_SOFT + GFX_DIRECTX_SAFE + GFX_DIRECTX_WIN + GFX_DIRECTX_OVL + GFX_GDI + + //Linux Graphics Modes + GFX_TEXT + GFX_AUTODETECT + GFX_AUTODETECT_FULLSCREEN + GFX_AUTODETECT_WINDOWED + GFX_SAFE + GFX_FBCON + GFX_VBEAF + GFX_SVGALIB + GFX_VGA + GFX_MODEX + + //X-Window Graphics Modes + GFX_TEXT + GFX_AUTODETECT + GFX_AUTODETECT_FULLSCREEN + GFX_AUTODETECT_WINDOWED + GFX_SAFE + GFX_XWINDOWS + GFX_XWINDOWS_FULLSCREEN + GFX_XDGA2 + GFX_XDGA2_SOFT + + //MacOS X Drivers + GFX_TEXT + GFX_AUTODETECT + GFX_AUTODETECT_FULLSCREEN + GFX_AUTODETECT_WINDOWED + GFX_SAFE + GFX_QUARTZ_FULLSCREEN + GFX_QUARTZ_WINDOW + */ + +#include "types.h" +#include "ffc.h" +#include "refInfo.h" +#include +#include +#include +#include +#include +#include "zc_alleg.h" +#include "gamedata.h" +#include "zc_array.h" + +#define ZELDA_VERSION 0x0250 //version of the program +#define VERSION_BUILD 29 //build number of this version +#define IS_BETA 0 //is this a beta? +#define DATE_STR "October 22, 2015" + +#define MIN_VERSION 0x0184 + +#define ZELDADAT_VERSION 0x0211 //version of zelda.dat +#define ZELDADAT_BUILD 17 //build of zelda.dat +#define SFXDAT_VERSION 0x0211 //version of sfx.dat +#define SFXDAT_BUILD 15 //build of sfx.dat +#define FONTSDAT_VERSION 0x0211 //version of fonts.dat +#define FONTSDAT_BUILD 18 //build of fonts.dat +#define QSTDAT_VERSION 0x0211 //version of qst.dat +#define QSTDAT_BUILD 18 //build of qst.dat +#define ZQUESTDAT_VERSION 0x0211 //version of zquest.dat +#define ZQUESTDAT_BUILD 18 //build of zquest.dat + +enum {ENC_METHOD_192B104=0, ENC_METHOD_192B105, ENC_METHOD_192B185, ENC_METHOD_211B9, ENC_METHOD_211B18, ENC_METHOD_MAX}; + +#ifdef ALLEGRO_DOS +//already defined in DOS +/* +#elif defined(ALLEGRO_WINDOWS) +#define PI 3.14159265358979323846 +#elif defined(ALLEGRO_MACOSX) +#define PI 3.14159265358979323846 +#elif defined(ALLEGRO_LINUX) +*/ +#else +#define PI 3.14159265358979323846 +#endif + +#define HP_PER_HEART 16 +#define DAMAGE_MULTIPLIER 2 + + +#define ZC_ID(a,b,c,d) (((a)<<24) | ((b)<<16) | ((c)<<8) | (d)) + +//ID values of the different section types +#define ID_HEADER ZC_ID('H','D','R',' ') //quest header +#define ID_RULES ZC_ID('R','U','L','E') //quest rules +#define ID_STRINGS ZC_ID('S','T','R',' ') //message strings +#define ID_MISC ZC_ID('M','I','S','C') //misc data +#define ID_TILES ZC_ID('T','I','L','E') //tiles +#define ID_COMBOS ZC_ID('C','M','B','O') //combos +#define ID_CSETS ZC_ID('C','S','E','T') //csets (and pal names?) +#define ID_MAPS ZC_ID('M','A','P',' ') //maps +#define ID_DMAPS ZC_ID('D','M','A','P') //dmaps +#define ID_DOORS ZC_ID('D','O','O','R') //door combo sets +#define ID_ITEMS ZC_ID('I','T','E','M') //items +#define ID_WEAPONS ZC_ID('W','P','N',' ') //weapons +#define ID_COLORS ZC_ID('M','C','L','R') //misc. colors +#define ID_ICONS ZC_ID('I','C','O','N') //save game icons +#define ID_GRAPHICSPACK ZC_ID('G','P','A','K') //graphics pack header +#define ID_INITDATA ZC_ID('I','N','I','T') //initialization data +#define ID_GUYS ZC_ID('G','U','Y',' ') //guys +#define ID_MIDIS ZC_ID('M','I','D','I') //midis +#define ID_CHEATS ZC_ID('C','H','T',' ') //cheats +#define ID_SAVEGAME ZC_ID('S','V','G','M') //save game data (used in the save game file) +#define ID_COMBOALIASES ZC_ID('C','M','B','A') //combo alias +#define ID_LINKSPRITES ZC_ID('L','I','N','K') //Link sprites +#define ID_SUBSCREEN ZC_ID('S','U','B','S') //subscreen data +#define ID_ITEMDROPSETS ZC_ID('D','R','O','P') //item drop set tables +#define ID_FAVORITES ZC_ID('F','A','V','S') //favorite combos and combo aliases +#define ID_FFSCRIPT ZC_ID('F','F','S','C') //ff scripts data +#define ID_SFX ZC_ID('S','F','X',' ') //sfx data + +//Version number of the different section types +#define V_HEADER 3 +#define V_RULES 13 +#define V_STRINGS 5 +#define V_MISC 7 +#define V_TILES 1 +#define V_COMBOS 7 +#define V_CSETS 4 +#define V_MAPS 18 +#define V_DMAPS 9 +#define V_DOORS 1 +#define V_ITEMS 25 +#define V_WEAPONS 6 +#define V_COLORS 2 +#define V_ICONS 1 +#define V_GRAPHICSPACK 1 +#define V_INITDATA 18 +#define V_GUYS 24 +#define V_MIDIS 4 +#define V_CHEATS 1 +#define V_SAVEGAME 11 +#define V_COMBOALIASES 2 +#define V_LINKSPRITES 5 +#define V_SUBSCREEN 6 +#define V_ITEMDROPSETS 2 +#define V_FFSCRIPT 6 +#define V_SFX 6 +#define V_FAVORITES 1 + +/* + * Compatible version number of the different section types + * Basically, the last version number that this section type + * is just an extension of (ie. new variables are stuck on the end) + * instead of a complete rewrite (or variables added to the middle). + * If this and the version number are the same, then this is + * a total reworking of the section and probably won't be able + * to be read by anything that was written for a previous version. + */ +#define CV_HEADER 3 +#define CV_RULES 1 +#define CV_STRINGS 2 +#define CV_MISC 7 +#define CV_TILES 1 +#define CV_COMBOS 1 +#define CV_CSETS 1 +#define CV_MAPS 9 +#define CV_DMAPS 1 +#define CV_DOORS 1 +#define CV_ITEMS 15 +#define CV_WEAPONS 1 +#define CV_COLORS 1 +#define CV_ICONS 1 +#define CV_GRAPHICSPACK 1 +#define CV_INITDATA 15 +#define CV_GUYS 3 +#define CV_MIDIS 3 +#define CV_CHEATS 1 +#define CV_SAVEGAME 5 +#define CV_COMBOALIASES 1 +#define CV_LINKSPRITES 1 +#define CV_SUBSCREEN 3 +#define CV_ITEMDROPSETS 1 +#define CV_FFSCRIPT 1 +#define CV_SFX 5 +#define CV_FAVORITES 1 + +extern int curr_tb_page; +extern bool triplebuffer_not_available; +extern int original_playing_field_offset; +extern int playing_field_offset; +extern int passive_subscreen_height; +extern int passive_subscreen_offset; + +extern int CSET_SIZE; +extern int CSET_SHFT; + +extern int readsize, writesize; +extern bool fake_pack_writing; + +// system colors +#define lc1(x) ((x)+192) // offset to 'level bg color' x (row 12) +#define lc2(x) ((x)+208) // offset to 'level fg color' x (row 13) +#define vc(x) ((x)+224) // offset to 'VGA color' x (row 14) +#define dvc(x) ((x)+240) // offset to dark 'VGA color' x (row 15) +#define BLACK 253 +#define WHITE 254 + +#define BYTE_FILTER 0xFF + +#define SINGLE_TILE_SIZE 128 +#define TILES_PER_ROW 20 +#define TILE_ROWS_PER_PAGE 13 +#define TILES_PER_PAGE (TILES_PER_ROW*TILE_ROWS_PER_PAGE) +#define TILE_PAGES 252 +#define OLDMAXTILES (TILES_PER_PAGE*6) // 1560 tiles +#define NEWMAXTILES (TILES_PER_PAGE*TILE_PAGES) // 32760 tiles +#define NEWTILE_SIZE2 (NEWMAXTILES*SINGLE_TILE_SIZE) // 4193280 bytes (new packed format, 6 pages) +#define OLDTILE_SIZE2 (OLDMAXTILES*SINGLE_TILE_SIZE) // 199680 bytes (new packed format, 6 pages) +// 133120 bytes (new packed format, 4 pages) +#define OLDTILE_SIZE (TILES_PER_PAGE*4*SINGLE_TILE_SIZE) +//#define NEWTILE_SIZE (260*6*128) // 199680 bytes (new packed format, 6 pages) +//#define OLDTILE_SIZE (260*4*128) // 133120 bytes (new packed format, 4 pages) +#define TILEBUF_SIZE (320*480) // 153600 bytes (old unpacked format) + +#define COMBOS_PER_ROW 20 + +//#define MAGICDRAINRATE 2 + +// quest stuff +#define ZQ_TILES 0 +#define ZQ_MIDIS2 1 //4 bytes +#define ZQ_CHEATS2 5 +#define ZQ_MAXDATA 20 +#define WAV_COUNT 256 + +#define MAXSCREENS 128 +#define MAXCUSTOMMIDIS192b177 32 // uses bit string for midi flags, so 32 bytes +#define MAXCUSTOMMIDIS 252 // uses bit string for midi flags, so 32 bytes +#define MIDIFLAGS_SIZE ((MAXCUSTOMMIDIS+7)>>3) +#define MAXCUSTOMTUNES 252 + +#define MAXMUSIC 256 // uses bit string for music flags, so 32 bytes +#define MUSICFLAGS_SIZE MAXMUSIC>>3 + +#define MAXMAPS2 255 // 4 times the old number +//#define MAXMAPS 16 +#define MAPSCRSNORMAL 128 +#define MAPSCRS192b136 132 +#define MAPSCRS 136 +#define TEMPLATES 8 +#define TEMPLATE 131 +#define TEMPLATE2 132 + +#define MAXQTS 256 +#define MAXMSGS 65535 +#define MAXDOORCOMBOSETS 256 +#define MAXDMAPS 512 //this and +#define MAXLEVELS 512 //this should be the same number (was 32) +#define OLDMAXLEVELS 256 +#define OLDMAXDMAPS 256 +#define MAXITEMS 256 +#define MAXWPNS 256 +#define OLDBETAMAXGUYS 256 //max 2.5 guys through beta 20 +#define MAXGUYS 512 +#define MAXITEMDROPSETS 256 +#define COMBOS_PER_PAGE 256 +#define COMBO_PAGES 255 +#define MAXCOMBOS COMBO_PAGES*COMBOS_PER_PAGE +#define MAXSUBSCREENITEMS 256 +#define MAXCUSTOMSUBSCREENS 128 +#define MAXFFCS 32 + +#define MAXFAVORITECOMMANDS 8 +#define MAXFAVORITECOMBOS 100 +#define MAXFAVORITECOMBOALIASES 100 + +#define MAGICPERBLOCK 32 +#define PALNAMESIZE 17 +// mapscr "valid" byte +#define mVALID 0x01 +#define mVERSION 0x80 + +// lvlitems flags +#define liTRIFORCE 1 +#define liMAP 2 +#define liCOMPASS 4 +#define liBOSS 8 +#define liBOSSKEY 16 + + +// door codes meaning: type | shows on subscreen map +// bit: 4321 0 +#define dWALL 0 // 0000 0 +#define dOPEN 1 // 0000 1 +#define dLOCKED 2 // 0001 0 +#define dUNLOCKED 3 // 0001 1 +#define dSHUTTER 4 // 0010 0 +#define dBOMB 6 // 0011 0 +#define dBOMBED 7 // 0011 1 +#define dWALK 8 // 0100 0 + +#define dBOSS 10 // 0101 0 +#define dOPENBOSS 11 // 0101 1 + +#define dOPENSHUTTER 12 // 0110 0 // special case (don't show on map) +#define d1WAYSHUTTER 14 // 0111 0 // never opens + +// screen flags +#define fSHUTTERS 1 +#define fITEM 2 +#define fDARK 4 +#define fROAR 8 // DEFUNCT +#define fWHISTLE 16 +#define fLADDER 32 +#define fMAZE 64 +#define fSEA 128 // DEFUNCT + +// flags2 +#define wfUP 1 +#define wfDOWN 2 +#define wfLEFT 4 +#define wfRIGHT 8 +#define fSECRET 16 // play "secret" sfx upon entering this screen +#define fAIRCOMBOS 32 +#define fFLOATTRAPS 64 +#define fCLEARSECRET 128 // clear all enemies to trigger secret entrance (Enemies->Secret) + +// flags3 +#define fHOLDITEM 1 +#define fCYCLEONINIT 2 +#define fINVISROOM 4 +#define fINVISLINK 8 +#define fNOSUBSCR 16 +#define fIWARPFULLSCREEN 32 // instawarps affect all sprites +#define fNOSUBSCROFFSET 64 // don't offset the screen when fNOSUBSCR is true +#define fENEMIESRETURN 128 // enemies always return + +//flags4 +#define fOVERHEADTEXT 1 +#define fITEMWARP 2 +#define fTIMEDDIRECT 4 //Specifies timed pit warp +#define fDISABLETIME 8 +#define fENEMYSCRTPERM 16 +#define fNOITEMRESET 32 +#define fSAVEROOM 64 +#define fAUTOSAVE 128 + +//flags5 +#define fRANDOMTIMEDWARP 1 +#define fDAMAGEWITHBOOTS 2 +#define fDIRECTAWARP 4 +#define fDIRECTSWARP 8 +#define fTEMPSECRETS 16 +// what is going on with 32? +#define fTOGGLEDIVING 64 +#define fNOFFCARRYOVER 128 + +//flags6 +#define fCAVEROOM 1 +#define fDUNGEONROOM 2 +#define fTRIGGERFPERM 4 +#define fCONTINUEHERE 8 +#define fNOCONTINUEHERE 16 +#define fTRIGGERF1631 32 +#define fTOGGLERINGDAMAGE 64 +#define fWRAPAROUNDFF 128 + +//flags7 +#define fLAYER3BG 1 +#define fLAYER2BG 2 +#define fITEMFALLS 4 +#define fSIDEVIEW 8 +#define fNOLINKMARK 16 +#define fSPECITEMMARK 32 +#define fWHISTLEPAL 64 +#define fWHISTLEWATER 128 + +//flags8 +// 1 - 16 are General Purpose (Scripts) +#define fMAZEvSIDEWARP 32 + +//lens layer effects +#define llNORMAL 0 +#define llLENSHIDES 8 +#define llLENSSHOWS 16 + +// enemy flags +#define efZORA 1 +#define efTRAP4 2 +#define efTRAP2 4 +#define efROCKS 8 +#define efFIREBALLS 16 +#define efLEADER 32 +#define efCARRYITEM 64 +#define efBOSS 128 + +// item "pick up" flags +#define ipBIGRANGE 1 // Collision rectangle is large +#define ipHOLDUP 2 // Link holds up item when he gets it +#define ipONETIME 4 // Getting this item sets mITEM +#define ipDUMMY 8 // Dummy item. Can't get this. +#define ipCHECK 16 // Check restrictions (money in a shop, etc.) +#define ipMONEY 32 // This item causes money loss (bomb upgrade, swindle room, etc.) +#define ipFADE 64 // Blinks if fadeclk>0 +#define ipENEMY 128 // Enemy is carrying it around +#define ipTIMER 256 // Disappears after a while +#define ipBIGTRI 512 // Large collision rectangle (used for large triforce) +#define ipNODRAW 1024 // Don't draw this (for underwater items) +#define ipONETIME2 2048 // Getting this item sets mBELOW +#define ipSPECIAL 4096 // This is the item in a Special Item room + + +enum +{ + wtCAVE, wtPASS, wtEXIT, wtSCROLL, wtIWARP, wtIWARPBLK, wtIWARPOPEN, + wtIWARPZAP, wtIWARPWAVE, wtNOWARP, wtWHISTLE, wtMAX +}; + +enum +{ + weINSTANT, weCIRCLE, weOVAL, weTRIANGLE, weSMAS, weBLINDS_SMOOTH, weBLINDS_STEPPED, weMOSAIC, weWAVE_WHITE, weWAVE_BLACK, weFADE_WHITE, weFADE_BLACK, weDEFAULT_OC, weDEST_DEFAULT, weMAX +}; +// sprite palettes +enum +{ + spAQUA, spGLEEOK, spDIG, spGANON, spBROWN, spPILE, spBLUE, spRED, + spGOLD, spICON1, spICON2, spICON3, spICON4, spGLEEOKF, spFROZEN +}; + +// dmap types +enum { dmDNGN, dmOVERW, dmCAVE, dmBSOVERW, dmMAX }; + +// dmap type bit masks (?) +#define dmfCONTINUE 128 +#define dmfTYPE 127 + +// map flags +enum +{ + mfNONE, mfPUSHUD, mfPUSH4, mfWHISTLE, mfBCANDLE, mfARROW, mfBOMB, mfFAIRY, + mfRAFT, mfARMOS_SECRET, mfARMOS_ITEM, mfSBOMB, mfRAFT_BRANCH, mfDIVE_ITEM, + mfLENSMARKER, mfZELDA, + mfSECRETS01, mfSECRETS02, mfSECRETS03, mfSECRETS04, /*16*/ + mfSECRETS05, mfSECRETS06, mfSECRETS07, mfSECRETS08, + mfSECRETS09, mfSECRETS10, mfSECRETS11, mfSECRETS12, + mfSECRETS13, mfSECRETS14, mfSECRETS15, mfSECRETS16, + mfTRAP_H, mfTRAP_V, mfTRAP_4, mfTRAP_LR, mfTRAP_UD, /*32*/ + mfENEMY0, mfENEMY1, mfENEMY2, mfENEMY3, mfENEMY4, /*37*/ + mfENEMY5, mfENEMY6, mfENEMY7, mfENEMY8, mfENEMY9, + mfPUSHLR, mfPUSHU, mfPUSHD, mfPUSHL, mfPUSHR, + mfPUSHUDNS, mfPUSHLRNS, mfPUSH4NS, mfPUSHUNS, + mfPUSHDNS, mfPUSHLNS, mfPUSHRNS, mfPUSHUDINS, + mfPUSHLRINS, mfPUSH4INS, mfPUSHUINS, + mfPUSHDINS, mfPUSHLINS, mfPUSHRINS, + mfBLOCKTRIGGER, mfNOBLOCKS, mfBRANG, mfMBRANG, + mfFBRANG, mfSARROW, mfGARROW, mfRCANDLE, mfWANDFIRE, mfDINSFIRE, + mfWANDMAGIC, mfREFMAGIC, mfREFFIREBALL, mfSWORD, mfWSWORD, + mfMSWORD, mfXSWORD, mfSWORDBEAM, mfWSWORDBEAM, mfMSWORDBEAM, + mfXSWORDBEAM, mfHOOKSHOT, mfWAND, mfHAMMER, mfSTRIKE, mfBLOCKHOLE, + mfMAGICFAIRY, mfALLFAIRY, mfSINGLE, mfSINGLE16, + mfNOENEMY, mfNOGROUNDENEMY, mfSCRIPT1, mfSCRIPT2, mfSCRIPT3, mfSCRIPT4, mfSCRIPT5, + mfRAFT_BOUNCE, mfMAX, mfPUSHED +}; + +// combo types +enum +{ + cNONE, cSTAIR, cCAVE, cWATER, cARMOS, cGRAVE, cDOCK, + cUNDEF, cPUSH_WAIT, cPUSH_HEAVY, cPUSH_HW, cL_STATUE, cR_STATUE, + cWALKSLOW, cCVUP, cCVDOWN, cCVLEFT, cCVRIGHT, cSWIMWARP, cDIVEWARP, + cLADDERHOOKSHOT, cTRIGNOFLAG, cTRIGFLAG, cZELDA, cSLASH, cSLASHITEM, + cPUSH_HEAVY2, cPUSH_HW2, cPOUND, cHSGRAB, cHSBRIDGE, cDAMAGE1, + cDAMAGE2, cDAMAGE3, cDAMAGE4, cC_STATUE, cTRAP_H, cTRAP_V, cTRAP_4, + cTRAP_LR, cTRAP_UD, cPIT, cHOOKSHOTONLY, cOVERHEAD, cNOFLYZONE, cMIRROR, + cMIRRORSLASH, cMIRRORBACKSLASH, cMAGICPRISM, cMAGICPRISM4, + cMAGICSPONGE, cCAVE2, cEYEBALL_A, cEYEBALL_B, cNOJUMPZONE, cBUSH, + cFLOWERS, cTALLGRASS, cSHALLOWWATER, cLOCKBLOCK, cLOCKBLOCK2, + cBOSSLOCKBLOCK, cBOSSLOCKBLOCK2, cLADDERONLY, cBSGRAVE, + cCHEST, cCHEST2, cLOCKEDCHEST, cLOCKEDCHEST2, cBOSSCHEST, cBOSSCHEST2, + cRESET, cSAVE, cSAVE2, /*cVERTICAL,*/ cCAVEB, cCAVEC, cCAVED, + cSTAIRB, cSTAIRC, cSTAIRD, cPITB, cPITC, cPITD, + cCAVE2B, cCAVE2C, cCAVE2D, cSWIMWARPB, cSWIMWARPC, cSWIMWARPD, + cDIVEWARPB, cDIVEWARPC, cDIVEWARPD, cSTAIRR, cPITR, + cAWARPA, cAWARPB, cAWARPC, cAWARPD, cAWARPR, + cSWARPA, cSWARPB, cSWARPC, cSWARPD, cSWARPR, cSTRIGNOFLAG, cSTRIGFLAG, + cSTEP, cSTEPSAME, cSTEPALL, cSTEPCOPY, cNOENEMY, cBLOCKARROW1, cBLOCKARROW2, + cBLOCKARROW3, cBLOCKBRANG1, cBLOCKBRANG2, cBLOCKBRANG3, cBLOCKSBEAM, cBLOCKALL, + cBLOCKFIREBALL, cDAMAGE5, cDAMAGE6, cDAMAGE7, cCHANGE/**DEPRECATED**/, cSPINTILE1, cSPINTILE2, + cSCREENFREEZE, cSCREENFREEZEFF, cNOGROUNDENEMY, cSLASHNEXT, cSLASHNEXTITEM, cBUSHNEXT, + cSLASHTOUCHY, cSLASHITEMTOUCHY, cBUSHTOUCHY, cFLOWERSTOUCHY, cTALLGRASSTOUCHY, + cSLASHNEXTTOUCHY, cSLASHNEXTITEMTOUCHY, cBUSHNEXTTOUCHY, cEYEBALL_4, cTALLGRASSNEXT, + cSCRIPT1, cSCRIPT2, cSCRIPT3, cSCRIPT4, cSCRIPT5, cMAX +}; + +#define QUESTRULES_SIZE 20 + +// "quest rules" flags (bit numbers in bit string) +enum +{ + // 1st byte out of 20 + qr_SOLIDBLK, qr_NOTMPNORET, qr_ALWAYSRET, qr_MEANTRAPS, + qr_BSZELDA, qr_FADE, qr_FADECS5, qr_FASTDNGN, + // 2 + qr_NOLEVEL3FIX, qr_COOLSCROLL, qr_NOSCROLL, qr_4TRI, + qr_EXPLICIT_RAFTING, qr_FASTFILL, qr_CAVEEXITNOSTOPMUSIC, qr_3TRI, + // 3 + qr_TIME, qr_FREEFORM, qr_KILLALL, qr_NOFLICKER, + qr_CONTFULL_DEP/*DEPRECATED*/, qr_RLFIX, qr_LENSHINTS, qr_LINKDUNGEONPOSFIX, + // 4 + qr_HOLDITEMANIMATION, qr_HESITANTPUSHBLOCKS, qr_HIDECARRIEDITEMS, qr_FFCSCROLL, + qr_RAFTLENS, qr_SMOOTHVERTICALSCROLLING, qr_WHIRLWINDMIRROR, qr_NOFLASHDEATH, + // 5 + qr_HOLDNOSTOPMUSIC, qr_FIREPROOFLINK, qr_OUCHBOMBS, qr_NOCLOCKS_DEP/*DEPRECATED*/, + qr_TEMPCLOCKS_DEP/*DEPRECATED*/, qr_BRKBLSHLDS_DEP/*DEPRECATED*/, qr_BRKNSHLDTILES, qr_MEANPLACEDTRAPS, + // 6 + qr_PHANTOMPLACEDTRAPS, qr_ALLOWFASTMSG, qr_LINKEDCOMBOS/*DEPRECATED*/, qr_NOGUYFIRES, + qr_HEARTRINGFIX, qr_NOHEARTRING, qr_OVERWORLDTUNIC, qr_SWORDWANDFLIPFIX, + // 7 + qr_ENABLEMAGIC, qr_MAGICWAND_DEP/*DEPRECATED*/, qr_MAGICCANDLE_DEP/*DEPRECATED*/, qr_MAGICBOOTS_DEP/*DEPRECATED*/, + qr_NONBUBBLEMEDICINE, qr_NONBUBBLEFAIRIES, qr_NONBUBBLETRIFORCE, qr_NEWENEMYTILES, + // 8 + qr_NOROPE2FLASH_DEP/*DEPRECATED*/, qr_NOBUBBLEFLASH_DEP/*DEPRECATED*/, qr_GHINI2BLINK_DEP, qr_WPNANIMFIX /* UNIMPLEMENTED */, + qr_PHANTOMGHINI2_DEP/*DEPRECATED*/, qr_Z3BRANG_HSHOT, qr_NOITEMMELEE, qr_SHADOWS, + // 9 + qr_TRANSSHADOWS, qr_QUICKSWORD, qr_BOMBHOLDFIX, qr_EXPANDEDLTM, + qr_NOPOTIONCOMBINE_DEP/*DEPRECATED*/, qr_LINKFLICKER, qr_SHADOWSFLICKER, qr_WALLFLIERS, + // 10 + qr_NOBOMBPALFLASH, qr_HEARTSREQUIREDFIX, qr_PUSHBLOCKCSETFIX, qr_TRANSLUCENTNAYRUSLOVEROCKET_DEP/*DEPRECATED*/, + qr_FLICKERINGNAYRUSLOVEROCKET_DEP/*DEPRECATED*/, qr_CMBCYCLELAYERS, qr_DMGCOMBOPRI, qr_WARPSIGNOREARRIVALPOINT, + // 11 + qr_LTTPCOLLISION, qr_LTTPWALK, qr_SLOWENEMYANIM_DEP/*DEPRECATED*/, qr_TRUEARROWS, + qr_NOSAVE, qr_NOCONTINUE, qr_QUARTERHEART, qr_NOARRIVALPOINT, + // 12 + qr_NOGUYPOOF, qr_ALLOWMSGBYPASS, qr_NODIVING, qr_LAYER12UNDERCAVE, + qr_NOSCROLLCONTINUE, qr_SMARTSCREENSCROLL, qr_RINGAFFECTDAMAGE, qr_ALLOW10RUPEEDROPS_DEP/*DEPRECATED*/, + // 13 + qr_TRAPPOSFIX, qr_TEMPCANDLELIGHT, qr_REDPOTIONONCE_DEP/*DEPRECATED*/, qr_OLDSTYLEWARP, + qr_NOBORDER, qr_OLDTRIBBLES_DEP/*DEPRECATED*/, qr_REFLECTROCKS /*DEPRECATED*/, qr_OLDPICKUP, + // 14 + qr_ENEMIESZAXIS, qr_SAFEENEMYFADE, qr_MORESOUNDS, qr_BRANGPICKUP, + qr_HEARTPIECEINCR_DEP/*DEPRECATED*/, qr_ITEMSONEDGES, qr_EATSMALLSHIELD_DEP/*DEPRECATED*/, qr_MSGFREEZE, + // 15 + qr_SLASHFLIPFIX, qr_FIREMAGICSPRITE_DEP/*DEPRECATED*/, qr_SLOWCHARGINGWALK, qr_NOWANDMELEE, + qr_SLOWBOMBFUSES_DEP/*DEPRECATED*/, qr_SWORDMIRROR, qr_SELECTAWPN, qr_LENSSEESENEMIES, + // 16 + qr_INSTABURNFLAGS, qr_DROWN, qr_MSGDISAPPEAR, qr_SUBSCREENOVERSPRITES, + qr_BOMBDARKNUTFIX, qr_LONGBOMBBOOM_DEP/*DEPRECATED*/, qr_OFFSETEWPNCOLLISIONFIX, qr_DMGCOMBOLAYERFIX, + // 17 + qr_ITEMSINPASSAGEWAYS, qr_LOG, qr_FIREPROOFLINK2, qr_NOITEMOFFSET, + qr_ITEMBUBBLE, qr_GOTOLESSNOTEQUAL /* Compatibility */, qr_LADDERANYWHERE, qr_HOOKSHOTLAYERFIX, + // 18 + qr_REPLACEOPENDOORS /* Compatibility */, qr_OLDLENSORDER /* Compatibility */, qr_NOFAIRYGUYFIRES /* Compatibility */, qr_SCRIPTERRLOG, + qr_TRIGGERSREPEAT /* Compatibility */, qr_ENEMIESFLICKER, qr_OVALWIPE, qr_TRIANGLEWIPE, + // 19 + qr_SMASWIPE, qr_NOSOLIDDAMAGECOMBOS /* Compatibility */, qr_SHOPCHEAT, qr_HOOKSHOTDOWNBUG /* Compatibility */, + qr_OLDHOOKSHOTGRAB /* Compatibility */, qr_PEAHATCLOCKVULN /* Compatibility */, qr_VERYFASTSCROLLING, qr_OFFSCREENWEAPONS /* Compatibility */, + qr_MAX +}; + +// room types +enum +{ + rNONE, rSP_ITEM, rINFO, rMONEY, rGAMBLE, rREPAIR, rRP_HC, rGRUMBLE, + rTRIFORCE, rP_SHOP, rSHOP, rBOMBS, rSWINDLE, r10RUPIES, rWARP, + rGANON, rZELDA, rUNUSED, rMUPGRADE, rLEARNSLASH, rARROWS, rTAKEONE, + rMAX +}; + +// directions +enum direction { up, down, left, right, l_up, r_up, l_down, r_down }; +const direction oppositeDir[]= {down, up, right, left, r_down, l_down, r_up, l_up}; +// refill stuff +enum { REFILL_NONE, REFILL_FAIRYDONE, REFILL_LIFE, REFILL_MAGIC, REFILL_ALL}; +#define REFILL_FAIRY -1 + +//Z-axis related +#define FEATHERJUMP 80 + +//other +#define MAXDRUNKCLOCK 500 + +enum +{ + dBUSHLEAVES, dFLOWERCLIPPINGS, dGRASSCLIPPINGS, dHAMMERSMACK, + dTALLGRASS, dRIPPLES, dNAYRUSLOVESHIELD, dHOVER, dMAXDECORATIONS +}; + +// items +enum // value matters because of current quest file data +{ + iRupy, i5Rupies, iHeart, iBombs, iClock, + iSword, iWSword, iMSword, iShield, iKey, + // 10 + iBCandle, iRCandle, iLetter, iArrow, iSArrow, + iBow, iBait, iBRing, iRRing, iBracelet, + // 20 + iTriforce, iMap, iCompass, iBrang, iMBrang, + iWand, iRaft,iLadder,iHeartC, iBPotion, + // 30 + iRPotion, iWhistle,iBook, iMKey, iFairyMoving, + iFBrang, iXSword, iMShield, i20Rupies, i50Rupies, + // 40 + i200Rupies, iWallet500, iWallet999, iPile, iBigTri, + iSelectA, iMisc1, iMisc2, iSBomb, iHCPiece, + // 50 + iAmulet, iFlippers, iHookshot, iLens, iHammer, + iBoots, iL2Bracelet, iGArrow, iMagicC, iSMagic, + // 60 + iLMagic, iGRing, iKillAll, iL2Amulet, iDinsFire, + iFaroresWind, iNayrusLove, iBossKey, iBow2, iFairyStill, + // 70 + i1ArrowAmmo, i5ArrowAmmo, i10ArrowAmmo, i30ArrowAmmo, iQuiver, + iQuiverL2, iQuiverL3, i1BombAmmo, i4BombAmmo, i8BombAmmo, + // 80 + i30BombAmmo, iBombBag, iBombBagL2, iBombBagL3, iLevelKey, + iSelectB, i10Rupies, i100Rupies, iCByrna, iLongshot, + // 90 + iLetterUsed,iRocsFeather,iHoverBoots,iSShield,iSpinScroll, + iCrossScroll,iQuakeScroll,iL2QuakeScroll,iL2SpinScroll,iWhispRing, + // 100 + iL2WhispRing, iChargeRing, iL2ChargeRing, iPerilScroll, iWalletL3, + iQuiverL4, iBombBagL4, iOldGlove, iL2Ladder,iWealthMedal, + // 110 + iL2WealthMedal, iL3WealthMedal,iHeartRing, iL2HeartRing, iL3HeartRing, + iMagicRing, iL2MagicRing, iL3MagicRing, iL4MagicRing, iStoneAgony, + // 120 + iStompBoots, iPerilRing, iWhimsicalRing, + iCustom1, iCustom2, iCustom3, iCustom4, iCustom5, + iCustom6, iCustom7, iCustom8, iCustom9, iCustom10, + iCustom11, iCustom12, iCustom13, iCustom14, iCustom15, + iCustom16, iCustom17, iCustom18, iCustom19, iCustom20, + iLast, + iMax=256 +}; + +// Shield projectile blocking +#define shROCK 0x001 +#define shARROW 0x002 +#define shBRANG 0x004 +#define shFIREBALL 0x008 +#define shSWORD 0x010 +#define shMAGIC 0x020 +#define shFLAME 0x040 +#define shSCRIPT 0x080 +#define shFIREBALL2 0x100 // Boss fireball, not ewFireball2 + +// item sets +enum +{ + isNONE, isDEFAULT, isBOMBS, isMONEY, isLIFE, isBOMB100, isSBOMB100, + isMAGIC, isMAGICBOMBS, isMAGICMONEY, isMAGICLIFE, isMAGIC2, isTALLGRASS, isMAX +}; + +// weapons (in qst data) +enum +{ + wSWORD, wWSWORD, wMSWORD, wXSWORD, wBRANG, + wMBRANG, wFBRANG, wBOMB, wSBOMB, wBOOM, +// 10 + wARROW, wSARROW, wFIRE, wWIND, wBAIT, + wWAND, wMAGIC, ewFIREBALL, ewROCK, ewARROW, +// 20 + ewSWORD, ewMAGIC, iwSpawn, iwDeath, iwSwim, + wHAMMER, wHSHEAD, wHSCHAIN_H, wHSHANDLE, wSSPARKLE, +// 30 + wGSPARKLE, wMSPARKLE, wFSPARKLE, iwHammerSmack, wGARROW, + ewFLAME, ewWIND, iwMMeter, wDINSFIRE1A, wDINSFIRE1B, +// 40 + wDINSFIRES1A, wDINSFIRES1B, wHSCHAIN_V, iwMore, iwBossMarker, + iwLinkSlash, wSWORDSLASH, wWSWORDSLASH, wMSWORDSLASH, wXSWORDSLASH, +// 50 + iwShadow, iwLargeShadow, iwBushLeaves, iwFlowerClippings, iwGrassClippings, + iwTallGrass, iwRipples, iwNPCs, wNAYRUSLOVE1A, wNAYRUSLOVE1B, +// 60 + wNAYRUSLOVES1A, wNAYRUSLOVES1B, wNAYRUSLOVE2A, wNAYRUSLOVE2B, wNAYRUSLOVES2A, + wNAYRUSLOVES2B, iwNayrusLoveShieldFront, iwNayrusLoveShieldBack, iwSubscreenVine, wCBYRNA, +// 70 + wCBYRNASLASH, wLSHEAD, wLSCHAIN_H, wLSHANDLE, wLSCHAIN_V, + wSBOOM, ewBOMB, ewSBOMB, ewBOOM, ewSBOOM, +// 80 + ewFIRETRAIL, ewFLAME2, ewFLAME2TRAIL, ewICE, iwHover, + wFIREMAGIC, iwQuarterHearts, wCBYRNAORB, //iwSideLadder, iwSideRaft, + + wLast, wMAX=256 +}; + +// weapon types in game engine +enum +{ + // 0 + wNone,wSword,wBeam,wBrang, + wBomb,wSBomb,wLitBomb,wLitSBomb, + // 8 + wArrow,wFire,wWhistle,wBait, + wWand,wMagic,wCatching,wWind, + // 16 + wRefMagic,wRefFireball,wRefRock, wHammer, + wHookshot, wHSHandle, wHSChain, wSSparkle, + // 24 + wFSparkle, wSmack, wPhantom, wCByrna, + wRefBeam, wStomp, + lwMax, + // Dummy weapons - must be between lwMax and wEnemyWeapons! + wScript1, wScript2, wScript3, wScript4, + wScript5, wScript6, wScript7, wScript8, + wScript9, wScript10, + // Enemy weapons + wEnemyWeapons=128, + //129 + ewFireball,ewArrow,ewBrang,ewSword, + ewRock,ewMagic,ewBomb,ewSBomb, + //137 + ewLitBomb,ewLitSBomb,ewFireTrail,ewFlame, + ewWind,ewFlame2,ewFlame2Trail, + //145 + ewIce,ewFireball2, + wMax +}; + +// phantom weapon types +enum +{ + pDINSFIREROCKET, pDINSFIREROCKETRETURN, pDINSFIREROCKETTRAIL, pDINSFIREROCKETTRAILRETURN, pMESSAGEMORE, + pNAYRUSLOVEROCKET1, pNAYRUSLOVEROCKETRETURN1, pNAYRUSLOVEROCKETTRAIL1, pNAYRUSLOVEROCKETTRAILRETURN1, + pNAYRUSLOVEROCKET2, pNAYRUSLOVEROCKETRETURN2, pNAYRUSLOVEROCKETTRAIL2, pNAYRUSLOVEROCKETTRAILRETURN2 +}; + +enum +{ + eNONE=0, + gNONE=0, gABEI, gAMA, gDUDE, gMOBLIN, + gFIRE, gFAIRY, gGORIYA, gZELDA, gABEI2, + //10 + gEMPTY, gDUMMY1, gDUMMY2, gDUMMY3, gDUMMY4, + gDUMMY5, gDUMMY6, gDUMMY7, gDUMMY8, gDUMMY9, + //20 + eSTART=20, + eOCTO1S=20, eOCTO2S, eOCTO1F, eOCTO2F, eTEK1, + eTEK2, eLEV1, eLEV2, eMOBLIN1, eMOBLIN2, + //30 + eLYNEL1, eLYNEL2, ePEAHAT, eZORA, eROCK, + eGHINI1, eGHINI2, eARMOS, eKEESE1, eKEESE2, + //40 + eKEESE3, eSTALFOS, eGEL, eZOL, eROPE, + eGORIYA1, eGORIYA2, eTRAP, eWALLM, eDKNUT1, + //50 + eDKNUT2, eBUBBLEST, eVIRE, eLIKE, eGIBDO, + ePOLSV, eWIZ1, eWIZ2, eRAQUAM, eMOLDORM, + //60 + eDODONGO, eMANHAN, eGLEEOK1, eGLEEOK2, eGLEEOK3, + eGLEEOK4, eDIG1, eDIG3, eDIGPUP1, eDIGPUP2, + //70 + eDIGPUP3, eDIGPUP4, eGOHMA1, eGOHMA2, eCENT1, + eCENT2, ePATRA1, ePATRA2, eGANON, eSTALFOS2, + //80 + eROPE2, eBUBBLESP, eBUBBLESR, eSHOOTFBALL, eITEMFAIRY, + eFIRE, eOCTO5, eDKNUT5, eGELTRIB, eZOLTRIB, + //90 + eKEESETRIB, eVIRETRIB, eDKNUT3, eLAQUAM, eMANHAN2, + eTRAP_H, eTRAP_V, eTRAP_LR, eTRAP_UD, eFWIZ, + //100 + eWWIZ, eCEILINGM, eFLOORM, ePATRABS, ePATRAL2, + ePATRAL3, eBAT, eBATROBE, eBATROBEKING, eGLEEOK1F, + //110 + eGLEEOK2F, eGLEEOK3F, eGLEEOK4F, eMWIZ, eDODONGOBS, + eDODONGOF, eTRIGGER, eBUBBLEIT, eBUBBLEIP, eBUBBLEIR, + //120 + eSTALFOS3, eGOHMA3, eGOHMA4, eNPCSTAND1, eNPCSTAND2, + eNPCSTAND3, eNPCSTAND4, eNPCSTAND5, eNPCSTAND6, eNPCWALK1, + //130 + eNPCWALK2, eNPCWALK3, eNPCWALK4, eNPCWALK5, eNPCWALK6, + eBOULDER, eGORIYA3, eLEV3, eOCTO3S, eOCTO3F, + //140 + eOCTO4S, eOCTO4F, eTRAP_8WAY, eTRAP_DIAGONAL, eTRAP_SLASH_C, + eTRAP_SLASH_LOS, eTRAP_BACKSLASH_C, eTRAP_BACKSLASH_LOS, eTRAP_CW_C, eTRAP_CW_LOS, + //150 + eTRAP_CCW_C, eTRAP_CCW_LOS, eSUMMONER, eIWIZ, eSHOOTMAGIC, + eSHOOTROCK, eSHOOTSPEAR, eSHOOTSWORD, eSHOOTFLAME, eSHOOTFLAME2, + //160 + eBOMBCHU, eFGEL, eFZOL, eFGELTRIB, eFZOLTRIB, + eTEK3, eSPINTILE1, eSPINTILE2, eLYNEL3, eFPEAHAT, + //170 + eMPOLSV, eWPOLSV, eDKNUT4, eFGHINI, eMGHINI, + eGRAPBUGHP, eGRAPBUGMP, e177, + + eMAXGUYS = MAXGUYS +}; + +#define OLDMAXGUYS e177 + +// enemy families +enum +{ + eeGUY=0, eeWALK, + eeSHOOT/*DEPRECATED*/, + eeTEK, eeLEV, eePEAHAT, eeZORA, eeROCK, + eeGHINI, eeARMOS/*DEPRECATED*/, eeKEESE, eeGEL/*DEPRECATED*/, eeZOL/*DEPRECATED*/, eeROPE/*DEPRECATED*/, eeGORIYA/*DEPRECATED*/, eeTRAP, + eeWALLM, eeBUBBLE/*DEPRECATED*/, eeVIRE/*DEPRECATED*/, eeLIKE/*DEPRECATED*/, eePOLSV/*DEPRECATED*/, eeWIZZ, eeAQUA, eeMOLD, + eeDONGO, eeMANHAN, eeGLEEOK, eeDIG, eeGHOMA, eeLANM, eePATRA, eeGANON, + eePROJECTILE, eeGELTRIB/*DEPRECATED*/, eeZOLTRIB/*DEPRECATED*/, eeVIRETRIB/*DEPRECATED*/, eeKEESETRIB/*DEPRECATED*/, eeSPINTILE, eeNONE, + eeFAIRY, eeFIRE, eeOTHER, + eeMAX +}; + +// enemy animation styles +enum +{ + aNONE, aFLIP, aUNUSED1, a2FRM, aUNUSED2, + aOCTO, aTEK, aLEV, aWALK, aZORA, + aNEWZORA, aGHINI, aARMOS, aROPE, aWALLM, + aNEWWALLM, aDWALK, aVIRE, a3FRM, aWIZZ, + aAQUA, aDONGO, aMANHAN, aGLEEOK, aDIG, + aGHOMA, aLANM, a2FRMPOS, a4FRM4EYE,a4FRM8EYE, + a4FRM4DIRF, a4FRM4DIR, a4FRM8DIRF, aARMOS4, a4FRMPOS4DIR, + a4FRMPOS8DIR, aUNUSED3, a4FRM8DIRB, aNEWTEK, a3FRM4DIR, + a2FRM4DIR, aNEWLEV, a2FRM4EYE, aNEWWIZZ, aNEWDONGO, + aDONGOBS, a4FRMPOS8DIRF, a4FRMPOS4DIRF, a4FRMNODIR, aGANON, a2FRMB, aMAX +}; +// deprecated styles +#define aFLIPSLOW 1 +#define a2FRMSLOW 3 +#define aNEWDWALK 42 +#define aNEWPOLV 39 +#define a4FRM3TRAP 36 + +// Enemy misc1 types +enum { e1tNORMAL, e1tEACHTILE, e1tCONSTANT, e1tHOMINGBRANG=2, e1tFAST, e1tSLANT, e1t3SHOTS, e1t4SHOTS, e1t5SHOTS, e1t3SHOTSFAST, e1tFIREOCTO, e1t8SHOTS, e1tSUMMON, e1tSUMMONLAYER, e1tLAST }; +// Enemy misc2 types +enum { e2tNORMAL, e2tSPLITHIT, e2tSPLIT, e2tFIREOCTO, e2tBOMBCHU, e2tTRIBBLE, e2tLAST }; +#define e2tKEESETRIB 1 + +// Enemy misc7 types +enum { e7tNORMAL, e7tTEMPJINX, e7tPERMJINX, e7tUNJINX, e7tTAKEMAGIC, e7tTAKERUPEES, e7tDRUNK, +// all from this point involve engulfing + e7tEATITEMS, e7tEATMAGIC, e7tEATRUPEES, e7tEATHURT, +// all from this point involve dragging + e7tWALLMASTER, e7tLAST + }; + +// Enemy misc8 types +enum { e8tSWORD, e8tITEM, e8tALL, e8tLAST }; + +// Enemy misc9 types +// Walker +enum { e9tNORMAL, e9tROPE, e9tVIRE, e9tPOLSVOICE, e9tARMOS, +// remainder unimplemented + e9tLEEVER, e9tZ3LEEVER, e9tZ3WALK, e9tZ3STALFOS, e9tLAST + }; + +/* +// Floater +enum { e9tPEAHAT=1, e9tGHINI }; +// Teleporter +enum { e9tBATROBE=1, e9tZ3WIZZROBE }; +// Traps +enum { e9tAUTOTRAP=1 }; +// Moldorm +enum { e9tMOLDORM=1, e9tVLANMOLA, e9tVMOLDORM, e9tZ3MOLDORM, //restricted to walkable combos + e9tTAIL, //only tail is vulnerable + e9tMINIMOLD, //doesn't segment + e9tBIGTAIL //doesn't segment, only tail is vulnerable + }; +*/ +enum +{ + edefBRANG, edefBOMB, edefSBOMB, edefARROW, edefFIRE, edefWAND, + edefMAGIC, edefHOOKSHOT, edefHAMMER, edefSWORD, edefBEAM, edefREFBEAM, edefREFMAGIC, + edefREFBALL, edefREFROCK, edefSTOMP, edefBYRNA, edefSCRIPT /* used to be unused edefSPIN */, + // Reserved for future use. + edefQUAKE, + edefLAST +}; + + +enum +{ + edNORMAL, // Take damage (or stun) + edHALFDAMAGE, // Take half damage + edQUARTDAMAGE, // Take 0.25 damage + edSTUNONLY, // Stun instead of taking damage. + edSTUNORCHINK, // If damage > 0, stun instead. Else, bounce off. + edSTUNORIGNORE, // If damage > 0, stun instead. Else, ignore. + edCHINKL1, // Bounces off, plays SFX_CHINK + edCHINKL2, // Bounce off unless damage >= 2 + edCHINKL4, // Bounce off unless damage >= 4 + edCHINKL6, // Bounce off unless damage >= 6 + edCHINKL8, // Bounce off unless damage >= 8 + edCHINK, // Bounces off, plays SFX_CHINK + edIGNOREL1, // Ignore unless damage > 1. + edIGNORE, // Do Nothing + ed1HKO, // One-hit knock-out + edLAST +}; +#define edX edIGNORE // Shorthand +// Remaining 16 reserved for future use. + +// enemy patters +enum { pRANDOM, pSIDES, pSIDESR, pCEILING, pCEILINGR, pRANDOMR }; + +enum { tfInvalid=0, tf4Bit, tf8Bit, tf16Bit, tf24Bit, tf32Bit, tfMax }; + +struct size_and_pos +{ + int x; + int y; + int w; + int h; +}; + +//#define OLDITEMCNT i90 +//#define OLDWPNCNT w84 +#define ITEMCNT iMax +#define WPNCNT wMAX + +struct tiledata +{ + byte format; + byte *data; +}; + +struct itemdata +{ + word tile; + byte misc; // 0000vhtf (vh:flipping, t:two hands, f:flash) + byte csets; // ffffcccc (f:flash cset, c:cset) + byte frames; // animation frame count + byte speed; // animation speed + byte delay; // extra delay factor (-1) for first frame + long ltm; // Link Tile Modifier + byte family; // What family the item is in + byte fam_type; // What type in this family the item is + byte power; // Damage, height, etc. + word flags; +#define ITEM_GAMEDATA 0x0001 // Whether this item sets the corresponding gamedata value or not +#define ITEM_EDIBLE 0x0002 // can be eaten by Like Like +#define ITEM_COMBINE 0x0004 // blue potion + blue potion = red potion +#define ITEM_DOWNGRADE 0x0008 +#define ITEM_FLAG1 0x0010 +#define ITEM_FLAG2 0x0020 +#define ITEM_KEEPOLD 0x0040 +#define ITEM_RUPEE_MAGIC 0x0080 +#define ITEM_UNUSED 0x0100 +#define ITEM_GAINOLD 0x0200 +#define ITEM_FLAG3 0x0400 +#define ITEM_FLAG4 0x0800 +#define ITEM_FLAG5 0x1000 + word script; // Which script the item is using + char count; + word amount; + short setmax; + word max; + byte playsound; + word collect_script; +// byte exp[10]; // not used + long initiald[8]; + byte initiala[2]; + byte wpn; + byte wpn2; + byte wpn3; + byte wpn4; + byte wpn5; + byte wpn6; + byte wpn7; + byte wpn8; + byte wpn9; + byte wpn10; + byte pickup_hearts; + long misc1; + long misc2; + long misc3; + long misc4; + long misc5; + long misc6; + long misc7; + long misc8; + long misc9; + long misc10; + byte magic; // Magic usage! + byte usesound; +}; + +struct wpndata +{ + word tile; + byte misc; // 000bvhff (vh:flipping, f:flash (1:NES, 2:BSZ)) + byte csets; // ffffcccc (f:flash cset, c:cset) + byte frames; // animation frame count + byte speed; // animation speed + byte type; // used by certain weapons +// byte wpn_type; + word script; +// byte exp; // not used +}; + +#define WF_BEHIND 0x10 //Weapon renders behind other sprites + +struct quest_template +{ + char name[31]; + char path[2048]; + //311 bytes +}; + +struct item_drop_object +{ + char name[64]; + word item[10]; + word chance[11]; //0=none +}; + +#define guy_bhit 0x00000001 +#define guy_invisible 0x00000002 +#define guy_neverret 0x00000004 +#define guy_doesntcount 0x00000008 + +#define guy_fadeflicker 0x00000010 +#define guy_fadeinstant 0x00000020 +/* +#define inv_bomb 0x00000040 +#define inv_sbomb 0x00000080 + +#define inv_arrow 0x00000100 +#define inv_L2arrow 0x00000200 +#define inv_fire 0x00000400 +#define inv_wand 0x00000800 + +#define inv_magic 0x00001000 +#define inv_hookshot 0x00002000 +#define inv_hammer 0x00004000 +#define inv_L3brang 0x00008000 + +#define inv_L1sword 0x00010000 +#define inv_L3sword 0x00020000 +#define inv_L1beam 0x00040000 +#define inv_L3beam 0x00080000 + +#define inv_refbeam 0x00100000 +#define inv_refmagic 0x00200000 +#define inv_refball 0x00400000 +#define inv_extra 0x00800000 +*/ +#define inv_front 0x01000000 +#define inv_left 0x02000000 +#define inv_right 0x04000000 +#define inv_back 0x08000000 + +#define guy_bkshield 0x10000000 // Shield can't be broken +//#define guy_mirror 0x20000000 // Shield is mirrored +//#define weak_L3brang 0x40000000 + +#define lens_only 0x80000000 + +#define guy_flashing 0x00000001 +#define eneflag_zora 0x00000002 +#define eneflag_rock 0x00000004 +#define eneflag_trap 0x00000008 + +#define cmbflag_trph 0x00000010 +#define cmbflag_trpv 0x00000020 +#define cmbflag_trp4 0x00000040 +#define cmbflag_trplr 0x00000080 + +#define cmbflag_trpud 0x00000100 +#define eneflag_trp2 0x00000200 +#define eneflag_fire 0x00000400 +#define cmbflag_armos 0x00000800 + +#define cmbflag_ghini 0x00001000 +#define eneflag_ganon 0x00002000 +#define guy_blinking 0x00004000 +#define guy_transparent 0x00008000 + +// Old flags +#define weak_arrow 0x20000000 +#define guy_superman 0x00000008 +#define guy_sbombonly 0x00000010 + +struct guydata +{ + dword flags; + dword flags2; + word tile; + byte width; + byte height; //0=striped, 1+=rectangular + word s_tile; //secondary (additional) tile(s) + byte s_width; + byte s_height; //0=striped, 1+=rectangular + word e_tile; + byte e_width; + byte e_height; + + short hp; + + short family, cset, anim, e_anim, frate, e_frate; + short dp, wdp, weapon; + + short rate, hrate, step, homing, grumble, item_set; + long misc1, misc2, misc3, misc4, misc5, misc6, misc7, misc8, misc9, misc10, misc11, misc12, misc13, misc14, misc15; + short bgsfx, bosspal, extend; + byte defense[edefLAST]; + // short startx, starty; + // short foo1,foo2,foo3,foo4,foo5,foo6; + byte hitsfx, deadsfx; +}; + + +struct mapscr +{ + byte valid; + byte guy; + word str; + byte room; + byte item; + byte hasitem; + byte tilewarptype[4]; + byte tilewarpoverlayflags; + word door_combo_set; + byte warpreturnx[4]; + byte warpreturny[4]; + word warpreturnc; + byte stairx; + byte stairy; + byte itemx; + byte itemy; + word color; + byte enemyflags; + byte door[4]; + word tilewarpdmap[4]; + byte tilewarpscr[4]; + byte exitdir; + word enemy[10]; + byte pattern; + byte sidewarptype[4]; + byte sidewarpoverlayflags; + byte warparrivalx; + byte warparrivaly; + byte path[4]; + byte sidewarpscr[4]; + word sidewarpdmap[4]; + byte sidewarpindex; + word undercombo; + byte undercset; + word catchall; + byte flags; + byte flags2; + byte flags3; + byte flags4; + byte flags5; + byte flags6; + byte flags7; + byte flags8; + byte flags9; + byte flags10; + byte csensitive; + word noreset; + word nocarry; + byte layermap[6]; + byte layerscreen[6]; + // byte layerxsize[6]; + // byte layerxspeed[6]; + // byte layerxdelay[6]; + // byte layerysize[6]; + // byte layeryspeed[6]; + // byte layerydelay[6]; + byte layeropacity[6]; + word timedwarptics; + byte nextmap; + byte nextscr; + word secretcombo[128]; + byte secretcset[128]; + byte secretflag[128]; + + std::vector data; + std::vector sflag; + std::vector cset; + word viewX; + word viewY; + byte scrWidth; + byte scrHeight; + + ///TODO: This is just plain wasteful and needs fixing at some point. + FFCSet ffcs; + //FFCSet* ffcs; + + dword ffcsUsed; // Each bit corresponds to an FFC + byte oceansfx; + byte bosssfx; + byte secretsfx; + byte holdupsfx; + + // for importing older quests... + byte old_cpage; + short screen_midi; + byte lens_layer; + + + void zero_memory() + { + //oh joy, this will be fun... + valid=0; + guy=0; + str=0; + room=0; + item=0; + hasitem=0; + tilewarpoverlayflags=0; + door_combo_set=0; + warpreturnc=0; + stairx=0; + stairy=0; + itemx=0; + itemy=0; + color=0; + enemyflags=0; + + exitdir=0; + pattern=0; + sidewarpoverlayflags=0; + warparrivalx=0; + warparrivaly=0; + + sidewarpindex=0; + undercombo=0; + undercset=0; + catchall=0; + flags=0; + flags2=0; + flags3=0; + flags4=0; + flags5=0; + flags6=0; + flags7=0; + flags8=0; + flags9=0; + flags10=0; + csensitive=0; + noreset=0; + nocarry=0; + timedwarptics=0; + nextmap=0; + nextscr=0; + + viewX=0; + viewY=0; + scrWidth=0; + scrHeight=0; + ffcsUsed=0; + + for(int i(0); i<4; i++) + { + door[i]=0; + tilewarpdmap[i]=0; + tilewarpscr[i]=0; + tilewarptype[i]=0; + warpreturnx[i]=0; + warpreturny[i]=0; + path[i]=0; + sidewarpscr[i]=0; + sidewarpdmap[i]=0; + sidewarptype[i]=0; + } + + for(int i(0); i<10; i++) + enemy[i]=0; + + for(int i(0); i<128; i++) + { + secretcombo[i]=0; + secretcset[i]=0; + secretflag[i]=0; + } + + for(int i(0); i<6; i++) + { + layermap[i]=0; + layerscreen[i]=0; + layeropacity[i]=0; + } + + ffcs.clear(); // Actually sets width and height to 15, not 0 + + oceansfx=0; + bosssfx=0; + secretsfx=0; + holdupsfx=0; + lens_layer=0; + + data.assign(176,0); + sflag.assign(176,0); + cset.assign(176,0); + //data.assign(data.size(),0); + //sflag.assign(sflag.size(),0); + //cset.assign(cset.size(),0); + } + + + mapscr() + { + // TODO: We can just create a single contiguous block for these. + //zero_memory() already assigns these to 0. + //data.resize(176,0); + //sflag.resize(176,0); + //cset.resize(176,0); + + zero_memory(); + } + + // Functions for AngelScript + word getData(int index) const { return data[index]; } + void setData(int index, word value) { data[index]=value; } + byte getCSet(int index) const { return cset[index]; } + void setCSet(int index, byte value) { cset[index]=value; } + byte getSFlag(int index) const { return sflag[index]; } + void setSFlag(int index, byte value) { sflag[index]=value; } + + word getSecretCombo(int index) const { return secretcombo[index]; } + void setSecretCombo(int index, word value) { secretcombo[index]=value; } + byte getSecretCSet(int index) const { return secretcset[index]; } + void setSecretCSet(int index, byte value) { secretcset[index]=value; } + byte getSecretFlag(int index) const { return secretflag[index]; } + void setSecretFlag(int index, byte value) { secretflag[index]=value; } + + FFC* getFFC(int index) { return ffcs.getPtr(index); } +}; + +struct ffscript +{ + word command; + long arg1; + long arg2; + char *ptr; +}; + + +enum +{ + sBCANDLE, sARROW, sBOMB, sSTAIRS, sSECRET01, sSECRET02, sSECRET03, + sSECRET04, sSECRET05, sSECRET06, sSECRET07, sSECRET08, sSECRET09, + sSECRET10, sSECRET11, sSECRET12, sSECRET13, sSECRET14, sSECRET15, + sSECRET16, sRCANDLE, sWANDFIRE, sDINSFIRE, sSARROW, sGARROW, + sSBOMB, sBRANG, sMBRANG, sFBRANG, sWANDMAGIC, sREFMAGIC, sREFFIREBALL, + sSWORD, sWSWORD, sMSWORD, sXSWORD, sSWORDBEAM, sWSWORDBEAM, + sMSWORDBEAM, sXSWORDBEAM, sHOOKSHOT, sWAND, sHAMMER, sSTRIKE +}; + +struct comboclass +{ + char name[64]; // name + byte block_enemies; // a (bit flags, 1=ground, 2=jump, 4=fly) + byte block_hole; // b + byte block_trigger; // c + byte block_weapon[32]; // d (ID of lweapons/eweapons to block) + short conveyor_x_speed; // e + short conveyor_y_speed; // f + word create_enemy; // g + byte create_enemy_when; // h + long create_enemy_change; // i + byte directional_change_type; // j + long distance_change_tiles; // k + short dive_item; // l + byte dock; // m + byte fairy; // n + byte ff_combo_attr_change; // o + long foot_decorations_tile; // p + byte foot_decorations_type; // q + byte hookshot_grab_point; // r + byte ladder_pass; // s + byte lock_block_type; // t + long lock_block_change; // u + byte magic_mirror_type; // v + short modify_hp_amount; // w + byte modify_hp_delay; // x + byte modify_hp_type; // y + short modify_mp_amount; // z + byte modify_mp_delay; // aa + byte modify_mp_type; // ab + byte no_push_blocks; // ac + byte overhead; // ad + byte place_enemy; // ae + byte push_direction; // af + byte push_weight; // ag + byte push_wait; // ah + byte pushed; // ai + byte raft; // aj + byte reset_room; // ak + byte save_point_type; // al + byte screen_freeze_type; // am + byte secret_combo; // an + byte singular; // ao + byte slow_movement; // ap + byte statue_type; // aq + byte step_type; // ar + long step_change_to; // as + byte strike_weapons[32]; // at + long strike_remnants; // au + byte strike_remnants_type; // av + long strike_change; // aw + short strike_item; // ax + short touch_item; // ay + byte touch_stairs; // az + byte trigger_type; // ba + byte trigger_sensitive; // bb + byte warp_type; // bc + byte warp_sensitive; // bd + byte warp_direct; // be + byte warp_location; // bf + byte water; // bg + byte whistle; // bh + byte win_game; // bi + byte block_weapon_lvl; // bj (maximum item level to block) +}; + +enum {cfOFFSET, cfMAX}; + +struct newcombo +{ + word tile; + word nextcombo; + word nexttimer; + byte flip; + byte walk; + byte type; + byte csets; + byte frames; + byte speed; + byte nextcset; + byte flag; + byte skipanim; + byte skipanimy; + byte animflags; + // TODO: It might be worth compressing newcombo into an aligned 16 byte block. + //17 (+3) +}; + +#define AF_FRESH 1 +#define AF_CYCLE 2 + +struct tiletype +{ + byte bitplanes; + byte *data; +}; + +struct ZCHEATS +{ + dword flags; + char codes[4][41]; + //168 +}; + +#define QH_IDSTR "AG Zelda Classic Quest File\n " +#define QH_NEWIDSTR "AG ZC Enhanced Quest File\n " +#define ENC_STR "Zelda Classic Quest File" + +struct zquestheader +{ + char id_str[31]; + //32 + short zelda_version; + word internal; + byte quest_number; + byte old_rules[2]; + byte old_map_count; + char old_str_count; + //41 + byte data_flags[ZQ_MAXDATA]; + byte old_rules2[2]; + char old_options; + char version[9]; + //73 + char title[65]; + char author[65]; + //byte padding; + //204 + // short pwdkey; + bool dirty_password; + char password[256]; + unsigned char pwd_hash[16]; + //236 + char minver[9]; + byte build; + byte use_keyfile; + byte old_foo[9]; + byte old_rules3[2]; + byte old_rules4[2]; + byte old_rules5[2]; + byte old_rules6[2]; + byte old_rules7[2]; + byte old_rules8[2]; + byte old_rules9[2]; + byte old_rules10[2]; + byte old_midi_flags[MIDIFLAGS_SIZE]; + //304 + byte old_foo2[18]; + char templatepath[2048]; + //602 +}; + +enum { msLINKED }; + +/* Note: Printable ASCII begins at 32 and ends at 126, inclusive. */ +#define MSGC_COLOUR 1 // 2 args +#define MSGC_SPEED 2 // 1 arg +#define MSGC_GOTOIFGLOBAL 3 // 3 args +#define MSGC_GOTOIFRAND 4 // 2 args +#define MSGC_GOTOIF 5 // 2 args +#define MSGC_GOTOIFCTR 6 // 3 args +#define MSGC_GOTOIFCTRPC 7 // 3 args +#define MSGC_GOTOIFTRI 8 // 2 args +#define MSGC_GOTOIFTRICOUNT 9 // 2 args +#define MSGC_CTRUP 10 // 2 args +#define MSGC_CTRDN 11 // 2 args +#define MSGC_CTRSET 12 // 2 args +#define MSGC_CTRUPPC 13 // 2 args +#define MSGC_CTRDNPC 14 // 2 args +#define MSGC_CTRSETPC 15 // 2 args +#define MSGC_GIVEITEM 16 // 1 arg +#define MSGC_TAKEITEM 17 // 1 arg +#define MSGC_SFX 20 // 1 arg +#define MSGC_MIDI 21 // 1 arg +#define MSGC_NAME 22 // 0 args, disabled +#define MSGC_NEWLINE 25 // 0 args +#define MSGC_GOTOIFYN 30 // 0 args, disabled + +enum +{ + font_zfont, /* 24, 32, 26, 5 */ + font_z3font, + font_z3smallfont, + font_deffont, + font_lfont, + font_lfont_l, + font_pfont, + font_mfont, + font_ztfont, + font_sfont, + font_sfont2, + font_spfont, + font_ssfont1, + font_ssfont2, + font_ssfont3, + font_ssfont4, + font_gblafont, + font_goronfont, + font_zoranfont, + font_hylian1font, + font_hylian2font, + font_hylian3font, + font_hylian4font, + font_gboraclefont, + font_gboraclepfont, + font_dsphantomfont, + font_dsphantompfont, + font_max +}; + +#define MSGSIZE 144 + +#define STRINGFLAG_WRAP 1 +#define STRINGFLAG_CONT 2 +#define STRINGFLAG_CENTER 4 +#define STRINGFLAG_RIGHT 8 + +struct MsgStr +{ + char s[MSGSIZE+1]; + word nextstring; + word tile; + byte cset; + bool trans; + byte font; + short x; + short y; // y position of message boxes. + unsigned short w; + unsigned short h; + byte sfx; // either WAV_MSG or something else. + word listpos; + byte vspace; + byte hspace; + byte stringflags; + + // Copy everything except listpos + MsgStr& operator=(MsgStr &other) + { + strncpy(s, other.s, MSGSIZE+1); + nextstring=other.nextstring; + copyStyle(other); + return *this; + } + + // Copy style data - everything except s, nextstring, and listpos + void copyStyle(MsgStr& other) + { + tile=other.tile; + cset=other.cset; + trans=other.trans; + font=other.font; + x=other.x; + y=other.y; + w=other.w; + h=other.h; + sfx=other.sfx; + vspace=other.vspace; + hspace=other.hspace; + stringflags=other.stringflags; + } +}; + +enum {dt_pass=0, dt_lock, dt_shut, dt_boss, dt_olck, dt_osht, dt_obos, dt_wall, dt_bomb, dt_walk, dt_max}; +enum {df_walktrans=0}; + +struct DoorComboSet +{ + char name[21]; + //byte padding; + //22 + word doorcombo_u[9][4]; //[door type][door combo] + byte doorcset_u[9][4]; //[door type][door combo] + word doorcombo_d[9][4]; //[door type][door combo] + byte doorcset_d[9][4]; //[door type][door combo] + //238 (216) + word doorcombo_l[9][6]; //[door type][door combo] + byte doorcset_l[9][6]; //[door type][door combo] + word doorcombo_r[9][6]; //[door type][door combo] + byte doorcset_r[9][6]; //[door type][door combo] + //562 (324) + word bombdoorcombo_u[2]; //rubble + byte bombdoorcset_u[2]; //rubble + word bombdoorcombo_d[2]; //rubble + byte bombdoorcset_d[2]; //rubble + //574 (12) + word bombdoorcombo_l[3]; //rubble + byte bombdoorcset_l[3]; //rubble + //byte padding; + word bombdoorcombo_r[3]; //rubble + byte bombdoorcset_r[3]; //rubble + //byte padding; + //594 (18) + word walkthroughcombo[4]; //[n, s, e, w] + byte walkthroughcset[4]; //[n, s, e, w] + + byte flags[2]; + byte expansion[30]; + //638 (44) +}; + +struct dmap +{ + byte map; + word level; + char xoff; + byte compass; + word color; + byte midi; + byte cont; + byte type; + //8 + byte grid[8]; + //16 + char name[21]; + char title[21]; + char intro[73]; + //byte padding; + //132 + word minimap_1_tile; //before getting map + byte minimap_1_cset; //cset for minimap 1 + //byte padding; + word minimap_2_tile; //after getting map + byte minimap_2_cset; //cset for minimap 2 + //byte padding; + //140 + word largemap_1_tile; //large map + byte largemap_1_cset; //cset for large + //byte padding; + word largemap_2_tile; //large map + byte largemap_2_cset; //cset for large + char tmusic[56]; + byte tmusictrack; + byte active_subscreen; + byte passive_subscreen; + // int emusic; + //byte padding; + //204 + byte disableditems[iMax]; + // 460 + long flags; +}; + +// DMap flags +#define dmfCAVES 0x0001 +#define dmf3STAIR 0x0002 +#define dmfWHIRLWIND 0x0004 +#define dmfGUYCAVES 0x0008 +#define dmfNOCOMPASS 0x0010 +#define dmfWAVY 0x0020 +#define dmfWHIRLWINDRET 0x0040 +#define dmfALWAYSMSG 0x0080 +#define dmfVIEWMAP 0x0100 +#define dmfDMAPMAP 0x0200 +#define dmfMINIMAPCOLORFIX 0x0400 +#define dmfSCRIPT1 0x0800 +#define dmfSCRIPT2 0x1000 +#define dmfSCRIPT3 0x2000 +#define dmfSCRIPT4 0x4000 +#define dmfSCRIPT5 0x8000 + +#define OLDMAXCOMBOALIASES 256 +#define MAXCOMBOALIASES 2048 + +struct combo_alias +{ + combo_alias() + { + memset(this, 0, sizeof(combo_alias)); + combos = new word[1]; + csets = new byte[1]; + combos[0] = 0; + csets[0] = 0; + } + + byte width; // Max 15 + byte height; // Max 10 + byte layermask; // Specifies layers to be drawn + word combo; // Optional thumbnail combo for the alias list + word cset; + word *combos; // Dynamic array. Will be stored in quest. + byte *csets; +}; + +struct shoptype +{ + char name[32]; + byte item[3]; + byte hasitem[3]; + word price[3]; + //10 +}; + +struct pondtype +{ + byte olditem[3]; + byte newitem[3]; + byte fairytile; + byte aframes; + byte aspeed; + word msg[15]; + byte foo[32]; + //72 +}; + +struct infotype +{ + char name[32]; + word str[3]; + //byte padding; + word price[3]; + //14 +}; + +struct warpring +{ + char name[32]; + word dmap[9]; + byte scr[9]; + byte size; + //18 +}; + +struct zcolors +{ + byte text, caption; + byte overw_bg, dngn_bg; + byte dngn_fg, cave_fg; + byte bs_dk, bs_goal; + byte compass_lt, compass_dk; + //10 + byte subscr_bg, subscr_shadow, triframe_color; + byte bmap_bg,bmap_fg; + byte link_dot; + //15 + byte triforce_cset; + byte triframe_cset; + byte overworld_map_cset; + byte dungeon_map_cset; + byte blueframe_cset; + //20 + word triforce_tile; + word triframe_tile; + word overworld_map_tile; + word dungeon_map_tile; + word blueframe_tile; + //30 + word HCpieces_tile; + byte HCpieces_cset; + byte msgtext; + byte foo[6]; + //40 + byte foo2[256]; + //296 bytes +}; + +struct palcycle +{ + byte first,count,speed; + //3 +}; + +struct miscQdata +{ + shoptype shop[256]; + //160 (160=10*16) + infotype info[256]; + //384 (224=14*16) + warpring warp[9]; + //528 (144=18*8) + palcycle cycles[256][3]; + //2832 (2304=3*256*3) + //2850 (18=2*2) + byte triforce[8]; // positions of triforce pieces on subscreen + //2858 (8) + zcolors colors; + //3154 (296) + word icons[4]; + //3162 (8=2*4) + //pondtype pond[16]; + //4314 (1152=72*16) + word endstring; + // byte dummy; // left over from a word + //word expansion[98]; + //4512 +}; + +#define MFORMAT_MIDI 0 +#define MFORMAT_NSF 1 + +//tune flags +#define tfDISABLESAVE 1 + +class zctune +{ + +public: + + char title[36]; + //20 + long start; + long loop_start; + long loop_end; + //32 + short loop; + short volume; + byte flags; + // 37 + void *data; + // 41 + + byte format; + + zctune() + { + data = NULL; + format = MFORMAT_MIDI; + reset(); + } + + zctune(char _title[36], long _start, long _loop_start, long _loop_end, short _loop,short _volume, void *_data, byte _format) + : start(_start), loop_start(_loop_start), loop_end(_loop_end), loop(_loop), volume(_volume), data(_data), format(_format) + { + //memcpy(title, _title, 20); //NOT SAFE for short strings + strncpy(title, _title, 36); + } + + void clear() + { + memset(title,0,36); + start = loop_start = loop_end = 0; + loop = volume = flags = 0; + data = NULL; + } + + void copyfrom(zctune z) + { + start = z.start; + loop_start = z.loop_start; + loop_end = z.loop_end; + loop = z.loop; + flags = z.flags; + volume = z.volume; + //memcpy(title, z.title,20); //NOT SAFE for short title strings + strncpy(title, z.title, 36); + data = z.data; + } + + void reset() + { + title[0]=0; + loop=1; + volume=144; + start=0; + loop_start=-1; + loop_end=-1; + flags=0; + + if(data) switch(format) + { + case MFORMAT_MIDI: + destroy_midi((MIDI*) data); + break; + + default: + break; + } + + data = NULL; + } + +}; + +/*typedef struct zcmidi_ // midi or other sound format (nsf ...) +{ + char title[20]; + //20 + long start; + long loop_start; + long loop_end; + //32 + short loop; + short volume; + //36 + byte format; + MIDI *midi; + //41 +} zcmidi_; +*/ + +/*typedef struct emusic +{ + char title[20]; + char filename[256]; +} emusic; +*/ + +enum itemType // used for gamedata ITEMS +{ + // 0 + itype_sword, itype_brang, itype_arrow, itype_candle, itype_whistle, + itype_bait, itype_letter, itype_potion, itype_wand, itype_ring, + itype_wallet, itype_amulet, itype_shield, itype_bow, itype_raft, + itype_ladder, itype_book, itype_magickey, itype_bracelet, itype_flippers, + // 20 + itype_boots, itype_hookshot, itype_lens, itype_hammer, itype_dinsfire, + itype_faroreswind, itype_nayruslove, itype_bomb, itype_sbomb, itype_clock, + itype_key, itype_magiccontainer, itype_triforcepiece, itype_map, itype_compass, + itype_bosskey, itype_quiver, itype_lkey, itype_cbyrna, itype_rupee, + // 40 + itype_arrowammo, itype_fairy, itype_magic, itype_heart, itype_heartcontainer, + itype_heartpiece, itype_killem, itype_bombammo, itype_bombbag, itype_rocs, + itype_hoverboots, itype_spinscroll,itype_crossscroll, itype_quakescroll,itype_whispring, + itype_chargering, itype_perilscroll, itype_wealthmedal,itype_heartring,itype_magicring, + // 60 + itype_spinscroll2, itype_quakescroll2, itype_agony, itype_stompboots, itype_whimsicalring, + itype_perilring, itype_misc, + // 67 + itype_custom1, itype_custom2, itype_custom3, itype_custom4, itype_custom5, + itype_custom6, itype_custom7, itype_custom8, itype_custom9, itype_custom10, + itype_custom11, itype_custom12, itype_custom13, itype_custom14, itype_custom15, + itype_custom16, itype_custom17, itype_custom18, itype_custom19, itype_custom20, + // 87 + itype_bowandarrow, itype_letterpotion, + itype_last, itype_max=255 +}; + +enum {i_sword=1, i_wsword, i_msword, i_xsword, imax_sword}; +enum {i_wbrang=1, i_mbrang, i_fbrang, imax_brang}; +enum {i_warrow=1, i_sarrow, i_garrow, imax_arrow}; +enum {i_bcandle=1, i_rcandle, imax_candle}; +enum {i_recorder=1, imax_whistle}; +enum {i_bait=1, imax_bait}; +enum {i_letter=1, i_letter_used, imax_letter}; +enum {i_bpotion=1, i_rpotion, imax_potion}; +enum {i_wand=1, imax_wand}; +enum {i_bring=2, i_rring, i_gring, imax_ring}; +enum {i_swallet=1, i_lwallet, i_mwallet, imax_wallet}; +enum {i_amulet1=1, i_amulet2, imax_amulet}; +enum {i_smallshield=1, i_largeshield, i_mirrorshield, imax_shield}; +enum {i_shortbow=1, i_longbow, imax_bow}; +enum {i_raft=1, imax_raft}; +enum {i_ladder=1, i_ladder2, imax_ladder}; +enum {i_book=1, imax_book}; +enum {i_magickey=1, imax_magickey}; +enum {i_oldglove=1, i_bracelet1, i_bracelet2, imax_bracelet}; +enum {i_flippers=1, imax_flippers}; +enum {i_boots=1, imax_boots}; +enum {i_hookshot=1, i_longshot, imax_hookshot}; +enum {i_lens=1, imax_lens}; +enum {i_hammer=1, imax_hammer}; +enum {i_dinsfire=1, imax_dinsfire}; +enum {i_faroreswind=1, imax_faroreswind}; +enum {i_nayruslove=1, imax_nayruslove}; +enum {i_quiver=1, i_quiverl2, i_quiverl3, i_quiverl4, imax_quiver}; +enum {i_cbyrna=1, imax_cbyrna}; +enum {i_rocs=1, imax_rocs}; +enum {i_hoverboots=1, imax_hoverboots}; +enum {i_spinscroll1=1, i_spinscroll2, imax_spinscroll}; +enum {i_crossscroll=1, imax_crossscroll}; +enum {i_quakescroll1=1, i_quakescroll2, imax_quakescroll}; +enum {i_whispring1=1, i_whispring2, imax_whispring}; +enum {i_chargering1=1, i_chargering2, imax_chargering}; +enum {i_perilscroll=1, imax_perilscroll}; +enum {i_shieldscroll=1, imax_shieldscroll}; +enum {i_wealthmedal=1, i_wealthmedal2, i_wealthmedal3, imax_wealthmedal}; +enum {i_heartring=1, i_heartring2, i_heartring3, imax_heartring}; +enum {i_magicring=1, i_magicring2, i_magicring3, i_magicring4, imax_magicring}; +enum {i_rupee=1, i_5rupee, i_10rupee, i_20rupee, i_50rupee, i_100rupee, i_200rupee, imax_rupee}; +enum {i_arrowa=1, i_5arrowa, i_10arrowa, i_30arrowa, imax_arrowa}; +enum {i_bomba=1, i_4bomba, i_8bomba, i_30bomba, imax_bomba}; +enum {i_bomb = 1, imax_bomb}; +enum {i_sbomb = 1, imax_sbomb}; +enum {i_bombbag1=1, i_bombbag2, i_bombbag3, i_bombbag4, imax_bombbag}; + +//enum {i_clock=1, imax_clock}; + +struct gamedata +{ + //private: + char _name[9]; + byte _quest; + //10 + //word _life,_maxlife; + //short _drupy; + //word _rupies,_arrows,_maxarrows, + word _deaths; + //20 + //byte _keys,_maxbombs, + byte /*_wlevel,*/_cheat; + //24 + bool item[MAXITEMS]; + byte items_off[MAXITEMS]; + //280 + word _maxcounter[32]; // 0 - life, 1 - rupees, 2 - bombs, 3 - arrows, 4 - magic, 5 - keys, 6-super bombs + word _counter[32]; + short _dcounter[32]; + + char version[9]; + char title[65]; + //354 + byte _hasplayed; + //byte padding; + //356 + dword _time; + //360 + byte _timevalid; + byte lvlitems[MAXLEVELS]; + byte lvlkeys[MAXLEVELS]; + //byte _HCpieces; + byte _continue_scrn; + word _continue_dmap; + //620 + /*word _maxmagic, _magic; + short _dmagic;*/ + //byte _magicdrainrate; + //byte _canslash; //Link slashes instead of stabs. + byte _generic[256]; // Generic gamedata. 0 - Heart pieces, 1- magicdrainrate, 2-canslash, 3-wlevel, + // 4- HC Pieces per container 5- Continue hearts 6- Continue percent (1=yes) + //byte padding[2]; + //636 + byte visited[MAXDMAPS]; + //892 (256) + byte bmaps[MAXDMAPS*64]; // the dungeon progress maps + //17276 (16384) + word maps[MAXMAPS2*MAPSCRSNORMAL]; // info on map changes, items taken, etc. + //82556 (65280) + byte guys[MAXMAPS2*MAPSCRSNORMAL]; // guy counts (though dungeon guys are reset on entry) + //115196 (32640) + char qstpath[2048]; + byte icon[128]; + byte pal[48]; + long screen_d[MAXDMAPS*MAPSCRSNORMAL][8]; // script-controlled screen variables + long global_d[256]; // script-controlled global variables + std::vector< ZCArray > globalRAM; + + byte awpn, bwpn; // Currently selected weapon slots + + bool isclearing; // The gamedata is being cleared + //115456 (260) + + // member functions + // public: + gamedata() + { + Clear(); + } + + ~gamedata() + {} + + void Clear(); + void Copy(const gamedata& g); + + gamedata &operator = (const gamedata& data) + { + this->Copy(data); + this->globalRAM=data.globalRAM; + return *this; + } + + char *get_name(); + void set_name(char *n); + + byte get_quest(); + void set_quest(byte q); + void change_quest(short q); + + word get_counter(byte c); + void set_counter(word change, byte c); + void change_counter(short change, byte c); + + word get_maxcounter(byte c); + void set_maxcounter(word change, byte c); + void change_maxcounter(short change, byte c); + + short get_dcounter(byte c); + void set_dcounter(short change, byte c); + void change_dcounter(short change, byte c); + + word get_life(); + void set_life(word l); + void change_life(short l); + + word get_maxlife(); + void set_maxlife(word m); + void change_maxlife(short m); + + short get_drupy(); + void set_drupy(short d); + void change_drupy(short d); + + word get_rupies(); + word get_spendable_rupies(); + void set_rupies(word r); + void change_rupies(short r); + + word get_maxarrows(); + void set_maxarrows(word a); + void change_maxarrows(short a); + + word get_arrows(); + void set_arrows(word a); + void change_arrows(short a); + + word get_deaths(); + void set_deaths(word d); + void change_deaths(short d); + + word get_keys(); + void set_keys(word k); + void change_keys(short k); + + word get_bombs(); + void set_bombs(word k); + void change_bombs(short k); + + word get_maxbombs(); + void set_maxbombs(word b, bool setSuperBombs=true); + void change_maxbombs(short b); + + word get_sbombs(); + void set_sbombs(word k); + void change_sbombs(short k); + + word get_wlevel(); + void set_wlevel(word l); + void change_wlevel(short l); + + byte get_cheat(); + void set_cheat(byte c); + void change_cheat(short c); + + byte get_hasplayed(); + void set_hasplayed(byte p); + void change_hasplayed(short p); + + dword get_time(); + void set_time(dword t); + void change_time(long long t); + + byte get_timevalid(); + void set_timevalid(byte t); + void change_timevalid(short t); + + byte get_HCpieces(); + void set_HCpieces(byte p); + void change_HCpieces(short p); + + byte get_hcp_per_hc(); + void set_hcp_per_hc(byte val); + + byte get_cont_hearts(); + void set_cont_hearts(byte val); + + bool get_cont_percent(); + void set_cont_percent(bool ispercent); + + byte get_continue_scrn(); + void set_continue_scrn(byte s); + void change_continue_scrn(short s); + + word get_continue_dmap(); + void set_continue_dmap(word d); + void change_continue_dmap(short d); + + word get_maxmagic(); + void set_maxmagic(word m); + void change_maxmagic(short m); + + word get_magic(); + void set_magic(word m); + void change_magic(short m); + + short get_dmagic(); + void set_dmagic(short d); + void change_dmagic(short d); + + byte get_magicdrainrate(); + void set_magicdrainrate(byte r); + void change_magicdrainrate(short r); + + byte get_canslash(); + void set_canslash(byte s); + void change_canslash(short s); + + short get_generic(byte c); + void set_generic(byte change, byte c); + void change_generic(short change, byte c); + + byte get_lkeys(); + + void set_item(int id, bool value); + void set_item_no_flush(int id, bool value); + inline bool get_item(int id) + { + return item[id]; + } + +}; + +// "initialization data" flags (bit numbers in bit string) +// These are DEFUNCT, it seems. +enum +{ + idE_RAFT, idE_LADDER, idE_BOOK, idE_KEY, + idE_FLIPPERS, idE_BOOTS, idE_HOVERBOOTS, idE_MAX +}; +enum +{ + idI_WAND, idI_LETTER, idI_LENS, idI_HOOKSHOT, + idI_BAIT, idI_HAMMER, idI_CBYRNA, idI_ROCS, idI_MAX +}; +enum { idI_DFIRE, idI_FWIND, idI_NLOVE, idI_MAX2 }; +enum { idM_CONTPERCENT, idM_DOUBLEMAGIC, idM_CANSLASH, idM_MAX }; +enum +{ + idBP_WOODENPERCENT, idBP_WHITEPERCENT, + idBP_MAGICPERCENT, idBP_MASTERPERCENT, idBP_MAX +}; + +struct zinitdata +{ + byte bombs, super_bombs; + bool items[256]; + //94 + byte hc; + word start_heart, cont_heart; + byte hcp, hcp_per_hc, max_bombs, keys; + byte arrows, max_arrows; + word rupies; + byte triforce; // bit flags + byte map[64]; + byte compass[64]; + byte boss_key[64]; + byte misc[16]; +// byte sword_hearts[4]; + byte last_map; //last map worked on + //220 + byte last_screen; //last screen worked on + word max_magic; + word magic; + byte bomb_ratio; // ratio of super bombs to bombs + byte msg_more_x, msg_more_y, msg_more_is_offset; + byte subscreen; + word start_dmap; + byte linkanimationstyle; + //238 + //byte expansion[98]; + //336 bytes total + byte level_keys[MAXLEVELS]; + int ss_grid_x; + int ss_grid_y; + int ss_grid_xofs; + int ss_grid_yofs; + int ss_grid_color; + int ss_bbox_1_color; + int ss_bbox_2_color; + int ss_flags; + byte subscreen_style; + byte usecustomsfx; + word max_rupees, max_keys; + byte gravity; + word terminalv; + byte msg_speed; + byte transition_type; // Can't edit, yet. + byte jump_link_layer_threshold; // Link is drawn above layer 3 if z > this. + byte link_swim_speed; +}; + +struct zcmap +{ + byte tileWidth; + byte tileHeight; + word subaWidth; + word subaHeight; + word subpWidth; + word subpHeight; + word scrResWidth; + word scrResHeight; + word viewWidth; + word viewHeight; + word viewX; + word viewY; + bool subaTrans; + bool subpTrans; +}; + + +/******************/ +/** Misc Stuff **/ +/******************/ + +/*#undef max +#undef min*/ +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) + +#define DCLICK_START 0 +#define DCLICK_RELEASE 1 +#define DCLICK_AGAIN 2 +#define DCLICK_NOT 3 + +template +INLINE T sign(T a) +{ + return T(a < 0 ? -1: 1); +} + +//#ifndef NOZSWAP +template +static INLINE void zc_swap(T &a,T &b) +{ + T c = a; + a = b; + b = c; +} +//#endif + +template +static INLINE bool is_between(T a, T b, T c, bool inclusive) +{ + if(a>b&&anormal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + c = pack_getc(f); + + if(pack_ferror(f)) + { + return false; + } + + if(keepdata==true) + { + *cp = c; + } + + readsize+=1; + return true; +} + +INLINE bool p_putc(int c,PACKFILE *f) +{ + bool success=true; + + if(!fake_pack_writing) + { + if(!f) return false; + +#ifdef NEWALLEGRO + + if(!(f->normal.flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#else + + if(!(f->flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#endif + + pack_putc(c,f); + success=(pack_ferror(f)==0); + } + + if(success) + { + writesize+=1; + } + + return success; +} + +INLINE bool p_igetw(void *p,PACKFILE *f,bool keepdata) +{ + short *cp = (short *)p; + int c; + + if(!f) return false; + +#ifdef NEWALLEGRO + + if(f->normal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + c = pack_igetw(f); + + if(pack_ferror(f)) + { + return false; + } + + if(keepdata==true) + { + *cp = c; + } + + readsize+=2; + return true; +} + +INLINE bool p_iputw(int c,PACKFILE *f) +{ + bool success=true; + + if(!fake_pack_writing) + { + if(!f) return false; + +#ifdef NEWALLEGRO + + if(!(f->normal.flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#else + + if(!(f->flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#endif + + pack_iputw(c,f); + success=(pack_ferror(f)==0); + } + + if(success) + { + writesize+=2; + } + + return success; +} + +INLINE bool p_igetl(void *p,PACKFILE *f,bool keepdata) +{ + dword *cp = (dword *)p; + long c; + + if(!f) return false; + +#ifdef NEWALLEGRO + + if(f->normal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + c = pack_igetl(f); + + if(pack_ferror(f)) + { + return false; + } + + if(keepdata==true) + { + *cp = c; + } + + readsize+=4; + return true; +} + +INLINE bool p_igetd(void *p, PACKFILE *f, bool keepdata) +{ + long temp; + bool result = p_igetl(&temp,f,keepdata); + *(int *)p=(int)temp; + return result; +} + +INLINE bool p_igetf(void *p,PACKFILE *f,bool keepdata) +{ + if(!f) return false; + +#ifdef NEWALLEGRO + + if(f->normal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + byte tempfloat[sizeof(float)]; + + if(!pfread(tempfloat,sizeof(float),f,true)) + return false; + + if(keepdata) + { + memset(p, 0,sizeof(float)); +#ifdef ALLEGRO_MACOSX + + for(int i=0; i<(int)sizeof(float); i++) + { + ((byte *)p)[i] = tempfloat[i]; + } + +#else + + for(int i=0; i<(int)sizeof(float); i++) + { + ((byte *)p)[sizeof(float)-i-1] = tempfloat[i]; + } + +#endif + } + + readsize += sizeof(float); + return true; +} + +INLINE bool p_iputl(long c,PACKFILE *f) +{ + bool success=true; + + if(!fake_pack_writing) + { + if(!f) return false; + +#ifdef NEWALLEGRO + + if(!(f->normal.flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#else + + if(!(f->flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#endif + + pack_iputl(c,f); + success=(pack_ferror(f)==0); + } + + if(success) + { + writesize+=4; + } + + return success; +} + +INLINE bool p_mgetw(void *p,PACKFILE *f,bool keepdata) +{ + short *cp = (short *)p; + int c; + + if(!f) return false; + +#ifdef NEWALLEGRO + + if(f->normal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + c = pack_mgetw(f); + + if(pack_ferror(f)) + { + return false; + } + + if(keepdata==true) + { + *cp = c; + } + + readsize+=2; + return true; +} + +INLINE bool p_mputw(int c,PACKFILE *f) +{ + bool success=true; + + if(!fake_pack_writing) + { + if(!f) return false; + +#ifdef NEWALLEGRO + + if(!(f->normal.flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#else + + if(!(f->flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#endif + + pack_mputw(c,f); + success=(pack_ferror(f)==0); + } + + if(success) + { + writesize+=2; + } + + return success; +} + +INLINE bool p_mgetl(void *p,PACKFILE *f,bool keepdata) +{ + dword *cp = (dword *)p; + long c; + + if(!f) return false; + +#ifdef NEWALLEGRO + + if(f->normal.flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#else + + if(f->flags&PACKFILE_FLAG_WRITE) return false; //must not be writing to file + +#endif + + if(pack_feof(f)) + { + return false; + } + + c = pack_mgetl(f); + + if(pack_ferror(f)) + { + return false; + } + + if(keepdata==true) + { + *cp = c; + } + + readsize+=4; + return true; +} + +INLINE bool p_mputl(long c,PACKFILE *f) +{ + bool success=true; + + if(!fake_pack_writing) + { + if(!f) return false; + +#ifdef NEWALLEGRO + + if(!(f->normal.flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#else + + if(!(f->flags&PACKFILE_FLAG_WRITE)) return false; //must be writing to file + +#endif + + pack_mputl(c,f); + success=(pack_ferror(f)==0); + } + + if(success) + { + writesize+=4; + } + + return success; +} + +INLINE bool isinRect(int x,int y,int rx1,int ry1,int rx2,int ry2) +{ + return x>=rx1 && x<=rx2 && y>=ry1 && y<=ry2; +} + +INLINE void SCRFIX() +{ + putpixel(screen,0,0,getpixel(screen,0,0)); +} + +// ack no, inline doesn't work this way -DD +//INLINE int new_return(int x) { fake_pack_writing=false; return x; } +#define new_return(x) {assert(x == 0); fake_pack_writing = false; return x; } + +//some methods for dealing with items +int getItemFamily(itemdata *items, int item); +void removeItemsOfFamily(gamedata *g, itemdata *items, int family); +void removeItemsOfFamily(zinitdata *i, itemdata *items, int family); +void removeLowerLevelItemsOfFamily(gamedata *g, itemdata *items, int family, int level); +int getHighestLevelOfFamily(zinitdata *source, itemdata *items, int family); +int getHighestLevelOfFamily(gamedata *source, itemdata *items, int family, bool checkenabled = false); +int getItemID(itemdata *items, int family, int level); +int getCanonicalItemID(itemdata *items, int family); +int getItemIDPower(itemdata *items, int family, int power); +void addOldStyleFamily(zinitdata *dest, itemdata *items, int family, char levels); +int computeOldStyleBitfield(zinitdata *source, itemdata *items, int family); + +extern void flushItemCache(); +#define NUMSCRIPTFFC 512 +#define NUMSCRIPTFFCOLD 256 +#define NUMSCRIPTITEM 256 +#define NUMSCRIPTGUYS 256 +#define NUMSCRIPTWEAPONS 256 +#define NUMSCRIPTGLOBAL 4 +#define NUMSCRIPTGLOBALOLD 3 +#define NUMSCRIPTLINK 3 +#define NUMSCRIPTSCREEN 256 + +#define GLOBAL_SCRIPT_INIT 0 +#define GLOBAL_SCRIPT_GAME 1 +#define GLOBAL_SCRIPT_END 2 +#define GLOBAL_SCRIPT_CONTINUE 3 + + +#endif //_ZDEFS_H_ diff --git a/src/zelda.cpp b/src/zelda.cpp new file mode 100644 index 0000000000..b31c62fc03 --- /dev/null +++ b/src/zelda.cpp @@ -0,0 +1,3265 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zelda.cc +// +// Main code for Zelda Classic. Originally written in +// SPHINX C--, now rewritten in DJGPP with Allegro. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include +#include +#include +#include +//#include +#include +#include +#include + +#include "zc_alleg.h" + +#include +#include +#include + +#include +#include + +#include "zc_malloc.h" +#include "mem_debug.h" +#include "zscriptversion.h" +#include "zcmusic.h" +#include "zdefs.h" +#include "zelda.h" +#include "tiles.h" +#include "colors.h" +#include "pal.h" +#include "aglogo.h" +#include "zsys.h" +#include "qst.h" +#include "matrix.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "save_gif.h" +#include "load_gif.h" // not really needed; we're just saving GIF files in ZC. +#include "fontsdat.h" +#include "particles.h" +#include "gamedata.h" +#include "ffscript.h" +#include "init.h" +#include +#include "zc_array.h" +#include "rendertarget.h" +#include "zconsole.h" +#include "win32.h" +#include "vectorset.h" +#include "single_instance.h" +#include "linkHandler.h" +#include "messageManager.h" +#include "room.h" +#include "screenFreezeState.h" +#include "sequence.h" +#include "sfxManager.h" +#include "sound.h" +#include "angelscript/aszc.h" + +#ifdef _MSC_VER +#include +#define stricmp _stricmp +#endif + +MessageManager messageMgr; +SFXManager sfxMgr; +LinkHandler linkHandler; +ScreenFreezeState freezeState(messageMgr); + +ZCMUSIC *zcmusic = NULL; +zinitdata zinit; +int colordepth; +int db=0; +//zinitdata zinit; +int detail_int[10]; //temporary holder for things you want to detail +int lens_hint_item[MAXITEMS][2]; //aclk, aframe +int lens_hint_weapon[MAXWPNS][5]; //aclk, aframe, dir, x, y +int strike_hint_counter=0; +int strike_hint_timer=0; +int strike_hint; +int slot_arg, slot_arg2; +char *SAVE_FILE = (char *)"zc.sav"; + +CScriptDrawingCommands script_drawing_commands; + +using std::string; +using std::pair; +extern std::map > ffcmap; + +int zq_screen_w, zq_screen_h; +int passive_subscreen_height=56; +int original_playing_field_offset=56; +int playing_field_offset=original_playing_field_offset; +int passive_subscreen_offset=0; +extern int directItem; +extern int directItemA; +extern int directItemB; + +bool is_large=false; + +bool standalone_mode=false; +char *standalone_quest=NULL; +bool skip_title=false; + +int favorite_combos[MAXFAVORITECOMBOS]; +int favorite_comboaliases[MAXFAVORITECOMBOALIASES]; + +void playLevelMusic(); + +volatile int logic_counter=0; +bool trip=false; +void update_logic_counter() +{ + ++logic_counter; +} +END_OF_FUNCTION(update_logic_counter) + +#ifdef _SCRIPT_COUNTER +volatile int script_counter=0; +void update_script_counter() +{ + ++script_counter; +} +END_OF_FUNCTION(update_script_counter) +#endif + + +void zcUSecSleep(int microseconds) +{ + // Different windows os with different hardware can still give varying results, + // so an option to replace allegro timers would be nice. +#ifdef ZC_EXPERIMENTAL_TIMER + #ifdef WIN32 + HANDLE timer; + LARGE_INTEGER ft; + + // Convert to 100 nanosecond interval, negative value indicates relative time + ft.QuadPart = -(10 * microseconds); + + timer = CreateWaitableTimerA(NULL, TRUE, NULL); + SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); + #else + rest(microseconds / 1000); + #endif +#endif +} + +//Timer frameTimer; +void throttleFPS() +{ + if(Throttlefps ^ (key[KEY_TILDE]!=0)) + { + if(zc_vsync == FALSE) + { + /*long long elapsed = frameTimer.GetMicroSeconds(); + zcUSecSleep(16690 - elapsed); + frameTimer.Reset();*/ + + // This function affects all global windows setting and schedules by any processes, + // but can improve accuracy. + // Todo:(Gleeok) This should be a config option but disabled by default. + #if 0 + timeBeginPeriod(1); + #endif + + int t = 0; + int restDuration = frame_rest_suggest; + while(logic_counter < 1) + { + // bugfix: win xp/7/8 have incompatible timers. + // preserve 60 fps and CPU based on user settings. -Gleeok + int ms = t >= 16 ? 0 : restDuration; + rest(ms); + t += frame_rest_suggest; //fixme: + } + + // This MUST be always be called after any timeBeginPeriod. + #if 0 + timeEndPeriod(1); + #endif + } + else + { + vsync(); + } + } + + logic_counter = 0; +} + +int onHelp() +{ + // restore_mouse(); + // doHelp(vc(15),vc(0)); + return D_O_K; +} +int d_dropdmaplist_proc(int ,DIALOG *,int) +{ + return D_O_K; +} + +static char dmap_str_buf[37]; +int dmap_list_size=MAXDMAPS; +bool dmap_list_zero=true; + +const char *dmaplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,dmap_list_size-1); + sprintf(dmap_str_buf,"%3d-%s",index+(dmap_list_zero?0:1), DMaps[index].name); + return dmap_str_buf; + } + + *list_size=dmap_list_size; + return NULL; +} + +int startdmapxy[6] = {0,0,0,0,0,0}; + +/**********************************/ +/******** Global Variables ********/ +/**********************************/ + +int curr_tb_page=0; +bool triplebuffer_not_available=false; + +RGB_MAP rgb_table; +COLOR_MAP trans_table, trans_table2; + +BITMAP *framebuf, *scrollbuf, *tmp_bmp, *tmp_scr, *screen2, *fps_undo, *tb_page[3], *real_screen, *temp_buf, *prim_bmp; +DATAFILE *data, *sfxdata, *fontsdata, *mididata; +FONT *nfont, *zfont, *z3font, *z3smallfont, *deffont, *lfont, *lfont_l, *pfont, *mfont, *ztfont, *sfont, *sfont2, *sfont3, *spfont, *ssfont1, *ssfont2, *ssfont3, *ssfont4, *gblafont, + *goronfont, *zoranfont, *hylian1font, *hylian2font, *hylian3font, *hylian4font, *gboraclefont, *gboraclepfont, *dsphantomfont, *dsphantompfont; +PALETTE RAMpal; +byte *colordata, *trashbuf; +//byte *tilebuf; +itemdata *itemsbuf; +wpndata *wpnsbuf; +comboclass *combo_class_buf; +guydata *guysbuf; +item_drop_object item_drop_sets[MAXITEMDROPSETS]; +ZCHEATS zcheats; +byte use_cheats; +byte use_tiles; +char palnames[MAXLEVELS][PALNAMESIZE]; +/* +tiledata *newtilebuf, *grabtilebuf; +newcombo *combobuf; +word animated_combo_table[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +word animated_combo_table4[MAXCOMBOS][2]; //[0]=combo, [1]=clock +word animated_combos; +word animated_combo_table2[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +word animated_combo_table24[MAXCOMBOS][2]; //[0]=combo, [1]=clock +word animated_combos2; +bool blank_tile_table[NEWMAXTILES]; //keeps track of blank tiles +bool blank_tile_quarters_table[NEWMAXTILES*4]; //keeps track of blank tiles +*/ +bool ewind_restart=false; + +word msg_count; +word door_combo_set_count; +short lensclk; +int lensid; // Lens's item id. -1 if lens is off. +int Bpos; +bool halt=false; +bool screenscrolling=false; +bool close_button_quit=false; +PALETTE tempbombpal; +bool usebombpal; + +int readsize, writesize; +bool fake_pack_writing=false; +combo_alias combo_aliases[MAXCOMBOALIASES]; //Temporarily here so ZC can compile. All memory from this is freed after loading the quest file. + +SAMPLE customsfxdata[WAV_COUNT]; +unsigned char customsfxflag[WAV_COUNT>>3]; +int sfxdat=1; +BITMAP *hw_screen; +int zqwin_scale; + +int jwin_pal[jcMAX]; +int gui_colorset=0; +int fullscreen; +byte frame_rest_suggest=0,forceExit=0,zc_vsync=0; +byte disable_triplebuffer=0,can_triplebuffer_in_windowed_mode=0; +byte zc_color_depth=8; +byte use_debug_console=0, use_win32_proc=1; //windows-build configs +int homescr,currscr,frame=0,currmap=0,dlevel,warpscr,worldscr; +int newscr_clk=0,opendoors=0,currdmap=0,fadeclk=-1,currgame=0,listpos=0; +int lastentrance=0,lastentrance_dmap=0,loadside, Bwpn, Awpn; +int digi_volume,midi_volume,sfx_volume,emusic_volume,currmidi,hasitem,whistleclk,pan_style; +int joystick_index=0,Akey,Bkey,Skey,Lkey,Rkey,Pkey,Exkey1,Exkey2,Exkey3,Exkey4,Abtn,Bbtn,Sbtn,Mbtn,Lbtn,Rbtn,Pbtn,Exbtn1,Exbtn2,Exbtn3,Exbtn4,Quit=0; +int DUkey, DDkey, DLkey, DRkey, ss_after, ss_speed, ss_density, ss_enable; +int hs_startx, hs_starty, hs_xdist, hs_ydist; +int cheat_goto_dmap=0, cheat_goto_screen=0, currcset; +int pitx, pity, refill_what, refill_why, heart_beep_timer=0, new_enemy_tile_start=1580; +int nets=1580, magicitem=-1, title_version, quakeclk=0, wavy=0; +int magicdrainclk=0, conveyclk=3, memrequested=0; +float avgfps=0; +dword fps_secs=0; +bool do_cheat_goto=false, do_cheat_light=false; +int checkx, checky; +int loadlast=0; +int skipcont=0; +int skipicon=0; + +bool show_layer_0=true, show_layer_1=true, show_layer_2=true, show_layer_3=true, show_layer_4=true, show_layer_5=true, show_layer_6=true, +//oveheard combos //pushblocks + show_layer_over=true, show_layer_push=true, show_sprites=true, show_ffcs=true, show_hitboxes=false, show_walkflags=false, show_ff_scripts=false; + + +bool Throttlefps, ClickToFreeze=false, Paused=false, Advance=false, ShowFPS, Showpal=false, disableClickToFreeze=false; +bool Playing, FrameSkip=false, TransLayers; +bool __debug=false,debug_enabled; +bool refreshpal,blockpath,loaded_guys,freeze_guys, + loaded_enemies,drawguys,details=false,watch; +bool darkroom=false,naturaldark=false,BSZ; //,NEWSUBSCR; +bool Udown,Ddown,Ldown,Rdown,Adown,Bdown,Sdown,Mdown,LBdown,RBdown,Pdown,Ex1down,Ex2down,Ex3down,Ex4down,AUdown,ADdown,ALdown,ARdown,F12,F11, F5,keyI, keyQ, + SystemKeys=true,NESquit,volkeys,useCD=false,boughtsomething=false, + fixed_door=false, hookshot_used=false, hookshot_frozen=false, + pull_link=false, hs_fix=false, + cheat_superman=false, gofast=false, checklink=true, didpit=false, heart_beep=true, + pausenow=false, is_on_conveyor, activated_timed_warp=false; + +byte COOLSCROLL; + +int SnapshotFormat, NameEntryMode=0; + +char zeldadat_sig[52]; +char sfxdat_sig[52]; +char fontsdat_sig[52]; +char cheat_goto_dmap_str[4]; +char cheat_goto_screen_str[3]; +short visited[6]; +byte guygrid[176]; +mapscr tmpscr[2]; +mapscr tmpscr2[6]; +mapscr tmpscr3[6]; +gamedata *game=NULL; +ffscript *ffscripts[NUMSCRIPTFFC]; +ffscript *itemscripts[NUMSCRIPTITEM]; +ffscript *globalscripts[NUMSCRIPTGLOBAL]; + +//If only... +ffscript *guyscripts[NUMSCRIPTGUYS]; +ffscript *wpnscripts[NUMSCRIPTWEAPONS]; +ffscript *linkscripts[NUMSCRIPTLINK]; +ffscript *screenscripts[NUMSCRIPTSCREEN]; + +extern refInfo globalScriptData; +extern word g_doscript; +extern bool global_wait; + +//ZScript array storage +std::vector globalRAM; +ZScriptArray localRAM[MAX_ZCARRAY_SIZE]; +byte arrayOwner[MAX_ZCARRAY_SIZE]; + +//script bitmap drawing +ZScriptDrawingRenderTarget* zscriptDrawingRenderTarget; + +DebugConsole DebugConsole::singleton = DebugConsole(); + + +void setZScriptVersion(int s_version) +{ + ZScriptVersion::setVersion(s_version); +} + +void initZScriptArrayRAM(bool firstplay) +{ + for(word i = 0; i < MAX_ZCARRAY_SIZE; i++) + { + localRAM[i].Clear(); + arrayOwner[i]=255; + } + + if(game->globalRAM.size() != 0) + game->globalRAM.clear(); + + if(firstplay) + { + //leave to global script ~Init to allocate global memory first time round + game->globalRAM.resize(getNumGlobalArrays()); + } + else + { + //allocate from save file + game->globalRAM.resize(saves[currgame].globalRAM.size()); + + for(dword i = 0; i < game->globalRAM.size(); i++) + { +#ifdef _DEBUGARRAYALLOC + al_trace("Global Array: %i\n",i); +#endif + ZScriptArray &from = saves[currgame].globalRAM[i]; + ZScriptArray &to = game->globalRAM[i]; + to.Resize(from.Size()); + + for(dword j = 0; j < from.Size(); j++) + { +#ifdef _DEBUGARRAYALLOC + al_trace("Element: %i\nInit: %i, From save file: %i\n", j, to[j], from[j]); +#endif + to[j] = from[j]; + } + } + } +} + +void initZScriptGlobalRAM() +{ + g_doscript = 1; + globalScriptData.Clear(); + clear_global_stack(); +} + +dword getNumGlobalArrays() +{ + word scommand, pc = 0, ret = 0; + + do + { + scommand = globalscripts[GLOBAL_SCRIPT_INIT][pc].command; + + if(scommand == ALLOCATEGMEMV || scommand == ALLOCATEGMEMR) + ret++; + + pc++; + } + while(scommand != 0xFFFF); + + return ret; +} + +//movingblock mblock2; //mblock[4]? +//LinkClass Link; + +int resx,resy,scrx,scry; +bool sbig; // big screen +bool sbig2; // bigger screen +int screen_scale = 2; //default = 2 (640x480) +bool scanlines; //do scanlines if sbig==1 +bool toogam=false; + +int cheat=0; // 0 = none; 1,2,3,4 = cheat level + +int mouse_down; // used to hold the last reading of 'gui_mouse_b()' status +int idle_count, active_count; + + +// quest file data +zquestheader QHeader; +byte quest_rules[QUESTRULES_SIZE]; +byte midi_flags[MIDIFLAGS_SIZE]; +byte music_flags[MUSICFLAGS_SIZE]; +word map_count; +MsgStr *MsgStrings; +int msg_strings_size; +DoorComboSet *DoorComboSets; +dmap *DMaps; +miscQdata QMisc; +std::vector TheMaps; +zcmap *ZCMaps; +byte *quest_file; +dword quest_map_pos[MAPSCRS*MAXMAPS2]; + +char *qstpath=NULL; +char *qstdir=NULL; +gamedata *saves=NULL; + +volatile int lastfps=0; +volatile int framecnt=0; +volatile int myvsync=0; + +/**********************************/ +/*********** Misc Data ************/ +/**********************************/ + +const char startguy[8] = {-13,-13,-13,-14,-15,-18,-21,-40}; + +const byte stx[4][9] = +{ + { 48, 80, 80, 96,112,144,160,160,192}, + { 48, 80, 80, 96,128,144,160,160,192}, + { 80, 80,128,128,160,160,192,192,208}, + { 32, 48, 48, 80, 80,112,112,160,160} +}; +const byte sty[4][9] = +{ + {112, 64,128, 96, 80, 96, 64,128,112}, + { 48, 32, 96, 64, 80, 64, 32, 96, 48}, + { 32,128, 64, 96, 64, 96, 48,112, 80}, + { 80, 48,112, 64, 96, 64, 96, 32,128} +}; + +const byte ten_rupies_x[10] = {120,112,128,96,112,128,144,112,128,120}; +const byte ten_rupies_y[10] = {49,65,65,81,81,81,81,97,97,113}; + +zctune tunes[MAXMIDIS] = +{ + // (title) (s) (ls) (le) (l) (vol) (midi)(fmt) + zctune((char *)"Zelda - Dungeon", 0, -1, -1, 1, 176, NULL, 0), + zctune((char *)"Zelda - Ending", 0, 129, 225, 1, 160, NULL, 0), + zctune((char *)"Zelda - Game Over", 0, -1, -1, 1, 224, NULL, 0), + zctune((char *)"Zelda - Level 9", 0, -1, -1, 1, 255, NULL, 0), + zctune((char *)"Zelda - Overworld", 0, 17, -1, 1, 208, NULL, 0), + zctune((char *)"Zelda - Title", 0, -1, -1, 0, 168, NULL, 0), + zctune((char *)"Zelda - Triforce", 0, -1, -1, 0, 168, NULL, 0) +}; + +// emusic enhancedMusic[MAXMUSIC]; + +bool bad_version(int version) +{ + // minimum zquest version allowed for any quest file + if(version < 0x183) + return true; + + return false; +} + +extern char *weapon_string[]; +extern char *item_string[]; +extern char *sfx_string[]; +extern char *guy_string[]; + + +/**********************************/ +/******* Other Source Files *******/ +/**********************************/ + +bool get_debug() +{ + //return false; //remove later + return __debug; +} + +void set_debug(bool d) +{ + __debug=d; + return; +} + +void hit_close_button() +{ + close_button_quit=true; + return; +} + +void Z_eventlog(const char *format,...) +{ + if(get_bit(quest_rules,qr_LOG)) + { + char buf[2048]; + + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + al_trace("%s",buf); + + if(zconsole) + printf("%s",buf); + } +} + +// Yay, more extern globals. +extern byte curScriptType; +extern word curScriptNum; +extern std::map > ffcmap; +extern std::map > globalmap; +extern std::map > itemmap; + +void Z_scripterrlog(const char * const format,...) +{ + if(get_bit(quest_rules,qr_SCRIPTERRLOG)) + { + switch(curScriptType) + { + case SCRIPT_GLOBAL: + al_trace("Global script %u (%s): ", curScriptNum+1, globalmap[curScriptNum].second.c_str()); + break; + + case SCRIPT_FFC: + al_trace("FFC script %u (%s): ", curScriptNum, ffcmap[curScriptNum-1].second.c_str()); + break; + + case SCRIPT_ITEM: + al_trace("Item script %u (%s): ", curScriptNum, itemmap[curScriptNum-1].second.c_str()); + break; + } + + char buf[2048]; + + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + al_trace("%s",buf); + + if(zconsole) + printf("%s",buf); + } +} + + +bool blockmoving; +#include "sprite.h" +movingblock mblock2; //mblock[4]? + +sprite_list guys, items, Ewpns, Lwpns, Sitems, chainlinks, decorations, particles; + +#include "zc_custom.h" +#include "link.h" +LinkClass Link; + +#include "maps.h" +#include "subscr.h" +#include "guys.h" + +#include "title.h" +#include "ending.h" + +#include "zc_sys.h" + +// Wait... this is only used by ffscript.cpp!? +void addLwpn(int x,int y,int z,int id,int type,int power,int dir, int parentid) +{ + Lwpns.add(new weapon((fix)x,(fix)y,(fix)z,id,type,power,dir,-1,parentid)); +} + +void ALLOFF(bool messagesToo, bool decorationsToo) +{ + /* + // It gets called anyway! + if(messagesToo) + messageMgr.clear(true); + */ + + roomItems.clear(); + + if(items.idCount(iPile)) + { + loadlvlpal(DMaps[currdmap].color); + } + + items.clear(); + guys.clear(); + Lwpns.clear(); + Ewpns.clear(); + chainlinks.clear(); + clearScriptHelperData(); + + if(decorationsToo) + decorations.clear(); + + particles.clear(); + + Link.resetflags(false); + Link.reset_hookshot(); + //linkedmsgclk=0; + // for(int i=0; i<1; i++) + mblock2.clk=0; + messageMgr.clear(true); + fadeclk=-1; + + lensclk = 0; + lensid=-1; + drawguys=Udown=Ddown=Ldown=Rdown=Adown=Bdown=Sdown=true; + + if(watch && !cheat_superman) + { + Link.setClock(false); + } + + // if(watch) + // Link.setClock(false); + watch=freeze_guys=loaded_guys=loaded_enemies=blockpath=false; + stop_sfx(WAV_BRANG); + + for(int i=0; i<176; i++) + guygrid[i]=0; + + sle_clk=0; + blockmoving=false; + fairy_cnt=0; + + if(usebombpal) + { + memcpy(RAMpal, tempbombpal, PAL_SIZE*sizeof(RGB)); + refreshpal=true; + usebombpal=false; + } +} + +fix LinkX() +{ + return Link.getX(); +} +fix LinkY() +{ + return Link.getY(); +} +fix LinkZ() +{ + return Link.getZ(); +} +int LinkHClk() +{ + return Link.getHClk(); +} +int LinkAction() +{ + return Link.getAction(); +} +int LinkCharged() +{ + return Link.isCharged(); +} + +int LinkSwordClk() +{ + return Link.getSwordClk(); +} +int LinkItemClk() +{ + return Link.getItemClk(); +} +void setSwordClk(int newclk) +{ + Link.setSwordClk(newclk); +} +void setItemClk(int newclk) +{ + Link.setItemClk(newclk); +} +int LinkLStep() +{ + return Link.getLStep(); +} +void LinkCheckItems() +{ + Link.checkitems(); +} +bool LinkGetDontDraw() +{ + return Link.getDontDraw(); +} +fix GuyX(int j) +{ + return guys.getX(j); +} +fix GuyY(int j) +{ + return guys.getY(j); +} +int GuyID(int j) +{ + return guys.getID(j); +} +int GuyMisc(int j) +{ + return guys.getMisc(j); +} +bool GuySuperman(int j) +{ + if((j>=guys.Count())||(j<0)) + { + return true; + } + + return ((enemy*)guys.spr(j))->superman !=0; +} + +int GuyCount() +{ + return guys.Count(); +} +void StunGuy(int j,int stun) +{ + if(stun<=0) return; + + if(((enemy*)guys.spr(j))->z==0 && canfall(((enemy*)guys.spr(j))->id)) + { + ((enemy*)guys.spr(j))->stunclk=zc_min(360,stun*4); + ((enemy*)guys.spr(j))->fall=-zc_min(FEATHERJUMP,(stun*8)+rand()%5); + } +} + +fix LinkModifiedX() +{ + if(screenscrolling && Link.getDir()==left) + return Link.getX()+256; + else + return Link.getX(); +} + +fix LinkModifiedY() +{ + if(screenscrolling && Link.getDir()==up) + return Link.getY()+176; + else + return Link.getY(); +} + +int LinkDir() +{ + return Link.getDir(); +} + +fix distance(int x1, int y1, int x2, int y2) + +{ + return (fix)sqrt(pow((double)abs(x1-x2),2)+pow((double)abs(y1-y2),2)); +} + +bool getClock() +{ + return Link.getClock(); +} +void setClock(bool state) +{ + Link.setClock(state); +} +void CatchBrang() +{ + Link.Catch(); +} + +/**************************/ +/***** Main Game Code *****/ +/**************************/ + +int load_quest(gamedata *g, bool report) +{ + chop_path(qstpath); + char *tempdir=(char *)""; +#ifndef ALLEGRO_MACOSX + tempdir=qstdir; +#endif + + if(g->get_quest()<255) + { + // Check the ZC directory first for 1st-4th quests; check qstdir if they're not there + sprintf(qstpath, "%s.qst", ordinal(g->get_quest())); + + if(!exists(qstpath)) + { + sprintf(qstpath,"%s%s.qst",tempdir,ordinal(g->get_quest())); + } + } + else + { + if(is_relative_filename(g->qstpath)) + { + sprintf(qstpath,"%s%s",qstdir,g->qstpath); + } + else + { + sprintf(qstpath,"%s", g->qstpath); + } + + // ZC paths are retarded. + // This is just an awful hack, and generally some of the worst code ever written, but it only ever gets run + // when there would be a "file not found error"... (it's easier than dealing with everything else. Sue me.) + // + // *side note* + // It does have a few perks though: You can now move around entire folders and sub-folders from one ZC directory to the next, + // and we can find them! You can even put all the ZC quests into different sub-directories and share save files, etc.. + // ~Gleeok + if(!exists(qstpath)) + { + al_trace("File not found \"%s\". Searching...\n", qstpath); + + if(exists(g->qstpath)) //not found? -try this place first: + { + sprintf(qstpath,"%s", g->qstpath); + al_trace("Set quest path to \"%s\".\n", qstpath); + } + else // Howsabout in here? + { + std::string gQstPath = g->qstpath; + size_t bs1 = 0; + size_t bs2 = std::string::npos; + + // Keep searching through every parent directory as if it was the current one. + while(bs1 != std::string::npos || bs2 != std::string::npos) + { + bs1 = gQstPath.find_first_of('/'); + if(bs1 != std::string::npos) + { + gQstPath = gQstPath.substr(bs1 + 1, std::string::npos); + } + else + { + bs2 = gQstPath.find_first_of('\\'); + if(bs2 != std::string::npos) + gQstPath = gQstPath.substr(bs2 + 1, std::string::npos); + } + + if(exists(gQstPath.c_str())) //Quick! Try it now! + { + sprintf(qstpath,"%s", gQstPath.c_str()); + al_trace("Set quest path to \"%s\".\n", qstpath); + break; + } + else //Still no dice eh? + { + char cwdbuf[260]; + memset(cwdbuf,0,260*sizeof(char)); + +#ifdef _ALLEGRO_WINDOWS + _getcwd(cwdbuf, 260); +#else + getcwd(cwdbuf, 260); +#endif + + std::string path = cwdbuf; + std::string fn; + + if(path.size() != 0 && + !(*(path.end()-1)=='/' || *(path.end()-1)=='\\') + ) + { + path += '/'; + } + + fn = path + gQstPath; + + if(exists(fn.c_str())) //Last chance for hookers and blackjack truck stop + { + sprintf(qstpath,"%s", fn.c_str()); + al_trace("Set quest path to \"%s\".\n", qstpath); + break; + } + } + } //while + + } + }//end hack + + } + + //setPackfilePassword(datapwd); + byte skip_flags[4]; + + for(int i=0; i<4; ++i) + { + skip_flags[i]=0; + } + + int ret = loadquest(qstpath,&QHeader,&QMisc,tunes+ZC_MIDI_COUNT,false,true,true,true,skip_flags); + //setPackfilePassword(NULL); + + if(!g->title[0] || g->get_hasplayed() == 0) + { + strcpy(g->version,QHeader.version); + strcpy(g->title,QHeader.title); + } + else + { + if(!ret && strcmp(g->title,QHeader.title)) + { + ret = qe_match; + } + } + + if(QHeader.minver[0]) + { + if(strcmp(g->version,QHeader.minver) < 0) + ret = qe_minver; + } + + if(ret && report) + { + system_pal(); + char buf1[80],buf2[80]; + sprintf(buf1,"Error loading %s:",get_filename(qstpath)); + sprintf(buf2,"%s",qst_error[ret]); + jwin_alert("File error",buf1,buf2,qstpath,"OK",NULL,13,27,lfont); + + if(standalone_mode) + { + exit(1); + } + + game_pal(); + } + + return ret; +} + +void init_dmap() +{ + // readjust disabled items; could also do dmap-specific scripts here + for(int i=0; iitems_off[i] &= (~1); // disable last bit - this one is set by dmap + game->items_off[i] |= DMaps[currdmap].disableditems[i]; // and reset if required + } + + flushItemCache(); + + return; +} + +int init_game() +{ + srand(time(0)); + //introclk=intropos=msgclk=msgpos=dmapmsgclk=0; + + messageMgr.clear(false); +//Some initialising globals + didpit=false; + Link.unfreeze(); + Link.reset_hookshot(); + Link.reset_ladder(); + //linkedmsgclk=0; + blockmoving=false; + gofast=false; + + cheat=0; + wavy=quakeclk=0; + show_layer_0=show_layer_1=show_layer_2=show_layer_3=show_layer_4=show_layer_5=show_layer_6=true; + show_layer_over=show_layer_push=show_sprites=show_ffcs=true; + cheat_superman=do_cheat_light=do_cheat_goto=show_walkflags=show_ff_scripts=show_hitboxes=false; + + for(int x = 0; x < MAXITEMS; x++) + { + lens_hint_item[x][0]=0; + lens_hint_item[x][1]=0; + } + + for(int x = 0; x < MAXWPNS; x++) + { + lens_hint_weapon[x][0]=0; + lens_hint_weapon[x][1]=0; + } + + +//Confuse the cheaters by moving the game data to a random location + if(game != NULL) + delete game; + + char *dummy = (char *) zc_malloc((rand()%(RAND_MAX/2))+32); + game = new gamedata; + game->Clear(); + + zc_free(dummy); + +//Copy saved data to RAM data (but not global arrays) + game->Copy(saves[currgame]); + flushItemCache(); + +//Load the quest + //setPackfilePassword(datapwd); + int ret = load_quest(game); + + if(ret != qe_OK) + { + Quit = qERROR; + //setPackfilePassword(NULL); + return 1; + } + + //setPackfilePassword(NULL); + + char keyfilename[2048]; + replace_extension(keyfilename, qstpath, "key", 2047); + bool gotfromkey=false; + + if(exists(keyfilename)) + { + char password[32], pwd[32]; + PACKFILE *fp = pack_fopen_password(keyfilename, F_READ,""); + char msg[80]; + memset(msg,0,80); + pfread(msg, 80, fp,true); + + if(strcmp(msg,"ZQuest Auto-Generated Quest Password Key File. DO NOT EDIT!")==0) + { + short ver; + byte bld; + p_igetw(&ver,fp,true); + p_getc(&bld,fp,true); + memset(password,0,32); + pfread(password, 30, fp,true); + /* + get-questpwd(&QHeader, pwd); + if (strcmp(pwd,password)==0) + { + gotfromkey=true; + } + */ + gotfromkey=check_questpwd(&QHeader, password); + memset(password,0,32); + memset(pwd,0,32); + } + + pack_fclose(fp); + } + + if(gotfromkey) + { + cheat=4; + } + + bool firstplay = (game->get_hasplayed() == 0); + + BSZ = get_bit(quest_rules,qr_BSZELDA)!=0; + //setuplinktiles(zinit.linkanimationstyle); + + COOLSCROLL = (get_bit(quest_rules,qr_COOLSCROLL)!=0 ? 1 : 0) | + (get_bit(quest_rules,qr_OVALWIPE)!=0 ? 2 : 0) | + (get_bit(quest_rules,qr_TRIANGLEWIPE)!=0 ? 4 : 0) | + (get_bit(quest_rules,qr_SMASWIPE)!=0 ? 8 : 0); + identifyCFEnemies(); + + // NEWSUBSCR = get_bit(quest_rules,qr_NEWSUBSCR); + + // homescr = currscr = DMaps[0].cont; + // currdmap = warpscr = worldscr=0; + if(firstplay) + { + game->set_continue_dmap(zinit.start_dmap); + resetItems(game,&zinit,true); + } + + currdmap = warpscr = worldscr=game->get_continue_dmap(); + init_dmap(); + + if(game->get_continue_scrn() >= 0x80) + { + //if ((DMaps[currdmap].type&dmfTYPE)==dmOVERW || QHeader.zelda_version <= 0x190) + if((DMaps[currdmap].type&dmfTYPE)==dmOVERW) + { + homescr = currscr = DMaps[currdmap].cont; + } + else + { + homescr = currscr = DMaps[currdmap].cont + DMaps[currdmap].xoff; + } + } + else + { + homescr = currscr = game->get_continue_scrn(); + } + + lastentrance = currscr; + game->set_continue_scrn(lastentrance); + lastentrance_dmap = currdmap; + currmap = DMaps[currdmap].map; + dlevel = DMaps[currdmap].level; + sle_x=sle_y=newscr_clk=opendoors=Bwpn=Bpos=0; + fadeclk=-1; + + if(DMaps[currdmap].flags&dmfVIEWMAP) + { + game->maps[(currmap*MAPSCRSNORMAL)+currscr] |= mVISITED; // mark as visited + } + + for(int i=0; i<6; i++) + { + visited[i]=-1; + } + + game->lvlitems[9] &= ~liBOSS; + + ALLOFF(); + whistleclk=-1; + currcset=DMaps[currdmap].color; + darkroom=naturaldark=false; + + tmpscr[0].zero_memory(); + tmpscr[1].zero_memory(); + + //Script-related nonsense + script_drawing_commands.Clear(); + + initZScriptArrayRAM(firstplay); + initZScriptGlobalRAM(); + global_wait=false; + + //loadscr(0,currscr,up); + loadscr(0,currdmap,currscr,-1,false); + putscr(scrollbuf,0,0,&tmpscr[0]); + putscrdoors(scrollbuf,0,0,&tmpscr[0]); + + //preloaded freeform combos + //ffscript_engine(true); Can't do this here! Global arrays haven't been allocated yet... ~Joe + + Link.init(); + Link.resetflags(true); + Link.setEntryPoints(LinkX(),LinkY()); + + copy_pal((RGB*)data[PAL_GUI].dat,RAMpal); + loadfullpal(); + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + lighting(false,true); + wavy=quakeclk=0; + + if(firstplay) + { + game->set_life(zinit.start_heart*HP_PER_HEART); + } + else + { + if(game->get_cont_percent()) + { + if(game->get_maxlife()%HP_PER_HEART==0) + game->set_life(((game->get_maxlife()*game->get_cont_hearts()/100)/HP_PER_HEART)*HP_PER_HEART); + else + game->set_life(game->get_maxlife()*game->get_cont_hearts()/100); + } + else + { + game->set_life(game->get_cont_hearts()*HP_PER_HEART); + } + } + + if(firstplay) + game->set_hasplayed(1); + + update_subscreens(); + + load_Sitems(&QMisc); + +//load the previous weapons -DD + bool usesaved = (game->get_quest() == 0xFF); //What was wrong with firstplay? + int apos = 0; + int bpos = 0; + + if(!get_bit(quest_rules,qr_SELECTAWPN)) + { + Awpn = selectSword(); + apos = -1; + bpos = selectWpn_new(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, -1); + } + else + { + apos = selectWpn_new(SEL_VERIFY_RIGHT, usesaved ? game->awpn : 0xFF); + bpos = selectWpn_new(SEL_VERIFY_RIGHT, usesaved ? game->bwpn : 0xFF, apos); + + if(bpos==0xFF) + { + bpos=apos; + apos=0; + } + + Awpn = Bweapon(apos); + directItemA = directItem; + } + + game->awpn = apos; + game->bwpn = bpos; + Bwpn = Bweapon(bpos); + directItemB = directItem; + update_subscr_items(); + + reset_subscr_items(); + + Link.setDontDraw(false); + show_subscreen_dmap_dots=true; + show_subscreen_items=true; + show_subscreen_numbers=true; + show_subscreen_life=true; + + Playing=true; + + map_bkgsfx(true); + openscreen(); + show_subscreen_numbers=true; + show_subscreen_life=true; + showCurrentDMapIntro(); + loadguys(); + + activated_timed_warp=false; + newscr_clk = frame; + + if(isdungeon() && currdmap>0) // currdmap>0 is weird, but at least one quest (Mario's Insane Rampage) depends on it + { + Link.stepforward(get_bit(quest_rules,qr_LTTPWALK) ? 11: 12, false); + } + + if(!Quit) + playLevelMusic(); + + if(firstplay) + { + memset(game->screen_d, 0, MAXDMAPS * 64 * 8 * sizeof(long)); + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_INIT); + } + else + { + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_CONTINUE); //Do this after global arrays have been loaded + } + + initZScriptGlobalRAM(); //Call again so we're set up for GLOBAL_SCRIPT_GAME + ffscript_engine(true); //Here is a much safer place... + + return 0; +} + +int cont_game() +{ + // introclk=intropos=msgclk=msgpos=dmapmsgclk=0; + didpit=false; + Link.unfreeze(); + Link.reset_hookshot(); + Link.reset_ladder(); + //linkedmsgclk=0; + blockmoving=0; + currdmap = lastentrance_dmap; + homescr = currscr = lastentrance; + currmap = DMaps[currdmap].map; + dlevel = DMaps[currdmap].level; + init_dmap(); + + for(int i=0; i<6; i++) + { + visited[i]=-1; + } + + if(dlevel==0) + { + game->lvlitems[9]&=~liBOSS; + } + + ALLOFF(); + whistleclk=-1; + currcset=DMaps[currdmap].color; + darkroom=naturaldark=false; + tmpscr[0].zero_memory(); + tmpscr[1].zero_memory(); + +//loadscr(0,currscr,up); + loadscr(0,currdmap,currscr,-1,false); + putscr(scrollbuf,0,0,&tmpscr[0]); + putscrdoors(scrollbuf,0,0,&tmpscr[0]); + script_drawing_commands.Clear(); + + //preloaded freeform combos + ffscript_engine(true); + + loadfullpal(); + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + lighting(false,true); + Link.init(); + wavy=quakeclk=0; + + //if(get_bit(zinit.misc,idM_CONTPERCENT)) + if(game->get_cont_percent()) + { + if(game->get_maxlife()%HP_PER_HEART==0) + game->set_life(((game->get_maxlife()*game->get_cont_hearts()/100)/HP_PER_HEART)*HP_PER_HEART); + else + game->set_life(game->get_maxlife()*game->get_cont_hearts()/100); + } + else + { + game->set_life(game->get_cont_hearts()*HP_PER_HEART); + } + + /* + else + game->life=3*HP_PER_HEART; + */ + + // for(int i=0; i<128; i++) + // key[i]=0; + + update_subscreens(); + Playing=true; + map_bkgsfx(true); + openscreen(); + show_subscreen_numbers=true; + show_subscreen_life=true; + showCurrentDMapIntro(); + loadguys(); + + if(!Quit) + { + playLevelMusic(); + + if(isdungeon()) + Link.stepforward(get_bit(quest_rules,qr_LTTPWALK)?11:12, false); + + newscr_clk=frame; + activated_timed_warp=false; + } + + initZScriptGlobalRAM(); + return 0; +} + +void restart_level() +{ + blackscr(16,true); + map_bkgsfx(false); + + if(dlevel) + { + currdmap = lastentrance_dmap; + homescr = currscr = lastentrance; + init_dmap(); + } + else + { + if((DMaps[currdmap].type&dmfTYPE)==dmOVERW) + { + homescr = currscr = DMaps[currdmap].cont; + } + else + { + homescr = currscr = DMaps[currdmap].cont + DMaps[currdmap].xoff; + } + } + + currmap = DMaps[currdmap].map; + dlevel = DMaps[currdmap].level; + + for(int i=0; i<6; i++) + visited[i]=-1; + + ALLOFF(); + whistleclk=-1; + darkroom=naturaldark=false; + tmpscr[0].zero_memory(); + tmpscr[1].zero_memory(); + + loadscr(0,currdmap,currscr,-1,false); + putscr(scrollbuf,0,0,&tmpscr[0]); + putscrdoors(scrollbuf,0,0,&tmpscr[0]); + //preloaded freeform combos + ffscript_engine(true); + + loadfullpal(); + ringcolor(false); + loadlvlpal(DMaps[currdmap].color); + lighting(false,true); + Link.init(); + currcset=DMaps[currdmap].color; + openscreen(); + map_bkgsfx(true); + Link.setEntryPoints(LinkX(),LinkY()); + show_subscreen_numbers=true; + show_subscreen_life=true; + loadguys(); + + if(!Quit) + { + playLevelMusic(); + + if(isdungeon()) + Link.stepforward(get_bit(quest_rules,qr_LTTPWALK)?11:12, false); + + newscr_clk=frame; + activated_timed_warp=false; + } +} + +//static char *dirstr[4] = {"Up","Down","Left","Right"}; +//static char *dirstr[32] = {"U","D","L","R"," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "}; + +//use detail_int[x] for global detail info +void show_details() +{ + //textprintf_ex(framebuf,font,-3,-5,WHITE,BLACK,"%-4d",whistleclk); + textprintf_ex(framebuf,font,0,8,WHITE,BLACK,"dlvl:%-2d dngn:%d", dlevel, isdungeon()?1:0); + textprintf_ex(framebuf,font,0,176,WHITE,BLACK,"%ld %s",game->get_time(),time_str_long(game->get_time())); + +// textprintf_ex(framebuf,font,200,16,WHITE,BLACK,"%3d",Link.getPushing()); +// for(int i=0; iid); + +// for(int i=0; iid, ((weapon*)Ewpns.spr(i))->tile, ((weapon*)Ewpns.spr(i))->clk, ((weapon*)Ewpns.spr(i))->aframe, wpnsbuf[((weapon*)Ewpns.spr(i))->id].frames); + +// for(int i=0; itile, ((weapon*)Lwpns.spr(i))->dir, ((weapon*)Lwpns.spr(i))->flip); + + for(int i=0; iid); + +// textprintf_ex(framebuf,font,90,16,WHITE,BLACK,"%3d, %3d",int(LinkModifiedX()),int(LinkModifiedY())); + //textprintf_ex(framebuf,font,90,24,WHITE,BLACK,"%3d, %3d",detail_int[0],detail_int[1]); +// textprintf_ex(framebuf,font,200,16,WHITE,BLACK,"%3d",Link.getAction()); + + /* + for(int i=0; i%3d %3d>%3d %3d<%3d %3d<%3d ", + int(Link.getX()+0+16), int(s->x+s->hxofs), int(Link.getY()+0+16), int(s->y+s->hyofs), + int(Link.getX()+0), int(s->x+s->hxofs+s->hxsz), int(Link.getY()+0), int(s->y+s->hyofs+s->hysz)); + } + */ +// textprintf_ex(framebuf,font,200,16,WHITE,BLACK,"gi=%3d",guycarryingitem); +} + +void show_ffscript_names() +{ + int ypos = 8; + + for(int i=0; i< MAXFFCS; i++) + { + if(tmpscr->ffcs[i].getScript()) + { + textout_shadowed_ex(framebuf,font, ffcmap[tmpscr->ffcs[i].getScript()-1].second.c_str(),2,ypos,WHITE,BLACK,-1); + ypos+=12; + } + } +} + +void do_dcounters() +{ + static bool sfxon = false; + + for(int i=0; i<32; i++) + { + if(game->get_dcounter(i)==0) + { + sfxon = false; + continue; + } + + if(frame&1) + { + sfxon = true; + + if(game->get_dcounter(i)>0) + { + int drain = (i==4 ? MAGICPERBLOCK/4 : 1); + drain = zc_min(game->get_dcounter(i),drain); + + if(game->get_counter(i) < game->get_maxcounter(i)) + { + game->change_counter(drain, i); + game->change_dcounter(-drain, i); + + if(game->get_dcounter(i) < 0) // Better safe + game->set_dcounter(0, i); + } + else + { + game->set_dcounter(0, i); + game->set_counter(game->get_maxcounter(i), i); + } + } + else + { + if(i!=1) // Only rupee drain is sounded + sfxon = false; + + int drain = (i==4 ? 2*game->get_magicdrainrate() : 1); + + if(game->get_counter(i)>0) + { + game->change_counter(-drain, i); + game->change_dcounter(drain, i); + + if(game->get_dcounter(i) > 0) // Better safe + game->set_dcounter(0, i); + } + else + { + game->set_dcounter(0, i); + game->set_counter(0, i); + } + } + } + + if((sfxon || i==1) && !lensclk && (i<2 || i==4)) // Life, Rupees and Magic + sfx(WAV_MSG); + } +} + +// Rename this... +void generalUpdates() +{ + if(do_cheat_goto) + { + didpit=true; + pitx=Link.getX(); + pity=Link.getY(); + Link.dowarp(3,0); + do_cheat_goto=false; + return; + } + + if(ewind_restart) + { + restart_level(); + Link.setXOfs(0); + Link.setAction(none); + ewind_restart=false; + return; + } + + if(do_cheat_light) + { + naturaldark = !naturaldark; + lighting(false, false); + do_cheat_light = false; + } + + if(fadeclk>=0) + { + if(fadeclk==0 && currscr<128) + blockpath=false; + + fadeclk--; + } + + for(int i=0; i<176; i++) + { + if(guygrid[i]>0) + --guygrid[i]; + } +} + +void game_loop() +{ + generalUpdates(); + freezeState.update(); + + animate_combos(); + load_control_state(); + + if(!freezeState.scriptDrawingFrozen()) + { + script_drawing_commands.Clear(); + } + + if(!freezeState.ffcsFrozen()) + { + update_freeform_combos(); + } + + // Arbitrary Rule 637: neither 'freeze' nor 'freezeff' freeze the global script. + if(!freezeState.globalScriptFrozen() && g_doscript) + { + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME); + } + + if(!freezeState.entitiesFrozen()) + { + mblock2.animate(0); + items.animate(); + items.check_conveyor(); + guys.animate(); + roaming_item(); + dragging_item(); + Ewpns.animate(); + checklink = true; + + for(int i = 0; i < (gofast ? 8 : 1); i++) + { + //if(Link.animate(0)) + if(linkHandler.update()) + { + if(!Quit) + { + Quit = qGAMEOVER; + } + + return; + } + + checklink=false; + } + + Lwpns.animate(); + decorations.animate(); + particles.animate(); + + if(conveyclk<=0) + { + conveyclk=3; + } + + --conveyclk; + check_collisions(); + dryuplake(); + cycle_palette(); + } + else if(!freezeState.guysAndFiresFrozen()) + { + for(int i=0; iignore_msg_freeze()) + guys.spr(i)->animate(i); + } + + if(global_wait) + { + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_GAME); + global_wait=false; + } + + draw_screen(tmpscr); + messageMgr.drawToScreen(framebuf, playing_field_offset); + + if(!freezeState.guysAndFiresFrozen()) + { + if(messageMgr.messageIsActive()) + { + messageMgr.update(); + if(!messageMgr.messageIsActive()) // Just finished? + { + Link.finishedmsg(); + if(get_bit(quest_rules,qr_MSGDISAPPEAR)) + blockpath=false; + } + } + + do_dcounters(); + + if(!freezeState.itemRefillsFrozen()) + { + if(current_item(itype_heartring)) + { + int itemid = current_item_id(itype_heartring); + int fskip = itemsbuf[itemid].misc2; + + if(fskip == 0 || frame % fskip == 0) + game->set_life(zc_min(game->get_life() + itemsbuf[itemid].misc1, game->get_maxlife())); + } + + if(current_item(itype_magicring)) + { + int itemid = current_item_id(itype_magicring); + int fskip = itemsbuf[itemid].misc2; + + if(fskip == 0 || frame % fskip == 0) + { + game->set_magic(zc_min(game->get_magic() + itemsbuf[itemid].misc1, game->get_maxmagic())); + } + } + + if(current_item(itype_wallet)) + { + int itemid = current_item_id(itype_wallet); + int fskip = itemsbuf[itemid].misc2; + + if(fskip == 0 || frame % fskip == 0) + { + game->set_rupies(zc_min(game->get_rupies() + itemsbuf[itemid].misc1, game->get_maxcounter(1))); + } + } + + if(current_item(itype_bombbag)) + { + int itemid = current_item_id(itype_bombbag); + + if(itemsbuf[itemid].misc1) + { + int fskip = itemsbuf[itemid].misc2; + + if(fskip == 0 || frame % fskip == 0) + { + game->set_bombs(zc_min(game->get_bombs() + itemsbuf[itemid].misc1, game->get_maxbombs())); + } + + if(itemsbuf[itemid].flags & ITEM_FLAG1) + { + int ratio = zinit.bomb_ratio; + + fskip = itemsbuf[itemid].misc2 * ratio; + + if(fskip == 0 || frame % fskip == 0) + { + game->set_sbombs(zc_min(game->get_sbombs() + zc_max(itemsbuf[itemid].misc1 / ratio, 1), game->get_maxbombs() / ratio)); + } + } + } + } + + if(current_item(itype_quiver) && game->get_arrows() != game->get_maxarrows()) + { + int itemid = current_item_id(itype_quiver); + int fskip = itemsbuf[itemid].misc2; + + if(fskip == 0 || frame % fskip == 0) + { + game->set_arrows(zc_min(game->get_arrows() + itemsbuf[itemid].misc1, game->get_maxarrows())); + } + } + } + + if(lensclk) + { + draw_lens_over(); + --lensclk; + } + + // Earthquake! + if(quakeclk>0) + { + playing_field_offset=56+((int)(sin((double)(--quakeclk*2-frame))*4)); + } + else + { + playing_field_offset=56; + } + + // Other effects in zc_sys.cpp + } + + // putpixel(framebuf, walkflagx, walkflagy+playing_field_offset, vc(int(rand()%16))); +} + +int get_currdmap() +{ + return currdmap; +} + +int get_dlevel() +{ + return dlevel; +} + +int get_currscr() +{ + return currscr; +} + +int get_homescr() +{ + return homescr; +} + +int get_bmaps(int si) +{ + return game->bmaps[si]; +} + +bool no_subscreen() +{ + return (tmpscr->flags3&fNOSUBSCR)!=0; +} + +/**************************/ +/********** Main **********/ +/**************************/ + +void PopulateInitDialog(); + +bool is_zquest() +{ + return false; +} + +bool screenIsScrolling() +{ + return screenscrolling; +} + +int isFullScreen() +{ + return !is_windowed_mode(); +} + +class TB_Handler //Dear Santa: please kill Easter bunny. I've been a good boy. +{ +public: + + TB_Handler() {} + ~TB_Handler() {} + + bool CanEnable() const + { + if(is_windowed_mode() && can_triplebuffer_in_windowed_mode == FALSE) + { + triplebuffer_not_available = true; + return false; + } + + return (disable_triplebuffer == FALSE); + } + bool GFX_can_triple_buffer() const + { + if(!CanEnable()) + { + triplebuffer_not_available = true; + return false; + } + + triplebuffer_not_available = false; + + if(!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) enable_triple_buffer(); + + if(!(gfx_capabilities & GFX_CAN_TRIPLE_BUFFER)) triplebuffer_not_available = true; + + return !triplebuffer_not_available; + } + void Destroy() const + { + if(disable_triplebuffer != FALSE || triplebuffer_not_available) return; + + for(int i=0; i<3; i++) + if(tb_page[i]) + destroy_bitmap(tb_page[i]); + } + void Create() const + { + if(!CanEnable()) + { + triplebuffer_not_available = true; + return; + } + + for(int i=0; i<3; ++i) + { + tb_page[i]=create_video_bitmap(SCREEN_W, SCREEN_H); + + if(!tb_page[i]) + { + triplebuffer_not_available = true; + break; + } + } + + Clear(); + } + void Clear() const + { + for(int i=0; i<3; i++) + clear_bitmap(tb_page[i]); + } +} +static Triplebuffer; + + + + + +int onFullscreen() +{ +#ifdef ALLEGRO_DOS + return D_O_K; +#endif + PALETTE oldpal; + get_palette(oldpal); + + show_mouse(NULL); + bool windowed=is_windowed_mode()!=0; + + // these will become ultra corrupted no matter what. + Triplebuffer.Destroy(); + + fullscreen=!fullscreen; + int ret=set_gfx_mode(windowed?GFX_AUTODETECT_FULLSCREEN:GFX_AUTODETECT_WINDOWED,resx,resy,0,0); + + if(ret!=0) + { + if(!windowed) + { + ret=set_gfx_mode(windowed?GFX_AUTODETECT_FULLSCREEN:GFX_AUTODETECT_WINDOWED,resx,resy,0,0); + + if(ret!=0) + { + Z_message("Can't set video mode (%d).\n", ret); + Z_message(allegro_error); + exit(1); + } + } + else + { + Z_message("Can't set video mode (%d).\n", ret); + Z_message(allegro_error); + exit(1); + } + } + + /* ZC will crash going from fullscreen to windowed mode if triple buffer is left unchecked. -Gleeok */ + if(Triplebuffer.GFX_can_triple_buffer()) + { + Triplebuffer.Create(); + Z_message("Triplebuffer enabled \n"); + } + else Z_message("Triplebuffer disabled \n"); + + //Everything set? + Z_message("gfx mode set at -%d %dbpp %d x %d \n", is_windowed_mode(), get_color_depth(), resx, resy); + + set_palette(oldpal); + gui_mouse_focus=0; + show_mouse(screen); + set_display_switch_mode(fullscreen?SWITCH_BACKAMNESIA:SWITCH_BACKGROUND); +// set_display_switch_callback(SWITCH_OUT, switch_out_callback);/ +// set_display_switch_callback(SWITCH_IN,switch_in_callback); + + return D_REDRAW; +} + +int main(int argc, char* argv[]) +{ + bool onlyInstance=true; + + if(!is_only_instance("zc.lck")) + { + if(used_switch(argc, argv, "-multiple")) + onlyInstance=false; + else + exit(1); + } + + switch(IS_BETA) + { + + case -1: + Z_title("Zelda Classic %s Alpha (Build %d)",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case 1: + Z_title("Zelda Classic %s Beta (Build %d)",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case 0: + Z_title("Zelda Classic %s (Build %d)",VerStr(ZELDA_VERSION), VERSION_BUILD); + } + + if(used_switch(argc, argv, "-standalone")) + { + standalone_mode=true; + + int arg=used_switch(argc, argv, "-standalone"); + + if(arg==argc-1) + { + Z_error("-standalone requires a quest file, e.g.\n" \ + " -standalone MyQuest.qst\n" \ + " -standalone \"Name with spaces.qst\""); + exit(1); + } + + standalone_quest=argv[arg+1]; + + if(stricmp(standalone_quest, "1st.qst")==0 || + stricmp(standalone_quest, "2nd.qst")==0 || + stricmp(standalone_quest, "3rd.qst")==0 || + stricmp(standalone_quest, "4th.qst")==0 || + stricmp(standalone_quest, "5th.qst")==0) + { + Z_error("Standalone mode can only be used with custom quests."); + exit(1); + } + + int len=strlen(standalone_quest); + + for(int i=0; iload_save+1)?atoi(argv[load_save+1]):0:0; + + if(!(used_switch(argc,argv,"-load"))) + if(used_switch(argc,argv,"-loadlast")) + load_save = loadlast; + + slot_arg = used_switch(argc,argv,"-slot"); + + if(argc <= (slot_arg+1)) + { + slot_arg = 0; + } + else + { + slot_arg2 = vbound(atoi(argv[slot_arg+1]), 1, MAXSAVES); + } + + if(standalone_mode) + { + load_save=1; + slot_arg=1; + slot_arg2=1; + } + + int fast_start = debug_enabled || used_switch(argc,argv,"-fast") || (!standalone_mode && (load_save || (slot_arg && (argc>(slot_arg+1))))); + skip_title = used_switch(argc, argv, "-notitle") > 0; + int save_arg = used_switch(argc,argv,"-savefile"); + + if(save_arg && (argc>(save_arg+1))) + { + SAVE_FILE = (char *)zc_malloc(2048); + sprintf(SAVE_FILE, "%s", argv[save_arg+1]); + + int len=strlen(SAVE_FILE); + + for(int i=0; i>3; i++) + { + customsfxflag[i] = 0; + } + + for(int i=0; i(res_arg+2))) + { + resx = atoi(argv[res_arg+1]); + resy = atoi(argv[res_arg+2]); + bool old_sbig = (argc>(res_arg+3))? stricmp(argv[res_arg+3],"big")==0 : 0; + bool old_sbig2 = (argc>(res_arg+3))? stricmp(argv[res_arg+3],"big2")==0 : 0; + +// mode = GFX_AUTODETECT; + } + + if(resx>=640 && resy>=480) + { + is_large=true; + } + + //request_refresh_rate(60); + + if(used_switch(argc,argv,"-fullscreen") || + (!used_switch(argc, argv, "-windowed") && get_config_int("zeldadx","fullscreen",1)==1)) + { + al_trace("Used switch: -fullscreen\n"); + tempmode = GFX_AUTODETECT_FULLSCREEN; + } + else if(used_switch(argc,argv,"-windowed") || get_config_int("zeldadx","fullscreen",1)==0) + { + al_trace("Used switch: -windowed\n"); + tempmode=GFX_AUTODETECT_WINDOWED; + } + + //set scale + if(resx < 320) resx = 320; + + if(resy < 240) resy = 240; + + screen_scale = zc_max(zc_min(resx / 320, resy / 240), 1); + + if(!game_vid_mode(tempmode, wait_ms_on_set_graphics)) + { + //what we need here is not rightousness but madness!!! + +#define TRY_SET_VID_MODE(scale) \ + Z_message("Unable to set gfx mode at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); \ + screen_scale=scale; \ + resx=320*scale; \ + resy=240*scale + + TRY_SET_VID_MODE(2); + + if(!game_vid_mode(tempmode, wait_ms_on_set_graphics)) + { + TRY_SET_VID_MODE(1); + + if(!game_vid_mode(tempmode, wait_ms_on_set_graphics)) + { + if(tempmode != GFX_AUTODETECT_WINDOWED) + { + tempmode=GFX_AUTODETECT_WINDOWED; + al_trace("-fullscreen not supported by your video driver! setting -windowed switch\n"); + TRY_SET_VID_MODE(2); + + if(!game_vid_mode(tempmode, wait_ms_on_set_graphics)) + { + TRY_SET_VID_MODE(1); + + if(!game_vid_mode(tempmode, wait_ms_on_set_graphics)) + { + Z_message("Unable to set gfx mode at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + al_trace("Fatal Error...Zelda Classic could not be initialized. Have a nice day :) \n"); + Z_error(allegro_error); + quit_game(); + } + else Z_message("set gfx mode succsessful at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + } + else Z_message("set gfx mode succsessful at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + } + else + { + al_trace("Fatal Error: could not create a window for Zelda Classic.\n"); + Z_error(allegro_error); + quit_game(); + } + } + else Z_message("set gfx mode succsessful at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + } + else Z_message("set gfx mode succsessful at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + } + else + { + Z_message("set gfx mode succsessful at -%d %dbpp %d x %d \n", tempmode, get_color_depth(), resx, resy); + } + + sbig = (screen_scale > 1); + set_display_switch_mode(is_windowed_mode()?SWITCH_BACKGROUND:SWITCH_BACKAMNESIA); + zq_screen_w = resx; + zq_screen_h = resy; + + real_screen = screen; + + if(Triplebuffer.GFX_can_triple_buffer()) + { + Triplebuffer.Create(); + } + + Z_message("Triplebuffer %savailable\n", triplebuffer_not_available?"not ":""); + + set_close_button_callback((void (*)()) hit_close_button); + set_window_title("Zelda Classic"); + + fix_dialogs(); + gui_mouse_focus = FALSE; + position_mouse(resx-16,resy-16); + + if(!onlyInstance) + { + clear_to_color(screen,BLACK); + system_pal(); + int ret=jwin_alert3("Multiple Instances", + "Another instance of ZC is already running.", + "Running multiple instances may cause your", + "save file to be deleted. Continue anyway?", + "&No","&Yes", 0, 'n', 'y', 0, lfont); + if(ret!=2) + { + if(forceExit) + exit(0); + + allegro_exit(); + return 0; + } + } + +// load saved games + Z_message("Loading saved games... "); + + if(load_savedgames() != 0) + { + Z_error("Insufficient memory"); + quit_game(); + } + + Z_message("OK\n"); + +#ifdef _WIN32 + // Nothing for them to do on other platforms + set_display_switch_callback(SWITCH_IN,switch_in_callback); + set_display_switch_callback(SWITCH_OUT,switch_out_callback); +#endif + + // AG logo + if(!fast_start) + { + set_volume(240,-1); + aglogo(tmp_scr, scrollbuf, resx, resy); + master_volume(digi_volume,midi_volume); + } + + // play the game + fix_menu(); + reset_items(true, &QHeader); + + clear_to_color(screen,BLACK); + Quit = (fast_start||skip_title) ? qQUIT : qRESET; + + rgb_map = &rgb_table; + + // set up an initial game save slot (for the list_saves function) + game = new gamedata; + game->Clear(); + +#ifdef _WIN32 + + if(use_win32_proc != FALSE) + { + al_trace("Config file warning: \"zc_win_proc_fix\" enabled switch found. This can cause crashes on some computers.\n"); + + if(win32data.zcSetCustomCallbackProc(win_get_window()) != 0) + { + use_win32_proc = FALSE; + } + } + +#endif + + while(Quit!=qEXIT) + { + // this is here to continually fix the keyboard repeat + set_keyboard_rate(250,33); + toogam = false; + titlescreen(load_save); + + load_save=0; + setup_combo_animations(); + setup_combo_animations2(); + + while(!Quit) + { +#ifdef _WIN32 + + if(use_win32_proc != FALSE) + { + win32data.Update(0); + } + +#endif + if(specialSequenceIsActive()) + { + updateSpecialSequence(); + draw_screen(tmpscr); + advanceframe(true); + } + else + { + game_loop(); + if(specialSequenceIsActive()) + // Check again because these used to start immediately, + // meaning the first update should be before advanceframe(). + updateSpecialSequence(); + advanceframe(true); + } + } + + tmpscr->flags3=0; + Playing=Paused=false; + + switch(Quit) + { + case qGAMEOVER: + // Not a good way to handle this... + beginSpecialSequence(seq_gameOver); + while(specialSequenceIsActive()) + { + updateSpecialSequence(); + // It does its own drawing for now. + advanceframe(true); + } + // Fall through + case qQUIT: + { + Link.setDontDraw(false); + show_subscreen_dmap_dots=true; + show_subscreen_numbers=true; + show_subscreen_items=true; + show_subscreen_life=true; + show_ff_scripts=false; + + initZScriptGlobalRAM(); + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_END); + + if(!skipcont&&!get_bit(quest_rules,qr_NOCONTINUE)) game_over(get_bit(quest_rules,qr_NOSAVE)); + + skipcont = 0; + } + break; + + case qWON: + { + Link.setDontDraw(false); + show_subscreen_dmap_dots=true; + show_subscreen_numbers=true; + show_subscreen_items=true; + show_subscreen_life=true; + + initZScriptGlobalRAM(); + ZScriptVersion::RunScript(SCRIPT_GLOBAL, GLOBAL_SCRIPT_END); + messageMgr.clear(false); // Should callbacks run? + ending(); + } + break; + + } + + kill_sfx(); + music_stop(); + clear_to_color(screen,BLACK); + } + + // clean up + + music_stop(); + kill_sfx(); + +quick_quit: + show_saving(screen); + save_savedgames(); + save_game_configs(); + Triplebuffer.Destroy(); + set_gfx_mode(GFX_TEXT,80,25,0,0); + //rest(250); // ??? + // if(useCD) + // cd_exit(); + quit_game(); + Z_message("Armageddon Games web site: http://www.armageddongames.com\n"); + Z_message("Zelda Classic web site: http://www.zeldaclassic.com\n"); + Z_message("Zelda Classic wiki: http://www.shardstorm.com/ZCwiki/\n"); + + __zc_debug_malloc_free_print_memory_leaks(); //this won't do anything without debug_malloc_logging defined. + + if(forceExit) //fix for the allegro at_exit() hang. + exit(0); + + allegro_exit(); + return 0; +} +END_OF_MAIN() + + +void remove_installed_timers() +{ + al_trace("Removing timers. \n"); + remove_int(update_logic_counter); + Z_remove_timers(); +#ifdef _SCRIPT_COUNTER + remove_int(update_script_counter); +#endif + +} + + +void delete_everything_else() //blarg. +{ + delete_combo_aliases(); + reset_subscr_items(); + delete_selectors(); + Sitems.clear(); + +} + +void quit_game() +{ + script_drawing_commands.Dispose(); //for allegro bitmaps + + remove_installed_timers(); + delete_everything_else(); + + al_trace("Freeing Data: \n"); + + if(game) delete game; + + if(data) unload_datafile(data); + + if(fontsdata) unload_datafile(fontsdata); + + if(sfxdata) unload_datafile(sfxdata); + + //if(mididata) unload_datafile(mididata); + // if(mappic) + // destroy_bitmap(mappic); + + al_trace("Bitmaps... \n"); + messageMgr.clear(false); // Needed to destroy any bitmaps it's still using + destroy_bitmap(framebuf); + destroy_bitmap(scrollbuf); + destroy_bitmap(tmp_scr); + destroy_bitmap(screen2); + destroy_bitmap(tmp_bmp); + destroy_bitmap(fps_undo); + destroy_bitmap(prim_bmp); + + al_trace("Subscreens... \n"); + + for(int i=0; i<4; i++) + { + for(int j=0; j debug_malloc_pool_type; +debug_malloc_pool_type debug_zc_malloc_allocated_pool; +#endif + +void* __zc_debug_malloc(size_t numBytes, const char* file, int line) +{ +#if ZC_WANT_DETAILED_MALLOC_LOGGING + static bool zcDbgMallocInit = false; + + if(!zcDbgMallocInit) + { + zcDbgMallocInit = true; + debug_zc_malloc_allocated_pool.reserve(1 << 17); + //yeah. completely ridiculous... there's no reason zc should ever need this many.. + //BUT it does... go figure + } + + totalBytesAllocated += numBytes; + + //char buf[1024]; + //sprintf(buf, "%i : %s, line %i, %u bytes allocated.\n", 0, file, line, numBytes); + //al_trace("%s", buf); + + al_trace("info: %i : %s, line %i, %u bytes, pool size %u, total %u,", + 0, + file, + line, + numBytes, + debug_zc_malloc_allocated_pool.size(), + totalBytesAllocated / 1024 + ); +#endif + + ZC_MALLOC_ALWAYS_ASSERT(numBytes != 0); + void* p = malloc(numBytes); + +#if ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("at address %x\n", (int)p); + + if(!p) + al_trace("____________ ERROR: __zc_debug_malloc: returned null. out of memory.\n"); + + debug_malloc_pool_type::insert_iterator_type it = debug_zc_malloc_allocated_pool.insert(p); + + if(!it.second) + al_trace("____________ ERROR: malloc returned identical address to one in use... No way Jose!\n"); + +#endif + + return p; +} + + +void __zc_debug_free(void* p, const char* file, int line) +{ + ZC_MALLOC_ALWAYS_ASSERT(p != 0); + +#if ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("alloc info: %i : %s line %i, freeing memory at address %x\n", 0, file, line, (int)p); + + size_t numErased = debug_zc_malloc_allocated_pool.erase(p); + + if(numErased == 0) + al_trace("____________ ERROR: __zc_debug_free: no known ptr to memory exists. ..attempting to free it anyways.\n"); + +#endif + + free(p); +} + + +void __zc_debug_malloc_free_print_memory_leaks() +{ +#if ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("LOGGING INFO FROM debug_zc_malloc_allocated_pool:\n"); + + for(debug_malloc_pool_type::iterator it = debug_zc_malloc_allocated_pool.begin(); + it != debug_zc_malloc_allocated_pool.end(); + ++it + ) + { + al_trace("block at address %x.\n", (int)*it); + } + +#endif +} + + +void __zc_always_assert(bool e, const char* expression, const char* file, int line) +{ + if(!e) + { + //for best results set a breakpoint in here. + char buf[1024]; + sprintf("ASSERTION FAILED! : %s, %s line %i\n", expression, file, line); + + al_trace("%s", buf); + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); + allegro_message("%s", buf); + //exit(-1); //flashing lights are probably enough. + } +} + + +/*** end of zelda.cc ***/ + diff --git a/src/zelda.h b/src/zelda.h new file mode 100644 index 0000000000..5b058316be --- /dev/null +++ b/src/zelda.h @@ -0,0 +1,366 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zelda.h +// +// Definitions, function prototypes, etc. for zelda.cc +// +//-------------------------------------------------------- + +#ifndef _ZELDA_H_ +#define _ZELDA_H_ + +/*********************************/ +/********** Definitions **********/ +/*********************************/ + +#include +#include "zdefs.h" +#include "zc_array.h" +#include "zeldadat.h" +#include "sfx.h" +#include "zcmusic.h" +#include "jwin.h" +#include "gamedata.h" +#include "zsys.h" +#include "script_drawing.h" + +int isFullScreen(); +int onFullscreen(); + +#define MAXMIDIS ZC_MIDI_COUNT+MAXCUSTOMTUNES + +#define MAX_IDLE 72000 // 20 minutes +#define MAX_ACTIVE 72000 // 20 minutes + +// saved games +#define MAXSAVES (standalone_mode?1:15) // It's constant enough... :p + +// game.maps[] flags +#define mSECRET 8192 // only overworld and caves use this +#define mVISITED 16384 // only overworld uses this + +#define mDOOR_UP 1 // only dungeons use this +#define mDOOR_DOWN 2 // '' +#define mDOOR_LEFT 4 // '' +#define mDOOR_RIGHT 8 // '' + +#define mITEM 16 // item (main screen) +#define mBELOW 32 // special item (underground) +#define mNEVERRET 64 // enemy never returns +#define mTMPNORET 128 // enemies don't return until you leave the dungeon + +#define mLOCKBLOCK 256 // if the lockblock on the screen has been triggered +#define mBOSSLOCKBLOCK 512 // if the bosslockblock on the screen has been triggered + +#define mCHEST 1024 // if the unlocked check on this screen has been opened +#define mLOCKEDCHEST 2048 // if the locked chest on this screen has been opened +#define mBOSSCHEST 4096 // if the boss chest on this screen has been opened +#define mOTHER3 32768 // overwrite this value, use for expansion + +/*********************************/ +/******** Enums & Structs ********/ +/*********************************/ + +enum { qQUIT=1, qRESET, qEXIT, qGAMEOVER, qCONT, qWON, qERROR }; + +// "special" walk flags +enum +{ + spw_none, spw_door, spw_clipright, spw_floater, spw_trap, spw_halfstep, + spw_water, spw_wizzrobe, spw_clipbottomright +}; + +// death & fade defs +enum +{ + fade_none, fade_flicker, fade_invisible, fade_flash_die, + fade_blue_poof +}; + +/*********************************/ +/*********** Procedures **********/ +/*********************************/ + +/* + + // aglogo.cc + int aglogo(BITMAP* frame); + + + // title.cc + void update_game_icons(); + + // zc_sys.cc + void color_layer(RGB *src,RGB *dest,char r,char g,char b,char pos,int from,int to); + void go(); + void comeback(); + void waitvsync(bool fast); + int input_idle(bool checkmouse); + int after_time(); + void hit_close_button(); + */ + +bool get_debug(); +void set_debug(bool d); + +void Z_eventlog(const char *format, ...); +void Z_scripterrlog(const char * const format, ...); + +// zelda.cc +void addLwpn(int x,int y,int z,int id,int type,int power,int dir, int parentid); +void ALLOFF(bool messagesToo = true, bool decorationsToo = true); +fix LinkX(); +fix LinkY(); +fix LinkZ(); +int LinkHClk(); +int LinkNayrusLoveShieldClk(); +int LinkSwordClk(); +int LinkItemClk(); +int LinkAction(); +int LinkCharged(); +bool LinkGetDontDraw(); +void setSwordClk(int newclk); +void setItemClk(int newclk); +int LinkLStep(); +void LinkCheckItems(); +fix LinkModifiedX(); +fix LinkModifiedY(); +fix GuyX(int j); +fix GuyY(int j); +int GuyID(int j); +int GuyMisc(int j); +void StunGuy(int j,int stun); +bool GuySuperman(int j); +int GuyCount(); +int LinkDir(); +fix distance(int x1, int y1, int x2, int y2); +bool getClock(); +void setClock(bool state); +void CatchBrang(); +int LinkAction(); + +void do_dcounters(); +void dointro(); +void init_dmap(); +int init_game(); +int cont_game(); +void restart_level(); +int load_quest(gamedata *g, bool report=true); +void show_details(); +void show_ffscript_names(); +//int init_palnames(); + +int get_currdmap(); +int get_dlevel(); +int get_currscr(); +int get_homescr(); +int get_bmaps(int si); +bool no_subscreen(); +bool is_zquest(); +bool screenIsScrolling(); +//void quit_game(); +int d_timer_proc(int msg, DIALOG *d, int c); +void showCurrentDMapIntro(); // Actually in link.cpp, but it shouldn't be + +//INLINE void SCRFIX() { putpixel(screen,0,0,getpixel(screen,0,0)); } + +/**********************************/ +/******** Global Variables ********/ +/**********************************/ + + +extern ZCMUSIC *zcmusic; + +extern int colordepth; +extern int db; +extern int detail_int[10]; //temporary holder for things you want to detail +extern zinitdata zinit; +extern int lens_hint_item[MAXITEMS][2]; //aclk, aframe +extern int lens_hint_weapon[MAXWPNS][5]; //aclk, aframe, dir, x, y +extern int strike_hint_counter; +extern int strike_hint_timer; +extern int strike_hint; + +extern RGB_MAP rgb_table; +extern COLOR_MAP trans_table, trans_table2; +extern BITMAP *framebuf, *scrollbuf, *tmp_bmp, *tmp_scr, *screen2, *fps_undo, *tb_page[3], *real_screen, *temp_buf, *temp_buf2, *prim_bmp; +extern DATAFILE *data, *sfxdata, *fontsdata, *mididata; +extern SAMPLE wav_refill; +extern FONT *nfont, *zfont, *z3font, *z3smallfont, *deffont, *lfont, *lfont_l, *pfont, *mfont, *ztfont, *sfont, *sfont2, *sfont3, *spfont, *ssfont1, *ssfont2, *ssfont3, *ssfont4, *gblafont, + *goronfont, *zoranfont, *hylian1font, *hylian2font, *hylian3font, *hylian4font, *gboraclefont, *gboraclepfont, *dsphantomfont, *dsphantompfont; +//extern FONT custom_fonts[MAXFONTS]; +extern PALETTE RAMpal; +extern byte *colordata; +//extern byte *tilebuf; +extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; +extern comboclass *combo_class_buf; +extern guydata *guysbuf; +extern item_drop_object item_drop_sets[MAXITEMDROPSETS]; +extern ZCHEATS zcheats; +extern byte use_cheats; +extern byte use_tiles; +extern char palnames[MAXLEVELS][17]; + +extern bool is_large; + +extern bool standalone_mode; +extern char *standalone_quest; +extern bool skip_title; + +/* +extern tiledata *newtilebuf, *grabtilebuf; +extern newcombo *combobuf; +extern word animated_combo_table[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table4[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos; +extern word animated_combo_table2[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table24[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos2; +extern bool blank_tile_table[NEWMAXTILES]; //keeps track of blank tiles +extern bool blank_tile_quarters_table[NEWMAXTILES*4]; //keeps track of blank tiles +*/ +extern bool ewind_restart; +extern word msg_count; +extern word door_combo_set_count; +extern short lensclk; +extern int lensid; +extern int Bpos; +extern volatile int logic_counter; +#ifdef _SCRIPT_COUNTER +extern volatile int script_counter; +#endif +extern bool halt; +extern bool screenscrolling; +extern bool close_button_quit; +extern int jwin_pal[jcMAX]; +extern int gui_colorset; +extern int fullscreen; +extern byte disable_triplebuffer, can_triplebuffer_in_windowed_mode; +extern byte frame_rest_suggest, forceExit, zc_vsync; +extern byte zc_color_depth; +extern byte use_debug_console, use_win32_proc; //windows only + +#ifdef _SCRIPT_COUNTER +void update_script_counter(); +#endif + +extern PALETTE tempbombpal; +extern bool usebombpal; + +extern int slot_arg, slot_arg2; +extern char *SAVE_FILE; + +extern int homescr,currscr,frame,currmap,dlevel,warpscr,worldscr; +extern int newscr_clk,opendoors,currdmap,fadeclk,currgame,listpos; +extern int lastentrance,lastentrance_dmap, loadside, Bwpn, Awpn; +extern int digi_volume,midi_volume,sfx_volume,emusic_volume,currmidi,hasitem,whistleclk,pan_style; +extern int joystick_index,Akey,Bkey,Skey,Lkey,Rkey,Pkey,Exkey1,Exkey2,Exkey3,Exkey4,Abtn,Bbtn,Sbtn,Mbtn,Lbtn,Rbtn,Pbtn,Exbtn1,Exbtn2,Exbtn3,Exbtn4,Quit; +extern int DUkey, DDkey, DLkey, DRkey, ss_after, ss_speed, ss_density, ss_enable; +extern int hs_startx, hs_starty, hs_xdist, hs_ydist; +extern int currcset, pitx, pity, refill_what, refill_why; +extern int heart_beep_timer, new_enemy_tile_start, nets, magicitem, title_version; +extern int quakeclk, wavy, magicdrainclk, conveyclk, memrequested; +extern dword fps_secs; +extern float avgfps; + +extern bool do_cheat_goto, do_cheat_light; +extern bool blockmoving; +extern bool Throttlefps, ClickToFreeze, Paused, Advance, ShowFPS, Showpal, Playing, FrameSkip, TransLayers, disableClickToFreeze; +extern bool refreshpal,blockpath,__debug,loaded_guys,freeze_guys; +extern bool loaded_enemies,drawguys,details,debug_enabled,watch; +extern bool Udown,Ddown,Ldown,Rdown,Adown,Bdown,Sdown,Mdown,LBdown,RBdown,Pdown,Ex1down,Ex2down,Ex3down,Ex4down,AUdown,ADdown,ALdown,ARdown,F12,F11,F5,keyI, keyQ; +extern bool SystemKeys,NESquit,volkeys,useCD,boughtsomething; +extern bool fixed_door, darkroom,naturaldark,BSZ; +extern bool hookshot_used, hookshot_frozen, pull_link; +extern bool hs_fix, cheat_superman, gofast, checklink; +extern bool ewind_restart, didpit, heart_beep, pausenow; +extern bool is_on_conveyor, activated_timed_warp; + +extern byte COOLSCROLL; + +extern int SnapshotFormat, NameEntryMode; + +extern bool show_layer_0, show_layer_1, show_layer_2, show_layer_3, show_layer_4, show_layer_5, show_layer_6, show_layer_over, show_layer_push, show_sprites, show_ffcs, show_hitboxes, show_walkflags, show_ff_scripts; + +extern int cheat_goto_dmap, cheat_goto_screen; +extern char cheat_goto_dmap_str[4]; +extern char cheat_goto_screen_str[3]; +extern short visited[6]; +extern byte guygrid[176]; +extern mapscr tmpscr[2]; +extern mapscr tmpscr2[6]; +extern mapscr tmpscr3[6]; +extern char sig_str[44]; +extern ffscript *ffscripts[512]; +extern ffscript *itemscripts[256]; +extern ffscript *globalscripts[NUMSCRIPTGLOBAL]; + +extern ffscript *guyscripts[256]; +extern ffscript *wpnscripts[256]; +extern ffscript *linkscripts[3]; +extern ffscript *screenscripts[256]; +extern SAMPLE customsfxdata[WAV_COUNT]; +extern int sfxdat; + +#define MAX_ZCARRAY_SIZE 4096 +typedef ZCArray ZScriptArray; +extern ZScriptArray localRAM[MAX_ZCARRAY_SIZE]; +extern byte arrayOwner[MAX_ZCARRAY_SIZE]; + +dword getNumGlobalArrays(); + +extern int resx,resy,scrx,scry; +extern bool sbig; // big screen +extern bool sbig2; //BIGGER SCREEN!!!! +extern int screen_scale; //user adjustable screen size. + +extern bool scanlines; //do scanlines if sbig==1 +extern bool toogam; + +extern int cheat; // 0 = none; 1,2,3,4 = cheat level + +extern int mouse_down; // used to hold the last reading of 'gui_mouse_b()' status +extern int idle_count, active_count; +extern char *qstpath; +extern char *qstdir; +extern gamedata *saves; +extern gamedata *game; + +extern volatile int lastfps; +extern volatile int framecnt; +extern void throttleFPS(); + +// quest file data +extern zquestheader QHeader; +extern byte quest_rules[QUESTRULES_SIZE]; +extern byte midi_flags[MIDIFLAGS_SIZE]; +extern byte music_flags[MUSICFLAGS_SIZE]; +extern word map_count; +extern MsgStr *MsgStrings; +extern int msg_strings_size; +extern DoorComboSet *DoorComboSets; +extern dmap *DMaps; +extern miscQdata QMisc; +extern std::vector TheMaps; +extern zcmap *ZCMaps; +extern byte *quest_file; + +/**********************************/ +/*********** Misc Data ************/ +/**********************************/ + +extern const char startguy[8]; +extern const byte stx[4][9]; +extern const byte sty[4][9]; +extern const byte ten_rupies_x[10]; +extern const byte ten_rupies_y[10]; +extern zctune tunes[MAXMIDIS]; +//extern zcmidi_ tunes[MAXMIDIS]; +//extern emusic enhancedMusic[MAXMUSIC]; +#endif + +/*** end of zelda.h ***/ + diff --git a/src/zeldadat.h b/src/zeldadat.h new file mode 100644 index 0000000000..e074cd1b05 --- /dev/null +++ b/src/zeldadat.h @@ -0,0 +1,45 @@ +/* Allegro datafile object indexes, produced by grabber v4.2.1, Unix */ +/* Datafile: /root/shardstorm.com/trunk/zelda.dat */ +/* Date: Fri Feb 9 12:27:03 2007 */ +/* Do not hand edit! */ + +#define _SIGNATURE 0 /* DATA */ +#define BMP_MOUSE 1 /* BMP */ +#define BMP_TITLE_NES 2 /* BMP */ +#define PAL_CREDITS 3 /* PAL */ +#define PAL_GUI 4 /* PAL */ +#define RLE_AGTEXT 5 /* RLE */ +#define RLE_CREDITS 6 /* RLE */ +#define TITLE_25 7 /* FILE */ + +#define TITLE_25_BMP_1 0 /* BMP */ +#define TITLE_25_BMP_2 1 /* BMP */ +#define TITLE_25_BMP_3 2 /* BMP */ +#define TITLE_25_BMP_4 3 /* BMP */ +#define TITLE_25_BMP_5 4 /* BMP */ +#define TITLE_25_PAL_1 5 /* PAL */ +#define TITLE_25_COUNT 6 + +#define TITLE_DX 8 /* FILE */ + +#define TITLE_DX_BMP_1 0 /* BMP */ +#define TITLE_DX_BMP_2 1 /* BMP */ +#define TITLE_DX_BMP_3 2 /* BMP */ +#define TITLE_DX_BMP_4 3 /* BMP */ +#define TITLE_DX_PAL_1 4 /* PAL */ +#define TITLE_DX_COUNT 5 + +#define WAV_00_AGFIRE 9 /* SAMP */ +#define ZC_MIDI 10 /* FILE */ + +#define ZC_MIDI_DUNGEON 0 /* MIDI */ +#define ZC_MIDI_ENDING 1 /* MIDI */ +#define ZC_MIDI_GAMEOVER 2 /* MIDI */ +#define ZC_MIDI_LEVEL9 3 /* MIDI */ +#define ZC_MIDI_OVERWORLD 4 /* MIDI */ +#define ZC_MIDI_TITLE 5 /* MIDI */ +#define ZC_MIDI_TRIFORCE 6 /* MIDI */ +#define ZC_MIDI_COUNT 7 + + + diff --git a/src/zq_class.cpp b/src/zq_class.cpp new file mode 100644 index 0000000000..c821e75be6 --- /dev/null +++ b/src/zq_class.cpp @@ -0,0 +1,11221 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_class.cc +// +// Contains zmap class and other main code for ZQuest. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +/************************/ +/****** ZMAP class ******/ +/************************/ + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include + +#include "encryption.h" +#include "ffc.h" +#include "gui.h" +#include "zq_class.h" +#include "zq_misc.h" +#include "zquest.h" +#include "qst.h" +#include "colors.h" +#include "tiles.h" +#include "zquestdat.h" +#include "zsys.h" +#include "sprite.h" +#include "items.h" +#include "maps.h" +#include "zc_sys.h" +#include "md5.h" +#include "zc_custom.h" +#include "subscr.h" +#include "zq_strings.h" +#include "zq_subscr.h" +#include "mem_debug.h" + +#define EPSILON 0.01 // Define your own tolerance +#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON))) + +//const char zqsheader[30]="Zelda Classic String Table\n\x01"; +extern char msgbuf[MSGSIZE*3]; + +extern std::string zScript; +extern std::map > ffcmap; +extern std::map > globalmap; +extern std::map > itemmap; +zmap Map; +int prv_mode=0; + +bool save_warn=true; + +void reset_dmap(int index) +{ + bound(index,0,MAXDMAPS-1); + memset(&DMaps[index],0,sizeof(dmap)); + sprintf(DMaps[index].title, " "); + sprintf(DMaps[index].intro, " "); +} + +void reset_dmaps() +{ + for(int i=0; i12) + { + if(!p_getc(&(temp_map.tileWidth),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.tileHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subaWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subaHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subpWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subpHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.scrResWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.scrResHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewX),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewY),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.subaTrans),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.subpTrans),f,true)) + { + return qe_invalid; + } + } + else + { + temp_map.scrResWidth = 256; + temp_map.scrResHeight = 224; + temp_map.tileWidth = 16; + temp_map.tileHeight = 11; + temp_map.viewWidth = 256; + temp_map.viewHeight = 176; + temp_map.viewX = 0; + temp_map.viewY = 64; + temp_map.subaWidth = 256; + temp_map.subaHeight = 168; + temp_map.subaTrans = false; + temp_map.subpWidth = 256; + temp_map.subpHeight = 56; + temp_map.subpTrans = false; + } + + for(int i=0; i12) + { + if(!p_getc(&(temp_map.tileWidth),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.tileHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subaWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subaHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subpWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.subpHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.scrResWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.scrResHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewWidth),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewHeight),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewX),f,true)) + { + return qe_invalid; + } + + if(!p_igetw(&(temp_map.viewY),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.subaTrans),f,true)) + { + return qe_invalid; + } + + if(!p_getc(&(temp_map.subpTrans),f,true)) + { + return qe_invalid; + } + } + else + { + temp_map.scrResWidth = 256; + temp_map.scrResHeight = 224; + temp_map.tileWidth = 16; + temp_map.tileHeight = 11; + temp_map.viewWidth = 256; + temp_map.viewHeight = 176; + temp_map.viewX = 0; + temp_map.viewY = 64; + temp_map.subaWidth = 256; + temp_map.subaHeight = 168; + temp_map.subaTrans = false; + temp_map.subpWidth = 256; + temp_map.subpHeight = 56; + temp_map.subpTrans = false; + } + + for(int i=0; i0) + { + + if((ZCMaps[prvscr.layermap[i]-1].tileWidth==ZCMaps[map].tileWidth) && (ZCMaps[prvscr.layermap[i]-1].tileHeight==ZCMaps[map].tileHeight)) + { + prvlayers[i]=TheMaps[(prvscr.layermap[i]-1)*MAPSCRS+prvscr.layerscreen[i]]; + + prvlayers[i].data.resize(_mapsSize, 0); + prvlayers[i].sflag.resize(_mapsSize, 0); + prvlayers[i].cset.resize(_mapsSize, 0); + + } + else + { + // memset(prvlayers+i,0,sizeof(mapscr)); + } + } + } + + prv_map=map; + prv_scr=scr; +} +int zmap::getCurrMap() +{ + return currmap; +} +bool zmap::isDark() +{ + return (screens[currscr].flags&4)!=0; +} +void zmap::setCurrMap(int index) +{ + int oldmap=currmap; + scrpos[currmap]=currscr; + currmap=bound(index,0,map_count); + screens=&TheMaps[currmap*MAPSCRS]; + + currscr=scrpos[currmap]; + loadlvlpal(getcolor()); + + if(currmap!=oldmap) + { + can_undo=false; + } + + reset_combo_animations2(); +} + +int zmap::getCurrScr() +{ + return currscr; +} +void zmap::setCurrScr(int scr) +{ + if(scr==currscr) return; + + int oldscr=currscr; + int oldcolor=getcolor(); + + if(!(screens[currscr].valid&mVALID)) + { + oldcolor=-1; + } + + currscr=bound(scr,0,MAPSCRS-1); + int newcolor=getcolor(); + loadlvlpal(newcolor); + + //setcolor(newcolor); + if(!(screens[currscr].valid&mVALID)) + { + newcolor=-1; + } + + if(newcolor!=oldcolor) + { + rebuild_trans_table(); + } + + if(currscr!=oldscr) + { + can_undo=false; + } + + reset_combo_animations2(); + setlayertarget(); +} + +void zmap::setlayertarget() +{ + layer_target_map = 0; + layer_target_multiple = 0; + + for(int m=0; mlayerscreen[w]==currscr && (ts->layermap[w]-1)==currmap) + { + if(layer_target_map > 0) + { + layer_target_multiple += 1; + continue; + } + + layer_target_map = m+1; + layer_target_scr = s; + } + } + } + } +} + +void zmap::setcolor(int c) +{ + if(screens[currscr].valid&mVALID) + { + screens[currscr].color = c; + + if(Color!=c) + { + Color = c; + loadlvlpal(c); + } + } +} + +int zmap::getcolor() +{ + if(prv_mode) + { + return prvscr.color; + } + + return screens[currscr].color; +} + +void zmap::resetflags() +{ + byte *di=&(screens[currscr].valid); + + for(int i=1; i<48; i++) + { + *(di+i)=0; + } +} + +word zmap::tcmbdat(int pos) +{ + return screens[TEMPLATE].data[pos]; +} + +word zmap::tcmbcset(int pos) +{ + return screens[TEMPLATE].cset[pos]; +} + +int zmap::tcmbflag(int pos) +{ + return screens[TEMPLATE].sflag[pos]; +} + +word zmap::tcmbdat2(int pos) +{ + return screens[TEMPLATE2].data[pos]; +} + +word zmap::tcmbcset2(int pos) +{ + return screens[TEMPLATE2].cset[pos]; +} + +int zmap::tcmbflag2(int pos) +{ + return screens[TEMPLATE2].sflag[pos]; +} + +void zmap::TemplateAll() +{ + for(int i=0; i<128; i++) + { + if((screens[i].valid&mVALID) && isDungeon(i)) + Template(-1,i); + } +} + +void zmap::Template(int floorcombo, int floorcset) +{ + Template(floorcombo, floorcset, currscr); +} + +void zmap::Template(int floorcombo, int floorcset, int scr) +{ + if(scr==TEMPLATE) + return; + + if(!(screens[scr].valid&mVALID)) + screens[scr].color=Color; + + screens[scr].valid|=mVALID; + + for(int i=0; i<32; i++) + { + screens[scr].data[i]=screens[TEMPLATE].data[i]; + screens[scr].cset[i]=screens[TEMPLATE].cset[i]; + screens[scr].sflag[i]=screens[TEMPLATE].sflag[i]; + } + + for(int i=144; i<176; i++) + { + screens[scr].data[i]=screens[TEMPLATE].data[i]; + screens[scr].cset[i]=screens[TEMPLATE].cset[i]; + screens[scr].sflag[i]=screens[TEMPLATE].sflag[i]; + } + + for(int y=2; y<=9; y++) + { + int j=y<<4; + screens[scr].data[j]=screens[TEMPLATE].data[j]; + screens[scr].cset[j]=screens[TEMPLATE].cset[j]; + screens[scr].sflag[j]=screens[TEMPLATE].sflag[j]; + ++j; + screens[scr].data[j]=screens[TEMPLATE].data[j]; + screens[scr].cset[j]=screens[TEMPLATE].cset[j]; + screens[scr].sflag[j]=screens[TEMPLATE].sflag[j]; + ++j; + j+=12; + screens[scr].data[j]=screens[TEMPLATE].data[j]; + screens[scr].cset[j]=screens[TEMPLATE].cset[j]; + screens[scr].sflag[j]=screens[TEMPLATE].sflag[j]; + ++j; + screens[scr].data[j]=screens[TEMPLATE].data[j]; + screens[scr].cset[j]=screens[TEMPLATE].cset[j]; + + screens[scr].sflag[j]=screens[TEMPLATE].sflag[j]; + ++j; + } + + if(floorcombo!=-1) + { + for(int y=2; y<9; y++) + for(int x=2; x<14; x++) + { + int i=(y<<4)+x; + screens[scr].data[i] = floorcombo; + screens[scr].cset[i] = floorcset; + } + } + + for(int i=0; i<4; i++) + putdoor(scr,i,screens[scr].door[i]); +} + +void zmap::putdoor(int side,int door) +{ + putdoor(currscr,side,door); +} + +void zmap::putdoor2(int side,int door) +{ + putdoor2(currscr,side,door); +} + + + +// void putdoor(int scr,int side,int door); +// void putdoor2(int scr,int side,int door); +// void dowarp(int type); +// void dowarp(int ring,int index); + +void zmap::clearscr(int scr) +{ + screens[scr].zero_memory(); + + for(int i=0; i<6; i++) + screens[scr].layeropacity[i]=255; + + screens[scr].valid=mVERSION; + screens[scr].screen_midi=-1; + screens[scr].csensitive=1; + screens[scr].bosssfx=screens[scr].oceansfx=0; + screens[scr].secretsfx=27; // WAV_SECRET + screens[scr].holdupsfx=20; // WAV_HOLDUP + + for(int i=0; i<32; i++) + { + screens[scr].ffcs[i].width=15; + screens[scr].ffcs[i].height=15; + } +} + +const char *loaderror[] = +{ + + "OK","File not found","Incomplete data", + "Invalid version","Invalid file" + +}; + +int zmap::load(const char *path) +{ + // int size=file_size(path); + + PACKFILE *f=pack_fopen_password(path,F_READ, ""); + + if(!f) + return 1; + + + short version; + byte build; + + //get the version + if(!p_igetw(&version,f,true)) + { + goto file_error; + } + + //get the build + if(!p_getc(&build,f,true)) + { + goto file_error; + } + + zcmap temp_map; + temp_map.scrResWidth = 256; + temp_map.scrResHeight = 224; + temp_map.tileWidth = 16; + temp_map.tileHeight = 11; + temp_map.viewWidth = 256; + temp_map.viewHeight = 176; + temp_map.viewX = 0; + temp_map.viewY = 64; + temp_map.subaWidth = 256; + temp_map.subaHeight = 168; + temp_map.subaTrans = false; + temp_map.subpWidth = 256; + temp_map.subpHeight = 56; + temp_map.subpTrans = false; + + for(int i=0; igetCurrMap(),i) == qe_invalid) + { + pack_fclose(f); + return 2; + } + } + + pack_fclose(f); + return 0; +} + + +bool zmap::ishookshottable(int bx, int by, int i) +{ + // Hookshots can be blocked by solid combos on all 3 ground layers. + newcombo c = combobuf[MAPCOMBO(bx,by)]; + + if(c.type != cHOOKSHOTONLY && c.type != cLADDERHOOKSHOT && c.walk&(1<>10+1)); + // text_mode(-1); + // textprintf_ex(dest,sfont,x+1,y+1,(sflag)==0x7800?vc(0):vc(15),-1,"%d",sflag); + if(sflag) + { + rectfill(dest,x,y,x+15,y+15,vc(sflag&15)); + textprintf_ex(dest,z3smallfont,x+1,y+1,vc(15-(sflag&15)),-1,"%d",sflag); + } + + if(combobuf[cmbdat].flag) + { + rectfill(dest,x,y+(sflag?8:0),x+15,y+15,vc((combobuf[cmbdat].flag)&15)); + textprintf_ex(dest,z3smallfont,x+1,y+9,vc(15-((combobuf[cmbdat].flag)&15)),-1,"%d",combobuf[cmbdat].flag); + } + } + + if(flags&cCSET) + { + bool inv = (((cmbdat&0x7800)==0x7800)&&(flags&cFLAGS)); + // text_mode(inv?vc(15):vc(0)); + textprintf_ex(dest,z3smallfont,x+9,y+9,inv?vc(0):vc(15),inv?vc(15):vc(0),"%d",cset); + } + else if(flags&cCTYPE) + { + bool inv = (((cmbdat&0x7800)==0x7800)&&(flags&cFLAGS)); + // text_mode(inv?vc(15):vc(0)); + textprintf_ex(dest,z3smallfont,x+1,y+9,inv?vc(0):vc(15),inv?vc(15):vc(0),"%d",c.type); + } +} + +void put_combo(BITMAP *dest,int x,int y,word cmbdat,int cset,int flags,int sflag) +{ + + newcombo c = combobuf[cmbdat]; + + if(c.tile==0) + { + rectfill(dest,x,y,x+15,y+15,0); + rectfill(dest,x+3,y+3,x+12,y+12,vc(4)); + return; + } + + putcombo(dest,x,y,cmbdat,cset); + + /* moved to put_walkflags + for(int i=0; i<4; i++) { + + int tx=((i&2)<<2)+x; + int ty=((i&1)<<3)+y; + if((flags&cWALK) && (c.walk&(1<>10+1)); + // text_mode(-1); + // textprintf_ex(dest,sfont,x+1,y+1,(sflag)==0x7800?vc(0):vc(15),-1,"%d",sflag); + if(sflag) + { + rectfill(dest,x,y,x+15,y+15,vc(sflag&15)); + textprintf_ex(dest,z3smallfont,x+1,y+1,vc(15-(sflag&15)),-1,"%d",sflag); + } + + if(combobuf[cmbdat].flag) + { + rectfill(dest,x,y+(sflag?8:0),x+15,y+15,vc((combobuf[cmbdat].flag)&15)); + textprintf_ex(dest,z3smallfont,x+1,y+1,vc(15-((combobuf[cmbdat].flag)&15)),-1,"%d",combobuf[cmbdat].flag); + } + } + + if(flags&cWALK) + { + put_walkflags(dest,x,y,cmbdat,0); + } + + if(flags&cCSET) + { + bool inv = (((cmbdat&0x7800)==0x7800)&&(flags&cFLAGS)); + // text_mode(inv?vc(15):vc(0)); + textprintf_ex(dest,z3smallfont,x+9,y+9,inv?vc(0):vc(15),inv?vc(15):vc(0),"%d",cset); + } + else if(flags&cCTYPE) + { + bool inv = (((cmbdat&0x7800)==0x7800)&&(flags&cFLAGS)); + // text_mode(inv?vc(15):vc(0)); + textprintf_ex(dest,z3smallfont,x+1,y+9,inv?vc(0):vc(15),inv?vc(15):vc(0),"%d",c.type); + } +} + + +void copy_mapscr(mapscr *dest, const mapscr *src) +{ + // oops, my bad. ..nvrmnd. XD + + dest->valid=src->valid; + dest->guy=src->guy; + dest->str=src->str; + dest->room=src->room; + dest->item=src->item; + dest->hasitem=src->hasitem; + + for(int i=0; i<4; i++) + dest->tilewarptype[i]=src->tilewarptype[i]; + + dest->tilewarpoverlayflags=src->tilewarpoverlayflags; + dest->door_combo_set=src->door_combo_set; + + for(int i=0; i<4; i++) + { + dest->warpreturnx[i]=src->warpreturnx[i]; + dest->warpreturny[i]=src->warpreturny[i]; + } + + dest->warpreturnc=src->warpreturnc; + dest->stairx=src->stairx; + dest->stairy=src->stairy; + dest->itemx=src->itemx; + dest->itemy=src->itemy; + dest->color=src->color; + dest->enemyflags=src->enemyflags; + + for(int i=0; i<4; i++) + dest->door[i]=src->door[i]; + + for(int i=0; i<4; i++) + { + dest->tilewarpdmap[i]=src->tilewarpdmap[i]; + dest->tilewarpscr[i]=src->tilewarpscr[i]; + } + + dest->exitdir=src->exitdir; + + for(int i=0; i<10; i++) + dest->enemy[i]=src->enemy[i]; + + dest->pattern=src->pattern; + + for(int i=0; i<4; i++) + dest->sidewarptype[i]=src->sidewarptype[i]; + + dest->sidewarpoverlayflags=src->sidewarpoverlayflags; + dest->warparrivalx=src->warparrivalx; + dest->warparrivaly=src->warparrivaly; + + for(int i=0; i<4; i++) + dest->path[i]=src->path[i]; + + for(int i=0; i<4; i++) + { + dest->sidewarpscr[i]=src->sidewarpscr[i]; + dest->sidewarpdmap[i]=src->sidewarpdmap[i]; + } + + dest->sidewarpindex=src->sidewarpindex; + dest->undercombo=src->undercombo; + dest->undercset=src->undercset; + dest->catchall=src->catchall; + dest->flags=src->flags; + dest->flags2=src->flags2; + dest->flags3=src->flags3; + dest->flags4=src->flags4; + dest->flags5=src->flags5; + dest->flags6=src->flags6; + dest->flags7=src->flags7; + dest->flags8=src->flags8; + dest->flags9=src->flags9; + dest->flags10=src->flags10; + dest->csensitive=src->csensitive; + dest->noreset=src->noreset; + dest->nocarry=src->nocarry; + + for(int i=0; i<6; i++) + { + dest->layermap[i]=src->layermap[i]; + dest->layerscreen[i]=src->layerscreen[i]; + dest->layeropacity[i]=src->layeropacity[i]; + } + + dest->timedwarptics=src->timedwarptics; + dest->nextmap=src->nextmap; + dest->nextscr=src->nextscr; + + for(int i=0; i<128; i++) + { + dest->secretcombo[i]=src->secretcombo[i]; + dest->secretcset[i]=src->secretcset[i]; + dest->secretflag[i]=src->secretflag[i]; + } + + dest->data=src->data; + dest->sflag=src->sflag; + dest->cset=src->cset; + dest->viewX=src->viewX; + dest->viewY=src->viewY; + dest->scrWidth=src->scrWidth; + dest->scrHeight=src->scrHeight; + dest->ffcsUsed=src->ffcsUsed; + + for(int i=0; i<32; i++) + dest->ffcs[i].copy(src->ffcs[i], FFC::copy_full); + + dest->oceansfx=src->oceansfx; + dest->bosssfx=src->bosssfx; + dest->secretsfx=src->secretsfx; + dest->holdupsfx=src->holdupsfx; + dest->old_cpage=src->old_cpage; + dest->screen_midi=src->screen_midi; + dest->lens_layer=src->lens_layer; +} + +void zmap::put_door(BITMAP *dest,int pos,int side,int type,int xofs,int yofs,bool ignorepos, int scr) +{ + int x=0,y=0; + mapscr *doorscreen=(prv_mode?get_prvscr():screens+scr); + + switch(side) + { + case up: + case down: + x=((pos&15)<<4)+xofs; + y=(ignorepos?0:(pos&0xF0))+yofs; + break; + + case left: + case right: + x=(ignorepos?0:((pos&15)<<4))+xofs; + y=(pos&0xF0)+yofs; + break; + } + + switch(type) + { + case dt_lock: + case dt_shut: + case dt_boss: + case dt_bomb: + switch(side) + { + case up: + put_combo(dest,x,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_u[type][0], + DoorComboSets[doorscreen->door_combo_set].doorcset_u[type][0],0,0); + put_combo(dest,x+16,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_u[type][1], + DoorComboSets[doorscreen->door_combo_set].doorcset_u[type][1],0,0); + put_combo(dest,x,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_u[type][2], + DoorComboSets[doorscreen->door_combo_set].doorcset_u[type][2],0,0); + put_combo(dest,x+16,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_u[type][3], + DoorComboSets[doorscreen->door_combo_set].doorcset_u[type][3],0,0); + break; + + case down: + put_combo(dest,x,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_d[type][0], + DoorComboSets[doorscreen->door_combo_set].doorcset_d[type][0],0,0); + put_combo(dest,x+16,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_d[type][1], + DoorComboSets[doorscreen->door_combo_set].doorcset_d[type][1],0,0); + put_combo(dest,x,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_d[type][2], + DoorComboSets[doorscreen->door_combo_set].doorcset_d[type][2],0,0); + put_combo(dest,x+16,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_d[type][3], + DoorComboSets[doorscreen->door_combo_set].doorcset_d[type][3],0,0); + break; + + case left: + put_combo(dest,x,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][0], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][0],0,0); + put_combo(dest,x,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][2], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][2],0,0); + put_combo(dest,x,y+32,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][4], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][4],0,0); + + if(x+16 >= dest->w) + break; + + put_combo(dest,x+16,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][1], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][1],0,0); + put_combo(dest,x+16,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][3], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][3],0,0); + put_combo(dest,x+16,y+32,DoorComboSets[doorscreen->door_combo_set].doorcombo_l[type][5], + DoorComboSets[doorscreen->door_combo_set].doorcset_l[type][5],0,0); + break; + + case right: + + put_combo(dest,x+16,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][1], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][1],0,0); + put_combo(dest,x+16,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][3], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][3],0,0); + put_combo(dest,x+16,y+32,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][5], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][5],0,0); + + if(x+16 <= 0) + break; + + put_combo(dest,x,y,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][0], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][0],0,0); + put_combo(dest,x,y+16,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][2], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][2],0,0); + put_combo(dest,x,y+32,DoorComboSets[doorscreen->door_combo_set].doorcombo_r[type][4], + DoorComboSets[doorscreen->door_combo_set].doorcset_r[type][4],0,0); + break; + } + + break; + + case dt_pass: + case dt_wall: + case dt_walk: + default: + break; + } +} + +void zmap::over_door(BITMAP *dest,int pos,int side,int xofs,int yofs,bool, int scr) +{ + int x=((pos&15)<<4)+xofs; + int y=(pos&0xF0)+yofs; + mapscr *doorscreen=(prv_mode?get_prvscr():screens+scr); + + + switch(side) + { + case up: + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_u[0]!=0) + { + overcombo(dest,x,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_u[0], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_u[0]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_u[1]!=0) + { + overcombo(dest,x+16,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_u[1], + + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_u[1]); + } + + break; + + case down: + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_d[0]!=0) + { + overcombo(dest,x,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_d[0], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_d[0]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_d[1]!=0) + { + overcombo(dest,x+16,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_d[1], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_d[1]); + } + + break; + + case left: + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[0]!=0) + { + overcombo(dest,x,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[0], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_l[0]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[1]!=0) + { + overcombo(dest,x,y+16, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[1], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_l[1]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[2]!=0) + { + overcombo(dest,x,y+32, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_l[2], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_l[2]); + } + + break; + + case right: + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[0]!=0) + { + overcombo(dest,x,y, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[0], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_r[0]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[1]!=0) + { + overcombo(dest,x,y+16, + + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[1], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_r[1]); + } + + if(DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[2]!=0) + { + overcombo(dest,x,y+32, + DoorComboSets[doorscreen->door_combo_set].bombdoorcombo_r[2], + DoorComboSets[doorscreen->door_combo_set].bombdoorcset_r[2]); + } + + break; + } +} + +bool zmap::misaligned(int map, int scr, int i, int dir) +{ + word cmbcheck1, cmbcheck2; + newcombo combocheck1, combocheck2; + combocheck1 = combobuf[0]; + combocheck2 = combobuf[0]; + combocheck1.walk = 0; + combocheck2.walk = 0; + + int layermap, layerscreen; + + switch(dir) + { + case up: + if(i>15) //not top row of combos + { + return false; + } + + if(scr<16) //top row of screens + { + return false; + + } + + //check main screen + cmbcheck1 = vbound(AbsoluteScr(map, scr)->data[i], 0, MAXCOMBOS-1); + cmbcheck2 = vbound(AbsoluteScr(map, scr-16)->data[i+160], 0, MAXCOMBOS-1); + combocheck1.walk|=combobuf[cmbcheck1].walk; + combocheck2.walk|=combobuf[cmbcheck2].walk; + + //check layer 1 + layermap=AbsoluteScr(map, scr)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr-16)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i+160]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + //check layer 2 + layermap=AbsoluteScr(map, scr)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr-16)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i+160]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + if(((combocheck1.walk&5)*2)!=(combocheck2.walk&10)) + { + return true; + } + + break; + + case down: + if(i<160) //not bottom row of combos + { + return false; + } + + if(scr>111) //bottom row of screens + { + return false; + } + + //check main screen + cmbcheck1 = vbound(AbsoluteScr(map, scr)->data[i], 0, MAXCOMBOS-1); + cmbcheck2 = vbound(AbsoluteScr(map, scr+16)->data[i-160], 0, MAXCOMBOS-1); + combocheck1.walk|=combobuf[cmbcheck1].walk; + combocheck2.walk|=combobuf[cmbcheck2].walk; + + + //check layer 1 + layermap=AbsoluteScr(map, scr)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr+16)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i-160]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + //check layer 2 + layermap=AbsoluteScr(map, scr)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr+16)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i-160]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + if((combocheck1.walk&10)!=((combocheck2.walk&5)*2)) + { + return true; + } + + break; + + case left: + if((i&0xF)!=0) //not left column of combos + { + return false; + } + + if((scr&0xF)==0) //left column of screens + { + return false; + } + + //check main screen + cmbcheck1 = AbsoluteScr(map, scr)->data[i]; + cmbcheck2 = AbsoluteScr(map, scr-1)->data[i+15]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + combocheck2.walk|=combobuf[cmbcheck2].walk; + + //check layer 1 + layermap=AbsoluteScr(map, scr)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr-1)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i+15]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + //check layer 2 + layermap=AbsoluteScr(map, scr)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr-1)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i+15]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + if(((combocheck1.walk&3)*4)!=(combocheck2.walk&12)) + { + return true; + } + + break; + + case right: + + if((i&0xF)!=15) //not right column of combos + { + return false; + } + + if((scr&0xF)==15) //right column of screens + { + return false; + } + + //check main screen + cmbcheck1 = AbsoluteScr(map, scr)->data[i]; + cmbcheck2 = AbsoluteScr(map, scr+1)->data[i-15]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + combocheck2.walk|=combobuf[cmbcheck2].walk; + + //check layer 1 + layermap=AbsoluteScr(map, scr)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr+1)->layermap[0]-1; + + if(layermap>-1 && layermaplayerscreen[0]; + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i-15]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + //check layer 2 + layermap=AbsoluteScr(map, scr)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + cmbcheck1 = AbsoluteScr(layermap, layerscreen)->data[i]; + combocheck1.walk|=combobuf[cmbcheck1].walk; + } + + layermap=AbsoluteScr(map, scr+1)->layermap[1]-1; + + if(layermap>-1 && layermaplayerscreen[1]; + + cmbcheck2 = AbsoluteScr(layermap, layerscreen)->data[i-15]; + combocheck2.walk|=combobuf[cmbcheck2].walk; + } + + if((combocheck1.walk&12)!=((combocheck2.walk&3)*4)) + { + return true; + } + + break; + } + + return false; +} + +void zmap::check_alignments(BITMAP* dest,int x,int y,int scr) +{ + int checkcombo; + + if(alignment_arrow_timer>31) + { + if(scr<0) + { + scr=currscr; + } + + if((scr<128)) //do the misalignment arrows + { + for(checkcombo=1; checkcombo<15; checkcombo++) //check the top row (except the corners) + { + if(misaligned(currmap, scr, checkcombo, up)) + { + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,0*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + } + } + + for(checkcombo=161; checkcombo<175; checkcombo++) //check the top row (except the corners) + { + if(misaligned(currmap, scr, checkcombo, down)) + { + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,1*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + } + } + + for(checkcombo=16; checkcombo<160; checkcombo+=16) //check the left side (except the corners) + { + if(misaligned(currmap, scr, checkcombo, left)) + { + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,2*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + } + } + + for(checkcombo=31; checkcombo<175; checkcombo+=16) //check the right side (except the corners) + { + if(misaligned(currmap, scr, checkcombo, right)) + { + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,3*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + } + } + + int tempalign; + + //check top left corner + checkcombo=0; + tempalign=0; + tempalign+=(misaligned(currmap, scr, checkcombo, up))?1:0; + tempalign+=(misaligned(currmap, scr, checkcombo, left))?2:0; + + switch(tempalign) + { + case 0: + break; + + case 1: //up + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,0*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 2: //left + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,2*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 3: //up-left + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,4*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + } + + //check top right corner + checkcombo=15; + tempalign=0; + tempalign+=(misaligned(currmap, scr, checkcombo, up))?1:0; + tempalign+=(misaligned(currmap, scr, checkcombo, right))?2:0; + + switch(tempalign) + { + case 0: + break; + + case 1: //up + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,0*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 2: //right + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,3*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 3: //up-right + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,5*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + } + + //check bottom left corner + checkcombo=160; + tempalign=0; + tempalign+=(misaligned(currmap, scr, checkcombo, down))?1:0; + tempalign+=(misaligned(currmap, scr, checkcombo, left))?2:0; + + switch(tempalign) + { + case 0: + break; + + case 1: //down + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,1*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 2: //left + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,2*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 3: //down-left + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,6*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + } + + //check bottom right corner + + checkcombo=175; + tempalign=0; + tempalign+=(misaligned(currmap, scr, checkcombo, down))?1:0; + tempalign+=(misaligned(currmap, scr, checkcombo, right))?2:0; + + switch(tempalign) + { + case 0: + break; + + case 1: //down + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,1*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 2: //right + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,3*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + + case 3: //down-right + masked_blit((BITMAP*)zcdata[BMP_ARROWS].dat,dest,7*17+1,1,((checkcombo&15)<<4)+x,(checkcombo&0xF0)+y,16,16); + break; + } + } + } +} + +// Takes array index layer num., not actual layer num. +int zmap::MAPCOMBO2(int lyr,int x,int y, int map, int scr) +{ + if(lyr<=-1) return MAPCOMBO(x,y,map,scr); + + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr *screen1; + + if(prv_mode) + { + screen1=get_prvscr(); + } + else + { + screen1=AbsoluteScr(currmap,currscr); + } + + int layermap; + layermap=screen1->layermap[lyr]-1; + + if(layermap<0 || layermap >= map_count) return 0; + + mapscr *layer; + + if(prv_mode) + layer = &prvlayers[lyr]; + else + layer = AbsoluteScr(layermap,screen1->layerscreen[lyr]); + + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return layer->data[combo]; +} + +int zmap::MAPCOMBO(int x,int y, int map, int scr) //map=-1,scr=-1 +{ + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr *screen1; + + if(prv_mode) + { + screen1=get_prvscr(); + } + else + { + screen1=AbsoluteScr(currmap,currscr); + } + + x = vbound(x, 0, 16*16); + y = vbound(y, 0, 11*16); + int combo = COMBOPOS(x,y); + + if(combo>175 || combo < 0) + return 0; + + return screen1->data[combo]; +} + +void zmap::draw(BITMAP* dest,int x,int y,int flags,int map,int scr) +{ + int antiflags=flags&~cFLAGS; + + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr *layer; + + if(prv_mode) + { + layer=get_prvscr(); + } + else + { + layer=AbsoluteScr(map,scr); + } + + int layermap, layerscreen; + layermap=layer->layermap[CurrentLayer-1]-1; + + if(layermap<0) + { + CurrentLayer=0; + } + + if(!(layer->valid&mVALID)) + { + // rectfill(dest,x,y,x+255,y+175,dvc(0+1)); + rectfill(dest,x,y,x+255,y+175,vc(1)); + + if(ShowMisalignments) + { + check_alignments(dest,x,y,scr); + } + + return; + } + + resize_mouse_pos=true; + + for(int k=1; k<3; k++) + { + if(k==1&&layer->flags7&fLAYER2BG) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],antiflags,0); + } + } + else + { + for(int i=0; i<176; i++) + { + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],antiflags,0); + } + } + } + } + } + + if(k==2&&layer->flags7&fLAYER3BG) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + if(!(layer->flags7&fLAYER2BG)) + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],antiflags,0); + else overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + if(!(layer->flags7&fLAYER2BG)) + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],antiflags,0); + else overcombotranslucent(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + } + } + } + } + } + + if(LayerMaskInt[0]!=0) + { + for(int i=0; i<176; i++) + { + word cmbdat = layer->data[i]; + byte cmbcset = layer->cset[i]; + int cmbflag = layer->sflag[i]; + + if(layer->flags7&fLAYER3BG||layer->flags7&fLAYER2BG) + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,cmbdat,cmbcset); + else put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,cmbdat,cmbcset,antiflags,cmbflag); + } + } + else + { + rectfill(dest,x,y,x+255,y+175,0); + } + + // int cs=2; + + for(int k=0; k<2; k++) + { + if(k==1&&layer->flags7&fLAYER2BG) continue; + + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + } + } + } + + if(k==0) + { + for(int i=31; i>=0; i--) + { + if(layer->ffcs[i].data) + { + if(!(layer->ffcs[i].flags&ffCHANGER)) + { + if(!(layer->ffcs[i].flags&ffOVERLAY)) + { + int tx=(layer->ffcs[i].x/10000)+x; + int ty=(layer->ffcs[i].y/10000)+y; + + if(layer->ffcs[i].flags&ffTRANS) + { + overcomboblocktranslucent(dest, tx, ty, layer->ffcs[i].data, layer->ffcs[i].cset,layer->ffcs[i].getTileWidth(), layer->ffcs[i].getTileHeight(),128); + //overtiletranslucent16(dest, combo_tile(layer->ffdata[i],tx,ty)+(j*20)+(l), tx, ty, layer->ffcset[i], combobuf[layer->ffdata[i]].flip, 128); + } + else + { + overcomboblock(dest, tx, ty, layer->ffcs[i].data, layer->ffcs[i].cset, layer->ffcs[i].getTileWidth(), layer->ffcs[i].getTileHeight()); + //overtile16(dest, combo_tile(layer->ffdata[i],tx,ty)+(j*20)+(l), tx, ty, layer->ffcset[i], combobuf[layer->ffdata[i]].flip); + } + } + } + } + } + } + } + + int doortype[4]; + + for(int i=0; i<4; i++) + { + switch(layer->door[i]) + { + case dOPEN: + doortype[i]=dt_pass; + break; + + case dLOCKED: + doortype[i]=dt_lock; + break; + + case d1WAYSHUTTER: + case dSHUTTER: + doortype[i]=dt_shut; + break; + + case dBOSS: + doortype[i]=dt_boss; + break; + + case dBOMB: + doortype[i]=dt_bomb; + break; + } + } + + switch(layer->door[up]) + { + case dBOMB: + over_door(dest,39,up,x,y,false, scr); + + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,7,up,doortype[up],x,y,false,scr); + break; + + case dWALK: + if(get_bit(DoorComboSets[screens[currscr].door_combo_set].flags,df_walktrans)) + { + overcombo(dest,((23&15)<<4)+8+x,(23&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[0], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[0]); + } + else + + { + put_combo(dest,((23&15)<<4)+8+x,(23&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[0], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[0],0,0); + } + + break; + } + + switch(layer->door[down]) + { + case dBOMB: + over_door(dest,135,down,x,y,false,scr); + + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,151,down,doortype[down],x,y,false,scr); + break; + + case dWALK: + if(get_bit(DoorComboSets[screens[currscr].door_combo_set].flags,df_walktrans)) + { + overcombo(dest,((151&15)<<4)+8+x,(151&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[1], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[1]); + } + else + { + put_combo(dest,((151&15)<<4)+8+x,(151&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[1], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[1],0,0); + } + + break; + } + + switch(layer->door[left]) + { + case dBOMB: + over_door(dest,66,left,x,y,false,scr); + + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,64,left,doortype[left],x,y,false,scr); + break; + + case dWALK: + if(get_bit(DoorComboSets[screens[currscr].door_combo_set].flags,df_walktrans)) + { + overcombo(dest,((81&15)<<4)+x,(81&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[2], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[2]); + } + else + { + put_combo(dest,((81&15)<<4)+x,(81&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[2], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[2],0,0); + } + + break; + } + + switch(layer->door[right]) + { + + case dBOMB: + over_door(dest,77,right,x,y,false,scr); + + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,78,right,doortype[right],x,y,false,scr); + break; + + case dWALK: + if(get_bit(DoorComboSets[screens[currscr].door_combo_set].flags,df_walktrans)) + { + overcombo(dest,((94&15)<<4)+x,(94&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[3], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[3]); + } + else + { + put_combo(dest,((94&15)<<4)+x,(94&0xF0)+y, + DoorComboSets[screens[currscr].door_combo_set].walkthroughcombo[3], + DoorComboSets[screens[currscr].door_combo_set].walkthroughcset[3],0,0); + } + + break; + } + + if((layer->hasitem != 0) && !(flags&cNOITEM)) + { + frame=0; + putitem2(dest,layer->itemx+x,layer->itemy+y+1-(get_bit(quest_rules, qr_NOITEMOFFSET)),layer->item,lens_hint_item[layer->item][0],lens_hint_item[layer->item][1], 0); + } + + for(int k=2; k<4; k++) + { + if(k==2&&layer->flags7&fLAYER3BG) continue; + + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + } + } + } + } + + if(LayerMaskInt[0]!=0) + { + for(int i=0; i<176; i++) + { + int ct1=layer->data[i]; + // int ct2=(ct1&0xFF)+(screens[currscr].cpage<<8); + int ct3=combobuf[ct1].type; + +// if (ct3==cOLD_OVERHEAD) + if(combo_class_buf[ct3].overhead) + { + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,layer->data[i],layer->cset[i]); + } + } + } + + for(int k=4; k<6; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]==255) + { + for(int i=0; i<176; i++) + { + overcombo(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i]); + } + } + else + { + for(int i=0; i<176; i++) + { + overcombotranslucent(dest,((i&15)<<4)+x,(i&0xF0)+y,prv_mode?prvlayers[k].data[i]:TheMaps[layerscreen].data[i],prv_mode?prvlayers[k].cset[i]:TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + } + } + } + + if(k==4) + { + for(int i=31; i>=0; i--) + { + if(layer->ffcs[i].data) + { + if(!(layer->ffcs[i].flags&ffCHANGER)) + { + if(layer->ffcs[i].flags&ffOVERLAY) + { + //overcombo(framebuf,(int)layer->ffx[i],(int)layer->ffy[i]+56,layer->ffdata[i],layer->ffcset[i]); + int tx=(layer->ffcs[i].x/10000)+x; + int ty=(layer->ffcs[i].y/10000)+y; + + if(layer->ffcs[i].flags&ffTRANS) + { + //overtiletranslucent16(dest, combo_tile(layer->ffdata[i],tx,ty)+(j*20)+(l), tx, ty, layer->ffcset[i], combobuf[layer->ffdata[i]].flip, 128); + overcomboblocktranslucent(dest,tx,ty,layer->ffcs[i].data, layer->ffcs[i].cset, layer->ffcs[i].getTileWidth(), layer->ffcs[i].getTileHeight(),128); + } + else + { + //overtile16(dest, combo_tile(layer->ffdata[i],tx,ty)+(j*20)+(l), tx, ty, layer->ffcset[i], combobuf[layer->ffdata[i]].flip); + overcomboblock(dest, tx, ty, layer->ffcs[i].data, layer->ffcs[i].cset, layer->ffcs[i].getTileWidth(), layer->ffcs[i].getTileHeight()); + } + } + } + } + } + } + + if(k==5) + { + for(int i=31; i>=0; i--) + { + if(layer->ffcs[i].data) + { + if(layer->ffcs[i].flags&ffCHANGER) + { + putpixel(dest,(layer->ffcs[i].x/10000)+x,(layer->ffcs[i].y/10000)+y,vc(rand()%16)); + } + } + } + } + } + + if(flags&cWALK) + { + if(LayerMaskInt[0]!=0) + { + for(int i=0; i<176; i++) + { + put_walkflags(dest,((i&15)<<4)+x,(i&0xF0)+y,layer->data[i], 0); + } + } + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=0; i<176; i++) + { + put_walkflags_layered(dest,((i&15)<<4)+x,(i&0xF0)+y,i, k); + } + } + } + } + } + + if(flags&cFLAGS) + { + if(LayerMaskInt[CurrentLayer]!=0) + { + for(int i=0; i<176; i++) + { + if(CurrentLayer==0) + { + put_flags(dest,((i&15)<<4)+x,(i&0xF0)+y,layer->data[i],layer->cset[i],flags,layer->sflag[i]); + } + else + { + if(prv_mode) + { + put_flags(dest,((i&15)<<4)+x,(i&0xF0)+y,prvlayers[CurrentLayer-1].data[i],prvlayers[CurrentLayer-1].cset[i],flags,prvlayers[CurrentLayer-1].sflag[i]); + } + else + { + int _lscr=(layer->layermap[CurrentLayer-1]-1)*MAPSCRS+layer->layerscreen[CurrentLayer-1]; + + if(_lscr>-1 && _lscrflags&cDARK; + + if(dark && !(flags&cNODARK)) + { + for(int j=0; j<80; j++) + { + for(int i=0; i<(80)-j; i++) + { + if(((i^j)&1)==0) + { + putpixel(dest,x+i,y+j,vc(blackout_color)); + } + } + } + } + + if(ShowMisalignments) + { + check_alignments(dest,x,y,scr); + } + + resize_mouse_pos=false; + +} + +void zmap::drawrow(BITMAP* dest,int x,int y,int flags,int c,int map,int scr) +{ + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr* layer=AbsoluteScr(map,scr); + int layermap=0, layerscreen=0; + + if(!(layer->valid&mVALID)) + { + // rectfill(dest,x,y,x+255,y+15,dvc(0+1)); + rectfill(dest,x,y,x+255,y+15,vc(1)); + return; + } + + int dark = layer->flags&4; + + resize_mouse_pos=true; + + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<(c&0xF0)+16; i++) + { + word cmbdat = (i < (int)layer->data.size() ? layer->data[i] : 0); + byte cmbcset = (i < (int)layer->data.size() ? layer->cset[i] : 0); + int cmbflag = (i < (int)layer->data.size() ? layer->sflag[i] : 0); + put_combo(dest,((i&15)<<4)+x,y,cmbdat,cmbcset,flags|dark,cmbflag); + } + } + else + { + rectfill(dest,x,y,x+255,y+15,0); + } + + // int cs=2; + + for(int k=1; k<3; k++) + { + if(LayerMaskInt[k+1]!=0 && (k==1)?(layer->flags7&fLAYER2BG):(layer->flags7&fLAYER3BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[2-1]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0 && !(k==1 && layer->flags7&fLAYER2BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + int doortype[4]; + + for(int i=0; i<4; i++) + { + switch(layer->door[i]) + { + case dOPEN: + doortype[i]=dt_pass; + break; + + case dLOCKED: + doortype[i]=dt_lock; + break; + + case d1WAYSHUTTER: + case dSHUTTER: + doortype[i]=dt_shut; + break; + + case dBOSS: + doortype[i]=dt_boss; + break; + + case dBOMB: + doortype[i]=dt_bomb; + break; + } + } + + if(c<16) + { + switch(layer->door[up]) + { + case dBOMB: + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,7,up,doortype[up],x,y+176,true,scr); + break; + } + } + else if(c>159) + { + switch(layer->door[down]) + { + case dBOMB: + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,151,down,doortype[down],x,y-16,true,scr); + break; + } + } + + for(int k=2; k<4; k++) + { + if(LayerMaskInt[k+1]!=0 && !(k==2 && layer->flags7&fLAYER3BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<(c&0xF0)+16; i++) + { + int ct1=layer->data[i]; + // int ct2=(ct1&0xFF)+(screens[currscr].cpage<<8); + int ct3=combobuf[ct1].type; + +// if (ct3==cOLD_OVERHEAD) + if(combo_class_buf[ct3].overhead) + { + overcombo(dest,((i&15)<<4)+x,y,layer->data[i],layer->cset[i]); + } + } + } + + for(int k=4; k<6; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,((i&15)<<4)+x,y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + if(flags&cWALK) + { + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<(c&0xF0)+16; i++) + { + put_walkflags(dest,((i&15)<<4)+x,y,layer->data[i],0); + } + } + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + put_walkflags_layered(dest,((i&15)<<4)+x,y,i, k); + } + } + } + } + } + + if(flags&cFLAGS) + { + if(LayerMaskInt[CurrentLayer]!=0) + { + for(int i=c; i<(c&0xF0)+16; i++) + { + if(CurrentLayer==0) + { + put_flags(dest,((i&15)<<4)+x,/*(i&0xF0)+*/y,layer->data[i],layer->cset[i],flags|dark,layer->sflag[i]); + } + else + { + int _lscr=(layer->layermap[CurrentLayer-1]-1)*MAPSCRS+layer->layerscreen[CurrentLayer-1]; + + if(_lscr>-1 && _lscrdata[i],layer->cset[i],flags|dark,layer->sflag[i]); + } + } + */ + } + + if(ShowMisalignments) + { + if(c<16) + { + check_alignments(dest,x,y,scr); + } + else if(c>159) + { + check_alignments(dest,x,y-160,scr); + } + } + + resize_mouse_pos=false; + +} + +void zmap::drawcolumn(BITMAP* dest,int x,int y,int flags,int c,int map,int scr) +{ + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr* layer=AbsoluteScr(map,scr); + int layermap=0, layerscreen=0; + + if(!(layer->valid&mVALID)) + { + // rectfill(dest,x,y,x+15,y+175,dvc(0+1)); + rectfill(dest,x,y,x+15,y+175,vc(1)); + return; + } + + int dark = layer->flags&4; + + resize_mouse_pos=true; + + + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<176; i+=16) + { + word cmbdat = layer->data[i]; + byte cmbcset = layer->cset[i]; + int cmbflag = layer->sflag[i]; + put_combo(dest,x,(i&0xF0)+y,cmbdat,cmbcset,flags|dark,cmbflag); + } + } + else + { + rectfill(dest,x,y,x+15,y+175,0); + } + + // int cs=2; + + for(int k=1; k<3; k++) + { + if(LayerMaskInt[k+1]!=0 && (k==1)?(layer->flags7&fLAYER2BG):(layer->flags7&fLAYER3BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[2-1]; + + for(int i=c; i<176; i+=16) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0 && !(k==1 && layer->flags7&fLAYER2BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<176; i+=16) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + int doortype[4]; + + for(int i=0; i<4; i++) + { + switch(layer->door[i]) + { + case dOPEN: + doortype[i]=dt_pass; + break; + + case dLOCKED: + doortype[i]=dt_lock; + break; + + case d1WAYSHUTTER: + case dSHUTTER: + doortype[i]=dt_shut; + break; + + case dBOSS: + doortype[i]=dt_boss; + break; + + case dBOMB: + doortype[i]=dt_bomb; + break; + } + } + + if((c&0x0F)==0) + { + switch(layer->door[left]) + { + + case dBOMB: + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + // put_door(dest,64,left,doortype[left],x+256,y,true); + put_door(dest,64,left,doortype[left],x,y,true,scr); + break; + } + } + else if((c&0x0F)==15) + { + switch(layer->door[right]) + { + case dBOMB: + case dOPEN: + case dLOCKED: + case d1WAYSHUTTER: + case dSHUTTER: + case dBOSS: + put_door(dest,78,right,doortype[right],x-16,y,true,scr); + break; + } + } + + for(int k=2; k<4; k++) + { + if(LayerMaskInt[k+1]!=0 && !(k==2 && layer->flags7&fLAYER3BG)) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<176; i+=16) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<176; i+=16) + { + int ct1=layer->data[i]; + // int ct2=(ct1&0xFF)+(screens[currscr].cpage<<8); + int ct3=combobuf[ct1].type; + +// if (ct3==cOLD_OVERHEAD) + if(combo_class_buf[ct3].overhead) + { + overcombo(dest,x,(i&0xF0)+y,layer->data[i],layer->cset[i]); + } + } + } + + for(int k=4; k<6; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<176; i+=16) + { + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i],layer->layeropacity[k]); + } + + else + { + overcombo(dest,x,(i&0xF0)+y,TheMaps[layerscreen].data[i],TheMaps[layerscreen].cset[i]); + } + } + } + } + } + + if(flags&cWALK) + { + if(LayerMaskInt[0]!=0) + { + for(int i=c; i<176; i+=16) + { + put_walkflags(dest,x,(i&0xF0)+y,layer->data[i],0); + } + } + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + for(int i=c; i<(c&0xF0)+16; i++) + { + put_walkflags_layered(dest,x,(i&0xF0)+y,i, k); + } + } + } + } + } + + if(flags&cFLAGS) + { + if(LayerMaskInt[CurrentLayer]!=0) + { + for(int i=c; i<176; i+=16) + { + if(CurrentLayer==0) + { + put_flags(dest,/*((i&15)<<4)+*/x,(i&0xF0)+y,layer->data[i],layer->cset[i],flags|dark,layer->sflag[i]); + } + else + { + int _lscr=(layer->layermap[CurrentLayer-1]-1)*MAPSCRS+layer->layerscreen[CurrentLayer-1]; + + if(_lscr>-1 && _lscrdata[i],layer->cset[i],flags|dark,layer->sflag[i]); + } + } + */ + } + + if(ShowMisalignments) + { + if((c&0x0F)==0) + { + check_alignments(dest,x,y,scr); + } + else if((c&0x0F)==15) + { + check_alignments(dest,x-240,y,scr); + } + } + + resize_mouse_pos=false; +} + +void zmap::drawblock(BITMAP* dest,int x,int y,int flags,int c,int map,int scr) +{ + if(map<0) + map=currmap; + + if(scr<0) + scr=currscr; + + mapscr* layer=AbsoluteScr(map,scr); + int layermap=0, layerscreen=0; + + if(!(layer->valid&mVALID)) + { + // rectfill(dest,x,y,x+15,y+15,dvc(0+1)); + rectfill(dest,x,y,x+15,y+15,vc(1)); + return; + } + + int dark = layer->flags&4; + + resize_mouse_pos=true; + + if(LayerMaskInt[0]!=0) + { + word cmbdat = layer->data[c]; + byte cmbcset = layer->cset[c]; + int cmbflag = layer->sflag[c]; + put_combo(dest,x,y,cmbdat,cmbcset,flags|dark,cmbflag); + } + else + { + rectfill(dest,x,y,x+15,y+15,0); + } + + // int cs=2; + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c]); + } + } + } + } + + for(int k=2; k<4; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c]); + } + } + } + } + + if(LayerMaskInt[0]!=0) + { + int ct1=layer->data[c]; + int ct3=combobuf[ct1].type; + +// if (ct3==cOLD_OVERHEAD) + if(combo_class_buf[ct3].overhead) + { + overcombo(dest,x,y,layer->data[c],layer->cset[c]); + } + } + + for(int k=4; k<6; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + + if(layer->layeropacity[k]<255) + { + overcombotranslucent(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c],layer->layeropacity[k]); + } + else + { + overcombo(dest,x,y,TheMaps[layerscreen].data[c],TheMaps[layerscreen].cset[c]); + } + } + } + } + + if(flags&cWALK) + { + if(LayerMaskInt[0]!=0) + { + put_walkflags(dest,x,y,layer->data[c],0); + } + + for(int k=0; k<2; k++) + { + if(LayerMaskInt[k+1]!=0) + { + layermap=layer->layermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + put_walkflags_layered(dest,x,y,c,k); + } + } + } + } + + if(flags&cFLAGS) + { + if(LayerMaskInt[CurrentLayer]!=0) + { + for(int i=c; i==c; i++) + { + if(CurrentLayer==0) + { + put_flags(dest,/*((i&15)<<4)+*/x,/*(i&0xF0)+*/y,layer->data[i],layer->cset[i],flags|dark,layer->sflag[i]); + } + else + { + int _lscr=(layer->layermap[CurrentLayer-1]-1)*MAPSCRS+layer->layerscreen[CurrentLayer-1]; + + if(_lscr>-1 && _lscrdata[c],layer->cset[c],flags|dark,layer->sflag[c]); + } + */ + } + + if(ShowMisalignments) + { + switch(c) + { + case 0: + check_alignments(dest,x,y,scr); + break; + + case 15: + check_alignments(dest,x-240,y,scr); + break; + + case 160: + check_alignments(dest,x,y-160,scr); + break; + + case 175: + check_alignments(dest,x-240,y-160,scr); + break; + } + } + + resize_mouse_pos=false; + +} + +void zmap::drawstaticblock(BITMAP* dest,int x,int y) +{ + if(InvalidStatic) + { + for(int dy=0; dy<16; dy++) + { + for(int dx=0; dx<16; dx++) + { + dest->line[y+dy][x+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(dest, x, y, x+15, y+15, vc(0)); + rect(dest, x, y, x+15, y+15, vc(15)); + line(dest, x, y, x+15, y+15, vc(15)); + line(dest, x, y+15, x+15, y, vc(15)); + } +} + +void zmap::drawstaticcolumn(BITMAP* dest,int x,int y) +{ + if(InvalidStatic) + { + for(int dy=0; dy<176; dy++) + { + for(int dx=0; dx<16; dx++) + { + dest->line[y+dy][x+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(dest, x, y, x+15, y+175, vc(0)); + rect(dest, x, y, x+15, y+175, vc(15)); + line(dest, x, y, x+15, y+175, vc(15)); + line(dest, x, y+175, x+15, y, vc(15)); + } +} + +void zmap::drawstaticrow(BITMAP* dest,int x,int y) +{ + if(InvalidStatic) + { + for(int dy=0; dy<16; dy++) + { + for(int dx=0; dx<256; dx++) + { + dest->line[y+dy][x+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(dest, x, y, x+255, y+15, vc(0)); + rect(dest, x, y, x+255, y+15, vc(15)); + line(dest, x, y, x+255, y+15, vc(15)); + line(dest, x, y+15, x+255, y, vc(15)); + } +} + +void zmap::draw_template(BITMAP* dest,int x,int y) +{ + for(int i=0; i<176; i++) + { + word cmbdat = screens[TEMPLATE].data[i]; + byte cmbcset = screens[TEMPLATE].cset[i]; + int cmbflag = screens[TEMPLATE].sflag[i]; + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,cmbdat,cmbcset,0,cmbflag); + } +} + +void zmap::draw_template2(BITMAP* dest,int x,int y) +{ + for(int i=0; i<176; i++) + { + word cmbdat = screens[TEMPLATE2].data[i]; + byte cmbcset = screens[TEMPLATE2].cset[i]; + int cmbflag = screens[TEMPLATE2].sflag[i]; + put_combo(dest,((i&15)<<4)+x,(i&0xF0)+y,cmbdat,cmbcset,0,cmbflag); + } +} + +void zmap::draw_secret(BITMAP *dest, int pos) +{ + word cmbdat = screens[TEMPLATE].data[pos]; + byte cmbcset = screens[TEMPLATE].cset[pos]; + int cmbflag = screens[TEMPLATE].sflag[pos]; + put_combo(dest,0,0,cmbdat,cmbcset,0,cmbflag); +} + +void zmap::draw_secret2(BITMAP *dest, int scombo) +{ + word cmbdat = screens[currscr].secretcombo[scombo]; + byte cmbcset = screens[currscr].secretcset[scombo]; + byte cmbflag = screens[currscr].secretflag[scombo]; + put_combo(dest,0,0,cmbdat,cmbcset,0,cmbflag); +} + +void zmap::scroll(int dir) +{ + if(currmapflags2&wfUP) + { + dowarp(1,Map.CurrScr()->sidewarpindex&3); + } + else if(currscr>15) + { + setCurrScr(currscr-16); + } + + break; + + case down: + if((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && Map.CurrScr()->flags2&wfDOWN) + { + dowarp(1,(Map.CurrScr()->sidewarpindex>>2)&3); + } + else if(currscrflags2&wfLEFT) + { + dowarp(1,(Map.CurrScr()->sidewarpindex>>4)&3); + } + else if(currscr&15) + { + setCurrScr(currscr-1); + } + + break; + + case right: + if((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && Map.CurrScr()->flags2&wfRIGHT) + { + dowarp(1,(Map.CurrScr()->sidewarpindex>>6)&3); + } + else if((currscr&15)<15 && currscrlayermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + copy_mapscr(&undomap[MAPSCRS+k], AbsoluteScr(layermap,layerscreen)); + } + } + + can_undo=true; +} + +void zmap::Uhuilai() +{ + mapscr *layer; + int layermap, layerscreen; + layer=AbsoluteScr(currmap,currscr); + + if(can_undo) + { + for(int x=0; xlayermap[k]-1; + + if(layermap>-1 && layermaplayerscreen[k]; + zc_swap(*AbsoluteScr(layermap,layerscreen),undomap[MAPSCRS+k]); + } + } + } +} + +void zmap::Copy() +{ + if(screens[currscr].valid&mVALID) + { + copy_mapscr(©mapscr, &screens[currscr]); + //copymapscr=screens[currscr]; + can_paste=true; + copymap=currmap; + copyscr=currscr; + copyffc = -1; + } +} + +void zmap::CopyFFC(int n) +{ + if(screens[currscr].valid&mVALID) + { + copy_mapscr(©mapscr, &screens[currscr]); + // Can't paste the screen itself + can_paste = false; + copymap=currmap; + copyscr=currscr; + copyffc = n; + } +} + +void zmap::Paste() +{ + if(can_paste) + { + Ugo(); + int oldcolor=getcolor(); + + if(!(screens[currscr].valid&mVALID)) + { + screens[currscr].valid |= mVALID; + screens[currscr].color = copymapscr.color; + } + + for(int i=0; i<4; i++) + { + putdoor(currscr,i,0); + } + + screens[currscr].door_combo_set = copymapscr.door_combo_set; + + for(int i=0; i<4; i++) + { + screens[currscr].door[i]=copymapscr.door[i]; + } + + for(int i=0; i<176; i++) + { + screens[currscr].data[i] = copymapscr.data[i]; + screens[currscr].cset[i] = copymapscr.cset[i]; + screens[currscr].sflag[i] = copymapscr.sflag[i]; + } + + for(int i=0; i<4; i++) + { + putdoor2(currscr,i,screens[currscr].door[i]); + } + + int newcolor=getcolor(); + loadlvlpal(newcolor); + + if(!(screens[currscr].valid&mVALID)) + { + newcolor=-1; + } + + if(newcolor!=oldcolor) + { + rebuild_trans_table(); + } + + saved=false; + } +} + +void zmap::PasteUnderCombo() +{ + if(can_paste) + { + Ugo(); + screens[currscr].undercombo = copymapscr.undercombo; + screens[currscr].undercset = copymapscr.undercset; + saved=false; + } +} + +void zmap::PasteSecretCombos() +{ + if(can_paste) + { + Ugo(); + + for(int i=0; i<128; i++) + { + screens[currscr].secretcombo[i] = copymapscr.secretcombo[i]; + screens[currscr].secretcset[i] = copymapscr.secretcset[i]; + screens[currscr].secretflag[i] = copymapscr.secretflag[i]; + } + + saved=false; + } +} + +void zmap::PasteFFCombos() +{ + if(can_paste) + { + Ugo(); + screens[currscr].ffcsUsed = copymapscr.ffcsUsed; + + for(int i=0; i<32; i++) + { + screens[currscr].ffcs[i].copy(copymapscr.ffcs[i], FFC::copy_full); + } + + saved=false; + } +} + +void zmap::PasteOneFFC(int i) //i - destination ffc slot +{ + if(copyffc < 0) // Sanity check + return; + + Ugo(); + screens[currscr].ffcs[i].copy(copymapscr.ffcs[copyffc], FFC::copy_pasteSingle); + + screens[currscr].ffcsUsed|=(1<=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + x=prvscr.data[i]; + y=animated_combo_table2[x][0]; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + if(newdata[i]==-1) + continue; + + prvscr.data[i]=newdata[i]; + prvscr.cset[i]=newcset[i]; + } + + for(int i=0; i<32; i++) + { + newdata[i]=-1; + newcset[i]=-1; + + x=prvscr.ffcs[i].data; + y=animated_combo_table[x][0]; + + //time to restart + if((animated_combo_table4[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; i<32; i++) + { + x=prvscr.ffcs[i].data; + y=animated_combo_table2[x][0]; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + } + } + + for(int i=0; i<32; i++) + { + if(newdata[i]==-1) + continue; + + prvscr.ffcs[i].data=newdata[i]; + prvscr.ffcs[i].cset=newcset[i]; + } + + if(get_bit(quest_rules,qr_CMBCYCLELAYERS)) + { + for(int j=0; j<6; j++) + { + if(prvlayers[j].data.empty()) + continue; + + for(int i=0; i<176; i++) + { + newdata[i]=-1; + newcset[i]=-1; + + x=(prvlayers[j]).data[i]; + y=animated_combo_table[x][0]; + + //time to restart + if((animated_combo_table4[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + x=(prvlayers[j]).data[i]; + y=animated_combo_table2[x][0]; + + //time to restart + if((animated_combo_table24[y][1]>=combobuf[x].speed) && + (combobuf[x].tile-combobuf[x].frames>=animated_combo_table2[x][1]-1) && + (combobuf[x].nextcombo!=0)) + { + newdata[i]=combobuf[x].nextcombo; + newcset[i]=combobuf[x].nextcset; + int c = newdata[i]; + + if(combobuf[c].animflags & AF_CYCLE) + { + restartanim2[c]=true; + } + } + } + + for(int i=0; i<176; i++) + { + if(newdata[i]==-1) + continue; + + prvlayers[j].data[i]=newdata[i]; + prvlayers[j].cset[i]=newcset[i]; + } + } + } + + for(int i=0; itimedwarptics; + } +} + +void zmap::dowarp2(int ring,int index) +{ + int dmap=misc.warp[ring].dmap[index]; + int scr=misc.warp[ring].scr[index]; + setCurrMap(DMaps[dmap].map); + setCurrScr(scr+DMaps[dmap].xoff); +} + +/******************************/ +/******** ZQuest stuff ********/ +/******************************/ + +bool save_msgstrs(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + if(writestrings(f, ZELDA_VERSION, VERSION_BUILD, 0, MAXMSGS)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool save_msgstrs_text(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + if(writestrings_text(f)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_msgstrs(const char *path, int startstring) +{ + //these are here to bypass compiler warnings about unused arguments + startstring=startstring; + + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + return false; + } + + if(section_id==ID_STRINGS) + { + if(readstrings(f, &header, true)==0) + { + pack_fclose(f); + return true; + } + else + { + pack_fclose(f); + return false; + } + } + + pack_fclose(f); + return false; +} + +bool save_pals(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + if(writecolordata(f, &misc, ZELDA_VERSION, VERSION_BUILD, 0, newerpdTOTAL)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_pals(const char *path, int startcset) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + return false; + } + + if(section_id==ID_CSETS) + { + if(readcolordata(f, &misc, ZELDA_VERSION, VERSION_BUILD, startcset, newerpdTOTAL-startcset, true)==0) + { + pack_fclose(f); + loadlvlpal(Color); + return true; + } + else + { + pack_fclose(f); + return false; + } + } + + return false; +} + +bool save_dmaps(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + if(writedmaps(f, ZELDA_VERSION, VERSION_BUILD, 0, MAXDMAPS)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_dmaps(const char *path, int startdmap) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + return false; + } + + if(section_id==ID_DMAPS) + { + if(readdmaps(f, NULL, ZELDA_VERSION, VERSION_BUILD, startdmap, MAXDMAPS-startdmap, true)==0) + { + pack_fclose(f); + return true; + } + else + { + pack_fclose(f); + return false; + } + } + + return false; +} +bool save_combos(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + reset_combo_animations(); + reset_combo_animations2(); + + if(writecombos(f, ZELDA_VERSION, VERSION_BUILD, 0, MAXCOMBOS)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_combos(const char *path, int startcombo) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + return false; + } + + if(section_id==ID_COMBOS) + { + if(readcombos(f, NULL, ZELDA_VERSION, VERSION_BUILD, startcombo, MAXCOMBOS-startcombo, true)==0) + { + pack_fclose(f); + return true; + } + else + { + pack_fclose(f); + // init_combos(true, &header); + return false; + } + } + + return false; +} + +bool save_tiles(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + // reset_combo_animations(); + if(writetiles(f, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_tiles(const char *path, int starttile) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + return false; + } + + if(section_id==ID_TILES) + { + if(readtiles(f, newtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, starttile, NEWMAXTILES-starttile, false, true)==0) + { + pack_fclose(f); + return true; + } + else + { + pack_fclose(f); + init_tiles(true, &header); + return false; + } + } + + return false; +} + +int writeguys(PACKFILE *f, zquestheader *Header); +bool save_guys(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + /* + int id = ID_GUYS; + if(!p_mputl(id,f)) + { + return false; + } + */ + + zquestheader h; + h.zelda_version = 0x250; + h.build = 21; + + if(writeguys(f, &h)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_guys(const char *path) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + zquestheader h; + h.zelda_version = 0x250; + h.build = 21; + + if(section_id==ID_GUYS) + { + if(readguys(f, &h, true)==0) + { + pack_fclose(f); + return true; + } + } + + pack_fclose(f); + return false; +} + + +//int writeguys(PACKFILE *f, zquestheader *Header); +bool save_combo_alias(const char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE, ""); + + if(!f) + { + return false; + } + + zquestheader h; + h.zelda_version = 0x250; + h.build = 21; + + if(writecomboaliases(f, 0, 0)==0) + { + pack_fclose(f); + return true; + } + + pack_fclose(f); + return false; +} + +bool load_combo_alias(const char *path) +{ + dword section_id; + PACKFILE *f = pack_fopen_password(path,F_READ, ""); + + if(!f) + { + return false; + } + + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + zquestheader h; + h.zelda_version = 0x250; + h.build = 21; + + if(section_id==ID_COMBOALIASES) + { + if(readcomboaliases(f, &h, 0, 0, true)==0) + { + pack_fclose(f); + return true; + } + } + + pack_fclose(f); + return false; +} + +bool load_zgp(const char *path) +{ + dword section_id; + dword section_version; + dword section_cversion; +// setPackfilePassword(NULL); + PACKFILE *f=pack_fopen_password(path,F_READ,""); + + if(!f) + return false; + + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id!=ID_GRAPHICSPACK) + { + pack_fclose(f); + return false; + } + + //section version info + if(!p_igetw(§ion_version,f,true)) + { + return 2; + } + + if(!p_igetw(§ion_cversion,f,true)) + { + return 3; + } + + //tiles + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_TILES) + { + if(readtiles(f, newtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false, true)!=0) + { + pack_fclose(f); + init_tiles(true, &header); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //combos + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_COMBOS) + { + if(readcombos(f, NULL, ZELDA_VERSION, VERSION_BUILD, 0, MAXCOMBOS, true)!=0) + { + pack_fclose(f); + // init_combos(true, &header); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //palettes + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_CSETS) + { + if(readcolordata(f, &misc, ZELDA_VERSION, VERSION_BUILD, 0, newerpdTOTAL, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //items + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_ITEMS) + { + if(readitems(f, ZELDA_VERSION, VERSION_BUILD, false, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //weapons + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_WEAPONS) + { + if(readweapons(f, &header, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //read the triforce pieces info and make sure it worked + //really do this? + + //read the game icons info and make sure it worked + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_ICONS) + { + if(readgameicons(f, &header, &misc, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //read the misc colors info and map styles info and make sure it worked + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_COLORS) + { + if(readmisccolors(f, &header, &misc, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //read the door combo sets and make sure it worked + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id==ID_DOORS) + { + if(readdoorcombosets(f, &header, true)!=0) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fclose(f); + return false; + } + + //read the template screens and make sure it worked + //really do this? + + //yay! it worked! close the file and say everything was ok. + loadlvlpal(Color); + setup_combo_animations(); + setup_combo_animations2(); + pack_fclose(f); + return true; +} + +bool save_zgp(const char *path) +{ +// jwin_alert("Error","This feature not yet implemented.",NULL,NULL,"O&K",NULL,'k',0,lfont); +// return false; + reset_combo_animations(); + reset_combo_animations2(); + + //open the file + PACKFILE *f=pack_fopen_password(path,F_WRITE, ""); + + if(!f) + return false; + + dword section_id=ID_GRAPHICSPACK; + dword section_version=V_GRAPHICSPACK; + dword section_cversion=CV_GRAPHICSPACK; + + //section id + if(!p_mputl(section_id,f)) + { + return 1; + } + + //section version info + if(!p_iputw(section_version,f)) + { + return 2; + } + + if(!p_iputw(section_cversion,f)) + { + return 3; + } + + //tiles + if(writetiles(f, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES)!=0) + { + pack_fclose(f); + return false; + } + + //combos + if(writecombos(f, ZELDA_VERSION, VERSION_BUILD, 0, MAXCOMBOS)!=0) + { + pack_fclose(f); + return false; + } + + //palettes + if(writecolordata(f, &misc, ZELDA_VERSION, VERSION_BUILD, 0, newerpdTOTAL)!=0) + { + pack_fclose(f); + return false; + } + + //items + if(writeitems(f, &header)!=0) + { + pack_fclose(f); + return false; + } + + //weapons + if(writeweapons(f, &header)!=0) + { + pack_fclose(f); + return false; + } + + //write the triforce pieces info and make sure it worked + //really do this? + + //write the game icons info and make sure it worked + if(writegameicons(f, &header, &misc)!=0) + { + pack_fclose(f); + return false; + } + + //write the misc colors info and map styles info and make sure it worked + if(writemisccolors(f, &header, &misc)!=0) + { + pack_fclose(f); + return false; + } + + //write the door combo sets and make sure it worked + if(writedoorcombosets(f, &header)!=0) + { + pack_fclose(f); + return false; + } + + //write the template screens and make sure it worked + //really do this? + + pack_fclose(f); + return true; +} + +bool save_subscreen(const char *path, bool *cancel) +{ +// jwin_alert("Error","This feature not yet implemented.",NULL,NULL,"O&K",NULL,'k',0,lfont); +// return false; + reset_combo_animations(); + reset_combo_animations2(); + *cancel = false; + + int ret; + sslist_dlg[0].dp2=lfont; + char *oldtitlestr=(char*)sslist_dlg[0].dp; + char *editstr=(char*)sslist_dlg[3].dp; + char *donestr=(char*)sslist_dlg[5].dp; + const char *newtitlestr="Export Subscreen"; + const char *okstr="OK"; + const char *cancelstr="Cancel"; + sslist_dlg[0].dp=(void *)newtitlestr; + sslist_dlg[3].dp=(void *)okstr; + sslist_dlg[4].proc = d_dummy_proc; + sslist_dlg[5].dp=(void *)cancelstr; + show_new_ss=false; + //strcpy((char*)sslist_dlg[3].dp,"Save"); + //strcpy((char*)sslist_dlg[4].dp,"Cancel"); + ret = zc_popup_dialog(sslist_dlg,2); + //strcpy((char*)sslist_dlg[3].dp,"Edit"); + //strcpy((char*)sslist_dlg[4].dp,"Done"); + sslist_dlg[0].dp=oldtitlestr; + sslist_dlg[3].dp=editstr; + sslist_dlg[4].proc = jwin_button_proc; + sslist_dlg[5].dp=donestr; + show_new_ss=true; + + if(ret==0||ret==5) + { + *cancel=true; + return true; + } + + //open the file + PACKFILE *f=pack_fopen_password(path,F_WRITE, ""); + + if(!f) + return false; + + dword section_id=ID_SUBSCREEN; + dword section_version=V_SUBSCREEN; + dword section_cversion=CV_SUBSCREEN; + + //section id + if(!p_mputl(section_id,f)) + { + pack_fclose(f); + return false; + } + + //section version info + if(!p_iputw(section_version,f)) + { + pack_fclose(f); + return false; + } + + if(!p_iputw(section_cversion,f)) + { + pack_fclose(f); + return false; + } + + //subscreens + if(write_one_subscreen(f,&header,sslist_dlg[2].d1)!=0) + { + pack_fclose(f); + return false; + } + + pack_fclose(f); + return true; +} + +bool load_subscreen(const char *path) +{ + int ret; + sslist_dlg[0].dp2=lfont; + char *oldtitlestr=(char*)sslist_dlg[0].dp; + char *editstr=(char*)sslist_dlg[3].dp; + char *donestr=(char*)sslist_dlg[5].dp; + const char *newtitlestr="Import Subscreen"; + const char *okstr="OK"; + const char *cancelstr="Cancel"; + sslist_dlg[0].dp=(void *)newtitlestr; + sslist_dlg[3].dp=(void *)okstr; + sslist_dlg[4].proc = d_dummy_proc; + sslist_dlg[5].dp=(void *)cancelstr; + //strcpy((char*)sslist_dlg[3].dp,"Write"); + //strcpy((char*)sslist_dlg[4].dp,"Cancel"); + ret = zc_popup_dialog(sslist_dlg,2); + //strcpy((char*)sslist_dlg[3].dp,"Edit"); + //strcpy((char*)sslist_dlg[4].dp,"Done"); + sslist_dlg[0].dp=(void *)oldtitlestr; + sslist_dlg[3].dp=(void *)editstr; + sslist_dlg[4].proc = jwin_button_proc; + sslist_dlg[5].dp=(void *)donestr; + + if(ret==0||ret==5) + { + return true; + } + + //open the file + PACKFILE *f=pack_fopen_password(path,F_READ, ""); + + if(!f) + return false; + + dword section_id; + dword section_version; + dword section_cversion; + + //section id + if(!p_mgetl(§ion_id,f,true)) + { + pack_fclose(f); + return false; + } + + if(section_id!=ID_SUBSCREEN) + { + pack_fclose(f); + return false; + } + + //section version info + if(!p_igetw(§ion_version,f,true)) + { + pack_fclose(f); + return false; + } + + if(!p_igetw(§ion_cversion,f,true)) + { + pack_fclose(f); + return false; + } + + //subscreens + if(read_one_subscreen(f,&header,true,sslist_dlg[2].d1,section_version,section_cversion)!=0) + { + pack_fclose(f); + return false; + } + + pack_fclose(f); + return true; +} + +bool setMapCount2(int c) +{ + int oldmapcount=map_count; + int currmap=Map.getCurrMap(); + + bound(c,1,MAXMAPS2); + map_count=c; + + try + { + TheMaps.resize(c*MAPSCRS); + } + catch(...) + { + jwin_alert("Error","Failed to change map count.",NULL,NULL,"O&K",NULL,'k',0,lfont); + return false; + } + + if(map_count>oldmapcount) + { + for(int mc=oldmapcount; mc=map_count) + { + DMaps[i].map=map_count-1; + } + } + } + + Map.setCurrMap(bound(currmap,0,c-1)); + + return true; +} + +extern BITMAP *bmap; + +int init_quest(const char *templatefile) +{ + char buf[2048]; + templatefile=templatefile; //here to prevent compiler warnings + load_quest("qst.dat#NESQST_NEW_QST",true,true); + sprintf(buf,"ZQuest - Untitled Quest"); + set_window_title(buf); + zinit.last_map = 0; + zinit.last_screen = 0; + + if(bmap != NULL) + { + destroy_bitmap(bmap); + bmap=NULL; + } + + return 0; +} + +void set_questpwd(const char *pwd, bool use_keyfile) +{ + //these are here to bypass compiler warnings about unused arguments + use_keyfile=use_keyfile; + + memset(header.password,0,256); + strcpy(header.password,pwd); + header.dirty_password=true; + + cvs_MD5Context ctx; + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)pwd, (unsigned)strlen(pwd)); + cvs_MD5Final(header.pwd_hash, &ctx); +} + + +bool is_null_pwd_hash(unsigned char *pwd_hash) +{ + cvs_MD5Context ctx; + unsigned char md5sum[16]; + char pwd[2]=""; + + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)pwd, (unsigned)strlen(pwd)); + cvs_MD5Final(md5sum, &ctx); + + return (memcmp(md5sum,pwd_hash,16)==0); +} + +static DIALOG pwd_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 224+22+1, 88+10+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Requires Authorization", NULL, NULL }, + { jwin_text_proc, 16, 28, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "File name:", NULL, NULL }, + // 2 (filename) + { jwin_text_proc, 72, 28, 128, 8, vc(11), vc(1), 0, 0, 24, 0, NULL, NULL, NULL }, + { jwin_text_proc, 16, 38, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Challenge:", NULL, NULL }, + // 4 (challenge hash) + { jwin_text_proc, 72, 38, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 16, 42+10, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Password:", NULL, NULL }, + // 6 (password) + { jwin_edit_proc, 72, 38+10, 120+39, 16, vc(12), vc(1), 0, 0, 255, 0, NULL, NULL, NULL }, + { jwin_button_proc, 42, 62+10, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 122, 62+10, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int reverse_string(char* str) +{ + + if(NULL==str) + { + return -1; //no std::string + } + + int l=(int)strlen(str)-1; //get the std::string length + + if(1==l) + { + return 1; + } + + char c; + + for(int x=0; x < l; x++,l--) + { + c = str[x]; + str[x] = str[l]; + str[l] = c; + } + + return 0; +} + + +int quest_access(const char *filename, zquestheader *hdr, bool compressed) +{ + //Protection against compiling a release version with password protection off. + static bool passguard = false; + +#if ( !(defined _DEBUG) || (defined _RELEASE || defined NDEBUG || defined _NDEBUG) ) +#define MUST_HAVE_PASSWORD + passguard = true; +#endif + +#if ( !(defined MUST_HAVE_PASSWORD) || defined _NPASS ) +#if (defined _MSC_VER || defined _NPASS) + assert(!passguard); + return 1; +#endif +#endif + + + char hash_string[33]; + + if(!compressed) + { + return 1; + } + + if((get_debug() && (!(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]))) || is_null_pwd_hash(hdr->pwd_hash)) + { + return 1; + } + + char pwd[256]; + char prompt[256]=""; + + char keyfilename[2048]; + replace_extension(keyfilename, filename, "key", 2047); + bool gotfromkey=false; + + if(exists(keyfilename)) + { + char password[256]; + PACKFILE *fp = pack_fopen_password(keyfilename, F_READ, ""); + char msg[80]; + memset(msg,0,80); + pfread(msg, 80, fp,true); + + if(strcmp(msg,"ZQuest Auto-Generated Quest Password Key File. DO NOT EDIT!")==0) + { + short ver = 0; + byte bld = 0; + short pwd_len; + p_igetw(&ver,fp,true); + p_getc(&bld,fp,true); + memset(password,0,256); + + if((ver > 0x211)||((ver == 0x211)&&(bld>1))) + { + pwd_len=256; + } + else + { + pwd_len=30; + } + + pfread(password, pwd_len, fp,true); + gotfromkey=check_questpwd(hdr, password); + memset(password,0,256); + memset(pwd,0,256); + } + + pack_fclose(fp); + } + + if(gotfromkey) + { + return true; + } + + pwd_dlg[0].dp2=lfont; + pwd_dlg[2].dp=get_filename(filename); + cvs_MD5Context ctx; + unsigned char md5sum[16]; + char response[33]; + + memcpy(md5sum, hdr->pwd_hash, 16); + + for(int i=0; i<300; ++i) + { + for(int j=0; j<16; ++j) + { + sprintf(response+j*2, "%02x", md5sum[j]); + } + + if(i&1) + { + reverse_string(response); + } + + if(i==149) + { + strcpy(hash_string, response); + } + + cvs_MD5Init(&ctx); + cvs_MD5Update(&ctx, (const unsigned char*)response, (unsigned)strlen(response)); + cvs_MD5Final(md5sum, &ctx); + } + + pwd_dlg[4].dp=hash_string; + + if(get_debug() && (key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])) + { + sprintf(prompt,"%s",response); + } + + pwd_dlg[6].dp=prompt; + + if(is_large) + large_dialog(pwd_dlg); + + int cancel = zc_popup_dialog(pwd_dlg,6); + + if(cancel == 8) + return 2; + + bool ret=check_questpwd(hdr, prompt); + + if(!ret) + { + ret=(strcmp(response,prompt)==0); + } + + memset(pwd,0,256); + return ret ? 1 : 0; +} + +// wrapper to reinitialize everything on an error +int load_quest(const char *filename, bool compressed, bool encrypted) +{ + char buf[2048]; +// if(encrypted) +// setPackfilePassword(datapwd); + byte skip_flags[4]; + + for(int i=0; i<4; ++i) + { + skip_flags[i]=0; + } + + int ret=loadquest(filename,&header,&misc,customtunes,true,compressed,encrypted,true,skip_flags); +// setPackfilePassword(NULL); + + if(ret!=qe_OK) + { + init_quest(NULL); + } + else + { + int accessret = quest_access(filename, &header, compressed); + + if(accessret != 1) + { + init_quest(NULL); + + if(accessret == 0) + ret=qe_pwd; + else + ret=qe_cancel; + } + else + { + Map.setCurrMap(vbound(Map.getCurrMap(),0,map_count-1)); + refresh(rALL); + refresh_pal(); + + if(bmap != NULL) + { + destroy_bitmap(bmap); + bmap=NULL; + } + + sprintf(buf,"ZQuest - [%s]", get_filename(filename)); +// if (compressed) + { + set_window_title(buf); + } + } + } + + return ret; +} + +bool write_midi(MIDI *m,PACKFILE *f) +{ + int c; + + if(!p_mputw(m->divisions,f)) return false; + + for(c=0; ctrack[c].len,f)) return false; + + if(m->track[c].len > 0) + { + if(!pfwrite(m->track[c].data,m->track[c].len,f)) + return false; + } + } + + return true; +} + +bool write_music(int format, MIDI* m, PACKFILE *f) +{ + // format - data format (midi, nsf, ...) + // m - pointer to data. + + int c; + + switch(format) + { + case MFORMAT_MIDI: + + if(!p_mputw(m->divisions,f)) return false; + + for(c=0; ctrack[c].len,f)) return false; + + if(m->track[c].len > 0) + { + if(!pfwrite(m->track[c].data,m->track[c].len,f)) + return false; + } + } + + break; + + case MFORMAT_NSF: + + break; + + default: + return false; + break; + } + + return true; +} + +int writeheader(PACKFILE *f, zquestheader *Header) +{ + dword section_id=ID_HEADER; + dword section_version=V_HEADER; + dword section_cversion=CV_HEADER; + dword section_size=0; + + //file header std::string + if(!pfwrite(Header->id_str,sizeof(Header->id_str),f)) + { + new_return(1); + } + + //section id + if(!p_mputl(section_id,f)) + { + new_return(2); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(3); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(4); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(5); + } + + writesize=0; + + //finally... section data + if(!p_iputw(Header->zelda_version,f)) + { + new_return(6); + } + + if(!p_putc(Header->build,f)) + { + new_return(7); + } + + if(!pfwrite(Header->pwd_hash,sizeof(Header->pwd_hash),f)) + { + new_return(8); + } + + if(!p_iputw(Header->internal,f)) + { + new_return(10); + } + + if(!p_putc(Header->quest_number,f)) + { + new_return(11); + } + + if(!pfwrite(Header->version,sizeof(Header->version),f)) + { + new_return(12); + } + + if(!pfwrite(Header->minver,sizeof(Header->minver),f)) + { + new_return(13); + } + + if(!pfwrite(Header->title,sizeof(Header->title),f)) + { + new_return(14); + } + + if(!pfwrite(Header->author,sizeof(Header->author),f)) + { + new_return(15); + } + + if(!p_putc(Header->use_keyfile,f)) + { + new_return(16); + } + + if(!pfwrite(Header->data_flags,sizeof(Header->data_flags),f)) + { + new_return(17); + } + + if(!pfwrite(Header->templatepath,sizeof(Header->templatepath),f)) + { + new_return(19); + } + + if(!p_putc(0,f)) //why are we doing this? + { + new_return(20); + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writeheader()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writerules(PACKFILE *f, zquestheader *Header) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_RULES; + dword section_version=V_RULES; + dword section_cversion=CV_RULES; + dword section_size=0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + if(!pfwrite(quest_rules,QUESTRULES_SIZE,f)) + { + new_return(5); + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writerules()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + + +int writedoorcombosets(PACKFILE *f, zquestheader *Header) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_DOORS; + dword section_version=V_DOORS; + dword section_cversion=CV_DOORS; + dword section_size=0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + if(!p_iputw(door_combo_set_count,f)) + { + new_return(5); + } + + for(int i=0; icolors.text,f)) + { + new_return(5); + } + + if(!p_putc(Misc->colors.caption,f)) + { + new_return(6); + } + + if(!p_putc(Misc->colors.overw_bg,f)) + { + new_return(7); + } + + if(!p_putc(Misc->colors.dngn_bg,f)) + { + new_return(8); + } + + if(!p_putc(Misc->colors.dngn_fg,f)) + { + new_return(9); + } + + if(!p_putc(Misc->colors.cave_fg,f)) + { + new_return(10); + } + + if(!p_putc(Misc->colors.bs_dk,f)) + { + new_return(11); + } + + if(!p_putc(Misc->colors.bs_goal,f)) + { + new_return(12); + } + + if(!p_putc(Misc->colors.compass_lt,f)) + { + new_return(13); + } + + if(!p_putc(Misc->colors.compass_dk,f)) + { + new_return(14); + } + + if(!p_putc(Misc->colors.subscr_bg,f)) + { + new_return(15); + } + + if(!p_putc(Misc->colors.triframe_color,f)) + { + new_return(16); + } + + if(!p_putc(Misc->colors.link_dot,f)) + { + new_return(17); + } + + if(!p_putc(Misc->colors.bmap_bg,f)) + { + new_return(18); + } + + if(!p_putc(Misc->colors.bmap_fg,f)) + { + new_return(19); + } + + if(!p_putc(Misc->colors.triforce_cset,f)) + { + new_return(20); + } + + if(!p_putc(Misc->colors.triframe_cset,f)) + { + new_return(21); + } + + if(!p_putc(Misc->colors.overworld_map_cset,f)) + { + new_return(22); + } + + if(!p_putc(Misc->colors.dungeon_map_cset,f)) + { + new_return(23); + } + + if(!p_putc(Misc->colors.blueframe_cset,f)) + { + new_return(24); + } + + if(!p_iputw(Misc->colors.triforce_tile,f)) + { + new_return(25); + } + + if(!p_iputw(Misc->colors.triframe_tile,f)) + { + new_return(26); + } + + if(!p_iputw(Misc->colors.overworld_map_tile,f)) + { + new_return(27); + } + + if(!p_iputw(Misc->colors.dungeon_map_tile,f)) + { + new_return(28); + } + + if(!p_iputw(Misc->colors.blueframe_tile,f)) + { + new_return(29); + } + + if(!p_iputw(Misc->colors.HCpieces_tile,f)) + { + new_return(30); + } + + if(!p_putc(Misc->colors.HCpieces_cset,f)) + { + new_return(31); + } + + if(!p_putc(Misc->colors.subscr_shadow,f)) + { + new_return(32); + } + + if(!p_putc(Misc->colors.msgtext,f)) + { + new_return(33); + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writemisccolors()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writegameicons(PACKFILE *f, zquestheader *Header, miscQdata *Misc) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_ICONS; + dword section_version=V_ICONS; + dword section_cversion=CV_ICONS; + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + for(int i=0; i<4; i++) + { + if(!p_iputw(Misc->icons[i],f)) + { + new_return(5); + } + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writegameicons()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writemisc(PACKFILE *f, zquestheader *Header, miscQdata *Misc) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_MISC; + dword section_version=V_MISC; + dword section_cversion=CV_MISC; + word shops=count_shops(Misc); + word infos=count_infos(Misc); + word warprings=count_warprings(Misc); + word triforces=8; + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //shops + if(!p_iputw(shops,f)) + { + new_return(5); + } + + for(int i=0; ishop[i].name,sizeof(Misc->shop[i].name),f)) + { + new_return(6); + } + + for(int j=0; j<3; j++) + { + if(!p_putc(Misc->shop[i].item[j],f)) + { + new_return(7); + } + } + + for(int j=0; j<3; j++) + { + if(!p_iputw(Misc->shop[i].price[j],f)) + { + new_return(8); + } + } + + for(int j=0; j<3; j++) + { + if(!p_putc(Misc->shop[i].hasitem[j],f)) + { + new_return(9); + } + } + } + + //infos + if(!p_iputw(infos,f)) + { + new_return(10); + } + + for(int i=0; iinfo[i].name,sizeof(Misc->info[i].name),f)) + { + new_return(11); + } + + for(int j=0; j<3; j++) + { + if(!p_iputw(Misc->info[i].str[j],f)) + { + new_return(12); + } + } + + for(int j=0; j<3; j++) + { + if(!p_iputw(Misc->info[i].price[j],f)) + { + new_return(13); + } + } + } + + //warp rings + if(!p_iputw(warprings,f)) + { + new_return(14); + } + + for(int i=0; iwarp[i].dmap[j],f)) + { + new_return(15); + } + } + + for(int j=0; j<9; j++) + { + if(!p_putc(Misc->warp[i].scr[j],f)) + { + new_return(16); + } + } + + if(!p_putc(Misc->warp[i].size,f)) + { + new_return(17); + } + } + + //triforce pieces + for(int i=0; itriforce[i],f)) + { + new_return(18); + } + } + + //end std::string + if(!p_iputw(Misc->endstring,f)) + { + new_return(19); + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writemisc()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writeitems(PACKFILE *f, zquestheader *Header) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_ITEMS; + dword section_version=V_ITEMS; + dword section_cversion=CV_ITEMS; + // dword section_size=0; + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + if(!p_iputw(iMax,f)) + { + new_return(5); + } + + for(int i=0; i=int(TheMaps.size())) + { + return qe_invalid; + } + + mapscr& screen=TheMaps.at(i*MAPSCRS+j); + + if(!p_putc(screen.valid,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.guy,f)) + { + return qe_invalid; + } + + { + if(!p_iputw(screen.str,f)) + { + return qe_invalid; + } + } + + if(!p_putc(screen.room,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.item,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.hasitem, f)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.tilewarptype[k],f)) + { + return qe_invalid; + } + } + + if(!p_iputw(screen.door_combo_set,f)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.warpreturnx[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.warpreturny[k],f)) + { + return qe_invalid; + } + } + + if(!p_iputw(screen.warpreturnc,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.stairx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.stairy,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.itemx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.itemy,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.color,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.enemyflags,f)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.door[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<4; k++) + { + if(!p_iputw(screen.tilewarpdmap[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.tilewarpscr[k],f)) + { + return qe_invalid; + } + } + + if(!p_putc(screen.tilewarpoverlayflags,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.exitdir,f)) + { + return qe_invalid; + } + + for(int k=0; k<10; k++) + { + { + if(!p_iputw(screen.enemy[k],f)) + { + return qe_invalid; + } + } + } + + if(!p_putc(screen.pattern,f)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.sidewarptype[k],f)) + { + return qe_invalid; + } + } + + if(!p_putc(screen.sidewarpoverlayflags,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.warparrivalx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.warparrivaly,f)) + { + return qe_invalid; + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.path[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<4; k++) + { + if(!p_putc(screen.sidewarpscr[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<4; k++) + { + if(!p_iputw(screen.sidewarpdmap[k],f)) + { + return qe_invalid; + } + } + + if(!p_putc(screen.sidewarpindex,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.undercombo,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.undercset,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.catchall,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags2,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags3,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags4,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags5,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.noreset,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.nocarry,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags6,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags7,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags8,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags9,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.flags10,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.csensitive,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.oceansfx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.bosssfx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.secretsfx,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.holdupsfx,f)) + { + return qe_invalid; + } + + for(int k=0; k<6; k++) + { + if(!p_putc(screen.layermap[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_putc(screen.layerscreen[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<6; k++) + { + if(!p_putc(screen.layeropacity[k],f)) + { + return qe_invalid; + } + } + + if(!p_iputw(screen.timedwarptics,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.nextmap,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.nextscr,f)) + { + return qe_invalid; + } + + for(int k=0; k<128; k++) + { + if(!p_iputw(screen.secretcombo[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<128; k++) + { + if(!p_putc(screen.secretcset[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<128; k++) + { + if(!p_putc(screen.secretflag[k],f)) + { + return qe_invalid; + } + } + + for(int k=0; k<(ZCMaps[i].tileWidth)*(ZCMaps[i].tileHeight); k++) + { + try + { + if(!p_iputw(screen.data.at(k),f)) + { + return qe_invalid; + } + } + catch(std::out_of_range& e) + { + return qe_invalid; + } + } + + for(int k=0; k<(ZCMaps[i].tileWidth)*(ZCMaps[i].tileHeight); k++) + { + try + { + if(!p_putc(screen.sflag.at(k),f)) + { + return qe_invalid; + } + } + catch(std::out_of_range& e) + { + return qe_invalid; + } + } + + for(int k=0; k<(ZCMaps[i].tileWidth)*(ZCMaps[i].tileHeight); k++) + { + try + { + if(!p_putc(screen.cset.at(k),f)) + { + return qe_invalid; + } + } + catch(std::out_of_range& e) + { + return qe_invalid; + } + } + + if(!p_iputw(screen.screen_midi,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.lens_layer,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcsUsed,f)) + { + return qe_invalid; + } + + for(int k=0; k<32; k++) + { + if((screen.ffcsUsed>>k)&1) + { + if(!p_iputw(screen.ffcs[k].data,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.ffcs[k].cset,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.ffcs[k].delay,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].x,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].y,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].xVel,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].yVel,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].xAccel,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].yAccel,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.ffcs[k].link,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.ffcs[k].width,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.ffcs[k].height,f)) + { + return qe_invalid; + } + + if(!p_iputl(screen.ffcs[k].flags,f)) + { + return qe_invalid; + } + + if(!p_iputw(screen.ffcs[k].script,f)) + { + return qe_invalid; + } + + for(int m=0; m<8; m++) + { + if(!p_iputl(screen.ffcs[k].initd[m],f)) + { + return qe_invalid; + } + } + + if(!p_putc(screen.ffcs[k].inita[0]/10000,f)) + { + return qe_invalid; + } + + if(!p_putc(screen.ffcs[k].inita[1]/10000,f)) + { + return qe_invalid; + } + } + } + + return qe_OK; +} + +int writemaps(PACKFILE *f, zquestheader *) +{ + dword section_id=ID_MAPS; + dword section_version=V_MAPS; + dword section_cversion=CV_MAPS; + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + if(!p_iputw(map_count,f)) + { + new_return(5); + } + + for(int i=0; icycles[i][j].first,f)) + { + new_return(16); + } + } + + for(int j=0; j<3; j++) + { + if(!p_putc(Misc->cycles[i][j].count,f)) + { + new_return(17); + } + } + + for(int j=0; j<3; j++) + { + if(!p_putc(Misc->cycles[i][j].speed,f)) + { + new_return(18); + } + } + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writecolordata()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writestrings(PACKFILE *f, word version, word build, word start_msgstr, word max_msgstrs) +{ + //these are here to bypass compiler warnings about unused arguments + version=version; + build=build; + start_msgstr=start_msgstr; + max_msgstrs=max_msgstrs; + + dword section_id=ID_STRINGS; + dword section_version=V_STRINGS; + dword section_cversion=CV_STRINGS; + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + if(!p_iputw(msg_count,f)) + { + return qe_invalid; + } + + for(int i=0; i msglistcache; + + for(int index = 1; index%d)___\n", str,MsgStrings[str].nextstring); + else + sprintf(ebuf,"\n\n___%d___\n", str); + + if(!pfwrite(&ebuf,(long)strlen(ebuf),f)) + { + return qe_invalid; + } + + encode_msg_str(str); + + if(!pfwrite(&msgbuf,(int)strlen(msgbuf),f)) + { + return qe_invalid; + } + } + } + + new_return(0); +} + + +int writetiles(PACKFILE *f, word version, word build, word start_tile, word max_tiles) +{ + //these are here to bypass compiler warnings about unused arguments + version=version; + build=build; + + word tiles_used; + dword section_id=ID_TILES; + dword section_version=V_TILES; + dword section_cversion=CV_TILES; + tiles_used = count_tiles(newtilebuf)-start_tile; + tiles_used = zc_min(tiles_used, max_tiles); + tiles_used = zc_min(tiles_used, NEWMAXTILES); + dword section_size = 0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + tiles_used=count_tiles(newtilebuf)-start_tile; + tiles_used=zc_min(tiles_used, max_tiles); + tiles_used=zc_min(tiles_used, NEWMAXTILES); + + if(!p_iputw(tiles_used,f)) + { + new_return(5); + } + + for(dword i=0; idata_flags[ZQ_CHEATS2],f)) + { + new_return(5); + } + + if(Header->data_flags[ZQ_CHEATS2]) + { + if(!p_iputl(zcheats.flags,f)) + { + new_return(6); + } + + if(!pfwrite(&zcheats.codes, sizeof(zcheats.codes), f)) + { + new_return(7); + } + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writecheats()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); +} + +int writeguys(PACKFILE *f, zquestheader *Header) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_GUYS; + dword section_version=V_GUYS; + dword section_cversion=CV_GUYS; + dword section_size=0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + //finally... section data + for(int i=0; i >::iterator it = ffcmap.begin(); it != ffcmap.end(); it++) + { + if(it->second.second != "") + { + numffcbindings++; + } + } + + if(!p_iputw(numffcbindings, f)) + { + new_return(2003); + } + + for(std::map >::iterator it = ffcmap.begin(); it != ffcmap.end(); it++) + { + if(it->second.second != "") + { + if(!p_iputw(it->first,f)) + { + new_return(2004); + } + + if(!p_iputl((long)it->second.second.size(), f)) + { + new_return(2005); + } + + if(!pfwrite((void *)it->second.second.c_str(), (long)it->second.second.size(),f)) + { + new_return(2006); + } + } + } + + word numglobalbindings=0; + + for(std::map >::iterator it = globalmap.begin(); it != globalmap.end(); it++) + { + if(it->second.second != "") + { + numglobalbindings++; + } + } + + if(!p_iputw(numglobalbindings, f)) + { + new_return(2007); + } + + for(std::map >::iterator it = globalmap.begin(); it != globalmap.end(); it++) + { + if(it->second.second != "") + { + if(!p_iputw(it->first,f)) + { + new_return(2008); + } + + if(!p_iputl((long)it->second.second.size(), f)) + { + new_return(2009); + } + + if(!pfwrite((void *)it->second.second.c_str(), (long)it->second.second.size(),f)) + { + new_return(2010); + } + } + } + + word numitembindings=0; + + for(std::map >::iterator it = itemmap.begin(); it != itemmap.end(); it++) + { + if(it->second.second != "") + { + numitembindings++; + } + } + + if(!p_iputw(numitembindings, f)) + { + new_return(2011); + } + + for(std::map >::iterator it = itemmap.begin(); it != itemmap.end(); it++) + { + if(it->second.second != "") + { + if(!p_iputw(it->first,f)) + { + new_return(2012); + } + + if(!p_iputl((long)it->second.second.size(), f)) + { + new_return(2013); + } + + if(!pfwrite((void *)it->second.second.c_str(), (long)it->second.second.size(),f)) + { + new_return(2014); + } + } + } + + if(writecycle==0) + { + section_size=writesize; + } + } + + if(writesize!=int(section_size) && save_warn) + { + char ebuf[80]; + sprintf(ebuf, "%d != %d", writesize, int(section_size)); + jwin_alert("Error: writeffscript()","writesize != section_size",ebuf,NULL,"O&K",NULL,'k',0,lfont); + } + + new_return(0); + //return 0; //this is just here to stomp the compiler from whining. + //the irony is that it causes an "unreachable code" warning. +} + +int write_one_ffscript(PACKFILE *f, zquestheader *Header, int i, ffscript **script) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + i=i; + + int num_commands; + + for(int j=0;; j++) + { + if((*script)[j].command==0xFFFF) + { + num_commands = j+1; + break; + } + } + + if(!p_iputl(num_commands,f)) + { + new_return(6); + } + + for(int j=0; j>3]; + +int writesfx(PACKFILE *f, zquestheader *Header) +{ + //these are here to bypass compiler warnings about unused arguments + Header=Header; + + dword section_id=ID_SFX; + dword section_version=V_SFX; + dword section_cversion=CV_SFX; + dword section_size=0; + + //section id + if(!p_mputl(section_id,f)) + { + new_return(1); + } + + //section version info + if(!p_iputw(section_version,f)) + { + new_return(2); + } + + if(!p_iputw(section_cversion,f)) + { + new_return(3); + } + + for(int writecycle=0; writecycle<2; ++writecycle) + { + fake_pack_writing=(writecycle==0); + + //section size + if(!p_iputl(section_size,f)) + { + new_return(4); + } + + writesize=0; + + for(int i=0; i>3; i++) + { + if(!p_putc(customsfxflag[i],f)) + { + new_return(5); + } + } + + for(int i=1; i0; --i) + { + sprintf(ext, "%s%d", ext1, i-1); + replace_extension(backupname, filepath, ext, 2047); + + if(exists(backupname)) + { + sprintf(ext, "%s%d", ext1, i); + replace_extension(backupname2, filepath, ext, 2047); + + if(exists(backupname2)) + { + remove(backupname2); + } + + rename(backupname, backupname2); + } + } + + //don't do this if we're not saving to the same name -DD + if(!timed_save && !strcmp(filepath, filename)) + { + sprintf(ext, "%s%d", ext1, 0); + replace_extension(backupname, filepath, ext, 2047); + rename(filepath, backupname); + } + } + + char *tmpfilename; + char tempfilestr[32]; // This is stupid... + + if(compress) + { + temp_name(tempfilestr); + tmpfilename=tempfilestr; + } + else + { + tmpfilename=(char *)filename; + } + + int ret; + ret = save_unencoded_quest(tmpfilename, compress); + + if(compress) + { + if(ret == 0) + { + box_out("Encrypting..."); + ret = encode_file_007(tmpfilename, filename,((INTERNAL_VERSION + rand()) & 0xffff) + 0x413F0000, ENC_STR, ENC_METHOD_MAX-1); + + if(ret) + { + ret += 100; + } + + box_out("okay."); + box_eol(); + } + + delete_file(tmpfilename); + } + + return ret; +} + +void center_zq_class_dialogs() +{ + jwin_center_dialog(pwd_dlg); +} + +void zmap::prv_secrets(bool high16only) +{ + mapscr *s = &prvscr; + mapscr *t = prvlayers; + int ft=0; + + for(int i=0; i<176; i++) + { + bool putit; + + if(!high16only) + { + for(int j=-1; j<6; j++) + { + int newflag = -1; + + for(int iter=0; iter<2; ++iter) + { + putit=true; + + if(t[j].data.empty()) + continue; + + int checkflag=combobuf[t[j].data[i]].flag; + + if(iter==1) + { + checkflag=t[j].sflag[i]; + } + + switch(checkflag) + { + case mfBCANDLE: + ft=sBCANDLE; + break; + + case mfRCANDLE: + ft=sRCANDLE; + break; + + case mfWANDFIRE: + ft=sWANDFIRE; + break; + + case mfDINSFIRE: + ft=sDINSFIRE; + break; + + case mfARROW: + ft=sARROW; + break; + + case mfSARROW: + ft=sSARROW; + break; + + case mfGARROW: + ft=sGARROW; + break; + + case mfSBOMB: + ft=sSBOMB; + break; + + case mfBOMB: + ft=sBOMB; + break; + + case mfBRANG: + ft=sBRANG; + break; + + case mfMBRANG: + ft=sMBRANG; + break; + + case mfFBRANG: + ft=sFBRANG; + break; + + case mfWANDMAGIC: + ft=sWANDMAGIC; + break; + + case mfREFMAGIC: + ft=sREFMAGIC; + break; + + case mfREFFIREBALL: + ft=sREFFIREBALL; + break; + + case mfSWORD: + ft=sSWORD; + break; + + case mfWSWORD: + ft=sWSWORD; + break; + + case mfMSWORD: + ft=sMSWORD; + break; + + case mfXSWORD: + ft=sXSWORD; + break; + + case mfSWORDBEAM: + ft=sSWORDBEAM; + break; + + case mfWSWORDBEAM: + ft=sWSWORDBEAM; + break; + + case mfMSWORDBEAM: + ft=sMSWORDBEAM; + break; + + case mfXSWORDBEAM: + ft=sXSWORDBEAM; + break; + + case mfHOOKSHOT: + ft=sHOOKSHOT; + break; + + case mfWAND: + ft=sWAND; + break; + + case mfHAMMER: + ft=sHAMMER; + break; + + case mfSTRIKE: + ft=sSTRIKE; + break; + + default: + putit = false; + break; + } + + if(putit) + { + if(j==-1) + { + s->data[i] = s->secretcombo[ft]; + s->cset[i] = s->secretcset[ft]; + newflag = s->secretflag[ft]; + } + else + { + t[j].data[i] = t[j].secretcombo[ft]; + t[j].cset[i] = t[j].secretcset[ft]; + newflag = t[j].secretflag[ft]; + } + } + } + + if(newflag >-1) + { + ((j==-1) ? s->sflag[i] : t[j].sflag[i]) = newflag; + } + } + } + + //if(true) + //{ + int newflag = -1; + + for(int iter=0; iter<2; ++iter) + { + int checkflag=combobuf[s->data[i]].flag; + + if(iter==1) + { + checkflag=s->sflag[i]; + } + + if((checkflag > 15)&&(checkflag < 32)) + { + s->data[i] = s->secretcombo[(checkflag)-16+4]; + s->cset[i] = s->secretcset[(checkflag)-16+4]; + newflag = s->secretflag[(checkflag)-16+4]; + // putit = true; + } + } + + if(newflag >-1) s->sflag[i] = newflag; + + for(int j=0; j<6; j++) + { + if(t[j].data.empty()||t[j].cset.empty()) continue; + + int newflag2 = -1; + + for(int iter=0; iter<2; ++iter) + { + int checkflag=combobuf[t[j].data[i]].flag; + + if(iter==1) + { + checkflag=t[j].sflag[i]; + } + + if((checkflag > 15)&&(checkflag < 32)) + { + t[j].data[i] = t[j].secretcombo[(checkflag)-16+4]; + t[j].cset[i] = t[j].secretcset[(checkflag)-16+4]; + newflag2 = t[j].secretflag[(checkflag)-16+4]; + // putit = true; + } + } + + if(newflag2 >-1) t[j].sflag[i] = newflag2; + } + + //} //if(true) + + /* + if(putit && refresh) + putcombo(scrollbuf,(i&15)<<4,i&0xF0,s->data[i],s->cset[i]); + */ + } + + //FFCs + for(int i=0; i<32; i++) + { + bool putit; + + if(!high16only) + { + for(int iter=0; iter<1; ++iter) + { + putit=true; + int checkflag=combobuf[s->ffcs[i].data].flag; + + if(iter==1) + { + checkflag=s->sflag[i]; + } + + switch(checkflag) + { + case mfBCANDLE: + ft=sBCANDLE; + break; + + case mfRCANDLE: + ft=sRCANDLE; + break; + + case mfWANDFIRE: + ft=sWANDFIRE; + break; + + case mfDINSFIRE: + ft=sDINSFIRE; + break; + + case mfARROW: + ft=sARROW; + break; + + case mfSARROW: + ft=sSARROW; + break; + + case mfGARROW: + ft=sGARROW; + break; + + case mfSBOMB: + ft=sSBOMB; + break; + + case mfBOMB: + ft=sBOMB; + break; + + case mfBRANG: + ft=sBRANG; + break; + + case mfMBRANG: + ft=sMBRANG; + break; + + case mfFBRANG: + ft=sFBRANG; + break; + + case mfWANDMAGIC: + ft=sWANDMAGIC; + break; + + case mfREFMAGIC: + ft=sREFMAGIC; + break; + + case mfREFFIREBALL: + ft=sREFFIREBALL; + break; + + case mfSWORD: + ft=sSWORD; + break; + + case mfWSWORD: + ft=sWSWORD; + break; + + case mfMSWORD: + ft=sMSWORD; + break; + + case mfXSWORD: + ft=sXSWORD; + break; + + case mfSWORDBEAM: + ft=sSWORDBEAM; + break; + + case mfWSWORDBEAM: + ft=sWSWORDBEAM; + break; + + case mfMSWORDBEAM: + ft=sMSWORDBEAM; + break; + + case mfXSWORDBEAM: + ft=sXSWORDBEAM; + break; + + case mfHOOKSHOT: + ft=sHOOKSHOT; + break; + + case mfWAND: + ft=sWAND; + break; + + case mfHAMMER: + ft=sHAMMER; + break; + + case mfSTRIKE: + ft=sSTRIKE; + break; + + default: + putit = false; + break; + } + + if(putit) + { + s->ffcs[i].data = s->secretcombo[ft]; + s->ffcs[i].cset = s->secretcset[ft]; + } + } + } + + if(!(s->flags2&fCLEARSECRET) || high16only || s->flags4&fENEMYSCRTPERM) + { + for(int iter=0; iter<1; ++iter) + { + int checkflag=combobuf[s->ffcs[i].data].flag; + + if(iter==1) + { + // FFCs can't have flags! Yet... + } + + if((checkflag > 15)&&(checkflag < 32)) + { + s->ffcs[i].data = s->secretcombo[checkflag-16+4]; + s->ffcs[i].cset = s->secretcset[checkflag-16+4]; + // putit = true; + } + } + } + } +} diff --git a/src/zq_class.h b/src/zq_class.h new file mode 100644 index 0000000000..58ab198d92 --- /dev/null +++ b/src/zq_class.h @@ -0,0 +1,265 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_class.cc +// +// Contains zmap class and other main code for ZQuest. +// +//-------------------------------------------------------- + +#ifndef _ZQ_CLASS_H_ +#define _ZQ_CLASS_H_ + +#include "zdefs.h" +#include + +#define COMBOPOS(x,y) (((y)&0xF0)+((x)>>4)) +#define COMBOX(pos) ((pos)%16*16) +#define COMBOY(pos) ((pos)&0xF0) + +void set_preview_mode(int prv); + +/************************/ +/****** ZMAP class ******/ +/************************/ + +void reset_dmap(int index); +//void mapfix_0x166(mapscr *scr); +bool setMapCount2(int c); +class zmap +{ + mapscr *screens; + int currmap,copymap; + int currscr,copyscr; + int copyffc; + int scrpos[MAXMAPS2+1]; + + mapscr copymapscr; + mapscr undomap[MAPSCRS+6]; + mapscr prvscr; //NEW + mapscr prvlayers[6]; + //int prv_mode; //NEW + int prv_cmbcycle, prv_map, prv_scr, prv_freeze, prv_advance, prv_time; //NEW + bool can_undo,can_paste,can_undo_map,can_paste_map,screen_copy; + // A screen which uses the current screen as a layer + int layer_target_map, layer_target_scr, layer_target_multiple; + +public: + + zmap(); + ~zmap(); + bool CanUndo(); + bool CanPaste(); + int CopyScr(); + int getCopyFFC(); + void Ugo(); + void Uhuilai(); + void Copy(); + void CopyFFC(int n); + void Paste(); + void PasteAll(); + void PasteToAll(); + void PasteAllToAll(); + void PasteUnderCombo(); + void PasteSecretCombos(); + void PasteFFCombos(); + void PasteOneFFC(int i); + void PasteWarps(); + void PasteScreenData(); + void PasteWarpLocations(); + void PasteDoors(); + void PasteLayers(); + void PasteRoom(); + void PasteGuy(); + void PastePalette(); + void PasteEnemies(); + void setCanPaste(bool _set); + void setCanUndo(bool _set); + void update_combo_cycling(); + void update_freeform_combos(); + int getMapCount(); + bool isDungeon(int scr); + bool isstepable(int combo); + bool ishookshottable(int bx, int by, int i); + int warpindex(int combo); + bool clearall(bool validate); + bool reset_templates(bool validate); + bool clearmap(bool newquest); + void clearscr(int scr); + void clearzcmap(int map); + int load(const char *path); + int save(const char *path); + int MAPCOMBO2(int lyr,int x,int y, int map = -1, int scr = -1); + int MAPCOMBO(int x,int y, int map = -1, int scr = -1); + void put_walkflags_layered(BITMAP *dest,int x,int y,int pos,int layer); + bool misaligned(int map, int scr, int i, int dir); + void check_alignments(BITMAP* dest,int x,int y,int scr=-1); + void draw(BITMAP *dest,int x,int y,int flags,int map,int scr); + void drawrow(BITMAP *dest,int x,int y,int flags,int c,int map,int scr); + void drawcolumn(BITMAP *dest,int x,int y,int flags,int c,int map,int scr); + void drawblock(BITMAP* dest,int x,int y,int flags,int c,int map,int scr); + void drawstaticblock(BITMAP* dest,int x,int y); + void drawstaticrow(BITMAP* dest,int x,int y); + void drawstaticcolumn(BITMAP* dest,int x,int y); + void draw_template(BITMAP *dest,int x,int y); + void draw_template2(BITMAP *dest,int x,int y); + void draw_secret(BITMAP *dest, int pos); + void draw_secret2(BITMAP *dest, int pos); + void scroll(int dir); + mapscr *CurrScr(); + mapscr *Scr(int scr); + mapscr *AbsoluteScr(int scr); + mapscr *AbsoluteScr(int map, int scr); + int getCurrMap(); + bool isDark(); + void setCurrMap(int index); + int getCurrScr(); + void setCurrScr(int scr); + void setlayertarget(); + void setcolor(int c); + int getcolor(); + void resetflags(); + word tcmbdat(int pos); + word tcmbcset(int pos); + int tcmbflag(int pos); + word tcmbdat2(int pos); + word tcmbcset2(int pos); + int tcmbflag2(int pos); + void put_door(BITMAP *dest,int pos,int side,int type,int xofs,int yofs,bool ignorepos, int scr); + void over_door(BITMAP *dest,int pos,int side,int xofs,int yofs,bool ignorepos, int scr); + void TemplateAll(); + void Template(int floorcombo, int floorcset); + void Template(int floorcombo, int floorcset, int scr); + void putdoor(int side,int door); + void putdoor2(int side,int door); + void putdoor(int scr,int side,int door); + void putdoor2(int scr,int side,int door); + void dowarp(int type, int index); + void prv_dowarp(int type, int index); + void dowarp2(int ring,int index); + void set_prvscr(int map, int scr); + mapscr* get_prvscr(); + void prv_secrets(bool); + int get_prv_map() + { + return prv_map; + } + int get_prv_scr() + { + return prv_scr; + } + void set_prvcmb(int set) + { + prv_cmbcycle=set; + } + int get_prvcmb() + { + return prv_cmbcycle; + } + void set_prvfreeze(int set) + { + prv_freeze=set; + } + int get_prvfreeze() + { + return prv_freeze; + } + void set_prvadvance(int set) + { + prv_advance=set; + } + int get_prvadvance() + { + return prv_advance; + } + void set_prvtime(int set) + { + prv_time=set; + } + int get_prvtime() + { + return prv_time; + } + int getLayerTargetMap(); + int getLayerTargetScr(); + int getLayerTargetMultiple(); +}; + +extern zmap Map; + +//bool read_old_mapfile(mapscr *scr, FILE *f); +extern const char *loaderror[]; + +void put_walkflags(BITMAP *dest,int x,int y,word cmbdat,int layer); +void put_flags(BITMAP *dest,int x,int y,word cmbdat,int cset,int flags,int sflag); +void put_combo(BITMAP *dest,int x,int y,word cmbdat,int cset,int flags,int sflag); +void copy_mapscr(mapscr *dest, const mapscr *src); +void delete_mapscr(mapscr *dest); + +/******************************/ +/******** ZQuest stuff ********/ +/******************************/ + +//word msg_count=0; +//const char zqsheader[30]; + +bool setMapCount2(int c); +int init_quest(const char *templatefile); +void set_questpwd(const char *pwd, bool use_keyfile); +int quest_access(const char *filename, zquestheader *hdr, bool compressed); +bool write_midi(MIDI *m,PACKFILE *f); +int load_quest(const char *filename, bool compressed, bool encrypted); +int save_unencoded_quest(const char *filename, bool compressed); +int save_quest(const char *filename, bool timed_save); + +int writemapscreen(PACKFILE *f, int i, int j); + +bool load_msgstrs(const char *path, int startstring); +bool save_msgstrs(const char *path); +bool save_msgstrs_text(const char *path); +int writestrings(PACKFILE *f, word version, word build, word start_msgstr, word max_msgstrs); +int writestrings_text(PACKFILE *f); + +bool load_pals(const char *path, int startcset); +bool save_pals(const char *path); +int writecolordata(PACKFILE *f, miscQdata *Misc, word version, word build, word start_cset, word max_csets); + +bool load_combos(const char *path, int startcombo); +bool save_combos(const char *path); +int writecombos(PACKFILE *f, word version, word build, word start_combo, word max_combos); +int writecomboaliases(PACKFILE *f, word version, word build); + +bool load_tiles(const char *path, int starttile); +bool save_tiles(const char *path); +int writetiles(PACKFILE *f, word version, word build, word start_tile, word max_tiles); + +bool load_dmaps(const char *path, int startdmap); +bool save_dmaps(const char *path); +int writedmaps(PACKFILE *f, word version, word build, word start_dmap, word max_dmaps); + +bool save_guys(const char *path); +bool load_guys(const char *path); + +bool load_zgp(const char *path); +bool save_zgp(const char *path); + +bool load_subscreen(const char *path); +bool save_subscreen(const char *path, bool *cancel); + +bool load_zqt(const char *path); +bool save_zqt(const char *path); + +void center_zq_class_dialogs(); + +int writeitems(PACKFILE *f, zquestheader *Header); +int writeweapons(PACKFILE *f, zquestheader *Header); +int writemisccolors(PACKFILE *f, zquestheader *Header, miscQdata *Misc); +int writegameicons(PACKFILE *f, zquestheader *Header, miscQdata *Misc); +int writedoorcombosets(PACKFILE *f, zquestheader *Header); +int write_one_subscreen(PACKFILE *f, zquestheader *Header, int i); +int writeffscript(PACKFILE *f, zquestheader *Header, bool keepdata); +int write_one_ffscript(PACKFILE *f, zquestheader *Header, int i, ffscript **script); +int writeitemdropsets(PACKFILE *f, zquestheader *Header); +int writefavorites(PACKFILE *f, zquestheader *Header); +#endif diff --git a/src/zq_cset.cpp b/src/zq_cset.cpp new file mode 100644 index 0000000000..2486a51d40 --- /dev/null +++ b/src/zq_cset.cpp @@ -0,0 +1,1662 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +//#include +#include +#include + +#include "gui.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "colors.h" +#include "pal.h" +#include "zquest.h" +#include "jwin.h" +#include "zsys.h" +#include "zq_tiles.h" +#include "zq_misc.h" +#include "zq_cset.h" + +#define edc 208 //246 +#define edi 209 //247 + +extern int d_dummy_proc(int msg,DIALOG *d,int c); +extern int d_dropdmaplist_proc(int msg,DIALOG *d,int c); +extern int onHelp(); +extern FONT *lfont; +extern int jwin_pal[jcMAX]; +extern const char *dmaplist(int index, int *list_size); +extern bool saved; +extern int dmap_list_size; +extern bool dmap_list_zero; +extern zinitdata zinit; +extern int startdmapxy[6]; +extern PALETTE RAMpal; + + +#include "gfxpal.h" + +int hue_x=96, hue_y=30, hue_h=16; +int light_x=74, light_y=52, light_w=16; +int sat_x=230, sat_y=52, sat_w=16; +int color_x=96, color_y=52, color_w=128, color_h=64; +int cset_x=96, cset_y=170, cset_h=8, cset_spacing=4; + +void get_cset(int dataset,int row,RGB *pal) +{ + saved=false; + + for(int i=0; i<16; i++) + { + colordata[(CSET(dataset)+i)*3] = pal[(row<<4)+i].r; + colordata[(CSET(dataset)+i)*3+1] = pal[(row<<4)+i].g; + colordata[(CSET(dataset)+i)*3+2] = pal[(row<<4)+i].b; + } +} + +void draw_edit_dataset_specs(int index,int copy) +{ + int window_xofs=0; + int window_yofs=0; + + if(is_large) + { + window_xofs=(zq_screen_w-480)>>1; + window_yofs=(zq_screen_h-360)>>1; + } + + jwin_draw_frame(screen, cset_x-2, cset_y+cset_h+cset_spacing-2, int(128*(is_large?1.5:1)+4), cset_h+4, FR_DEEP); + + for(int i=0; i<16; i++) + { + rectfill(screen,int((i<<3)*(is_large?1.5:1))+cset_x,cset_y+cset_h+cset_spacing,int((i<<3)*(is_large?1.5:1)+cset_x+cset_h-1),cset_y+cset_h+cset_spacing+cset_h-1,14*16+i); + } + + // text_mode(ed1); + rectfill(screen,int(96*(is_large?1.5:1)+window_xofs),int(193*(is_large?1.5:1)+window_yofs),int(223*(is_large?1.5:1)+window_xofs),int(220*(is_large?1.5:1)+window_yofs),jwin_pal[jcBOX]); + textout_ex(screen,(is_large?lfont_l:font),"\x88",int((index<<3)*(is_large?1.5:1)+cset_x),int(193*(is_large?1.5:1)+window_yofs),jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + + if(copy>=0) + { + textout_ex(screen,(is_large?lfont_l:font),"\x81",int((copy<<3)*(is_large?1.5:1)+cset_x),int(193*(is_large?1.5:1)+window_yofs),jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + } + + textprintf_ex(screen,(is_large?lfont_l:font),88*(is_large?2:1)+window_xofs,int(204*(is_large?1.5:1)+window_yofs),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old: %2d - %2d %2d %2d",index, RAMpal[12*16+index].r,RAMpal[12*16+index].g,RAMpal[12*16+index].b); + textprintf_ex(screen,(is_large?lfont_l:font),88*(is_large?2:1)+window_xofs,int(214*(is_large?1.5:1)+window_yofs),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New: %2d - %2d %2d %2d",index, RAMpal[14*16+index].r,RAMpal[14*16+index].g,RAMpal[14*16+index].b); +} + +void init_colormixer() +{ + jwin_draw_frame(screen, hue_x-2, hue_y-2, int(128*(is_large?1.5:1)+4), hue_h+4, FR_DEEP); + + for(int i=0; i<128; i++) + { + RAMpal[i] = _RGB(gfx_pal+i*3); //hue + rectfill(screen,int(floor(i*(is_large?1.5:1))+hue_x),hue_y,int(ceil(i*(is_large?1.5:1))+hue_x),hue_y+hue_h-1,i); + } + + jwin_draw_frame(screen, light_x-2, light_y-2, light_w+4, int(64*(is_large?1.5:1)+4), FR_DEEP); + + for(int i=0; i<32; i++) + { + RAMpal[i+128] = _RGB(i<<1,i<<1,i<<1); //lightness + rectfill(screen,light_x,((int)floor(i*(is_large?1.5:1))<<1)+light_y, + light_x+light_w-1,((int)ceil(i*(is_large?1.5:1))<<1)+light_y+1,i+128); + } + + // rect(screen,95,31,224,96,ed15); + // rect(screen,224,31,240,96,ed15); + set_palette_range(RAMpal,0,255,false); +} + +void colormixer(int color,int gray,int ratio) +{ + int window_xofs=0; + int window_yofs=0; + + if(is_large) + { + window_xofs=int(zq_screen_w-320*(is_large?1.5:1))>>1; + window_yofs=int(zq_screen_h-240*(is_large?1.5:1))>>1; + color /= 1.5; + ratio /= 1.5; + gray /= 1.5; + } + + custom_vsync(); + scare_mouse(); + + jwin_draw_frame(screen, sat_x-2, sat_y-2, sat_w+4, int(64*(is_large?1.5:1)+4), FR_DEEP); + + for(int i=0; i<32; i++) + { + RAMpal[i+160] = mixRGB(gfx_pal[color*3],gfx_pal[color*3+1], + gfx_pal[color*3+2],gray,gray,gray,i<<1); //saturation + rectfill(screen,sat_x,((int)floor(i*(is_large?1.5:1))<<1)+sat_y, + sat_x+sat_w-1,((int)ceil(i*(is_large?1.5:1))<<1)+sat_y+1,i+160); + } + + RAMpal[edc] = mixRGB(gfx_pal[color*3],gfx_pal[color*3+1],gfx_pal[color*3+2],gray,gray,gray,ratio); + RAMpal[edi] = invRGB(RAMpal[edc]); + set_palette_range(RAMpal,160,255,false); + + jwin_draw_frame(screen, color_x-2, color_y-2, color_w+4, color_h+4, FR_DEEP); + rectfill(screen,color_x,color_y,color_x+color_w-1,color_y+color_h-1,edc); + + if(is_large) + { + color *=1.5; + ratio *=1.5; + gray *=1.5; + } + + _allegro_hline(screen,color_x,gray+color_y,color_x+color_w-1,edi); + _allegro_vline(screen,color+color_x,color_y,color_y+color_h-1,edi); + _allegro_hline(screen,sat_x,ratio+sat_y,sat_x+sat_w-1,edi); + // text_mode(ed1); + textprintf_centre_ex(screen,font,zq_screen_w/2,int(color_y+color_h+10*(is_large?1.5:1)),jwin_pal[jcBOXFG],jwin_pal[jcBOX]," RGB - %2d %2d %2d ",RAMpal[edc].r,RAMpal[edc].g,RAMpal[edc].b); + unscare_mouse(); + SCRFIX(); +} + +int color = 0; +int gray = 0; +int ratio = 32; + + + +void edit_dataset(int dataset) +{ + PALETTE holdpal; + memcpy(holdpal,RAMpal,sizeof(RAMpal)); + int index = 0; + + hue_x=96; + hue_y=30; + hue_h=16; + light_x=74; + light_y=52; + light_w=16; + sat_x=230; + sat_y=52; + sat_w=16; + color_x=96; + color_y=52; + color_w=128; + color_h=64; + cset_x=96; + cset_y=170; + cset_h=8; + cset_spacing=4; + int ok_button_x=240, ok_button_y=152, ok_button_w=61, ok_button_h=21; + int cancel_button_x=240, cancel_button_y=184, cancel_button_w=61, cancel_button_h=21; + int insert_button_x=130, insert_button_y=140, insert_button_w=61, insert_button_h=21; + int window_xofs=0; + int window_yofs=0; + bool just_clicked=false; + + if(is_large) + { + window_xofs=(zq_screen_w-480)>>1; + window_yofs=(zq_screen_h-360)>>1; + hue_x = int(hue_x*1.5); + hue_y = int(hue_y*1.5); + hue_h = int(hue_h*1.5); + hue_x+=window_xofs; + hue_y+=window_yofs; + light_x = int(light_x*1.5); + light_y = int(light_y*1.5); + light_w = int(light_w*1.5); + light_x+=window_xofs; + light_y+=window_yofs; + sat_x = int(sat_x*1.5); + sat_y = int(sat_y*1.5); + sat_x+=window_xofs; + sat_y+=window_yofs; + sat_w = int(sat_w*1.5); + color_x = int(color_x*1.5); + color_y = int(color_y*1.5); + color_w =int(color_w*1.5); + color_h = int(color_h*1.5); + color_x+=window_xofs; + color_y+=window_yofs; + cset_x = int(cset_x*1.5); + cset_y = int(cset_y*1.5); + cset_h = int(cset_h*1.5); + cset_x+=window_xofs; + cset_y+=window_yofs; + cset_spacing = int(cset_spacing*1.5); + ok_button_x = int(ok_button_x*1.5); + ok_button_y = int(ok_button_y*1.5); + ok_button_x+=window_xofs; + ok_button_y+=window_yofs; + ok_button_w = int(ok_button_w*1.5); + ok_button_h = int(ok_button_h*1.5); + cancel_button_x = int(cancel_button_x*1.5); + cancel_button_y = int(cancel_button_y*1.5); + cancel_button_x+=window_xofs; + cancel_button_y+=window_yofs; + cancel_button_w = int(cancel_button_w*1.5); + cancel_button_h = int(cancel_button_h*1.5); + insert_button_x = int(insert_button_x*1.5); + insert_button_y = int(insert_button_y*1.5); + insert_button_x+=window_xofs; + insert_button_y+=window_yofs; + insert_button_w = int(insert_button_w*1.5); + insert_button_h = int(insert_button_h*1.5); + } + + custom_vsync(); + scare_mouse(); + + if(is_large) + rectfill(screen, 0, 0, screen->w, screen->h, 128); + + jwin_draw_win(screen, window_xofs, window_yofs, int(320*(is_large?1.5:1)), int(240*(is_large?1.5:1)), FR_WIN); + FONT *oldfont=is_large?lfont_l:nfont; + font=lfont; + jwin_draw_titlebar(screen, 3+window_xofs, 3+window_yofs, int((320*(is_large?1.5:1))-6), 18, "Edit CSet", true); + font = oldfont; + //draw_x_button(screen, 320 - 21, 5, 0); + load_cset(RAMpal,12,dataset); + load_cset(RAMpal,14,dataset); + set_palette_range(RAMpal,0,255,false); + + init_colormixer(); + colormixer(color,gray,ratio); + + jwin_draw_frame(screen, cset_x-2, cset_y-2, int(128*(is_large?1.5:1)+4), cset_h+4, FR_DEEP); + + for(int i=0; i<16; i++) + { + rectfill(screen,int((i<<3)*(is_large?1.5:1)+cset_x),cset_y,int((i<<3)*(is_large?1.5:1)+cset_x+cset_h-1),cset_y+cset_h-1,12*16+i); + } + + draw_edit_dataset_specs(index,-1); + + draw_text_button(screen,ok_button_x,ok_button_y,ok_button_w,ok_button_h,"OK",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + draw_text_button(screen,cancel_button_x,cancel_button_y,cancel_button_w,cancel_button_h,"Cancel",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + draw_text_button(screen,insert_button_x,insert_button_y,insert_button_w,insert_button_h,"Insert",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + + unscare_mouse(); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + while(gui_mouse_b()) + { + /* do nothing */ + } + + bool bdown=false; + int doing=0; + //doing: + //1=hue + //2=color index + //3=saturation + + int copy=-1; + + int done=0; + + do + { + rest(4); + bool setpal=false; + int x=gui_mouse_x(); + int y=gui_mouse_y(); + + if(gui_mouse_b()==1 && !bdown) + { + just_clicked=true; + + if(isinRect(x,y,color_x,color_y,color_x+color_w-1,color_y+color_h-1)) + { + doing=1; //hue/lightness (color) + } + + if(isinRect(x,y,sat_x,sat_y,sat_x+sat_w-1,sat_y+(is_large?96:64)-1)) + { + doing=3; //saturation + } + + if(isinRect(x,y,cset_x,cset_y,cset_x+(is_large?192:128)-1,cset_y+(cset_h*2)+cset_spacing+10)) + { + doing=2; //color index + } + + if(isinRect(x,y,ok_button_x,ok_button_y,ok_button_x+ok_button_w-1,ok_button_y+ok_button_h-1)) + { + if(do_text_button(ok_button_x,ok_button_y,ok_button_w,ok_button_h,"OK",jwin_pal[jcBOXFG],jwin_pal[jcBOX],true)) + { + done=2; + } + } + + if(!doing && isinRect(x,y,cancel_button_x,cancel_button_y,cancel_button_x+cancel_button_w-1,cancel_button_y+cancel_button_h-1)) + { + if(do_text_button(cancel_button_x,cancel_button_y,cancel_button_w,cancel_button_h,"Cancel",jwin_pal[jcBOXFG],jwin_pal[jcBOX],true)) + { + done=1; + } + } + + if(isinRect(x,y,int(320*(is_large?1.5:1) - 21+window_xofs), 5+window_yofs, int(320*(is_large?1.5:1) - 21 + 15+window_xofs), 5 + 13+window_yofs)) + { + if(do_x_button(screen, int(320*(is_large?1.5:1) - 21+window_xofs), 5+window_yofs)) + { + done=1; + } + } + + if(isinRect(x,y,insert_button_x,insert_button_y,insert_button_x+insert_button_w-1,insert_button_y+insert_button_h-1)) + { + if(do_text_button_reset(insert_button_x,insert_button_y,insert_button_w,insert_button_h,"Insert",jwin_pal[jcBOXFG],jwin_pal[jcBOX],true)) + { + RAMpal[14*16+index] = RAMpal[edc]; + setpal=true; + } + } + + bdown=true; + } + + if(gui_mouse_b()==1) + { + switch(doing) + { + case 1: // hue/lightness + color = vbound(x-color_x,0,is_large?191:127); + gray = vbound(y-light_y,0,is_large?95:63); + break; + + case 2: // color index + { + int new_index=vbound((int)((x-cset_x)/(is_large?1.5:1))>>3,0,15); + + if(index!=new_index && !just_clicked) + { + if(indexnew_index; i--) + zc_swap(RAMpal[14*16+i], RAMpal[14*16+i-1]); + } + + setpal=true; + } + + index = new_index; + break; + } + + case 3: // saturation + ratio = vbound(y-sat_y,0,is_large?95:63); + break; + } + } + + just_clicked=false; + + if(gui_mouse_b()==0) + { + bdown=false; + doing=0; + } + + if(keypressed()) + { + int k = readkey(); + + switch(k>>8) + { + case KEY_ESC: + done=1; + break; + + case KEY_ENTER: + done=2; + break; + + case KEY_LEFT: + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + zc_swap(RAMpal[14*16+index], RAMpal[14*16+((index-1)&15)]); + setpal=true; + } + + index=(index-1)&15; + break; + } + + case KEY_RIGHT: + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + zc_swap(RAMpal[14*16+index], RAMpal[14*16+((index+1)&15)]); + setpal=true; + } + + index=(index+1)&15; + break; + } + + case KEY_HOME: + ++RAMpal[14*16+index].r; + RAMpal[14*16+index].r&=0x3F; + setpal=true; + break; + + case KEY_END: + --RAMpal[14*16+index].r; + RAMpal[14*16+index].r&=0x3F; + setpal=true; + break; + + case KEY_UP: + ++RAMpal[14*16+index].g; + RAMpal[14*16+index].g&=0x3F; + setpal=true; + break; + + case KEY_DOWN: + --RAMpal[14*16+index].g; + RAMpal[14*16+index].g&=0x3F; + setpal=true; + break; + + case KEY_PGUP: + ++RAMpal[14*16+index].b; + RAMpal[14*16+index].b&=0x3F; + setpal=true; + break; + + case KEY_PGDN: + --RAMpal[14*16+index].b; + RAMpal[14*16+index].b&=0x3F; + setpal=true; + break; + + case KEY_C: + copy=index; + break; + + case KEY_V: + if(copy>=0) + { + RAMpal[14*16+index]=RAMpal[14*16+copy]; + setpal=true; + copy=-1; + } + + break; + + case KEY_M: + if(copy>=0) + { + RGB temp=RAMpal[14*16+index]; + RAMpal[14*16+index]=RAMpal[14*16+copy]; + RAMpal[14*16+copy]=temp; + setpal=true; + copy=-1; + } + + break; + + case KEY_I: + case KEY_INSERT: + RAMpal[14*16+index]=RAMpal[edc]; + setpal=true; + break; + + case KEY_F1: + doHelp(jwin_pal[jcTEXTFG],jwin_pal[jcTEXTBG]); + break; + + case KEY_S: + onSnapshot(); + break; + + default: + switch(k&255) + { + case '4': + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + zc_swap(RAMpal[14*16+index], RAMpal[14*16+((index-1)&15)]); + setpal=true; + } + + index=(index-1)&15; + break; + } + + case '6': + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + zc_swap(RAMpal[14*16+index], RAMpal[14*16+((index+1)&15)]); + setpal=true; + } + + index=(index+1)&15; + break; + } + + case '7': + ++RAMpal[14*16+index].r; + RAMpal[14*16+index].r&=0x3F; + setpal=true; + break; + + case '1': + --RAMpal[14*16+index].r; + RAMpal[14*16+index].r&=0x3F; + setpal=true; + break; + + case '8': + ++RAMpal[14*16+index].g; + RAMpal[14*16+index].g&=0x3F; + setpal=true; + break; + + case '2': + --RAMpal[14*16+index].g; + RAMpal[14*16+index].g&=0x3F; + setpal=true; + break; + + case '9': + ++RAMpal[14*16+index].b; + RAMpal[14*16+index].b&=0x3F; + setpal=true; + break; + + case '3': + --RAMpal[14*16+index].b; + RAMpal[14*16+index].b&=0x3F; + setpal=true; + break; + } + } + } + + if(gui_mouse_b() && (doing==1 || doing==3)) + { + colormixer(color,gray,ratio); + } + else + { + custom_vsync(); + scare_mouse(); + + if(setpal) + set_palette_range(RAMpal,14*16,15*16,false); + + draw_edit_dataset_specs(index,copy); + unscare_mouse(); + SCRFIX(); + } + + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + // else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + } + while(!done); + + if(done==2) + { + get_cset(dataset,14,RAMpal); + saved=false; + } + + font = nfont; + + // RAMpal = holdpal; + + memcpy(RAMpal, holdpal, sizeof(holdpal)); + + set_palette(RAMpal); + + while(gui_mouse_b()) + { + /* do nothing */ + } +} + +int pal_index(RGB *pal,RGB c) +{ + for(int i=0; i<256; i++) + if(pal[i].r==c.r && pal[i].g==c.g && pal[i].b==c.b) + return i; + + return -1; +} + +void grab_dataset(int dataset) +{ + int row=0; + static int palx=176; + static int paly=64; + int imagex=0; + int imagey=0; + int buttonx=184; + int buttony=195; + int filenamex=0; + int filenamey=232; + + if(is_large) + { + palx=665; + paly=354; + imagex=4; + imagey=4; + buttonx=570; + buttony=521; + filenamex=4; + filenamey=583; + } + + PALETTE tmp; + + if(!pic && load_the_pic(&pic,picpal)) + return; + + get_palette(imagepal); + + create_rgb_table(&rgb_table, imagepal, NULL); + rgb_map = &rgb_table; + create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL); + + int jwin_pal2[jcMAX]; + memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX); + + jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]]; + jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]]; + jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]]; + jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]]; + jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]]; + jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]]; + jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]]; + jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]]; + jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]]; + jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]]; + jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]]; + jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]]; + jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]]; + gui_bg_color=jwin_pal[jcBOX]; + gui_fg_color=jwin_pal[jcBOXFG]; + gui_mg_color=jwin_pal[jcMEDDARK]; + jwin_set_colors(jwin_pal); + + get_bw(picpal,pblack,pwhite); + int bg = gui_bg_color; + int fg = gui_fg_color; + gui_bg_color = pblack; + gui_fg_color = pwhite; + + char fname[13]; + extract_name(imagepath,fname,FILENAME8_3); + + draw_bw_mouse(pwhite, MOUSE_BMP_NORMAL, MOUSE_BMP_BLANK); + scare_mouse(); + clear_bitmap(screen2); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_BLANK][0]); + unscare_mouse(); + set_palette(picpal); + + bool redraw=true; + bool reload=false; + int done=0; + int f=0; + FONT *fnt = font; + + if(is_large) + font = lfont_l; + + do + { + rest(1); + int x=gui_mouse_x(); + int y=gui_mouse_y(); + + custom_vsync(); + + if(reload) + { + reload=false; + + if(load_the_pic(&pic,picpal)==2) + done=1; + else + { + clear_bitmap(screen2); + set_palette(picpal); + redraw=true; + } + } + + if(redraw) + { + redraw=false; + scare_mouse(); + clear_to_color(screen2,is_large?jwin_pal[jcBOX]:pblack); + + if(is_large) + { + jwin_draw_frame(screen2,imagex-2,imagey-2,658,551,FR_DEEP); + rectfill(screen2, imagex, imagey, imagex+654-1, imagey+547-1, jwin_pal[jcBOXFG]); + jwin_draw_frame(screen2,palx-3,paly-3,134,134,FR_DEEP); + } + + blit(pic,screen2,0,0,imagex,imagey,pic->w,pic->h); + textout_ex(screen2,is_large?lfont_l:font,fname,filenamex,filenamey,is_large?jwin_pal[jcBOXFG]:pwhite,is_large?jwin_pal[jcBOX]:pblack); + draw_text_button(screen2,buttonx,buttony+(is_large?36:24),(is_large?90:60),(is_large?31:21),"File",pblack,pwhite,0,true); + draw_text_button(screen2,buttonx+(is_large?114:76),buttony, + (is_large?90:60),(is_large?31:21),"OK",pblack,pwhite,0,true); + draw_text_button(screen2,buttonx+(is_large?114:76),buttony+(is_large?36:24), + (is_large?90:60),(is_large?31:21),"Cancel",pblack,pwhite,0,true); + unscare_mouse(); + } + + if((gui_mouse_b()&1) && isinRect(x,y,palx,paly,palx+127,paly+127)) + { + row=((y-paly)>>3); + } + + if((gui_mouse_b()&1) && isinRect(x,y,buttonx,buttony+(is_large?36:24),buttonx+(is_large?90:60),buttony+(is_large?36+31:24+21))) + { + if(do_text_button(buttonx,buttony+(is_large?36:24),(is_large?90:60),(is_large?31:21),"File",pblack,pwhite,true)) + { + reload=true; + } + } + + if((gui_mouse_b()&1) && isinRect(x,y,buttonx+(is_large?114:76),buttony,buttonx+(is_large?114+90:76+60),buttony+(is_large?31:21))) + { + if(do_text_button(buttonx+(is_large?114:76),buttony,(is_large?90:60),(is_large?31:21),"OK",pblack,pwhite,true)) + { + done=2; + } + } + + if((gui_mouse_b()&1) && isinRect(x,y,buttonx+(is_large?114:76),buttony+(is_large?36:24),buttonx+(is_large?114+90:76+60),buttony+(is_large?36+31:24+21))) + { + if(do_text_button(buttonx+(is_large?114:76),buttony+(is_large?36:24),(is_large?90:60),(is_large?31:21),"Cancel",pblack,pwhite,true)) + { + done=1; + } + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_ESC: + done=1; + break; + + case KEY_ENTER: + done=2; + break; + + case KEY_SPACE: + reload=true; + break; + + case KEY_UP: + row=(row-1)&15; + break; + + case KEY_DOWN: + row=(row+1)&15; + break; + + case KEY_LEFT: + case KEY_RIGHT: + if(!is_large) + { + palx = 192-palx; + redraw=true; + } + + break; + + case KEY_TAB: + // tmp = picpal; + memcpy(tmp,picpal,sizeof(picpal)); + + for(int i=0; i<16; i++) + tmp[(row<<4)+i] = invRGB(tmp[(row<<4)+i]); + + for(int i=0; i<12; i++) + { + custom_vsync(); + + if(i&2) + set_palette(picpal); + else + set_palette(tmp); + + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + + break; + } + } + + scare_mouse(); + + for(int i=0; i<256; i++) + { + int x2=((i&15)<<3)+palx; + int y2=((i>>4)<<3)+paly; + rectfill(screen2,x2,y2,x2+7,y2+7,i); + } + + ++f; + rect(screen2,palx-1,paly-1,palx+128,paly+128,is_large?pblack:pwhite); + rect(screen2,palx-1,(row<<3)+paly-1,palx+128,(row<<3)+paly+8,(f&2)?pwhite:pblack); + blit(screen2, screen, 0, 0, 0, 0, screen->w, screen->h); + unscare_mouse(); + SCRFIX(); + + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + while(!done); + + if(done==2) + get_cset(dataset,row,picpal); + + font = fnt; + + gui_bg_color = bg; + gui_fg_color = fg; + + while(gui_mouse_b()) + { + /* do nothing */ + } + + scare_mouse(); + + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + clear_to_color(mouse_bmp[MOUSE_BMP_BLANK][0],0); + memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX); + + gui_bg_color=jwin_pal[jcBOX]; + gui_fg_color=jwin_pal[jcBOXFG]; + gui_mg_color=jwin_pal[jcMEDDARK]; + jwin_set_colors(jwin_pal); + + rgb_map = &zq_rgb_table; + unscare_mouse(); +} + +byte cset_hold[15][16*3]; +byte cset_hold_cnt; +bool cset_ready = false; +int cset_count,cset_first; +PALETTE pal,undopal; + +//#define FLASH 243 +//byte rc[16] = {253,248,0,0,0,0,0,246,247,249,250,251,252,240,255,254}; + +void undo_pal() +{ + for(int i=0; i>4); + sprintf(buf[i*5+1],"%X",c.first&15); + sprintf(buf[i*5+2],"%X",c.count&15); + sprintf(buf[i*5+3],"%d",c.count>>4); + sprintf(buf[i*5+4],"%d",c.speed); + } + + for(int i=0; i<15; i++) + cycle_dlg[i+10].dp = buf[i]; + + if(is_large) + large_dialog(cycle_dlg); + + if(zc_popup_dialog(cycle_dlg,3)==2) + { + saved=false; + reset_pal_cycling(); + + for(int i=0; i<3; i++) + { + palcycle c; + c.first = (atoi(buf[i*5])&7)<<4; + c.first += xtoi(buf[i*5+1])&15; + c.count = xtoi(buf[i*5+2])&15; + c.count += (atoi(buf[i*5+3])&15)<<4; + c.speed = atoi(buf[i*5+4]); + misc.cycles[level][i] = c; + } + } +} + +void draw_cset_proc(DIALOG *d) +{ + int d1 = zc_min(d->d1, d->d2); + int d2 = zc_max(d->d1, d->d2); + + + d_bitmap_proc(MSG_DRAW,d,0); + // text_mode(d->bg); + + // rect(screen,d->x,(d1<<3)+d->y,d->x+d->w-1,(d2<<3)+d->y+7,FLASH); + rect(screen,d->x,int((d1<<3)*(is_large?1.5:1)+d->y),d->x+d->w-1,int((d2<<3)*(is_large?1.5:1)+d->y+(is_large?11:7)),dvc(0)); //highlights currently selected cset + int drc; + + if((d->flags & D_GOTFOCUS)) + drc = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; + else + drc = d->bg; + + dotted_rect(d->x-1, d->y-1, d->x+d->w, d->y+d->h, drc, d->bg); +} + +int d_cset_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_START: + d->d2 = d->d1; + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_DRAW: + draw_cset_proc(d); + break; + + case MSG_CLICK: + { + bool dragging=false; + int src=0; + int x; + int y; + + // Start dragging? + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + x=gui_mouse_x(); + y=gui_mouse_y(); + + if(isinRect(x,y,d->x,d->y,d->x+d->w-1,d->y+d->h-1)) + { + dragging=true; + src=vbound((int)((y-d->y) / (is_large?1.5:1))>>3,0,15) * 16 + + vbound((int)((x-d->x) / (is_large?1.5:1))>>3,0,15); + } + } + + do + { + x=gui_mouse_x(); + y=gui_mouse_y(); + + if(!dragging && isinRect(x,y,d->x,d->y,d->x+d->w-1,d->y+d->h-1)) + { + d->d2 = vbound((int)((y-d->y)/(is_large?1.5:1))>>3,0,15); + + if(!(key_shifts&KB_SHIFT_FLAG)) + d->d1 = d->d2; + } + + custom_vsync(); + scare_mouse(); + draw_cset_proc(d); + unscare_mouse(); + //sniggles + // ((RGB*)d->dp3)[243]=((RGB*)d->dp3)[rc[(fc++)&15]]; + // set_palette_range(((RGB*)d->dp3),FLASH,FLASH,false); + ((RGB*)d->dp3)[dvc(0)]=((RGB*)d->dp3)[rand()%14+dvc(1)]; + set_palette_range(((RGB*)d->dp3),dvc(0),dvc(0),false); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + while(gui_mouse_b()); + + if(dragging && isinRect(x,y,d->x,d->y,d->x+d->w-1,d->y+d->h-1)) + { + int dest=vbound((int)((y-d->y) / (is_large?1.5:1))>>3,0,15) * 16 + + vbound((int)((x-d->x) / (is_large?1.5:1))>>3,0,15); + + if(src!=dest) + { + memcpy(undopal,pal,sizeof(pal)); + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + for(int i=0; i<3; i++) + zc_swap(*(((byte*)d->dp2)+dest*3+i), *(((byte*)d->dp2)+src*3+i)); + } + else + { + for(int i=0; i<3; i++) + *(((byte*)d->dp2)+dest*3+i) = *(((byte*)d->dp2)+src*3+i); + } + + for(int i=0; i>8; + + switch(k) + { + case KEY_UP: + if(d->d2>0) --d->d2; + + if(!shift) d->d1 = d->d2; + + break; + + case KEY_DOWN: + if(d->d2<((int)ceil((d->h)/(is_large?1.5:1))>>3)-1) + ++d->d2; + + if(!shift) d->d1 = d->d2; + + break; + + case KEY_PGUP: + d->d2=0; + + if(!shift) d->d1 = d->d2; + + break; + + case KEY_PGDN: + d->d2=((int)ceil((d->h)/(is_large?1.5:1))>>3)-1; + + if(!shift) d->d1 = d->d2; + + break; + + case KEY_C: + cset_hold_cnt=0; + + for(int row=0; row <= abs(d->d1 - d->d2); row++) + { + int d1 = zc_min(d->d1,d->d2); + ++cset_hold_cnt; + + for(int i=0; i<16*3; i++) + cset_hold[row][i] = *(((byte*)d->dp2)+CSET(d1+row)*3+i); + } + + cset_ready=true; + break; + + + case KEY_V: + if(cset_ready) + { + // undopal=pal; + memcpy(undopal,pal,sizeof(pal)); + int d1 = zc_min(d->d1,d->d2); + + for(int row=0; rowdp2)+CSET(d1+row)*3+i) = cset_hold[row][i]; + } + + for(int i=0; i 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + return D_USED_CHAR; + } + } + + return D_O_K; +} + +byte mainpal_csets[30] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, 11,11,12,12,12,11, 10,10,10,12,10,10,10,10,9 }; +byte levelpal_csets[26] = { 2,3,4,9,2,3,4,2,3,4, 2, 3, 4, 15,15,15,15, 7,7,7, 8,8,8, 0,0,0 }; +byte levelpal2_csets[26] = { 2,3,4,9,2,0,1,2,3,4, 5, 6, 7, 15,15,15,15, 8, 9,9,9,9,9,9,9,9 }; +byte spritepal_csets[30] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, 14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14 }; +byte spritepal2_csets[30] = { 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, 14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14 }; + +static DIALOG colors_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 40, 16, 240+1, 216+1, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + + { jwin_frame_proc, 103, 48, 96, 256, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_cset_proc, 106, 51, 256, 96, jwin_pal[jcBOXFG], jwin_pal[jcLIGHT], 0, 0, 0, 0, NULL, NULL, NULL }, + + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 102, 0, 16, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 104, 39, 128, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "0123456789ABCDEF", NULL, NULL }, + // 19 + + { jwin_button_proc, 60, 178, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 'e', D_EXIT, 0, 0, (void *) "&Edit", NULL, NULL }, + { jwin_button_proc, 130, 178, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 'g', D_EXIT, 0, 0, (void *) "&Grab", NULL, NULL }, + { jwin_button_proc, 200, 178, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_EXIT, 0, 0, (void *) "Cycle", NULL, NULL }, + { jwin_button_proc, 244, 152, 25, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 'u', D_EXIT, 0, 0, (void *) "&U", NULL, NULL }, + // 23 + + { jwin_button_proc, 60, 204, 131, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 'l', D_EXIT, 0, 0, (void *) "&Load to CS 9", NULL, NULL }, + + { jwin_button_proc, 200, 204, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { jwin_rtext_proc, 60, 164, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Name: ", NULL, NULL }, + { jwin_edit_proc, 88, 160, 136, 16, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 16, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 110, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "0", NULL, NULL }, + { jwin_ctext_proc, 118, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "1", NULL, NULL }, + { jwin_ctext_proc, 126, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "2", NULL, NULL }, + { jwin_ctext_proc, 134, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "3", NULL, NULL }, + { jwin_ctext_proc, 142, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "4", NULL, NULL }, + { jwin_ctext_proc, 150, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "5", NULL, NULL }, + { jwin_ctext_proc, 158, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "6", NULL, NULL }, + { jwin_ctext_proc, 166, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "7", NULL, NULL }, + { jwin_ctext_proc, 174, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "8", NULL, NULL }, + { jwin_ctext_proc, 182, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "9", NULL, NULL }, + { jwin_ctext_proc, 190, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "A", NULL, NULL }, + { jwin_ctext_proc, 198, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "B", NULL, NULL }, + { jwin_ctext_proc, 206, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "C", NULL, NULL }, + { jwin_ctext_proc, 214, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "D", NULL, NULL }, + { jwin_ctext_proc, 222, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "E", NULL, NULL }, + { jwin_ctext_proc, 230, 39, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "F", NULL, NULL }, + + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int EditColors(const char *caption,int first,int count,byte *label) +{ + + char tempstuff[17]; + cset_first=first; + cset_count=count; + + for(int i=240; i<256; i++) + { + pal[i] = RAMpal[i]; + } + + go(); + + int bw = 128; + int bh = count*8; + + if(colors_dlg[0].d1) + { + bw = (is_large?192:128); + bh = count*(is_large?12:8); + } + + BITMAP *bmp = create_bitmap_ex(8,(is_large?192:128),count*(is_large?12:8)); + + if(!bmp) + return 0; + + for(int i=0; i<16*count; i++) + { + int x=int(((i&15)<<3)*(is_large?1.5:1)); + int y=int(((i>>4)<<3)*(is_large?1.5:1)); + rectfill(bmp,x,y,x+(is_large ? 15:7),y+(is_large ? 15:7),i); + } + + colors_dlg[2].dp = bmp; + colors_dlg[2].w = bw; + colors_dlg[2].h = bh; + colors_dlg[2].d1 = colors_dlg[2].d1 = 0; + colors_dlg[2].dp2 = colordata+CSET(first)*3; + colors_dlg[2].dp3 = pal; + colors_dlg[1].w = bw + 6; + colors_dlg[1].h = bh + 6; + colors_dlg[21].proc = (count==pdLEVEL) ? jwin_button_proc : d_dummy_proc; + colors_dlg[21].dp = get_bit(quest_rules,qr_FADE) ? (void *) "Cycle" : (void *) "Dark"; + colors_dlg[26].dp = tempstuff; + colors_dlg[25].x =(count==pdLEVEL)?colors_dlg[0].x+60:colors_dlg[0].x+12; + colors_dlg[25].w =(count==pdLEVEL)?48:0; + colors_dlg[25].dp =(count==pdLEVEL)?(void *) "Name: ":(void *) " "; + colors_dlg[26].proc =(count==pdLEVEL) ? jwin_edit_proc : d_dummy_proc; + colors_dlg[26].x =(count==pdLEVEL)?colors_dlg[0].x+63:colors_dlg[0].x+12; + colors_dlg[26].w =(count==pdLEVEL)?134:0; + colors_dlg[26].d1 =(count==pdLEVEL)?16:0; + colors_dlg[26].dp =(count==pdLEVEL)?palnames[(first-poLEVEL)/pdLEVEL]:NULL; + + //char (*buf)[4]= new char[count][4]; + char buf[50][4]; + + for(int i=0; i<15; i++) + { + if(i 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + + ret = shutdown_dialog(p); + + if(ret==19) + { + memcpy(undopal,pal,sizeof(pal)); + edit_dataset(first+colors_dlg[2].d2); + } + + if(ret==20) + { + memcpy(undopal,pal,sizeof(pal)); + grab_dataset(first+colors_dlg[2].d2); + } + + if(ret==21) + { + if(!get_bit(quest_rules,qr_FADE)) + { + calc_dark(first); + } + else + { + edit_cycles((first-poLEVEL)/pdLEVEL); + } + } + + if(ret==22) + { + undo_pal(); + } + } + while(ret<23&&ret!=0); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + clear_to_color(screen,vc(0)); + set_palette(RAMpal); + + loadlvlpal(Color); + + if(ret==23) + { + load_cset(RAMpal,9,first+colors_dlg[2].d2); + set_pal(); + } + + saved=false; //It's just easier this way :) + // gui_fg_color = vc(14); + // gui_bg_color = vc(1); + // gui_mg_color = vc(9); + + comeback(); + destroy_bitmap(bmp); + //delete[] buf; + return int(ret==23); +} + +int onColors_Main() +{ + int l9 = EditColors("Main Palette",0,pdFULL,mainpal_csets); + + // copy main to level 0 + int di = CSET(poLEVEL)*3; + int si = CSET(2)*3; + + for(int i=0; i. +// + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include +#include +#include + +#include "gui.h" +#include "zc_custom.h" +#include "zq_custom.h" +#include "tiles.h" +#include "zq_tiles.h" +#include "zq_misc.h" +#include "zquest.h" +#include "items.h" +#include "zsys.h" +#include "sfx.h" +#include "init.h" +#include "ffasm.h" +#include "defdata.h" +#include "zc_malloc.h" + +extern int ex; +extern void reset_itembuf(itemdata *item, int id); +extern const char *item_class_list(int index, int *list_size); +extern const char *sfxlist(int index, int *list_size); +// zq_subscr.cpp +extern int d_qtile_proc(int msg,DIALOG *d,int c); +extern int d_ctl_proc(int msg,DIALOG *d,int c); +extern int d_csl_proc(int msg,DIALOG *d,int c); +extern int d_csl2_proc(int msg,DIALOG *d,int c); +extern int d_tileblock_proc(int msg,DIALOG *d,int c); +extern int d_stilelist_proc(int msg,DIALOG *d,int c); +extern int sstype_drop_proc(int msg,DIALOG *d,int c); +extern int jwin_fontdrop_proc(int msg,DIALOG *d,int c); +extern int jwin_tflpcheck_proc(int msg,DIALOG *d,int c); +extern int jwin_lscheck_proc(int msg,DIALOG *d,int c); + +extern int biw_cnt; +extern int biic_cnt; + + + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + + +int link_animation_speed = 1; //lower is faster animation + +int d_ecstile_proc(int msg,DIALOG *d,int c); + +int d_cstile_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + { + int f = 0; + int t = d->d1; + int cs = d->d2; + + if(select_tile(t,f,1,cs,true)) + { + d->d1 = t; + d->d2 = cs; + return D_REDRAW; + } + } + break; + + case MSG_DRAW: + if(is_large) + { + d->w = 36; + d->h = 36; + } + + BITMAP *buf = create_bitmap_ex(8,20,20); + BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(d->d1) + overtile16(buf,d->d1,2,2,d->d2,0); + + stretch_blit(buf, bigbmp, 2,2, 17, 17, 2, 2, d->w-2, d->h-2); + destroy_bitmap(buf); + jwin_draw_frame(bigbmp,0,0,d->w,d->h,FR_DEEP); + blit(bigbmp,screen,0,0,d->x,d->y,d->w,d->h); + destroy_bitmap(bigbmp); + } + + // text_mode(d->bg); + FONT *fonty = is_large ? font : pfont; + textprintf_ex(screen,fonty,d->x+d->w,d->y+2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile: %d",d->d1); + textprintf_ex(screen,fonty,d->x+d->w,d->y+text_height(fonty)+3,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet: %d",d->d2); + break; + } + + return D_O_K; +} + +void large_dialog(DIALOG *d) +{ + large_dialog(d, 1.5f); +} + +void large_dialog(DIALOG *d, float RESIZE_AMT) +{ + if(d[0].d1 == 0) + { + d[0].d1 = 1; + int oldwidth = d[0].w; + int oldheight = d[0].h; + int oldx = d[0].x; + int oldy = d[0].y; + d[0].x -= int(float(d[0].w)/RESIZE_AMT); + d[0].y -= int(float(d[0].h)/RESIZE_AMT); + d[0].w = int(float(d[0].w)*RESIZE_AMT); + d[0].h = int(float(d[0].h)*RESIZE_AMT); + + for(int i=1; d[i].proc!=NULL; i++) + { + // Place elements horizontally + double xpc = ((double)(d[i].x - oldx) / (double)oldwidth); + d[i].x = int(d[0].x + (xpc*double(d[0].w))); + + // Horizontally resize elements + if((d[i].proc == d_maptile_proc && d[i].dp2!=(void*)1) || d[i].proc==d_intro_edit_proc || d[i].proc==d_title_edit_proc) + { + d[i].x += (int)(float(d[i].w)/4.f); + } + else if(d[i].proc == d_comboframe_proc) + { + d[i].w *= 2; + d[i].w -= 4; + } + else if(d[i].proc == d_wflag_proc || d[i].proc==d_bitmap_proc || d[i].proc == d_maptile_proc || d[i].proc==d_qtile_proc || d[i].proc==d_tileblock_proc) + { + d[i].w *= 2; + } + else if(d[i].proc == jwin_button_proc) + d[i].w = int(d[i].w*1.5); + else d[i].w = int(float(d[i].w)*RESIZE_AMT); + + // Place elements vertically + double ypc = ((double)(d[i].y - oldy) / (double)oldheight); + d[i].y = int(d[0].y + (ypc*double(d[0].h))); + + // Vertically resize elements + if((d[i].proc == d_maptile_proc && d[i].dp2!=(void*)1) || d[i].proc==d_intro_edit_proc || d[i].proc==d_title_edit_proc) + { + } + else if(d[i].proc == jwin_edit_proc || d[i].proc == jwin_check_proc || d[i].proc == jwin_checkfont_proc || d[i].proc == jwin_tflpcheck_proc || d[i].proc == jwin_lscheck_proc) + { + d[i].h = int((double)d[i].h*1.5); + } + else if(d[i].proc == jwin_droplist_proc || d[i].proc == d_ndroplist_proc || d[i].proc == d_idroplist_proc || d[i].proc == d_nidroplist_proc || d[i].proc == d_dropdmaplist_proc + || d[i].proc == d_dropdmaptypelist_proc || d[i].proc == jwin_as_droplist_proc || d[i].proc == d_ffcombolist_proc || d[i].proc == sstype_drop_proc || d[i].proc == d_ctl_proc + || d[i].proc == jwin_fontdrop_proc || d[i].proc == d_csl_proc || d[i].proc == d_csl2_proc || d[i].proc == d_stilelist_proc || d[i].proc == d_comboalist_proc) + { + d[i].y += int((double)d[i].h*0.25); + d[i].h = int((double)d[i].h*1.25); + } + else if(d[i].proc == d_comboframe_proc) + { + d[i].h *= 2; + d[i].h -= 4; + } + else if(d[i].proc == d_wflag_proc || d[i].proc==d_bitmap_proc || d[i].proc == d_maptile_proc || d[i].proc==d_qtile_proc || d[i].proc==d_tileblock_proc) + { + d[i].h *= 2; + } + else if(d[i].proc == jwin_button_proc) + d[i].h = int(d[i].h*1.5); + else d[i].h = int(float(d[i].h)*RESIZE_AMT); + + // Fix frames + if(d[i].proc == jwin_frame_proc) + { + d[i].x++; + d[i].y++; + d[i].w-=4; + d[i].h-=4; + } + + // Fix menus + if(d[i].proc == jwin_menu_proc) + { + d[i].y=d[0].y+23; + d[i].h=13; + } + } + } + + for(int i=1; d[i].proc != NULL; i++) + { + if(d[i].proc==jwin_slider_proc) + continue; + + // Bigger font + bool bigfontproc = (d[i].proc != jwin_initlist_proc && d[i].proc != jwin_droplist_proc && d[i].proc != jwin_abclist_proc && d[i].proc != d_ilist_proc && d[i].proc != d_wlist_proc && d[i].proc != jwin_list_proc && d[i].proc != d_dmaplist_proc + && d[i].proc != d_dropdmaplist_proc && d[i].proc != d_xmaplist_proc && d[i].proc != d_dropdmaptypelist_proc && d[i].proc != d_warplist_proc && d[i].proc != d_warplist_proc && d[i].proc != d_wclist_proc && d[i].proc != d_ndroplist_proc + && d[i].proc != d_idroplist_proc && d[i].proc != d_nidroplist_proc && d[i].proc != jwin_as_droplist_proc && d[i].proc != d_ffcombolist_proc && d[i].proc != d_enelist_proc && d[i].proc != sstype_drop_proc && d[i].proc != d_ctl_proc + && d[i].proc != jwin_fontdrop_proc && d[i].proc != d_csl_proc && d[i].proc != d_csl2_proc && d[i].proc != d_stilelist_proc && d[i].proc != d_comboalist_proc); + + if(bigfontproc && !d[i].dp2) + { + //d[i].dp2 = (d[i].proc == jwin_edit_proc) ? sfont3 : lfont_l; + d[i].dp2 = lfont_l; + } + else if(!bigfontproc) + { +// ((ListData *)d[i].dp)->font = &sfont3; + ((ListData *) d[i].dp)->font = &lfont_l; + } + + // Make checkboxes work + if(d[i].proc == jwin_check_proc) + d[i].proc = jwin_checkfont_proc; + else if(d[i].proc == jwin_radio_proc) + d[i].proc = jwin_radiofont_proc; + } + + jwin_center_dialog(d); +} + +/*****************************/ +/****** onCustomItems ******/ +/*****************************/ + +struct ItemNameInfo +{ + int iclass; + char *power; + char *misc1; + char *misc2; + char *misc3; + char *misc4; + char *misc5; + char *misc6; + char *misc7; + char *misc8; + char *misc9; + char *misc10; + char *flag1; + char *flag2; + char *flag3; + char *flag4; + char *flag5; + char *wpn1; + char *wpn2; + char *wpn3; + char *wpn4; + char *wpn5; + char *wpn6; + char *wpn7; + char *wpn8; + char *wpn9; + char *wpn10; + char *actionsnd; +}; + + +static ItemNameInfo inameinf[]= +{ + //itemclass power misc1 misc2 misc3 misc4 misc5 misc6 misc7 misc8 misc9 misc10 flag1 flag2 flag3 flag4 flag5 wpn1 wpn2 wpn3 wpn4 wpn5 wpn6 wpn7 wpn8 wpn9 wpn10 action sound + { itype_fairy, NULL, (char *)"HP Regained:", (char *)"MP Regained:", (char *)"Step Speed:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"HP. R. Is Percent", (char *)"MP. R. Is Percent", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Item Drop Sound:" }, + { itype_triforcepiece, NULL, (char *)"Cutscene MIDI:", (char *)"Cutscene Type (0-1):", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Side Warp Out", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_shield, NULL, (char *)"Block Flags:", (char *)"Reflect Flags:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"De/Reflection Sound:" }, + { itype_agony, (char *)"Sensitivity:", (char *)"Vibration Frequency", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_wealthmedal, NULL, (char *)"Discount Amount:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"D. A. Is Percent", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_cbyrna, (char *)"Beam Damage:", (char *)"Beam Speed Divisor:", (char *)"Orbit Radius:", (char *)"Number Of Beams:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Penetrates Enemies", NULL, NULL, (char *)"Can Slash", NULL, (char *)"Stab Sprite:", (char *)"Slash Sprite:", (char *)"Beam Sprite:", (char *)"Sparkle Sprite:", (char *)"Damaging Sparkle Sprite:", NULL, NULL, NULL, NULL, NULL, (char *)"Orbit Sound:" }, + { itype_whispring, (char *)"Jinx Divisor:", (char *)"Jinx Type:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Perm. Jinx Are Temp.", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_ladder, (char *)"Four-Way:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_magickey, (char *)"Dungeon Level:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Lesser D. Levels Also", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_wallet, (char *)"Infinite Supply:", (char *)"Increase Amount:", (char *)"Delay Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_quiver, (char *)"Infinite Supply:", (char *)"Increase Amount:", (char *)"Delay Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_bombbag, (char *)"Infinite Supply:", (char *)"Increase Amount:", (char *)"Delay Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Super Bombs Also", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_quakescroll2, (char *)"Damage Multiplier:", (char *)"Stun Duration:", (char *)"Stun Radius:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Quake Sound:" }, + { itype_quakescroll, (char *)"Damage Multiplier:", (char *)"Stun Duration:", (char *)"Stun Radius:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Quake Sound:" }, + { itype_perilscroll, NULL, (char *)"Maximum Hearts:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_spinscroll2, (char *)"Damage Multiplier:", (char *)"Number of Spins:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Spinning Sound:" }, + { itype_spinscroll, (char *)"Damage Multiplier:", (char *)"Number of Spins:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Spinning Sound:" }, + { itype_clock, NULL, (char *)"Duration (0 = Infinite):", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_magicring, (char *)"Infinite Magic:", (char *)"Increase Amount:", (char *)"Delay Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_heartring, NULL, (char *)"Increase Amount:", (char *)"Delay Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + //itemclass power misc1 misc2 misc3 misc4 misc5 misc6 misc7 misc8 misc9 misc10 flag1 flag2 flag3 flag4 flag5 wpn1 wpn2 wpn3 wpn4 wpn5 wpn6 wpn7 wpn8 wpn9 wpn10 action sound + { itype_chargering, NULL, (char *)"Charging Duration:", (char *)"Magic C. Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_hoverboots, NULL, (char *)"Hover Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Halo Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Hovering Sound:" }, + { itype_rocs, (char *)"Height Multiplier:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Jumping Sound:" }, + { itype_sbomb, (char *)"Damage:", (char *)"Fuse Duration (0 = Remote):", (char *)"Max. On Screen:", (char *)"Damage to Link:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Bomb Sprite:", (char *)"Explosion Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Explosion Sound:" }, + { itype_bomb, (char *)"Damage:", (char *)"Fuse Duration (0 = Remote):", (char *)"Max. On Screen:", (char *)"Damage to Link:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Use 1.92 Timing", NULL, NULL, NULL, NULL, (char *)"Bomb Sprite:", (char *)"Explosion Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Explosion Sound:" }, + { itype_nayruslove, NULL, (char *)"Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Rocket Flickers", (char *)"Translucent Rocket", (char *)"Translucent Shield", (char *)"Shield Flickers", NULL, (char *)"Left Rocket Sprite:", (char *)"L. Rocket Return Sprite:", (char *)"L. Rocket Sparkle Sprite:", (char *)"L. Return Sparkle Sprite:", (char *)"Shield Sprite (2x2, Over):", (char *)"Right Rocket Sprite:", (char *)"R. Rocket Return Sprite:", (char *)"R. Rocket Sparkle Sprite:", (char *)"R. Return Sparkle Sprite:", (char *)"Shield Sprite (2x2, Under):", (char *)"Shield Sound:" }, + { itype_faroreswind, NULL, (char *)"Warp Animation (0-2):", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Wind Sound:" }, + { itype_dinsfire, (char *)"Damage:", (char *)"Number of Flames:", (char *)"Circle Width:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Don't Provide Light", (char *)"Falls in Sideview", NULL, NULL, (char *)"Rocket Up Sprite:", (char *)"Rocket Down Sprite:", (char *)"R. Up Sparkle Sprite:", (char *)"R. Down Sparkle Sprite:", (char *)"Flame Sprite:", NULL, NULL, NULL, NULL, NULL, (char *)"Ring Sound:" }, + { itype_hammer, (char *)"Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Hammer Sprite:", (char *)"Smack Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Pound Sound:" }, + { itype_lens, NULL, (char *)"Lens Width:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Activation Sound:" }, + { itype_hookshot, (char *)"Damage:", (char *)"Chain Length:", (char *)"Chain Links:", (char *)"Block Flags:", (char *)"Reflect Flags:", NULL, NULL, NULL, NULL, NULL, NULL, (char *)"No Handle Damage", NULL, NULL, NULL, NULL, (char *)"Tip Sprite:", (char *)"Chain Sprite (H):", (char *)"Chain Sprite (V):", (char *)"Handle Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Firing Sound:" }, + { itype_boots, (char *)"Damage Combo Level:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Not Solid Combos", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_bracelet, (char *)"Push Combo Level:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Once Per Screen", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_book, (char *)"Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Fire Magic", NULL, NULL, NULL, NULL, (char *)"Magic Sprite:", (char *)"Flame Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Firing Sound:" }, + { itype_ring, (char *)"Damage Divisor:", (char *)"Link Sprite Pal:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_wand, (char *)"Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Allow Magic w/o Book", NULL, NULL, (char *)"Can Slash", NULL, (char *)"Stab Sprite:", (char *)"Slash Sprite:", (char *)"Magic Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Firing Sound:" }, + { itype_bait, NULL, (char *)"Duration:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Bait Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Baiting Sound:" }, + { itype_potion, NULL, (char *)"HP Regained:", (char *)"MP Regained:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"HP R. Is Percent", (char *)"MP R. Is Percent", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_whistle, NULL, (char *)"Whirlwind Direction:", (char *)"Warp Ring:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"One W.Wind Per Scr.", NULL, NULL, NULL, NULL, (char *)"Whirlwind Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Music Sound:" }, + { itype_candle, (char *)"Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Once Per Screen", (char *)"Don't Provide Light", NULL, (char *)"Can Slash", NULL, (char *)"Stab Sprite:", (char *)"Slash Sprite:", (char *)"Flame Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Firing Sound:" }, + { itype_arrow, (char *)"Damage:", (char *)"Duration (0 = Infinite):", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Penetrate Enemies", NULL, NULL, NULL, NULL, (char *)"Arrow Sprite:", (char *)"Sparkle Sprite:", (char *)"Damaging Sparkle Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Firing Sound:" }, + { itype_brang, (char *)"Damage:", (char *)"Range (0 = Infinite):", NULL, (char *)"Block Flags:", (char *)"Reflect Flags:", NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Corrected Animation", (char *)"Directional Sprites", (char *)"Do Not Return", NULL, NULL, (char *)"Boomerang Sprite:", (char *)"Sparkle Sprite:", (char *)"Damaging Sparkle Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Spinning Sound:" }, + { itype_sword, (char *)"Damage:", (char *)"Beam Hearts:", (char *)"Beam Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"B.H. Is Percent", (char *)"B.D. Is Percent", (char *)"B. Penetrates Enemies", (char *)"Can Slash", NULL, (char *)"Stab Sprite:", (char *)"Slash Sprite:", (char *)"Beam Sprite:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Stabbing/Slashing Sound:" }, + { itype_whimsicalring, (char *)"Damage Bonus:", (char *)"Chance (1 in n):", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (char *)"Whimsy Sound:" }, + { itype_perilring, (char *)"Damage Divisor:", (char *)"Maximum Hearts:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_stompboots, (char *)"Damage:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { itype_bow, (char *)"Arrow Speed:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + +static std::map *inamemap = NULL; + +std::map *getItemNameMap() +{ + if(inamemap == NULL) + { + inamemap = new std::map(); + + for(int i=0;; i++) + { + ItemNameInfo *inf = &inameinf[i]; + + if(inf->iclass == -1) + break; + + (*inamemap)[inf->iclass] = inf; + } + } + + return inamemap; +} + +static int itemdata_flags_list[] = +{ + // dialog control number + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -1 +}; + +static int itemdata_gfx_list[] = +{ + // dialog control number + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -1 +}; + +static int itemdata_pickup_list[] = +{ + // dialog control number + 92, 93, 94, 95, 96, 97, 98, 99, 100, /*101, 102,*/ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -1 +}; + +static int itemdata_script_list[] = +{ + // dialog control number + /*131, 132,*/ 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, -1 +}; + +static int itemdata_scriptargs_list[] = +{ + // dialog control number + 101, 102, 131, 132, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, -1 +}; + +static TABPANEL itemdata_tabs[] = +{ + // (text) + { (char *)"Data", D_SELECTED, itemdata_flags_list, 0, NULL }, + { (char *)"GFX", 0, itemdata_gfx_list, 0, NULL }, + { (char *)"Pickup", 0, itemdata_pickup_list, 0, NULL }, + { (char *)"Action", 0, itemdata_script_list, 0, NULL }, + { (char *)"Scripts", 0, itemdata_scriptargs_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static ListData item_class__list(item_class_list, &pfont); +static ListData weapon_list(weaponlist, &pfont); + +static char counterlist_str_buf[12]; + +const char *counterlist(int index, int *list_size) +{ + if(index >= 0) + { + bound(index,0,32); + + switch(index) + { + case 0: + return "None"; + + case 1: + return "Life"; + + case 2: + return "Rupees"; + + case 3: + return "Bombs"; + + case 4: + return "Arrows"; + + case 5: + return "Magic"; + + case 6: + return "Keys"; + + case 7: + return "Super Bombs"; + + default: + sprintf(counterlist_str_buf,"Script %d",index-7); + return counterlist_str_buf; + } + } + + *list_size = 33; + return NULL; +} + +static ListData counter_list(counterlist, &pfont); + +int jwin_nbutton_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + d=d; + + FONT *tfont=font; + + switch(msg) + { + case MSG_DRAW: + tfont=font; + font=is_large?lfont_l:nfont; + jwin_draw_text_button(screen, d->x, d->y, d->w, d->h, (char*)d->dp, d->flags, true); + font=tfont; + return D_O_K; + break; + } + + return jwin_button_proc(msg, d, c); +} + +const char *itemscriptdroplist(int index, int *list_size) +{ + if(index<0) + { + *list_size = biitems_cnt; + return NULL; + } + + return biitems[index].first.c_str(); +} + +//droplist like the dialog proc, naming scheme for this stuff is awful... +static ListData itemscript_list(itemscriptdroplist, &pfont); + + +static DIALOG itemdata_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 320, 237, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_tab_proc, 4, 25, 312, 182, 0, 0, 0, 0, 0, 0, (void *) itemdata_tabs, NULL, (void *)itemdata_dlg }, + { jwin_nbutton_proc, 58, 212, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_nbutton_proc, 129, 212, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_nbutton_proc, 200, 212, 61, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Defaults", NULL, NULL }, + + // 6 + { jwin_text_proc, 8, 48, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 55, 44, 150, 16, vc(12), vc(1), 0, 0, 63, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 8, 66, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Class:", NULL, NULL }, + { jwin_droplist_proc, 55, 62, 150, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 3, 0, (void *) &item_class__list, NULL, NULL }, + + //10 + { jwin_text_proc, 236, 48, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Level:", NULL, NULL }, + { jwin_edit_proc, 283, 44, 28, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 8, 84, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Power:", NULL, NULL }, + { jwin_edit_proc, 87, 80, 28, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + //14 + { jwin_check_proc, 120, 80, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Equipment Item", NULL, NULL }, + { jwin_check_proc, 120, 90, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Misc. Flag 1", NULL, NULL }, + { jwin_check_proc, 120, 100, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Misc. Flag 2", NULL, NULL }, + { jwin_check_proc, 215, 80, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Misc. Flag 3", NULL, NULL }, + { jwin_check_proc, 215, 90, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Misc. Flag 4", NULL, NULL }, + { jwin_check_proc, 215, 100, 95, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Misc. Flag 5", NULL, NULL }, + + //20 + { jwin_text_proc, 8, 115, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 1:", NULL, NULL }, + { jwin_edit_proc, 107, 111, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 133, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 2:", NULL, NULL }, + { jwin_edit_proc, 107, 129, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 151, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 3:", NULL, NULL }, + { jwin_edit_proc, 107, 147, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 169, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 4:", NULL, NULL }, + { jwin_edit_proc, 107, 165, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 187, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 5:", NULL, NULL }, + { jwin_edit_proc, 107, 183, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + //30 + { jwin_text_proc, 177, 115, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 6:", NULL, NULL }, + { jwin_edit_proc, 276, 111, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 177, 133, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 7:", NULL, NULL }, + { jwin_edit_proc, 276, 129, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 177, 151, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 8:", NULL, NULL }, + { jwin_edit_proc, 276, 147, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 177, 169, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 9:", NULL, NULL }, + { jwin_edit_proc, 276, 165, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 177, 187, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc. Attribute 10:", NULL, NULL }, + { jwin_edit_proc, 276, 183, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + //40 + { jwin_button_proc, 205, 65, 12, 12, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "?", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //47 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //57 + { jwin_text_proc, 8, 48, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Flash CSet:", NULL, NULL }, + { jwin_edit_proc, 107, 44, 35, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 66, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Animation Frames:", NULL, NULL }, + { jwin_edit_proc, 107, 62, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 84, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Animation Speed:", NULL, NULL }, + { jwin_edit_proc, 107, 80, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 102, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Initial Delay:", NULL, NULL }, + { jwin_edit_proc, 107, 98, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 120, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Link Tile Modification:", NULL, NULL }, + { jwin_edit_proc, 107, 116, 35, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + + //67 + { d_dummy_proc, 8, 136, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) NULL, NULL, NULL }, + + { d_cstile_proc, 145, 44, 20, 20, vc(11), vc(1), 0, 0, 0, 6, NULL, NULL, NULL }, + { jwin_check_proc, 145, 69, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Flash ", NULL, NULL }, + { jwin_check_proc, 145, 80, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "2-Hand", NULL, NULL }, + + { jwin_button_proc, 149, 100, 53, 21, vc(14), vc(1), 't', D_EXIT, 0, 0, (void *) "&Test", NULL, NULL }, + + //72 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //82 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //92 + { jwin_text_proc, 8, 66, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Increase Amount:", NULL, NULL }, + { jwin_edit_proc, 107, 62, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + { jwin_check_proc, 147, 66, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Gradual", NULL, NULL }, + + { jwin_text_proc, 8, 48, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Counter Reference:", NULL, NULL }, + { jwin_droplist_proc, 107, 44, 72, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &counter_list, NULL, NULL }, + { jwin_text_proc, 147, 84, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "But Not Above:", NULL, NULL }, + { jwin_edit_proc, 204, 80, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 84, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Increase Counter Max:", NULL, NULL }, + { jwin_edit_proc, 107, 80, 35, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + //101 + { jwin_text_proc, 112+10, 47+38, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Pickup Script:", NULL, NULL }, + { jwin_droplist_proc, 112+10, 47+38+10, 150, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &itemscript_list, NULL, NULL }, + //{ jwin_edit_proc, 55, 98, 28, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 102, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Sound:", NULL, NULL }, + { jwin_edit_proc, 107, 98, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 8, 120, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hearts Required:", NULL, NULL }, + { jwin_edit_proc, 107, 116, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + + { jwin_check_proc, 8, 142, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Keep Lower Level Items", NULL, NULL }, + { jwin_check_proc, 8, 152, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Gain All Lower Level Items", NULL, NULL }, + { jwin_check_proc, 8, 162, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Can Be Eaten By Enemies", NULL, NULL }, + { jwin_check_proc, 8, 172, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Upgrade Item When Collected Twice", NULL, NULL }, + + //111 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //121 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //131 + { jwin_text_proc, 112+10, 47+38+10 + 18, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Action Script:", NULL, NULL }, + { jwin_droplist_proc, 112+10, 47+38+10*2 + 18, 150, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &itemscript_list, NULL, NULL }, + //{ jwin_edit_proc, 55, 44, 28, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 48, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Magic Cost:", NULL, NULL }, + { jwin_edit_proc, 125, 44, 28, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 161, 48, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Sound:", NULL, NULL }, + { jwin_edit_proc, 284, 44, 28, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + + { jwin_check_proc, 8, 62, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Remove Item When Used", NULL, NULL }, + { jwin_check_proc, 161, 62, 60, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Uses Rupees Instead Of Magic", NULL, NULL }, + + //139 + { jwin_text_proc, 8, 74, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 1:", NULL, NULL }, + { jwin_droplist_proc, 8, 83, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 8, 100, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 2:", NULL, NULL }, + { jwin_droplist_proc, 8, 109, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 8, 126, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 3:", NULL, NULL }, + { jwin_droplist_proc, 8, 135, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 8, 152, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 4:", NULL, NULL }, + { jwin_droplist_proc, 8, 161, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 8, 178, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 5:", NULL, NULL }, + { jwin_droplist_proc, 8, 187, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + + //149 + { jwin_text_proc, 161, 74, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 6:", NULL, NULL }, + { jwin_droplist_proc, 161, 83, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 161, 100, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 7:", NULL, NULL }, + { jwin_droplist_proc, 161, 109, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 161, 126, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 8:", NULL, NULL }, + { jwin_droplist_proc, 161, 135, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 161, 152, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 9:", NULL, NULL }, + { jwin_droplist_proc, 161, 161, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + { jwin_text_proc, 161, 178, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon 10:", NULL, NULL }, + { jwin_droplist_proc, 161, 187, 151, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &weapon_list, NULL, NULL }, + + //159 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //169 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //179 + { jwin_text_proc, 6+10, 29+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D0:", NULL, NULL }, + { jwin_text_proc, 6+10, 47+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D1:", NULL, NULL }, + { jwin_text_proc, 6+10, 65+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D2:", NULL, NULL }, + { jwin_text_proc, 6+10, 83+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D3:", NULL, NULL }, + { jwin_text_proc, 6+10, 101+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D4:", NULL, NULL }, + { jwin_text_proc, 6+10, 119+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D5:", NULL, NULL }, + { jwin_text_proc, 6+10, 137+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D6:", NULL, NULL }, + { jwin_text_proc, 6+10, 155+20, 24, 12, 0, 0, 0, 0, 0, 0, (void *) "D7:", NULL, NULL }, + { jwin_edit_proc, 34+10, 25+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 43+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 61+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 79+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 97+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 115+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 133+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 151+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 112+10, 29+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "A1:", NULL, NULL }, + { jwin_text_proc, 112+10, 47+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "A2:", NULL, NULL }, + //74 + { jwin_edit_proc, 140+10, 25+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 140+10, 43+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, +}; + +void setLabels(int iclass) +{ + std::map *nmap = getItemNameMap(); + std::map::iterator it = nmap->find(iclass); + ItemNameInfo *inf = NULL; + + if(it != nmap->end()) + inf = it->second; + + + if(inf == NULL) + itemdata_dlg[12].dp = (void *)"Power:"; + else if(inf->power == NULL) + { + itemdata_dlg[12].dp = (void *)""; + itemdata_dlg[13].flags |= D_DISABLED; + } + else + { + itemdata_dlg[12].dp = inf->power; + itemdata_dlg[13].flags &= ~D_DISABLED; + } + + // Disable the Equipment item checkbox + if((iclass >= itype_rupee && iclass <= itype_bombammo) || + (iclass >= itype_key && iclass <= itype_magiccontainer) || + (iclass >= itype_map && iclass <= itype_bosskey) || iclass == itype_clock || + iclass==itype_lkey || iclass==itype_misc || + iclass==itype_bowandarrow || iclass==itype_letterpotion) + { + itemdata_dlg[14].dp = (void *)""; + itemdata_dlg[14].flags |= D_DISABLED; + itemdata_dlg[14].flags &= ~D_SELECTED; + } + else + { + itemdata_dlg[14].dp = (void *)"Equipment Item"; + itemdata_dlg[14].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->flag1 == NULL)) + { + itemdata_dlg[15].dp = (void *)""; + itemdata_dlg[15].flags |= D_DISABLED; + } + else + { + itemdata_dlg[15].dp = inf->flag1; + itemdata_dlg[15].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->flag2 == NULL)) + { + itemdata_dlg[16].dp = (void *)""; + itemdata_dlg[16].flags |= D_DISABLED; + } + else + { + itemdata_dlg[16].dp = inf->flag2; + itemdata_dlg[16].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->flag3 == NULL)) + { + itemdata_dlg[17].dp = (void *)""; + itemdata_dlg[17].flags |= D_DISABLED; + } + else + { + itemdata_dlg[17].dp = inf->flag3; + itemdata_dlg[17].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->flag4 == NULL)) + { + itemdata_dlg[18].dp = (void *)""; + itemdata_dlg[18].flags |= D_DISABLED; + } + else + { + itemdata_dlg[18].dp = inf->flag4; + itemdata_dlg[18].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->flag5 == NULL)) + { + itemdata_dlg[19].dp = (void *)""; + itemdata_dlg[19].flags |= D_DISABLED; + } + else + { + itemdata_dlg[19].dp = inf->flag5; + itemdata_dlg[19].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc1 == NULL)) + { + itemdata_dlg[20].dp = (void *)""; + itemdata_dlg[21].flags |= D_DISABLED; + } + else + { + itemdata_dlg[20].dp = inf->misc1; + itemdata_dlg[21].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc2 == NULL)) + { + itemdata_dlg[22].dp = (void *)""; + itemdata_dlg[23].flags |= D_DISABLED; + } + else + { + itemdata_dlg[22].dp = inf->misc2; + itemdata_dlg[23].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc3 == NULL)) + { + itemdata_dlg[24].dp = (void *)""; + itemdata_dlg[25].flags |= D_DISABLED; + } + else + { + itemdata_dlg[24].dp = inf->misc3; + itemdata_dlg[25].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc4 == NULL)) + { + itemdata_dlg[26].dp = (void *)""; + itemdata_dlg[27].flags |= D_DISABLED; + } + else + { + itemdata_dlg[26].dp = inf->misc4; + itemdata_dlg[27].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc5 == NULL)) + { + itemdata_dlg[28].dp = (void *)""; + itemdata_dlg[29].flags |= D_DISABLED; + } + else + { + itemdata_dlg[28].dp = inf->misc5; + itemdata_dlg[29].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc6 == NULL)) + { + itemdata_dlg[30].dp = (void *)""; + itemdata_dlg[31].flags |= D_DISABLED; + } + else + { + itemdata_dlg[30].dp = inf->misc6; + itemdata_dlg[31].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc7 == NULL)) + { + itemdata_dlg[32].dp = (void *)""; + itemdata_dlg[33].flags |= D_DISABLED; + } + else + { + itemdata_dlg[32].dp = inf->misc7; + itemdata_dlg[33].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc8 == NULL)) + { + itemdata_dlg[34].dp = (void *)""; + itemdata_dlg[35].flags |= D_DISABLED; + } + else + { + itemdata_dlg[34].dp = inf->misc8; + itemdata_dlg[35].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc9 == NULL)) + { + itemdata_dlg[36].dp = (void *)""; + itemdata_dlg[37].flags |= D_DISABLED; + } + else + { + itemdata_dlg[36].dp = inf->misc9; + itemdata_dlg[37].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->misc10 == NULL)) + { + itemdata_dlg[38].dp = (void *)""; + itemdata_dlg[39].flags |= D_DISABLED; + } + else + { + itemdata_dlg[38].dp = inf->misc10; + itemdata_dlg[39].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->actionsnd == NULL)) + itemdata_dlg[135].dp = (void *)""; + else + itemdata_dlg[135].dp = inf->actionsnd; + + if((inf == NULL) || (inf->wpn1 == NULL)) + { + itemdata_dlg[139].dp = (void *)""; + itemdata_dlg[140].flags |= D_DISABLED; + } + else + { + itemdata_dlg[139].dp = inf->wpn1; + itemdata_dlg[140].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn2 == NULL)) + { + itemdata_dlg[141].dp = (void *)""; + itemdata_dlg[142].flags |= D_DISABLED; + } + else + { + itemdata_dlg[141].dp = inf->wpn2; + itemdata_dlg[142].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn3 == NULL)) + { + itemdata_dlg[143].dp = (void *)""; + itemdata_dlg[144].flags |= D_DISABLED; + } + else + { + itemdata_dlg[143].dp = inf->wpn3; + itemdata_dlg[144].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn4 == NULL)) + { + itemdata_dlg[145].dp = (void *)""; + itemdata_dlg[146].flags |= D_DISABLED; + } + else + { + itemdata_dlg[145].dp = inf->wpn4; + itemdata_dlg[146].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn5 == NULL)) + { + itemdata_dlg[147].dp = (void *)""; + itemdata_dlg[148].flags |= D_DISABLED; + } + else + { + itemdata_dlg[147].dp = inf->wpn5; + itemdata_dlg[148].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn6 == NULL)) + { + itemdata_dlg[149].dp = (void *)""; + itemdata_dlg[150].flags |= D_DISABLED; + } + else + { + itemdata_dlg[149].dp = inf->wpn6; + itemdata_dlg[150].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn7 == NULL)) + { + itemdata_dlg[151].dp = (void *)""; + itemdata_dlg[152].flags |= D_DISABLED; + } + else + { + itemdata_dlg[151].dp = inf->wpn7; + itemdata_dlg[152].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn8 == NULL)) + { + itemdata_dlg[153].dp = (void *)""; + itemdata_dlg[154].flags |= D_DISABLED; + } + else + { + itemdata_dlg[153].dp = inf->wpn8; + itemdata_dlg[154].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn9 == NULL)) + { + itemdata_dlg[155].dp = (void *)""; + itemdata_dlg[156].flags |= D_DISABLED; + } + else + { + itemdata_dlg[155].dp = inf->wpn9; + itemdata_dlg[156].flags &= ~D_DISABLED; + } + + if((inf == NULL) || (inf->wpn10 == NULL)) + { + itemdata_dlg[157].dp = (void *)""; + itemdata_dlg[158].flags |= D_DISABLED; + } + else + { + itemdata_dlg[157].dp = inf->wpn10; + itemdata_dlg[158].flags &= ~D_DISABLED; + } +} + +void itemdata_help(int id) +{ + if(id < 0 || id > itype_max) return; + + if(id >= itype_custom1 && id <= itype_custom20) + { + jwin_alert(itype_names[id],"This has no built-in effect, but can be given","special significance using ZScripts or ZASM.","","O&K",NULL,'k',0,lfont); + } + else if(id >= itype_last) + { + jwin_alert("Undefined Item Class","This type currently has no use. Do not","use it in your quests, as its purpose may change","in future versions of Zelda Classic.","O&K",NULL,'k',0,lfont); + } + else if(id 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + if(keypressed()) + { + readkey(); + break; + } + + if(gui_mouse_b()) + break; + } + + comeback(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + destroy_bitmap(buf); + destroy_bitmap(buf2); + itemsbuf = hold; +} + + +void edit_itemdata(int index) +{ + char frm[8], spd[8], fcs[8], dly[8], ltm[8]; + char /*cls[8],*/ cll[8], amt[8], fmx[8], max[8], asn[8]; + char snd[8], mgc[8], hrt[8], pow[8]; + char name[64], zname[64]; + char ms1[8], ms2[8], ms3[8], ms4[8], ms5[8], ms6[8], ms7[8], ms8[8], ms9[8], ms10[8]; + char itemnumstr[75]; + char da[10][13]; + + sprintf(itemnumstr,"Item %d: %s", index, item_string[index]); + sprintf(fcs,"%d",itemsbuf[index].csets>>4); + sprintf(frm,"%d",itemsbuf[index].frames); + sprintf(spd,"%d",itemsbuf[index].speed); + sprintf(dly,"%d",itemsbuf[index].delay); + sprintf(ltm,"%ld",itemsbuf[index].ltm); + sprintf(cll,"%d",itemsbuf[index].fam_type); + sprintf(amt,"%d",(itemsbuf[index].amount&0x4000)?(-(itemsbuf[index].amount&0x3FFF)):(itemsbuf[index].amount&0x3FFF)); + sprintf(fmx,"%d",itemsbuf[index].max); + sprintf(max,"%d",itemsbuf[index].setmax); + sprintf(snd,"%d",itemsbuf[index].playsound); + sprintf(ms1,"%ld",itemsbuf[index].misc1); + sprintf(ms2,"%ld",itemsbuf[index].misc2); + sprintf(ms3,"%ld",itemsbuf[index].misc3); + sprintf(ms4,"%ld",itemsbuf[index].misc4); + sprintf(ms5,"%ld",itemsbuf[index].misc5); + sprintf(ms6,"%ld",itemsbuf[index].misc6); + sprintf(ms7,"%ld",itemsbuf[index].misc7); + sprintf(ms8,"%ld",itemsbuf[index].misc8); + sprintf(ms9,"%ld",itemsbuf[index].misc9); + sprintf(ms10,"%ld",itemsbuf[index].misc10); + sprintf(mgc,"%d",itemsbuf[index].magic); + sprintf(hrt,"%d",itemsbuf[index].pickup_hearts); + sprintf(pow,"%d",itemsbuf[index].power); + sprintf(asn,"%d",itemsbuf[index].usesound); + sprintf(name,"%s",item_string[index]); + + for(int j=0; j<8; j++) + sprintf(da[j],"%.4f",itemsbuf[index].initiald[j]/10000.0); + + sprintf(da[8],"%d",itemsbuf[index].initiala[0]/10000); + sprintf(da[9],"%d",itemsbuf[index].initiala[1]/10000); + + itemdata_dlg[0].dp = itemnumstr; + itemdata_dlg[0].dp2 = lfont; + + if(biic_cnt==-1) + { + build_biic_list(); + } + + if(biw_cnt==-1) + { + build_biw_list(); + } + + itemdata_dlg[7].dp = name; + + for(int j=0; j>4); + sprintf(frm,"%d",test.frames); + sprintf(spd,"%d",test.speed); + sprintf(dly,"%d",test.delay); + sprintf(ltm,"%ld",test.ltm); + + sprintf(cll,"%d",test.fam_type); + sprintf(amt,"%d",test.amount&0x4000?-(test.amount&0x3FFF):test.amount&0x3FFF); + sprintf(fmx,"%d",test.max); + sprintf(max,"%d",test.setmax); + } + + if(ret==5) + { + //do not reset graphics fields! -DD + //memset(&test, 0, sizeof(itemdata)); + //test.family=0xFF; + + reset_itembuf(&test, index); + + sprintf(fcs,"%d",test.csets>>4); + sprintf(frm,"%d",test.frames); + sprintf(spd,"%d",test.speed); + sprintf(dly,"%d",test.delay); + sprintf(ltm,"%ld",test.ltm); + sprintf(cll,"%d",test.fam_type); + sprintf(amt,"%d",test.amount&0x4000?-(test.amount&0x3FFF):test.amount&0x3FFF); + sprintf(fmx,"%d",test.max); + sprintf(max,"%d",test.setmax); + pickupscript = test.script; + sprintf(snd,"%d",test.playsound); + pickupscript = test.collect_script; + sprintf(ms1,"%ld",test.misc1); + sprintf(ms2,"%ld",test.misc2); + sprintf(ms3,"%ld",test.misc3); + sprintf(ms4,"%ld",test.misc4); + sprintf(ms5,"%ld",test.misc5); + sprintf(ms6,"%ld",test.misc6); + sprintf(ms7,"%ld",test.misc7); + sprintf(ms8,"%ld",test.misc8); + sprintf(ms9,"%ld",test.misc9); + sprintf(ms10,"%ld",test.misc10); + sprintf(mgc,"%d",test.magic); + sprintf(hrt,"%d",test.pickup_hearts); + sprintf(pow,"%d",test.power); + sprintf(asn,"%d",test.usesound); + sprintf(zname, "zz%03d", index); + sprintf(name,"%s",index= 0) + { + build_biw_list(); + edit_itemdata(index); + index = select_item("Select Item",index,true,foo); + } + + refresh(rMAP+rCOMBOS); + return D_O_K; +} + +/****************************/ +/****** onCustomWpns ******/ +/****************************/ + +static DIALOG wpndata_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 55, 40, 210, 163, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_cstile_proc, 198, 84, 20, 20, vc(11), vc(1), 0, 0, 0, 6, NULL, NULL, NULL }, + { jwin_button_proc, 90, 176, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 176, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_check_proc, 198, 109, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Auto-flash", NULL, NULL }, + { jwin_check_proc, 198, 120, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "2P Flash", NULL, NULL }, + { jwin_check_proc, 198, 131, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "H-Flip", NULL, NULL }, + { jwin_check_proc, 198, 142, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "V-Flip", NULL, NULL }, + { jwin_text_proc, 61, 88, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Flash CSet:", NULL, NULL }, + //10 + { jwin_text_proc, 61, 106, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Animation Frames:", NULL, NULL }, + { jwin_text_proc, 61, 124, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Animation Speed:", NULL, NULL }, + { jwin_text_proc, 61, 142, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Miscellaneous Type:", NULL, NULL }, + { jwin_edit_proc, 160, 88, 35, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 160, 106, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 160, 124, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 160, 142, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_check_proc, 198, 153, 65, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Behind", NULL, NULL }, + { jwin_edit_proc, 92, 65, 155, 16, vc(12), vc(1), 0, 0, 64, 0, NULL, NULL, NULL }, + { jwin_text_proc, 61, 69, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + + +void edit_weapondata(int index) +{ + char frm[8], spd[8], fcs[8], typ[8]; + char name[64]; + char wpnnumstr[75]; + + sprintf(wpnnumstr, "Sprite %d: %s", index, weapon_string[index]); + wpndata_dlg[0].dp = wpnnumstr; + wpndata_dlg[0].dp2 = lfont; + wpndata_dlg[2].d1 = wpnsbuf[index].tile; + wpndata_dlg[2].d2 = wpnsbuf[index].csets&15; + + for(int i=0; i<4; i++) + wpndata_dlg[i+5].flags = (wpnsbuf[index].misc&(1<>4); + sprintf(frm,"%d",wpnsbuf[index].frames); + sprintf(spd,"%d",wpnsbuf[index].speed); + sprintf(typ,"%d",wpnsbuf[index].type); + wpndata_dlg[13].dp = fcs; + wpndata_dlg[14].dp = frm; + wpndata_dlg[15].dp = spd; + wpndata_dlg[16].dp = typ; + sprintf(name,"%s",weapon_string[index]); + wpndata_dlg[18].dp = name; + + if(is_large) + { + large_dialog(wpndata_dlg); + } + + int ret; + wpndata test; + + do + { + ret = zc_popup_dialog(wpndata_dlg,3); + + test.tile = wpndata_dlg[2].d1; + test.csets = wpndata_dlg[2].d2; + + test.misc = 0; + + for(int i=0; i<4; i++) + if(wpndata_dlg[i+5].flags & D_SELECTED) + test.misc |= 1<= 0) + { + edit_weapondata(index); + index = select_weapon("Select Weapon",index); + } + + refresh(rMAP+rCOMBOS); + return D_O_K; +} + +/****************************/ +/***** onCustomEnemies *****/ +/****************************/ + + +static int enedata_data_list[] = +{ + 2,3,4,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30, + 31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,138,139,140,141,143,-1 +}; + +static int enedata_data2_list[] = +{ + 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,179,180,181,182,183,184,187,188,189,190,-1 +}; + +static int enedata_flags_list[] = +{ + 74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,98,99,100,101,102,103,104,105,106,120,121,-1 +}; + +static int enedata_flags2_list[] = +{ + 90,91,92,93,94,95,96,97,-1 +}; + +static int enedata_flags3_list[] = +{ + 107,108,109,110,111,112,113,114,115,116,117,118,119,185,186,-1 +}; + +static int enedata_defense_list[] = +{ + 144,145,146,147,148,149,150,151,152,161,162,163,164,165,166,167,168,169,178,-1 +}; + +static int enedata_defense2_list[] = +{ + 153,154,155,156,157,158,159,160,170,171,172,173,174,175,176,177,191,192,-1 +}; + +static TABPANEL enedata_tabs[] = +{ + { (char *)"Data 1", D_SELECTED, enedata_data_list, 0, NULL }, + { (char *)"Data 2", 0, enedata_data2_list, 0, NULL }, + { (char *)"Misc. Flags", 0, enedata_flags_list, 0, NULL }, +//{ (char *)"Flags 2", 0, enedata_flags2_list, 0, NULL }, + { (char *)"Defenses 1", 0, enedata_defense_list, 0, NULL }, + { (char *)"Defenses 2", 0, enedata_defense2_list, 0, NULL }, + { (char *)"Spawn Flags", 0, enedata_flags3_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +list_data_struct bief[eeMAX]; +int bief_cnt=-1; + +void build_bief_list() +{ + int start=bief_cnt=0; + + for(int i=start; i0; i--) + zc_swap(bief[i],bief[i-1]); + + break; + } + } +} + +const char *enetypelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = bief_cnt; + return NULL; + } + + return bief[index].s; +} + +list_data_struct biea[wMAX]; +int biea_cnt=-1; + +void build_biea_list() +{ + int start=biea_cnt=0; + + for(int i=start; i0 && strcmp(biea[j].s,"")) + zc_swap(biea[i],biea[j]); +} + + +const char *eneanimlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = biea_cnt; + return NULL; + } + + return biea[index].s; +} + +const char *itemsetlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,count_item_drop_sets()-1); + return item_drop_sets[index].name; + // return itemset_string[index]; + } + + *list_size=count_item_drop_sets(); + return NULL; +} + +list_data_struct biew[wMax-wEnemyWeapons]; +int biew_cnt=-1; + +void build_biew_list() +{ + biew_cnt=0; + + for(int i=0; i=0) + { + bound(index,0,biew_cnt-1); + return biew[index].s; + } + + *list_size=biew_cnt; + return NULL; +} + +const char *defenselist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,edLAST-1); + + switch(index) + { + default: + return "(None)"; + + case edHALFDAMAGE: + return "1/2 Damage"; + + case edQUARTDAMAGE: + return "1/4 Damage"; + + case edSTUNONLY: + return "Stun"; + + case edSTUNORCHINK: + return "Stun Or Block"; + + case edSTUNORIGNORE: + return "Stun Or Ignore"; + + case edCHINKL1: + return "Block If < 1"; + + case edCHINKL2: + return "Block If < 2"; + + case edCHINKL4: + return "Block If < 4"; + + case edCHINKL6: + return "Block If < 6"; + + case edCHINKL8: + return "Block If < 8"; + + case edCHINK: + return "Block"; + + case edIGNOREL1: + return "Ignore If < 1"; + + case edIGNORE: + return "Ignore"; + + case ed1HKO: + return "One-Hit-Kill"; + } + } + + *list_size = edLAST; + return NULL; +} + + +// +// Enemy Misc. Attribute label swapping device +// +struct EnemyNameInfo +{ + int family; + char *misc[10]; + void* list[10]; +}; + +const char *walkmisc1list(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,e1tLAST-1); + return walkmisc1_string[index]; + } + + *list_size = e1tLAST; + return NULL; +} + +const char *walkmisc2list(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,e2tTRIBBLE); + return walkmisc2_string[index]; + } + + *list_size = e2tTRIBBLE+1; + return NULL; +} + +const char *walkmisc7list(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,e7tEATHURT); + return walkmisc7_string[index]; + } + + *list_size = e7tEATHURT+1; + return NULL; +} + +const char *walkmisc9list(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,e9tARMOS); + return walkmisc9_string[index]; + } + + *list_size = e9tARMOS+1; + return NULL; +} + +const char *gleeokmisc3list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Breath" : "1 Shot"); + } + + *list_size = 2; + return NULL; +} + +const char *gohmamisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index==2 ? "Breath" : index==1 ? "3 Shots" : "1 Shot"); + } + + *list_size = 3; + return NULL; +} + +const char *manhandlamisc2list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "2x2 (8 Heads)" : "1x1 (4 Heads)"); + } + + *list_size = 2; + return NULL; +} + +const char *aquamisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Left (Facing Right)" : "Right (Facing Left)"); + } + + *list_size = 2; + return NULL; +} + +const char *patramisc4list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Oval" : "Big Circle"); + } + + *list_size = 2; + return NULL; +} + +const char *patramisc5list(int index, int *list_size) +{ + if(index>=0) + { + return (index==2 ? "Inner Eyes" : index==1 ? "Center Eye" : "None"); + } + + *list_size = 3; + return NULL; +} + +const char *patramisc10list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "2x2 Patra" : "1x1 Patra"); + } + + *list_size = 2; + return NULL; +} + +const char *dodongomisc10list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "BS-Zelda" : "NES"); + } + + *list_size = 2; + return NULL; +} + +const char *digdoggermisc10list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Kid" : "Digdogger"); + } + + *list_size = 2; + return NULL; +} + +const char *walkerspawnlist(int index, int *list_size) +{ + if(index>=0) + { + return (index==2 ? "Instant" : index==1 ? "Flicker" : "Puff"); + } + + *list_size = 3; + return NULL; +} + +const char *wizzrobemisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Phase" : "Teleport"); + } + + *list_size = 2; + return NULL; +} + +const char *wizzrobemisc2list(int index, int *list_size) +{ + if(index>=0) + { + return (index==3 ? "Summon (Layer)" : index==2 ? "Summon" : index==1 ? "8 Shots" : "1 Shot"); + } + + *list_size = 4; + return NULL; +} + +const char *keesemisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Bat" : "Keese"); + } + + *list_size = 2; + return NULL; +} + +const char *keesemisc2list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Tribble" : "Normal"); + } + + *list_size = 2; + return NULL; +} + +const char *trapmisc2list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Constant" : "Line Of Sight"); + } + + *list_size = 2; + return NULL; +} + +const char *trapmisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index==2 ? "Vertical" : index==1 ? "Horizontal" : "4-Way"); + } + + *list_size = 3; + return NULL; +} + +const char *leevermisc1list(int index, int *list_size) +{ + if(index>=0) + { + if(index==0) + return "Link's path"; + else if(index==1) + return "In place"; + else if(index==2) + return "Link's path + second"; + } + + *list_size = 3; + return NULL; +} + +const char *rockmisc1list(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "2x2" : "1x1"); + } + + *list_size = 2; + return NULL; +} + +// 0: no, 1: yes +const char *yesnomisclist(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "Yes" : "No"); + } + + *list_size = 2; + return NULL; +} + +// 0: yes, 1: no +const char *noyesmisclist(int index, int *list_size) +{ + if(index>=0) + { + return (index ? "No" : "Yes"); + } + + *list_size = 2; + return NULL; +} + +static ListData walkmisc1_list(walkmisc1list, is_large? &lfont_l : &font); +static ListData walkmisc2_list(walkmisc2list, is_large? &lfont_l : &font); +static ListData walkmisc7_list(walkmisc7list, is_large? &lfont_l : &font); +static ListData walkmisc9_list(walkmisc9list, is_large? &lfont_l : &font); + +static ListData gleeokmisc3_list(gleeokmisc3list, is_large? &lfont_l : &font); +static ListData gohmamisc1_list(gohmamisc1list, is_large? &lfont_l : &font); +static ListData manhandlamisc2_list(manhandlamisc2list, is_large? &lfont_l : &font); +static ListData aquamisc1_list(aquamisc1list, is_large? &lfont_l : &font); + +static ListData patramisc4_list(patramisc4list, is_large? &lfont_l : &font); +static ListData patramisc5_list(patramisc5list, is_large? &lfont_l : &font); +static ListData patramisc10_list(patramisc10list, is_large? &lfont_l : &font); + +static ListData dodongomisc10_list(dodongomisc10list, is_large? &lfont_l : &font); + +static ListData keesemisc1_list(keesemisc1list, is_large? &lfont_l : &font); +static ListData keesemisc2_list(keesemisc2list, is_large? &lfont_l : &font); + +static ListData digdoggermisc10_list(digdoggermisc10list, is_large? &lfont_l : &font); + +static ListData wizzrobemisc1_list(wizzrobemisc1list, is_large? &lfont_l : &font); +static ListData wizzrobemisc2_list(wizzrobemisc2list, is_large? &lfont_l : &font); + +static ListData trapmisc1_list(trapmisc1list, is_large? &lfont_l : &font); +static ListData trapmisc2_list(trapmisc2list, is_large? &lfont_l : &font); + +static ListData leevermisc1_list(leevermisc1list, is_large? &lfont_l : &font); +static ListData rockmisc1_list(rockmisc1list, is_large? &lfont_l : &font); + +static ListData yesnomisc_list(yesnomisclist, is_large? &lfont_l : &font); +static ListData noyesmisc_list(noyesmisclist, is_large? &lfont_l : &font); + +static EnemyNameInfo enameinf[]= +{ + { + eeWALK, { "Shot Type:", "Death Type:", "Death Attr. 1:", "Death Attr. 2:", "Death Attr. 3:", "Extra Shots:", "Touch Effects:", "Effect Strength:", "Walk Style:", "Walk Attr.:" }, + { (void*)&walkmisc1_list, (void*)&walkmisc2_list, NULL, NULL, NULL, NULL, (void*)&walkmisc7_list, NULL, (void*)&walkmisc9_list, NULL } + }, + { + eeGLEEOK, { "Heads:", "Head HP:", "Shot Type:", NULL, "Neck Segments:", "Neck Offset 1:", "Neck Offset 2:", "Head Offset:", "Fly Head Offset:", NULL }, + { NULL, NULL, (void*)&gleeokmisc3_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeDIG, { "Enemy 1 ID:", "Enemy 2 ID:", "Enemy 3 ID:", "Enemy 4 ID:", "Enemy 1 Qty:", "Enemy 2 Qty:", "Enemy 3 Qty:", "Enemy 4 Qty:", "Unused:", "Type:" }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (void*)&digdoggermisc10_list } + }, + { + eePATRA, { "Outer Eyes:", "Inner Eyes:", "Eyes' HP:", "Eye Movement:", "Shooters:", "Pattern Odds:", "Pattern Cycles:", "Eye Offset:", "Eye CSet:", "Type:" }, + { NULL, NULL, NULL, (void*)&patramisc4_list, (void*)&patramisc5_list, NULL, NULL, NULL, NULL, (void*)&patramisc10_list } + }, + { + eePROJECTILE, { "Shot Type:", NULL, "Shot Attr. 1:", "Shot Attr. 2:", NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&walkmisc1_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeGHOMA, { "Shot Type:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&gohmamisc1_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeAQUA, { "Side:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&aquamisc1_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeMANHAN, { "Frame rate:", "Size:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, (void*)&manhandlamisc2_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeLANM, { "Segments:", "Segment Lag:", "Item per segment:", NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, &yesnomisc_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeMOLD, { "Segments:", "Item per segment:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, &yesnomisc_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeWIZZ, { "Walk Style:", "Shot Type:", "Shot Attr. 1:", "Solid Combos OK:", "Teleport Delay:", NULL, NULL, NULL, NULL, NULL }, + { (void*)&wizzrobemisc1_list, (void*)&wizzrobemisc2_list, NULL, &yesnomisc_list, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeDONGO,{ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Type :" }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (void*)&dodongomisc10_list } + }, + { + eeKEESE, { "Walk Style:", "Death Type:", "Enemy ID:", NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&keesemisc1_list, (void*)&keesemisc2_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeTEK, { "1/n jump start:", "1/n jump cont.:", "Jump Z velocity:", NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeLEV, { "Emerge style:", "Submerged CSet:", "Emerging step:", NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&leevermisc1_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeWALLM,{ "Fixed distance:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&noyesmisc_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeTRAP, { "Direction:", "Move Style:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { (void*)&trapmisc1_list, (void*)&trapmisc2_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + }, + { + eeROCK, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Rock size:" }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (void*)&rockmisc1_list } + }, + { + eeNONE, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Boss Death Trigger:" }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (void*)&yesnomisc_list } + }, + { + eeGUY, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Boss Death Trigger:" }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, (void*)&yesnomisc_list } + }, + { + -1, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } + } +}; + +static std::map *enamemap = NULL; + +std::map *getEnemyNameMap() +{ + if(enamemap == NULL) + { + enamemap = new std::map(); + + for(int i=0;; i++) + { + EnemyNameInfo *inf = &enameinf[i]; + + if(inf->family == -1) + break; + + (*enamemap)[inf->family] = inf; + } + } + + return enamemap; +} + +static ListData itemset_list(itemsetlist, &font); +static ListData eneanim_list(eneanimlist, &font); +static ListData enetype_list(enetypelist, &font); +static ListData eweapon_list(eweaponlist, &font); + +static ListData defense_list(defenselist, &font); +static ListData walkerspawn_list(walkerspawnlist, &font); + +static ListData sfx__list(sfxlist, &font); + +static DIALOG enedata_dlg[] = +{ + { jwin_win_proc, 0, 0, 320, 240, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_tab_proc, 4, 24, 312, 192, 0, 0, 0, 0, 0, 0, (void *) enedata_tabs, NULL, (void *)enedata_dlg }, + //2 + { d_ecstile_proc, 16, 62, 20, 20, vc(11), vc(1), 0, 0, 0, 6, NULL, NULL, NULL }, + { d_ecstile_proc, 52, 62, 20, 20, vc(11), vc(1), 0, 0, 0, 6, NULL, NULL, NULL }, + { d_ecstile_proc, 88, 62, 20, 20, vc(11), vc(1), 0, 0, 0, 6, NULL, NULL, NULL }, + //5 + { jwin_button_proc, 50, 220, 61, 16, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 130, 220, 61, 16, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + //7 + { jwin_text_proc, 21, 46, 30, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Old", NULL, NULL }, + { jwin_text_proc, 44, 46, 30, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Special", NULL, NULL }, + { jwin_text_proc, 90, 46, 30, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "New", NULL, NULL }, + { jwin_text_proc, 6, 90, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "W:", NULL, NULL }, + { jwin_text_proc, 6, 108, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "H:", NULL, NULL }, + //12 + { jwin_text_proc, 42, 90, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "W:", NULL, NULL }, + { jwin_text_proc, 42, 108, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "H:", NULL, NULL }, + { jwin_text_proc, 78, 90, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "W:", NULL, NULL }, + { jwin_text_proc, 78, 108, 10, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "H:", NULL, NULL }, + //16 + { jwin_text_proc, 114, 54, 30, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_text_proc, 114, 72, 30, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "HP:", NULL, NULL }, + { jwin_text_proc, 114, 90, 50, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Damage:", NULL, NULL }, + { jwin_text_proc, 114, 108, 50, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "W. Damage:", NULL, NULL }, + { jwin_text_proc, 140, 126, 35, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hunger:", NULL, NULL }, + //21 + { jwin_text_proc, 210, 72, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Random Rate:", NULL, NULL }, + { jwin_text_proc, 210, 90, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Halt Rate:", NULL, NULL }, + { jwin_text_proc, 210, 108, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Homing Factor:", NULL, NULL }, + { jwin_text_proc, 210, 126, 60, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Step Speed:", NULL, NULL }, + //25 + { jwin_text_proc, 8, 126, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Weapon:", NULL, NULL }, + { jwin_text_proc, 8, 144, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 8, 162, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "O. Anim:", NULL, NULL }, + { jwin_text_proc, 8, 180, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "E. Anim:", NULL, NULL }, + { jwin_text_proc, 8, 198, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Item Set:", NULL, NULL }, + //30 + { jwin_edit_proc, 16, 86, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 16, 104, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 52, 86, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 52, 104, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 88, 86, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 88, 104, 22, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + //36 + { jwin_edit_proc, 144, 50, 166, 16, vc(12), vc(1), 0, 0, 63, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 166, 68, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 166, 86, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 166, 104, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 186, 122, 20, 16, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + //41 + { jwin_edit_proc, 280, 68, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 280, 86, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 280, 104, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 280, 122, 30, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + //45 + { jwin_droplist_proc, 51, 122, 85, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &eweapon_list, NULL, NULL }, + { jwin_droplist_proc, 51, 140, 110, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &enetype_list, NULL, NULL }, + { jwin_droplist_proc, 51, 158, 184, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &eneanim_list, NULL, NULL }, + { jwin_droplist_proc, 51, 176, 184, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &eneanim_list, NULL, NULL }, + { jwin_droplist_proc, 51, 194, 184, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &itemset_list, NULL, NULL }, + //50 + { d_dummy_proc, 240, 144, 40, 8, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 240, 144, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Pal CSet:", NULL, NULL }, + { d_dummy_proc, 280, 140, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 280, 140, 30, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + //54 + { jwin_text_proc, 6, 54, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 1:", NULL, NULL }, + { jwin_text_proc, 6, 72, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 2:", NULL, NULL }, + { jwin_text_proc, 6, 90, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 3:", NULL, NULL }, + { jwin_text_proc, 6, 108, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 4:", NULL, NULL }, + { jwin_text_proc, 6, 126, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 5:", NULL, NULL }, + { jwin_text_proc, 6, 144, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 6:", NULL, NULL }, + { jwin_text_proc, 160, 54, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 7:", NULL, NULL }, + { jwin_text_proc, 160, 72, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 8:", NULL, NULL }, + { jwin_text_proc, 160, 90, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 9:", NULL, NULL }, + { jwin_text_proc, 160, 108, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 10:", NULL, NULL }, + //64 + { jwin_edit_proc, 86, 50, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 86, 68, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 86, 86, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 86, 104, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 86, 122, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 86, 140, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 242, 50, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 242, 68, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 242, 86, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 242, 104, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + //74 + { jwin_check_proc, 6, 50, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Damaged By Power 0 Weapons", NULL, NULL }, + { jwin_check_proc, 6, 60, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is Invisible", NULL, NULL }, + { jwin_check_proc, 6, 70, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Never Returns After Death", NULL, NULL }, + { jwin_check_proc, 6, 80, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Doesn't Count As Beatable Enemy", NULL, NULL }, + { d_dummy_proc, 6, 180, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 100, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 110, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 120, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + //82 + { d_dummy_proc, 6, 130, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 140, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 150, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 160, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 170, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 180, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 190, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 200, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + //90 + { d_dummy_proc, 6, 50, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 60, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 70, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 80, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 90, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 100, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 110, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { d_dummy_proc, 6, 120, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + //98 + { jwin_check_proc, 6, 130, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Shielded In Front", NULL, NULL }, + { jwin_check_proc, 6, 140, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Shielded On Left", NULL, NULL }, + { jwin_check_proc, 6, 150, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Shielded On Right", NULL, NULL }, + { jwin_check_proc, 6, 160, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Shielded In Back", NULL, NULL }, + { jwin_check_proc, 6, 170, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Hammer Can Break Shield", NULL, NULL }, + { d_dummy_proc, 6, 190, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Shield Is Mirrored", NULL, NULL }, + { d_dummy_proc, 6, 200, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unused", NULL, NULL }, + { jwin_check_proc, 6, 90, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Can Only Be Seen By Lens Of Truth", NULL, NULL }, + //106 + { jwin_check_proc, 6, 100, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is Flashing", NULL, NULL }, + { jwin_check_proc, 6, 50, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Zora\" Screen Flag", NULL, NULL }, + { jwin_check_proc, 6, 60, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Falling Rocks\" Screen Flag", NULL, NULL }, + { jwin_check_proc, 6, 70, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Corner Traps\" Screen Flag", NULL, NULL }, + { jwin_check_proc, 6, 80, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Horz Trap\" Combo Type/Flag", NULL, NULL }, + { jwin_check_proc, 6, 90, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Vert Trap\" Combo Type/Flag", NULL, NULL }, + { jwin_check_proc, 6, 100, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"4-Way Trap\" Combo Type/Flag", NULL, NULL }, + { jwin_check_proc, 6, 110, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"LR Trap\" Combo Type/Flag", NULL, NULL }, + //114 + { jwin_check_proc, 6, 120, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"UD Trap\" Combo Type/Flag", NULL, NULL }, + { jwin_check_proc, 6, 130, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Middle Traps\" Screen Flag", NULL, NULL }, + { jwin_check_proc, 6, 140, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Statue Fire\" Screen Flag", NULL, NULL }, + { jwin_check_proc, 6, 150, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Armos\" Combo Type", NULL, NULL }, + { jwin_check_proc, 6, 160, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Grave\" Combo Type", NULL, NULL }, + { jwin_check_proc, 6, 170, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Spawned By \"Ganon\" Room Type", NULL, NULL }, + { jwin_check_proc, 6, 110, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is Flickering", NULL, NULL }, + { jwin_check_proc, 6, 120, 280, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is Translucent", NULL, NULL }, + //122 + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //130 + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 160, 40, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //138 + { jwin_text_proc, 240, 162, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "F. Rate:", NULL, NULL }, + { jwin_text_proc, 240, 180, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "F. Rate:", NULL, NULL }, + { jwin_edit_proc, 280, 158, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 280, 176, 30, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_check_proc, 165, 144, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Use Pal CSet", NULL, NULL }, + //143 - note: these are defenses 0-16, 17 is at 191 + { jwin_text_proc, 6, 54, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Boomerang Defense:", NULL, NULL }, + { jwin_text_proc, 6, 72, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Bomb Defense:", NULL, NULL }, + { jwin_text_proc, 6, 90, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Super Bomb Defense:", NULL, NULL }, + { jwin_text_proc, 6, 108, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Arrow Defense:", NULL, NULL }, + { jwin_text_proc, 6, 126, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Fire Defense:", NULL, NULL }, + { jwin_text_proc, 6, 144, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Wand Melee Defense:", NULL, NULL }, + { jwin_text_proc, 6, 162, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Magic Defense:", NULL, NULL }, + { jwin_text_proc, 6, 180, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hookshot Defense:", NULL, NULL }, + { jwin_text_proc, 6, 198, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hammer Defense:", NULL, NULL }, + { jwin_text_proc, 6, 54, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Sword Defense:", NULL, NULL }, + { jwin_text_proc, 6, 72, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Sword Beam Defense:", NULL, NULL }, + { jwin_text_proc, 6, 90, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Refl. Beam Defense:", NULL, NULL }, + { jwin_text_proc, 6, 108, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Refl. Magic Defense:", NULL, NULL }, + { jwin_text_proc, 6, 126, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Refl. Fireball Defense:", NULL, NULL }, + { jwin_text_proc, 6, 144, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Refl. Rock Defense:", NULL, NULL }, + { jwin_text_proc, 6, 162, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Stomp Boots Defense:", NULL, NULL }, + { jwin_text_proc, 6, 180, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Byrna Beam Defense:", NULL, NULL }, + //161 + { jwin_droplist_proc, 126, 54-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 72-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 90-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 108-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 126-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 144-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 162-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 180-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 198-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 54-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 72-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 90-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 108-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 126-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 144-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 162-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_droplist_proc, 126, 180-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { jwin_button_proc, 255, 54-4, 48, 16, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Set All", NULL, NULL }, + //179 + { jwin_text_proc, 8, 162, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "BG Sound:", NULL, NULL }, + { jwin_text_proc, 8, 180, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hit Sound:", NULL, NULL }, + { jwin_text_proc, 8, 198, 45, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Death Sound:", NULL, NULL }, + //182 + { jwin_droplist_proc, 86, 158, 140, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &sfx__list, NULL, NULL }, + { jwin_droplist_proc, 86, 176, 140, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &sfx__list, NULL, NULL }, + { jwin_droplist_proc, 86, 194, 140, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &sfx__list, NULL, NULL }, + { jwin_text_proc, 6, 184, 95, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Spawn Animation:", NULL, NULL }, + { jwin_droplist_proc, 86, 180, 85, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &walkerspawn_list, NULL, NULL }, + { jwin_text_proc, 160, 126, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 11:", NULL, NULL }, + { jwin_text_proc, 160, 144, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Misc Attr. 12:", NULL, NULL }, + { jwin_edit_proc, 242, 122, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 242, 140, 65, 16, vc(12), vc(1), 0, 0, 6, 0, NULL, NULL, NULL }, + + // 191 + { jwin_text_proc, 6, 198, 80, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Script Weapon Defense:", NULL, NULL }, + { jwin_droplist_proc, 126, 198-4, 115, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &defense_list, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +void setEnemyLabels(int family) +{ + std::map *nmap = getEnemyNameMap(); + std::map::iterator it = nmap->find(family); + EnemyNameInfo *inf = NULL; + + if(it != nmap->end()) + inf = it->second; + + // Default labels + enedata_dlg[54].dp = (void*)"Misc. Attr. 1:"; + enedata_dlg[55].dp = (void*)"Misc. Attr. 2:"; + enedata_dlg[56].dp = (void*)"Misc. Attr. 3:"; + enedata_dlg[57].dp = (void*)"Misc. Attr. 4:"; + enedata_dlg[58].dp = (void*)"Misc. Attr. 5:"; + enedata_dlg[59].dp = (void*)"Misc. Attr. 6:"; + enedata_dlg[60].dp = (void*)"Misc. Attr. 7:"; + enedata_dlg[61].dp = (void*)"Misc. Attr. 8:"; + enedata_dlg[62].dp = (void*)"Misc. Attr. 9:"; + enedata_dlg[63].dp = (void*)"Misc. Attr. 10:"; + + if(family==eeKEESE || family==eeGHINI || family==eePEAHAT || family==eeMANHAN + || family==eeGLEEOK || family==eePATRA || family==eeDIG) + enedata_dlg[22].dp = (void*)"Turn Freq.:"; + else + enedata_dlg[22].dp = (void*)"Halt Rate:"; + + for(int i = 0; i < 10; i++) + { + if(inf != NULL) + { + if(inf->misc[i]!=NULL) + { + enedata_dlg[54+i].dp = inf->misc[i]; + //enedata_dlg[54+i].flags = enedata_dlg[64+i].flags = 0; + } + else + { + //enedata_dlg[64+i].flags = enedata_dlg[54+i].flags = D_DISABLED; + } + } + + if(inf != NULL && inf->list[i] != NULL) + { + enedata_dlg[64+i].proc = jwin_droplist_proc; + enedata_dlg[64+i].fg = jwin_pal[jcTEXTFG]; + enedata_dlg[64+i].bg = jwin_pal[jcTEXTBG]; + ((ListData*)inf->list[i])->font = (is_large ? &lfont_l : &font); + enedata_dlg[64+i].dp = inf->list[i]; + enedata_dlg[64+i].dp2 = NULL; + enedata_dlg[64+i].h = (is_large ? 22 : 16); + } + else + { + enedata_dlg[64+i].proc = jwin_edit_proc; + enedata_dlg[64+i].fg = vc(14); + enedata_dlg[64+i].bg = vc(1); + enedata_dlg[64+i].dp = NULL; + enedata_dlg[64+i].d1 = 6; + enedata_dlg[64+i].h = int(16 * (is_large ? 1.5 : 1)); + enedata_dlg[64+i].dp2 = (is_large ? lfont_l : font); + } + } + + bool r = 0 != get_bit(quest_rules,qr_NEWENEMYTILES); + enedata_dlg[r ? 47 : 48].flags |= D_DISABLED; + enedata_dlg[r ? 48 : 47].flags &= ~D_DISABLED; + enedata_dlg[r ? 140 : 141].flags |= D_DISABLED; + enedata_dlg[r ? 141 : 140].flags &= ~D_DISABLED; + + if(family==eeTRAP || family==eeROCK || family==eeDONGO || family==eeGANON) + { + for(int j=0; j <= edefBYRNA+1 /* + the Set All button*/; j++) enedata_dlg[j+161].flags |= D_DISABLED; + + enedata_dlg[192].flags |= D_DISABLED; + } + else + { + for(int j=0; j <= edefBYRNA+1 /* + the Set All button*/; j++) enedata_dlg[j+161].flags &= ~D_DISABLED; + + enedata_dlg[192].flags &= ~D_DISABLED; + } + + if(!(family==eeWALK || family==eeFIRE || family==eeOTHER)) + { + enedata_dlg[98].flags |= D_DISABLED; + enedata_dlg[99].flags |= D_DISABLED; + enedata_dlg[100].flags |= D_DISABLED; + enedata_dlg[101].flags |= D_DISABLED; + enedata_dlg[102].flags |= D_DISABLED; + enedata_dlg[186].flags |= D_DISABLED; + } + else + { + enedata_dlg[98].flags &= ~D_DISABLED; + enedata_dlg[99].flags &= ~D_DISABLED; + enedata_dlg[100].flags &= ~D_DISABLED; + enedata_dlg[101].flags &= ~D_DISABLED; + enedata_dlg[102].flags &= ~D_DISABLED; + enedata_dlg[186].flags &= ~D_DISABLED; + } +} + +int d_ecstile_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + int *tempint=enedata_flags2_list; + tempint=tempint; + + switch(msg) + { + case MSG_CLICK: + { + int f = -8; // Suppress Flip, but in a way that the lowest 3 bits are 0. (Trust me here.) -L + int t = d->d1; + int cs = d->d2; + + if(select_tile(t,f,1,cs,true)) + { + d->d1 = t; + enedata_dlg[2].d2 = cs; + enedata_dlg[3].d2 = cs; + enedata_dlg[4].d2 = cs; + return D_REDRAW; + } + } + break; + + case MSG_DRAW: + if(is_large) + { + d->w = 36; + d->h = 36; + } + + BITMAP *buf = create_bitmap_ex(8,20,20); + BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(d->d1) + overtile16(buf,d->d1,2,2,d->d2,0); + + stretch_blit(buf, bigbmp, 2,2, 17, 17, 2, 2, d->w-3, d->h-3); + destroy_bitmap(buf); + jwin_draw_frame(bigbmp,0,0,d->w,d->h,FR_DEEP); + blit(bigbmp,screen,0,0,d->x,d->y,d->w,d->h); + destroy_bitmap(bigbmp); + } + + // text_mode(d->bg); + break; + } + + return D_O_K; +} + +void edit_enemydata(int index) +{ + char hp[8], dp[8], wdp[8], rat[8], hrt[8], hom[8], grm[8], spd[8], + frt[8], efr[8], bsp[8]; + char w[8],h[8],sw[8],sh[8],ew[8],eh[8]; + char name[64]; + char ms[12][8]; + char enemynumstr[75]; + + //disable the missing dialog items! + //else they will lurk in the background + //stealing mouse focus -DD + for(int i=0; enedata_flags2_list[i] != -1; i++) + { + enedata_dlg[enedata_flags2_list[i]].proc = d_dummy_proc; + enedata_dlg[enedata_flags2_list[i]].x = 0; + enedata_dlg[enedata_flags2_list[i]].y = 0; + enedata_dlg[enedata_flags2_list[i]].w = 0; + enedata_dlg[enedata_flags2_list[i]].h = 0; + } + + sprintf(enemynumstr,"Enemy %d: %s", index, guy_string[index]); + enedata_dlg[0].dp = enemynumstr; + enedata_dlg[0].dp2 = lfont; + enedata_dlg[2].d1 = guysbuf[index].tile; + enedata_dlg[2].d2 = guysbuf[index].cset; + enedata_dlg[3].d1 = guysbuf[index].s_tile; + enedata_dlg[3].d2 = guysbuf[index].cset; + enedata_dlg[4].d1 = guysbuf[index].e_tile; + enedata_dlg[4].d2 = guysbuf[index].cset; + + // Enemy weapon list + if(guysbuf[index].weapon==wNone) + { + enedata_dlg[45].d1 = 0; + } + else + { + if(biew_cnt==-1) + { + build_biew_list(); + } + + for(int j=0; jlistFunc(-1,&size); + // Bound ms[i] as well as enedata_dlg[64+i].d1 + sprintf(ms[i],"%d",vbound(atoi(ms[i]), 0, size)); + enedata_dlg[64+i].d1 = atoi(ms[i]); + } + else + enedata_dlg[64+i].dp = ms[i]; + } + + enedata_dlg[189].dp = ms[10]; + enedata_dlg[190].dp = ms[11]; + + ret = zc_popup_dialog(enedata_dlg,3); + + test.tile = enedata_dlg[2].d1; + test.cset = enedata_dlg[2].d2; + test.s_tile = enedata_dlg[3].d1; + test.e_tile = enedata_dlg[4].d1; + + test.width = vbound(atoi(w),0,20); + test.height = vbound(atoi(h),0,20); + test.s_width = vbound(atoi(sw),0,20); + test.s_height = vbound(atoi(sh),0,20); + test.e_width = vbound(atoi(ew),0,20); + test.e_height = vbound(atoi(eh),0,20); + + test.weapon = enedata_dlg[45].d1 != 0 ? biew[enedata_dlg[45].d1].i + wEnemyWeapons : wNone; + test.family = bief[enedata_dlg[46].d1].i; + test.anim = biea[enedata_dlg[47].d1].i; + test.e_anim = biea[enedata_dlg[48].d1].i; + test.item_set = enedata_dlg[49].d1; + + test.hp = vbound(atoi(hp), 0, 32767); //0x7FFF, not 0xFFFF? + test.dp = vbound(atoi(dp), 0, 32767); + test.wdp = vbound(atoi(wdp), 0, 32767); + test.grumble = vbound(atoi(grm), 0, 4); + + test.rate = vbound(atoi(rat), 0, (test.family == eeFIRE || test.family == eeOTHER)?32767:16); + test.hrate = vbound(atoi(hrt), 0, (test.family == eeFIRE || test.family == eeOTHER)?32767:16); + test.homing = vbound(atoi(hom), 0, (test.family == eeFIRE || test.family == eeOTHER)?32767:256); + test.step = vbound(atoi(spd),0, (test.family == eeFIRE || test.family == eeOTHER)?32767:1000); + + test.frate = vbound(atoi(frt),0,256); + test.e_frate = vbound(atoi(efr),0,256); + test.bosspal = vbound(atoi(bsp),-1,29); + test.bgsfx = enedata_dlg[182].d1; + test.hitsfx = enedata_dlg[183].d1; + test.deadsfx = enedata_dlg[184].d1; + + test.misc1 = (enedata_dlg[64].proc==jwin_droplist_proc) ? enedata_dlg[64].d1 : atol(ms[0]); + test.misc2 = (enedata_dlg[65].proc==jwin_droplist_proc) ? enedata_dlg[65].d1 : atol(ms[1]); + test.misc3 = (enedata_dlg[66].proc==jwin_droplist_proc) ? enedata_dlg[66].d1 : atol(ms[2]); + test.misc4 = (enedata_dlg[67].proc==jwin_droplist_proc) ? enedata_dlg[67].d1 : atol(ms[3]); + test.misc5 = (enedata_dlg[68].proc==jwin_droplist_proc) ? enedata_dlg[68].d1 : atol(ms[4]); + test.misc6 = (enedata_dlg[69].proc==jwin_droplist_proc) ? enedata_dlg[69].d1 : atol(ms[5]); + test.misc7 = (enedata_dlg[70].proc==jwin_droplist_proc) ? enedata_dlg[70].d1 : atol(ms[6]); + test.misc8 = (enedata_dlg[71].proc==jwin_droplist_proc) ? enedata_dlg[71].d1 : atol(ms[7]); + test.misc9 = (enedata_dlg[72].proc==jwin_droplist_proc) ? enedata_dlg[72].d1 : atol(ms[8]); + test.misc10 = (enedata_dlg[73].proc==jwin_droplist_proc) ? enedata_dlg[73].d1 : atol(ms[9]); + test.misc11 = atol(ms[10]); + test.misc12 = atol(ms[11]); + + for(int j=0; j <= edefBYRNA; j++) + { + test.defense[j] = enedata_dlg[j+161].d1; + } + + test.defense[edefSCRIPT] = enedata_dlg[192].d1; + + + for(int i=0; i<32; i++) + test.flags |= (enedata_dlg[74+i].flags & D_SELECTED) ? (1<= 0) + { + //I can't get the fucking dialog to handle a simple copy paste so I stuck it here else I'm going to rage kill something. + //,,.Someone feel free to fix the thing properly later on. -Gleeok + if(key[KEY_OPENBRACE]) //copy + { + if(index != 0) + copiedGuy=index; + } + else if(key[KEY_CLOSEBRACE]) //paste + { + if(copiedGuy>0 && index!=0) + { + guysbuf[index]=guysbuf[copiedGuy]; + saved=false; + } + } + else + { + if(index != 0) + edit_enemydata(index); + } + + index = select_enemy("Select Enemy",index,true,true,foo); + } + + refresh(rMAP+rCOMBOS); + return D_O_K; +} + + +int onCustomGuys() +{ + return D_O_K; +} + +int d_ltile_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + //d1=dir + //d2=type (determines how to animate) + //fg=cset (6) + enum {lt_clock, lt_tile, lt_flip, lt_extend}; + static int bg=makecol(0, 0, 0); + int *p=(int*)d->dp3; + int oldtile=0; + int oldflip=0; + + switch(msg) + { + case MSG_START: + { + d->dp3=(int*)zc_malloc(sizeof(int)*4); + p=(int*)d->dp3; + p[lt_clock]=0; + p[lt_tile]=0; + p[lt_flip]=0; + p[lt_extend]=0; + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], d->d2, d->d1, zinit.linkanimationstyle); + break; + } + + case MSG_CLICK: + { + int t; + int f; + int extend; + int cs = 6; + linktile(&t, &f, &extend, d->d2, d->d1, zinit.linkanimationstyle); + + switch(extend) + { + case 0: + if(!isinRect(gui_mouse_x(),gui_mouse_y(),d->x+2+8, d->y+2+4, d->x+(16*(is_large+1))+8+2, d->y+(16+16*(is_large+1))+2)) + { + return D_O_K; + } + + break; + + case 1: + if(!isinRect(gui_mouse_x(),gui_mouse_y(),d->x+2+8, d->y+2+4, d->x+(16*(is_large+1))+8+2, d->y+(4+32*(is_large+1))+2)) + { + return D_O_K; + } + + break; + + case 2: + if(!isinRect(gui_mouse_x(),gui_mouse_y(),d->x+2+8, d->y+4, d->x+(32*(is_large+1))+8+2, d->y+(4+32*(is_large+1))+2)) + { + return D_O_K; + } + + break; + } + + if(select_tile(t,f,2,cs,false,extend, true)) + { + extend=ex; + setlinktile(t,f,extend,d->d2,d->d1); + return D_REDRAW; + } + } + break; + + case MSG_VSYNC: + oldtile=p[lt_tile]; + oldflip=p[lt_flip]; + p[lt_clock]++; + + switch(zinit.linkanimationstyle) + { + case las_original: //2-frame + switch(d->d2) + { + case ls_charge: + case ls_walk: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], d->d2, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=6) + { + if(d->d1==up&&d->d2==ls_walk) + { + p[lt_flip]=1; //h flip + } + else + { + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + } + }; + + if(p[lt_clock]>=11) + { + p[lt_clock]=-1; + } + + break; + + case ls_jump: + if(p[lt_clock]>=24) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=36) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_jump, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=p[lt_extend]==2?((int)p[lt_clock]/8)*2:((int)p[lt_clock]/8); + } + + break; + + case ls_slash: + if(p[lt_clock]<6) + { + linktile(&p[lt_tile], &p[lt_flip], ls_slash, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<13) + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + + if(p[lt_clock]>=16) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_stab: + if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<13) + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + + if(p[lt_clock]>=16) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_pound: + if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_pound, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<30) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=31) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_float: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=12) + { + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + }; + + if(p[lt_clock]>=23) + { + p[lt_clock]=-1; + } + + break; + + case ls_swim: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_swim, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=12) + { + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + }; + + if(p[lt_clock]>=23) + { + p[lt_clock]=-1; + } + + break; + + case ls_dive: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_dive, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=50) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + }; + + if((p[lt_clock]/12)&1) + { + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + }; + + if(p[lt_clock]>=81) + { + p[lt_clock]=-1; + } + + break; + + case ls_landhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_landhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_cast: + linktile(&p[lt_tile], &p[lt_flip], ls_cast, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]<96) + { + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + }; + + if(p[lt_clock]>=194) + { + p[lt_clock]=-1; + } + + break; + + default: + break; + } + + break; + + case las_bszelda: //3-frame BS + switch(d->d2) + { + case ls_charge: + case ls_walk: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], d->d2, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=anim_3_4(p[lt_clock],7)*(p[lt_extend]==2?2:1); + + if(p[lt_clock]>=27) + { + p[lt_clock]=-1; + } + + break; + + case ls_jump: + if(p[lt_clock]>=24) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=36) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_jump, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=p[lt_extend]==2?((int)p[lt_clock]/8)*2:((int)p[lt_clock]/8); + } + + break; + + case ls_slash: + if(p[lt_clock]<6) + { + linktile(&p[lt_tile], &p[lt_flip], ls_slash, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<13) + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + + if(p[lt_clock]>=16) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_stab: + if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<13) + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + p[lt_extend]==2?p[lt_tile]+=2:p[lt_tile]++; //tile++ + + if(p[lt_clock]>=16) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_pound: + if(p[lt_clock]<12) + { + linktile(&p[lt_tile], &p[lt_flip], ls_pound, d->d1, zinit.linkanimationstyle); + } + else if(p[lt_clock]<30) + { + linktile(&p[lt_tile], &p[lt_flip], ls_stab, d->d1, zinit.linkanimationstyle); + } + else + { + linktile(&p[lt_tile], &p[lt_flip], ls_walk, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=31) + { + p[lt_clock]=-1; + } + }; + + break; + + case ls_float: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=anim_3_4(p[lt_clock],7)*(p[lt_extend]==2?2:1); + + if(p[lt_clock]>=55) + { + p[lt_clock]=-1; + } + + break; + + case ls_swim: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_swim, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=anim_3_4(p[lt_clock],7)*(p[lt_extend]==2?2:1); + + if(p[lt_clock]>=55) + { + p[lt_clock]=-1; + } + + break; + + case ls_dive: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_dive, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=50) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + }; + + p[lt_tile]+=anim_3_4(p[lt_clock],7)*(p[lt_extend]==2?2:1); + + if(p[lt_clock]>=81) + { + p[lt_clock]=-1; + } + + break; + + case ls_landhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_landhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_cast: + linktile(&p[lt_tile], &p[lt_flip], ls_cast, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]<96) + { + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + }; + + if(p[lt_clock]>=194) + { + p[lt_clock]=-1; + } + + break; + + default: + break; + } + + break; + + case las_zelda3slow: //multi-frame Zelda 3 (slow) + case las_zelda3: //multi-frame Zelda 3 + switch(d->d2) + { + case ls_charge: + case ls_walk: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], d->d2, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=(64*(link_animation_speed))) + { + p[lt_tile]+=(p[lt_extend]==2?2:1); + + int l=((p[lt_clock]/link_animation_speed)&15); + l-=((l>3)?1:0)+((l>12)?1:0); + p[lt_tile]+=(l/2)*(p[lt_extend]==2?2:1); + + //p[lt_tile]+=(((p[lt_clock]>>2)%8)*(p[lt_extend]==2?2:1)); + if(p[lt_clock]>=255) + { + p[lt_clock]=-1; + } + } + + break; + + case ls_jump: + if(p[lt_clock]>=24) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=36) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_jump, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=p[lt_extend]==2?((int)p[lt_clock]/8)*2:((int)p[lt_clock]/8); + } + + break; + + case ls_slash: + if(p[lt_clock]>23) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_slash, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=(((p[lt_clock]>>2)%6)*(p[lt_extend]==2?2:1)); + + if(p[lt_clock]>=47) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + } + + break; + + case ls_stab: + if(p[lt_clock]>35) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_stab, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=(((p[lt_clock]>>2)%3)*(p[lt_extend]==2?2:1)); + + if(p[lt_clock]>=47) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + } + + break; + + case ls_pound: + if(p[lt_clock]>35) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_pound, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=(((p[lt_clock]>>2)%3)*(p[lt_extend]==2?2:1)); + + if(p[lt_clock]>=47) + { + p[lt_clock]=-1; + } + } + else + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_walk, d->d1, zinit.linkanimationstyle); + } + + break; + + case ls_float: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=((p[lt_clock]/6)%4)<<(p[lt_extend]==2?1:0); + + if(p[lt_clock]>=23) + { + p[lt_clock]=-1; + } + + break; + + case ls_swim: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_swim, d->d1, zinit.linkanimationstyle); + p[lt_tile]+=((p[lt_clock]/12)%4)<<(p[lt_extend]==2?1:0); + + if(p[lt_clock]>=47) + { + p[lt_clock]=-1; + } + + break; + + case ls_dive: + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_dive, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]>=50) + { + linktile(&p[lt_tile], &p[lt_flip], &p[lt_extend], ls_float, d->d1, zinit.linkanimationstyle); + }; + + p[lt_tile]+=((p[lt_clock]/6)%4)<<(p[lt_extend]==2?1:0); + + if(p[lt_clock]>=81) + { + p[lt_clock]=-1; + } + + break; + + case ls_landhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_landhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold1: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold1, d->d1, zinit.linkanimationstyle); + break; + + case ls_waterhold2: + linktile(&p[lt_tile], &p[lt_flip], ls_waterhold2, d->d1, zinit.linkanimationstyle); + break; + + case ls_cast: + linktile(&p[lt_tile], &p[lt_flip], ls_cast, d->d1, zinit.linkanimationstyle); + + if(p[lt_clock]<96) + { + linktile(&p[lt_tile], &p[lt_flip], ls_landhold2, d->d1, zinit.linkanimationstyle); + }; + + if(p[lt_clock]>=194) + { + p[lt_clock]=-1; + } + + break; + + default: + break; + } + + break; + + default: + break; + } + + if((p[lt_tile]!=oldtile)||(p[lt_flip]!=oldflip)) + { + d->flags|=D_DIRTY; + } + + break; + + case MSG_DRAW: + { + BITMAP *buf=create_bitmap_ex(8,1,1); + BITMAP *buf2=buf; + int dummy1, dummy2; + int extend; + linktile(&dummy1, &dummy2, &extend, d->d2, d->d1, zinit.linkanimationstyle); + int w = 16; + int h = 16; + + switch(extend) + { + case 0: //16x16 + break; + + case 1: //16x32 + w = 16; + h = 32; + break; + + case 2: //32x32 + w = 32; + h = 32; + break; + + default: + break; + } + + buf = create_bitmap_ex(8,w,h); + + if(is_large) + { + w *= 2; + h *= 2; + } + + BITMAP *bigbmp = create_bitmap_ex(8,w+4,h+4); + + if(buf && bigbmp) + { + clear_to_color(buf, bg); + + switch(extend) + { + case 0: + overtile16(buf,p[lt_tile],0,0,6,p[lt_flip]); + stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, w, h); + jwin_draw_frame(bigbmp,0, 0, w+4, h+4, FR_DEEP); + blit(bigbmp,screen,0,0,d->x+8,d->y+4,w+4,h+4); + break; + + case 1: + overtile16(buf,p[lt_tile]-TILES_PER_ROW,0,0,6,p[lt_flip]); + overtile16(buf,p[lt_tile],0,16,6,p[lt_flip]); + stretch_blit(buf, bigbmp, 0,0, 16, 32, 2, 2, w, h); + jwin_draw_frame(bigbmp,0, 0, w+4, h+4, FR_DEEP); + blit(bigbmp,screen,0,0,d->x+8,d->y+4,w+4,h+4); + break; + + case 2: + overtile16(buf,p[lt_tile]-TILES_PER_ROW,8,0,6,p[lt_flip]); //top middle + overtile16(buf,p[lt_tile]-TILES_PER_ROW-(p[lt_flip]?-1:1),-8,0,6,p[lt_flip]); //top left + overtile16(buf,p[lt_tile]-TILES_PER_ROW+(p[lt_flip]?-1:1),8+16,0,6,p[lt_flip]); //top right + overtile16(buf,p[lt_tile]-(p[lt_flip]?-1:1),-8,18,6,p[lt_flip]); //bottom left + overtile16(buf,p[lt_tile]+(p[lt_flip]?-1:1),8+16,18,6,p[lt_flip]); //bottom right + overtile16(buf,p[lt_tile],8,16,6,p[lt_flip]); //bottom middle + stretch_blit(buf, bigbmp, 0,0, 32, 32, 2, 2, w, h); + jwin_draw_frame(bigbmp,0, 0, w+4, h+4, FR_DEEP); + blit(bigbmp,screen,0,0,d->x+8,d->y+4,w+4,h+4); + break; + + default: + break; + } + + destroy_bitmap(bigbmp); + destroy_bitmap(buf); + destroy_bitmap(buf2); + } + } + break; + + case MSG_END: + { + zc_free(d->dp3); + break; + } + } + + return D_O_K; +} + +static int linktile_land_walk_list[] = +{ + // dialog control number + 11, 12, 13, 14, 15, 16, 17, 18, -1 +}; + +static int linktile_land_slash_list[] = +{ + // dialog control number + 19, 20, 21, 22, 23, 24, 25, 26, -1 +}; + +static int linktile_land_stab_list[] = +{ + // dialog control number + 27, 28, 29, 30, 31, 32, 33, 34, -1 +}; + +static int linktile_land_pound_list[] = +{ + // dialog control number + 35, 36, 37, 38, 39, 40, 41, 42, -1 +}; + +static int linktile_land_hold_list[] = +{ + // dialog control number + 43, 44, 45, 46, -1 +}; + +static int linktile_land_cast_list[] = +{ + // dialog control number + 47, -1 +}; + +static int linktile_land_jump_list[] = +{ + // dialog control number + 77, 78, 79, 80, 81, 82, 83, 84, -1 +}; + +static int linktile_land_charge_list[] = +{ + // dialog control number + 85, 86, 87, 88, 89, 90, 91, 92, -1 +}; + +static TABPANEL linktile_land_tabs[] = +{ + // (text) + { (char *)"Walk", D_SELECTED, linktile_land_walk_list, 0, NULL }, + { (char *)"Slash", 0, linktile_land_slash_list, 0, NULL }, + { (char *)"Stab", 0, linktile_land_stab_list, 0, NULL }, + { (char *)"Pound", 0, linktile_land_pound_list, 0, NULL }, + { (char *)"Jump", 0, linktile_land_jump_list, 0, NULL }, + { (char *)"Charge", 0, linktile_land_charge_list, 0, NULL }, + { (char *)"Hold", 0, linktile_land_hold_list, 0, NULL }, + { (char *)"Cast", 0, linktile_land_cast_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static int linktile_water_float_list[] = +{ + // dialog control number + 48, 49, 50, 51, 52, 53, 54, 55, -1 +}; + +static int linktile_water_swim_list[] = +{ + // dialog control number + 56, 57, 58, 59, 60, 61, 62, 63, -1 +}; + +static int linktile_water_dive_list[] = +{ + // dialog control number + 64, 65, 66, 67, 68, 69, 70, 71, -1 +}; + +static int linktile_water_hold_list[] = +{ + // dialog control number + 72, 73, 74, 75, -1 +}; + +static TABPANEL linktile_water_tabs[] = +{ + // (text) + { (char *)"Float", D_SELECTED, linktile_water_float_list, 0, NULL }, + { (char *)"Swim", 0, linktile_water_swim_list, 0, NULL }, + { (char *)"Dive", 0, linktile_water_dive_list, 0, NULL }, + { (char *)"Hold", 0, linktile_water_hold_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static int linktile_land_list[] = +{ + // dialog control number + 9, -1 +}; + +static int linktile_water_list[] = +{ + // dialog control number + 10, -1 +}; + +static TABPANEL linktile_tabs[] = +{ + // (text) + { (char *)"Land", D_SELECTED, linktile_land_list, 0, NULL }, + { (char *)"Water", 0, linktile_water_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +const char *animationstyles[las_max]= { "Original", "BS-Zelda", "Zelda 3", "Zelda 3 (Slow Walk)" }; + +const char *animationstylelist(int index, int *list_size) +{ + if(index>=0) + { + return animationstyles[index]; + } + + *list_size=las_max; + return NULL; +} + +const char *swimspeeds[2]= { "Slow", "Fast" }; + +const char *swimspeedlist(int index, int *list_size) +{ + if(index>=0) + { + return swimspeeds[index]; + } + + *list_size=2; + return NULL; +} + +int jwin_as_droplist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_droplist_proc(msg,d,c); + + switch(msg) + { + case MSG_CHAR: + case MSG_CLICK: + zinit.linkanimationstyle=d->d1; + + if(zinit.linkanimationstyle==las_zelda3slow) + { + link_animation_speed=2; + } + else + { + link_animation_speed=1; + } + } + + return ret; +} + +static ListData animationstyle_list(animationstylelist, &font); +static ListData swimspeed_list(swimspeedlist, &font); + +static DIALOG linktile_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 320, 240, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Link Sprites", NULL, NULL }, + { d_vsync_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { jwin_button_proc, 90, 215, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 215, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 5 + { jwin_check_proc, 217, 200, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Large Link Hit Box", NULL, NULL }, + { jwin_text_proc, 4, 201, 17, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Animation Style:", NULL, NULL }, + { jwin_as_droplist_proc, 77, 197, 78, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &animationstyle_list, NULL, NULL }, + { jwin_tab_proc, 4, 25, 312, 150, 0, 0, 0, 0, 0, 0, (void *) linktile_tabs, NULL, (void *)linktile_dlg }, + // 9 + { jwin_tab_proc, 7, 46, 305, 125, 0, 0, 0, 0, 0, 0, (void *) linktile_land_tabs, NULL, (void *)linktile_dlg }, + { jwin_tab_proc, 7, 46, 305, 125, 0, 0, 0, 0, 0, 0, (void *) linktile_water_tabs, NULL, (void *)linktile_dlg }, + // 11 (walk sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 15 (walk sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_walk, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_walk, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_walk, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_walk, NULL, NULL, NULL }, + // 19 (slash spritetitles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 23 (slash sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_slash, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_slash, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_slash, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_slash, NULL, NULL, NULL }, + // 27 (stab sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 31 (stab sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_stab, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_stab, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_stab, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_stab, NULL, NULL, NULL }, + // 35 (pound sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 39 (pound sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_pound, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_pound, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_pound, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_pound, NULL, NULL, NULL }, + // 43 (hold sprite titles) + { jwin_rtext_proc, 67, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "One Hand", NULL, NULL }, + { jwin_rtext_proc, 67, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Two Hands", NULL, NULL }, + // 45 (hold sprites) + { d_ltile_proc, 70, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_landhold1, NULL, NULL, NULL }, + { d_ltile_proc, 70, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_landhold2, NULL, NULL, NULL }, + // 47 (casting sprites) + { d_ltile_proc, 70, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_cast, NULL, NULL, NULL }, + + // 48 (float sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 52 (float sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_float, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_float, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_float, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_float, NULL, NULL, NULL }, + // 56 (swim sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 60 (swim sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_swim, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_swim, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_swim, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_swim, NULL, NULL, NULL }, + // 64 (dive sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 68 (dive sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_dive, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_dive, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_dive, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_dive, NULL, NULL, NULL }, + // 72 (hold sprite titles) + { jwin_rtext_proc, 67, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "One Hand", NULL, NULL }, + { jwin_rtext_proc, 67, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Two Hands", NULL, NULL }, + // 74 (hold sprites) + { d_ltile_proc, 70, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_waterhold1, NULL, NULL, NULL }, + { d_ltile_proc, 70, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_waterhold2, NULL, NULL, NULL }, + { jwin_check_proc, 217, 186, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Diagonal Movement", NULL, NULL }, + // 77 (jump sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 81 (jump sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_jump, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_jump, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_jump, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_jump, NULL, NULL, NULL }, + // 85 (charge sprite titles) + { jwin_rtext_proc, 33, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up", NULL, NULL }, + { jwin_rtext_proc, 101, 88, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down", NULL, NULL }, + { jwin_rtext_proc, 33, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left", NULL, NULL }, + { jwin_rtext_proc, 101, 126, 32, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right", NULL, NULL }, + // 89 (charge sprites) + { d_ltile_proc, 36, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, up, ls_charge, NULL, NULL, NULL }, + { d_ltile_proc, 104, 74, 40, 40, 6, jwin_pal[jcBOX], 0, 0, down, ls_charge, NULL, NULL, NULL }, + { d_ltile_proc, 36, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, left, ls_charge, NULL, NULL, NULL }, + { d_ltile_proc, 104, 112, 40, 40, 6, jwin_pal[jcBOX], 0, 0, right, ls_charge, NULL, NULL, NULL }, + // 93 + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 4, 183, 17, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Swim Speed:", NULL, NULL }, + { jwin_droplist_proc, 77, 179, 78, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &swimspeed_list, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + +int onCustomLink() +{ + //setuplinktiles(zinit.linkanimationstyle); + if(zinit.linkanimationstyle==las_zelda3slow) + { + link_animation_speed=2; + } + else + { + link_animation_speed=1; + } + + linktile_dlg[0].dp2=lfont; + linktile_dlg[5].flags = get_bit(quest_rules, qr_LTTPCOLLISION)? D_SELECTED : 0; + linktile_dlg[76].flags = get_bit(quest_rules, qr_LTTPWALK)? D_SELECTED : 0; + linktile_dlg[95].d1=(zinit.link_swim_speed<60)?0:1; + linktile_dlg[7].d1=zinit.linkanimationstyle; + + if(is_large) + large_dialog(linktile_dlg, 2.0); + + int oldWalkSpr[4][3]; + int oldStabSpr[4][3]; + int oldSlashSpr[4][3]; + int oldFloatSpr[4][3]; + int oldSwimSpr[4][3]; + int oldDiveSpr[4][3]; + int oldPoundSpr[4][3]; + int oldJumpSpr[4][3]; + int oldChargeSpr[4][3]; + int oldCastSpr[3]; + int oldHoldSpr[2][2][3]; + memcpy(oldWalkSpr, walkspr, 4*3*sizeof(int)); + memcpy(oldStabSpr, stabspr, 4*3*sizeof(int)); + memcpy(oldSlashSpr, slashspr, 4*3*sizeof(int)); + memcpy(oldFloatSpr, floatspr, 4*3*sizeof(int)); + memcpy(oldSwimSpr, swimspr, 4*3*sizeof(int)); + memcpy(oldDiveSpr, divespr, 4*3*sizeof(int)); + memcpy(oldPoundSpr, poundspr, 4*3*sizeof(int)); + memcpy(oldJumpSpr, jumpspr, 4*3*sizeof(int)); + memcpy(oldChargeSpr, chargespr, 4*3*sizeof(int)); + memcpy(oldCastSpr, castingspr, 3*sizeof(int)); + memcpy(oldHoldSpr, holdspr, 2*2*3*sizeof(int)); + + + int ret = popup_dialog_through_bitmap(screen2,linktile_dlg,3); + + if(ret==3) + { + saved=false; + set_bit(quest_rules, qr_LTTPCOLLISION, (linktile_dlg[5].flags&D_SELECTED)?1:0); + set_bit(quest_rules, qr_LTTPWALK, (linktile_dlg[76].flags&D_SELECTED)?1:0); + zinit.link_swim_speed=(linktile_dlg[95].d1==0)?50:67; + } + else + { + memcpy(walkspr, oldWalkSpr, 4*3*sizeof(int)); + memcpy(stabspr, oldStabSpr, 4*3*sizeof(int)); + memcpy(slashspr, oldSlashSpr, 4*3*sizeof(int)); + memcpy(floatspr, oldFloatSpr, 4*3*sizeof(int)); + memcpy(swimspr, oldSwimSpr, 4*3*sizeof(int)); + memcpy(divespr, oldDiveSpr, 4*3*sizeof(int)); + memcpy(poundspr, oldPoundSpr, 4*3*sizeof(int)); + memcpy(jumpspr, oldJumpSpr, 4*3*sizeof(int)); + memcpy(chargespr, oldChargeSpr, 4*3*sizeof(int)); + memcpy(castingspr, oldCastSpr, 3*sizeof(int)); + memcpy(holdspr, oldHoldSpr, 2*2*3*sizeof(int)); + } + + ret=ret; + return D_O_K; +} + +void center_zq_custom_dialogs() +{ + jwin_center_dialog(itemdata_dlg); + jwin_center_dialog(linktile_dlg); + jwin_center_dialog(wpndata_dlg); + jwin_center_dialog(enedata_dlg); +} + diff --git a/src/zq_custom.h b/src/zq_custom.h new file mode 100644 index 0000000000..1044d7796b --- /dev/null +++ b/src/zq_custom.h @@ -0,0 +1,48 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_custom.cc +// +// Custom item, enemy, etc. for ZQuest. +// +//-------------------------------------------------------- + +#ifndef _ZQ_CUSTOM_H_ +#define _ZQ_CUSTOM_H_ + +void large_dialog(DIALOG *d); +void large_dialog(DIALOG *d, float RESIZE_AMT); +int d_cstile_proc(int msg,DIALOG *d,int c); +int jwin_as_droplist_proc(int msg,DIALOG *d,int c); + +struct list_data_struct +{ + char *s; + int i; +}; + +/*****************************/ +/****** onCustomItems ******/ +/*****************************/ + +void test_item(itemdata test); +void edit_itemdata(int index); +int onCustomItems(); + +/****************************/ +/****** onCustomWpns ******/ +/****************************/ + +enum { ws_2_frame, ws_3_frame, ws_max }; + +void edit_weapondata(int index); +int onCustomWpns(); +int onCustomEnemies(); +void edit_enemydata(int index); +int onCustomGuys(); +int d_ltile_proc(int msg,DIALOG *d,int c); +int onCustomLink(); +void center_zq_custom_dialogs(); +#endif + diff --git a/src/zq_doors.cpp b/src/zq_doors.cpp new file mode 100644 index 0000000000..42eb973911 --- /dev/null +++ b/src/zq_doors.cpp @@ -0,0 +1,1705 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include + +#include "gui.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "jwin.h" +#include "zsys.h" +#include "zc_sys.h" +#include "zq_misc.h" +#include "tiles.h" +#include "zq_class.h" +#include "zq_tiles.h" +#include "zquest.h" + +extern void large_dialog(DIALOG *d, float RESIZE_AMT); +extern int d_dummy_proc(int msg,DIALOG *d,int c); +extern int d_combo_proc(int msg,DIALOG *d,int c); +extern int select_data(const char *prompt,int index,const char *(proc)(int,int*), FONT *title_font); +extern void refresh(int flags); +DoorComboSet *DoorComboSets; +extern void restore_mouse(); +extern std::vector TheMaps; +extern zquestheader header; +extern word map_count; +extern int d_timer_proc(int msg, DIALOG *d, int c); + + +extern FONT *lfont; + +extern int onHelp(); +extern int jwin_pal[jcMAX]; +extern bool saved; + +word door_combo_set_count; + + + +const char *doors_string[8]= {"Wall","Open","Locked","Shutter","Bombable","Walk-through","1-Way Shutter","Boss"}; + +const char *doorslist(int index, int *list_size) +{ + if(index>=0) + { + if(index>7) + index=7; + + return doors_string[index]; + } + + *list_size=8; + return NULL; +} + +static const char *sidestr[4] = {"Top","Bottom","Left","Right"}; + +int door_to_index(int door) +{ + switch(door) + { + case 1: + case 2: + return door; + + case 4: + return 3; + + case 6: + return 4; + + case 8: + return 5; + + case 14: + return 6; + + case 10: + return 7; + } + + return 0; +} + +void edit_door(int side) +{ + int index=door_to_index(Map.CurrScr()->door[side]); + char sidename[80]; + sprintf(sidename, "Select %s Door Type", sidestr[side]); + int ret=select_data(sidename,index,doorslist,lfont); + + if(ret!=-1) + { + switch(ret) + { + case 0: + case 1: + case 2: + index=ret; + break; + + case 3: + index=4; + break; + + case 4: + index=6; + break; + + case 5: + index=8; + break; + + case 6: + index=14; + break; + + case 7: + index=10; + break; + + default: + index=0; + } + + saved=false; + // Map.Ugo(); + Map.putdoor(side,index); + refresh(rMAP | rNOCURSOR); + } +} + +const char *doorcombosetlist(int index, int *list_size); + +static ListData doorcomboset_list(&doorcombosetlist, &font); + +static DIALOG door_select_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 40, 32, 240, 164, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Door", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 119, 79, 81, 15, vc(14), vc(9), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 119, 125, 81, 15, vc(14), vc(9), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 69, 102, 75, 15, vc(14), vc(9), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 175, 102, 75, 15, vc(14), vc(9), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 86, 171, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 171, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 64, 142, 120, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Door Combo Set:", NULL, NULL }, + { jwin_droplist_proc, 64, 150, 192, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &doorcomboset_list, NULL, NULL }, + { jwin_text_proc, 48, 59, 150, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Note: This only applies to 'NES Dungeon' screens!", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +int onDoors() +{ + restore_mouse(); + door_select_dlg[0].dp2 = lfont; + + if(Map.getCurrScr()==TEMPLATE) + return D_O_K; + + if(Map.getCurrMap()>=Map.getMapCount()) + return D_O_K; + + Map.Ugo(); + bool done=false; + int ret=0; + door_select_dlg[9].d1=Map.CurrScr()->door_combo_set; + + // Put the names of the door types on the buttons. + for(int i=0; i<4; i++) + { + door_select_dlg[i+2].dp = (void *)doors_string[door_to_index(Map.CurrScr()->door[i])]; + } + + // so as not to always override other combos if there was no change in door type + byte old_door[4]; + + for(int i=0; i<4; i++) + old_door[i] = Map.CurrScr()->door[i]; + + if(is_large) + large_dialog(door_select_dlg, 1.5); + + do + { + ret = zc_popup_dialog(door_select_dlg,-1); + Map.CurrScr()->door_combo_set=door_select_dlg[9].d1; + + switch(ret) + { + case 2: + case 3: + case 4: + case 5: + edit_door(ret-2); + door_select_dlg[ret].dp = (void *)doors_string[door_to_index(Map.CurrScr()->door[ret-2])]; + break; + + case 6: + for(int i=0; i<4; i++) + { + if(old_door[i] != Map.CurrScr()->door[i]) + Map.putdoor(i,Map.CurrScr()->door[i]); + } + + done=true; + break; + + case 0: + case 7: + for(int i=0; i<4; i++) + { + Map.putdoor(i,Map.CurrScr()->door[i]); + } + + Map.Uhuilai(); + done=true; + } + } + while(!done); + + return D_O_K; +} + +/************************************/ +/********** onDoorCombos **********/ +/************************************/ + +/* + word doorcombo_u[7][4]; //[door type][door combo] + byte doorcset_u[7][4]; //[door type][door combo] + word doorcombo_d[7][4]; //[door type][door combo] + byte doorcset_d[7][4]; //[door type][door combo] + word doorcombo_l[7][6]; //[door type][door combo] + byte doorcset_l[7][6]; //[door type][door combo] + word doorcombo_r[7][6]; //[door type][door combo] + byte doorcset_r[7][6]; //[door type][door combo] + word bombdoorcombo_u[6]; //[door type][door combo] + byte bombdoorcset_u[6]; //[door type][door combo] + word bombdoorcombo_d[6]; //[door type][door combo] + byte bombdoorcset_d[6]; //[door type][door combo] + word bombdoorcombo_l[9]; //[door type][door combo] + byte bombdoorcset_l[9]; //[door type][door combo] + word bombdoorcombo_r[9]; //[door type][door combo] + byte bombdoorcset_r[9]; //[door type][door combo] + word walkthroughcombo[4]; //[n, s, e, w] + byte walkthroughcset[4]; //[n, s, e, w] + */ + +DoorComboSet working_dcs; + +void fix_dcs(int dir) +{ + switch(dir) + { + case up: + { + //first combo copying + for(int i=0; i=0) + { + if(index>=door_combo_set_count) + index=door_combo_set_count-1; + + return DoorComboSets[index].name; + } + + *list_size=door_combo_set_count; + return NULL; +} + +int doorcombosetlist_del(); +int copydcs(); +int pastedcs(); +int replacedcs(); + +static ListData doorcombosetlist_dlg_list(doorcombosetlist, &font); + +static DIALOG doorcombosetlist_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 52, 40, 216+1, 150, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Edit Door Combo Set", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_list_proc, 68, 65, 185, 96, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &doorcombosetlist_dlg_list, NULL, NULL }, + { jwin_button_proc, 90, 165, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 165, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, 0, (void *) doorcombosetlist_del, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'c', 0, 0, 0, (void *) copydcs, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'v', 0, 0, 0, (void *) pastedcs, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'r', 0, 0, 0, (void *) replacedcs, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void reset_doorcomboset(int index); +void fix_door_combo_set(word &door_combo_set, byte index); + +int doorcombosetlist_del() +{ + char buf[25]; + int d=doorcombosetlist_dlg[2].d1; + + if((d>0 || door_combo_set_count>2) && d index) + --door_combo_set; +} + + +void reset_doorcomboset(int index) +{ + bound(index,0,MAXDOORCOMBOSETS-1); + memset(&DoorComboSets[index], 0, sizeof(DoorComboSet)); +} + +void init_doorcombosets() +{ + for(int i=0; i"); + } + + if(is_large) + large_dialog(doorcombosetlist_dlg,1.5); + + int ret=zc_popup_dialog(doorcombosetlist_dlg,2); + index=doorcombosetlist_dlg[2].d1; + + int doedit=false; + + switch(ret) + { + case 2: + case 3: + doedit=true; + break; + + case 0: + case 4: + index=-1; + break; + } + + if(hasroom) + memset(DoorComboSets[--door_combo_set_count].name,0,sizeof(DoorComboSets[0].name)); + + if(doedit) + { + editdoorcomboset(index); + refresh(rMENU); + } + } + + comeback(); + return D_O_K; +} + +void center_zq_door_dialogs() +{ + jwin_center_dialog(door_select_dlg); + jwin_center_dialog(doorcomboset_dlg); + jwin_center_dialog(doorcombosetlist_dlg); +} + diff --git a/src/zq_doors.h b/src/zq_doors.h new file mode 100644 index 0000000000..cca5283111 --- /dev/null +++ b/src/zq_doors.h @@ -0,0 +1,14 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- + +extern int onDoors(); +extern int onDoorCombos(); +extern void center_zq_door_dialogs(); + diff --git a/src/zq_files.cpp b/src/zq_files.cpp new file mode 100644 index 0000000000..74e8cfe97b --- /dev/null +++ b/src/zq_files.cpp @@ -0,0 +1,1558 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_files.cc +// +// File support for ZQuest. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include + +#include "gui.h" +#include "zq_files.h" +#include "zdefs.h" +#include "zq_misc.h" +#include "zquest.h" +#include "qst.h" +#include "zsys.h" +#include "zq_class.h" +#include "tiles.h" +#include "zq_tiles.h" +#include "zq_custom.h" +#include "zc_malloc.h" + +#ifdef _MSC_VER +#define getcwd _getcwd +#define stricmp _stricmp +#define strupr _strupr +#endif + +char qtbuf[31]; + +void reset_qt(int index) +{ + bound(index,0,MAXQTS-1); + char *s=QuestTemplates[index].name; + + for(int i=0; i<31; i++) + *(s++)=0; + + s=QuestTemplates[index].path; + + for(int i=0; i<2048; i++) + *(s++)=0; +} + +void init_qts() +{ + for(int i=0; i=0) + { + if(index>=qt_count) + index=qt_count-1; + + return QuestTemplates[index].name; + } + + *list_size=qt_count; + return NULL; +} + +static ListData qtlist_dlg_list(qtlist, &font); + +static DIALOG qtlist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 303, 149, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Pick Quest Template", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_list_proc, 5, 26, 271, 87, jwin_pal[jcBOXFG], jwin_pal[jcLIGHT], 0, D_EXIT, 0, 0, (void *) &qtlist_dlg_list, NULL, NULL }, + { jwin_button_proc, 278, 44, 21, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { jwin_button_proc, 278, 73, 21, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + { jwin_button_proc, 30, 120, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 110, 120, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 190, 120, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, 0, (void *) qtlist_del, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int qtlist_del() +{ + if(qtlist_dlg[2].d1>0 && qtlist_dlg[2].d1-1) + { + bool hasroom=false; + + if(qt_count"); + } + } + + if(is_large) + large_dialog(qtlist_dlg); + + qtlist_dlg[2].x=int(qtlist_dlg[0].x+(edit?5:15)*(is_large?1.5:1)); + qtlist_dlg[3].proc=edit?jwin_button_proc:d_dummy_proc; + qtlist_dlg[4].proc=edit?jwin_button_proc:d_dummy_proc; + qtlist_dlg[5].proc=edit?jwin_button_proc:d_dummy_proc; + qtlist_dlg[6].x=int(qtlist_dlg[0].x+(edit?110:80)*(is_large?1.5:1)); + qtlist_dlg[7].x=int(qtlist_dlg[0].x+(edit?190:160)*(is_large?1.5:1)); + qtlist_dlg[8].proc=edit?d_keyboard_proc:d_dummy_proc; + + int ret=zc_popup_dialog(qtlist_dlg,2); + + index=qtlist_dlg[2].d1; + + int doedit=false; + + switch(ret) + { + case 2: + if(edit) + { + doedit=true; + } + else + { + if(index>0&&!valid_zqt(QuestTemplates[index].path)) + { + jwin_alert("ZQuest","Invalid Quest Template",NULL,NULL,"O&K",NULL,'k',0,lfont); + } + else + { + strcpy(header.templatepath, QuestTemplates[index].path); + index=-1; + } + } + + break; + + case 5: + doedit=true; + break; + + case 3: + if(index>1&&index0&&index0&&!valid_zqt(QuestTemplates[index].path)) + { + jwin_alert("ZQuest","Invalid Quest Template",NULL,NULL,"O&K",NULL,'k',0,lfont); + } + else + { + if(!edit) + { + strcpy(header.templatepath, QuestTemplates[index].path); + } + + index=-1; + } + + break; + + case 0: + case 7: + if(edit) + { + qt_count=backup_qt_count+1; + memcpy(QuestTemplates,BackupQTs,sizeof(quest_template)*qt_count); + } + + index=-2; + break; + + case 8: + char buf[30]; + strncpy(buf,QuestTemplates[index].name,30); + + if(jwin_alert("Confirm Deletion", "Delete this quest template?",buf,"(The file will still exist.)","Yes","No",'y',27,lfont)==1) + { + for(int i=index; i0 && doedit) + { + edit_qt(index); + } + } + + zc_free(BackupQTs); + return index; +} + +int onQuestTemplates() +{ + ListQTs(true); + return D_O_K; +} + +int NewQuestFile(int template_slot) +{ + memset(filepath,0,255); + memset(temppath,0,255); +#ifdef ALLEGRO_MACOSX + sprintf(filepath, "../../../"); + sprintf(temppath, "../"); +#endif + first_save=false; + box_start(1, "Initializing Quest", lfont, pfont, false); + box_out("Please wait."); + box_eol(); + box_out("This may take a few moments."); + box_eol(); + + init_quest(QuestTemplates[template_slot].path); + saved=true; + box_end(false); + refresh(rALL); + return D_O_K; +} + +static int ruleset=0; +int d_ruleset_radio_proc(int msg,DIALOG *d,int c); +int d_rulesettext_proc(int msg, DIALOG *d, int c); + +static DIALOG ruleset_dlg[] = +{ + { jwin_win_proc, 0, 0, 230, 180, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "New Quest", NULL, NULL }, + { jwin_button_proc, 76, 153, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_frame_proc, 102, 80, 112, 43, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + + { d_dummy_proc, 20, 71, 61, 9, vc(14), vc(1), 0, 0, 0, 0, 0, NULL, NULL }, + { d_ruleset_radio_proc, 20, 81, 61, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Authentic NES", NULL, NULL }, + { d_ruleset_radio_proc, 20, 91, 61, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Fixed NES", NULL, NULL }, + { d_ruleset_radio_proc, 20, 101, 61, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "BS-Zelda", NULL, NULL }, + { d_ruleset_radio_proc, 20, 111, 61, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Zelda 3-esque", NULL, NULL }, + { d_rulesettext_proc, 108, 85, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + // 9 + { jwin_text_proc, 16, 24, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "You have embarked on a new quest! Please specify which", NULL, NULL }, + { jwin_text_proc, 16, 34, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "initial set of Quest Rules you want to enable for this", NULL, NULL }, + { jwin_text_proc, 16, 44, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "quest. Quest Rules affect the behaviour and features of", NULL, NULL }, + { jwin_text_proc, 16, 54, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "the game engine and how different your quest is from", NULL, NULL }, + { jwin_text_proc, 16, 64, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "the NES game 'The Legend of Zelda'.", NULL, NULL }, + // 14 + { jwin_text_proc, 16, 28, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "You have embarked on a new quest!", NULL, NULL }, + { jwin_text_proc, 16, 38, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Please select an initial set of Quest Rules", NULL, NULL }, + { jwin_text_proc, 16, 48, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "for your quest. Quest Rules affect", NULL, NULL }, + { jwin_text_proc, 16, 58, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "the features of the game engine.", NULL, NULL }, + + { jwin_text_proc, 16, 130, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "After creation, individual Quest Rules can be", NULL, NULL }, + { jwin_text_proc, 16, 140, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "set in the Rules submenu of the Quest menu.", NULL, NULL }, + // There's no d_timer_proc; don't be silly. + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_ruleset_radio_proc(int msg,DIALOG *d,int c) +{ + int temp = ruleset; + int ret = jwin_radiofont_proc(msg,d,c); + + if(ruleset_dlg[3].flags & D_SELECTED) ruleset =0; + else if(ruleset_dlg[4].flags & D_SELECTED) ruleset =1; + else if(ruleset_dlg[5].flags & D_SELECTED) ruleset =2; + else if(ruleset_dlg[6].flags & D_SELECTED) ruleset =3; + else if(ruleset_dlg[7].flags & D_SELECTED) ruleset =4; + + if(temp != ruleset) + { + return D_REDRAW; + } + + return ret; +} + +int d_rulesettext_proc(int msg, DIALOG *d, int) +{ + if(msg!=MSG_DRAW) + return D_O_K; + + char buf[31]; + char buf2[31]; + char buf3[31]; + char buf4[31]; + + switch(ruleset) + { + case 1: // Original NES + sprintf(buf, "Matches the behaviour of"); + sprintf(buf2, "'The Legend of Zelda'."); + sprintf(buf3, "All but a few rules are off."); + sprintf(buf4, " "); + break; + + case 2: // Fixed NES + sprintf(buf, "Various bugs in 'The Legend"); + sprintf(buf2, "of Zelda' are fixed."); + sprintf(buf3, "All Quest Rules in the NES"); + sprintf(buf4, "Fixes category are on."); + break; + + case 3: // BS Zelda + sprintf(buf, "Fixed NES, plus BS-Zelda"); + sprintf(buf2, "animations, new enemy tiles,"); + sprintf(buf3, "fast scrolling, new push-"); + sprintf(buf4, "blocks, transition wipes, etc."); + break; + + case 4: // Zelda 3-esque + sprintf(buf, "BS-Zelda, plus diagonal Link"); + sprintf(buf2, "movement, new message strings,"); + sprintf(buf3, "magic and arrow meters, more"); + sprintf(buf4, "sound effects, drowning, etc."); + break; + } + + FONT *f = is_large ? font : sfont2; + textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],buf); + textprintf_ex(screen,f,d->x,d->y+(is_large?12:8),jwin_pal[jcBOXFG],jwin_pal[jcBOX],buf2); + textprintf_ex(screen,f,d->x,d->y+(is_large?24:16),jwin_pal[jcBOXFG],jwin_pal[jcBOX],buf3); + textprintf_ex(screen,f,d->x,d->y+(is_large?36:24),jwin_pal[jcBOXFG],jwin_pal[jcBOX],buf4); + return D_O_K; +} + +int PickRuleset() +{ + ruleset_dlg[0].dp2=lfont; + + // Large Mode conversion + if(!is_large) + ruleset_dlg[2].proc = d_dummy_proc; + + int start = (is_large?14:9); + int end = (is_large?17:13); + + for(int i = start; i <= end; i++) + { + ruleset_dlg[i].proc = d_dummy_proc; + } + + if(is_large) + large_dialog(ruleset_dlg); + + int ret = zc_popup_dialog(ruleset_dlg,1); + + if(ret==1) + { + if(ruleset>0) + { + for(int i=0; i 0) + PickRuleset(); + + return D_O_K; +} + +int onSave() +{ + restore_mouse(); + + if(disable_saving) + { + jwin_alert("ZQuest","Saving is","disabled in this version.",NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; + } + + if(!first_save) + return onSaveAs(); + else if(OverwriteProtection) + { + jwin_alert("ZQuest","Overwriting quests is disabled.","Change this in the options dialog.",NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; + } + + int ret = save_quest(filepath, false); + char buf[80],name[13]; + extract_name(filepath,name,FILENAME8_3); + + if(!ret) + { + sprintf(buf,"Saved %s",name); + jwin_alert("ZQuest",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + saved=true; + first_save=true; + header.dirty_password=false; + } + else + { + sprintf(buf,"Error saving %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + last_timed_save[0]=0; + return D_O_K; +} + +int onSaveAs() +{ + if(disable_saving) + { + jwin_alert("ZQuest","Saving is","disabled in this version.",NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; + } + + if(!getname("Save Quest As (.qst)","qst",NULL,filepath,true)) + return D_O_K; + + if(exists(temppath)) + { + if(OverwriteProtection) + { + jwin_alert("ZQuest","Overwriting quests is disabled.","Change this in the options dialog.",NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; + } + + if(jwin_alert("Confirm Overwrite",temppath,"already exists.","Write over existing file?","&Yes","&No",'y','n',lfont)==2) + { + return D_O_K; + } + } + + int ret = save_quest(temppath, false); + char buf[1024],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(!ret) + { + strcpy(filepath,temppath); + sprintf(buf,"ZQuest - [%s]", get_filename(filepath)); + set_window_title(buf); + sprintf(buf,"Saved %s",name); + jwin_alert("ZQuest",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + saved=true; + first_save=true; + header.dirty_password=false; + } + else + { + sprintf(buf,"Error saving %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rMENU); + last_timed_save[0]=0; + return D_O_K; +} + +int onOpen() +{ + bool compressed=true; + bool encrypted=true; + restore_mouse(); + + if(checksave()==0) + return D_O_K; + + static EXT_LIST list[] = + { + { (char *)"Quest Files (*.qst)", (char *)"qst" }, + { (char *)"Unencrypted Quest Files (*.qsu)", (char *)"qsu" }, + { (char *)"Quest Auto-backups (*.qb?)", (char *)"qb0,qb1,qb2,qb3,qb4,qb5,qb6,qb7,qb8,qb9" }, + { (char *)"Quest Timed Auto-saves (*.qt?)", (char *)"qt0,qt1,qt2,qt3,qt4,qt5,qt6,qt7,qt8,qt9" }, + { (char *)"Uncompressed Quest Timed Auto-saves (*.qu?)", (char *)"qu0,qu1,qu2,qu3,qu4,qu5,qu6,qu7,qu8,qu9" }, + { (char *)"All Files (*.*)", NULL }, + { NULL, NULL } + }; + + if(!getname("Load File",NULL,list,filepath,true)) + return D_O_K; + + char ext[2048]; + char ext2[5]; + strcpy(ext,get_extension(temppath)); + strupr(ext); + + for(int i=0; i<10; ++i) + { + sprintf(ext2,"qu%d",i); + + if(stricmp(ext,ext2)==0) + { + compressed=false; + encrypted=false; + break; + } + } + + if(stricmp(ext,"qsu")==0) + { + compressed=false; + encrypted=false; + } + + + int ret = load_quest(temppath, compressed, encrypted); + + if(ret == qe_OK) + { + saved = true; + strcpy(filepath, temppath); + first_save=true; + } + else if(ret == qe_cancel) + { + saved = true; + filepath[0]=0; + } + else + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,qst_error[ret],NULL,"O&K",NULL,'k',0,lfont); + filepath[0]=0; + } + + setup_combo_animations(); + setup_combo_animations2(); + Map.setCurrMap(zinit.last_map); + Map.setCurrScr(zinit.last_screen); + Map.setCanPaste(false); + Map.setCanUndo(false); + rebuild_trans_table(); + rebuild_string_list(); + onDrawingModeNormal(); + refresh(rALL); + last_timed_save[0]=0; + return D_O_K; +} + +int onRevert() +{ + if(jwin_alert("Confirm Revert","Are you sure you want to lose","all changes since last save?",NULL,"Yes","No",'y','n',lfont)==2) + { + return D_O_K; + } + + if(filepath[0]!=0) + { + int ret = load_quest(filepath, true, true); + + if(!ret) + { + saved = true; + } + else + { + char buf[80],name[13]; + extract_name(filepath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,qst_error[ret],NULL,"O&K",NULL,'k',0,lfont); + filepath[0]=0; + } + + setup_combo_animations(); + setup_combo_animations2(); + refresh(rALL); + } + else + { + NewQuestFile(0); + + if(RulesetDialog > 0) + PickRuleset(); + } + + onDrawingModeNormal(); + last_timed_save[0]=0; + return D_O_K; +} + +static DIALOG import_map_bias_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 80, 80-8, 160+1, 64+20+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Import Bias", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 120+10, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 120+10, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_radio_proc, 130, 104-8, 96+1, 8+1, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Total Copy", NULL, NULL }, + { jwin_radio_proc, 130, 114-8, 120+1, 8+1, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Prefer Original", NULL, NULL }, + { jwin_radio_proc, 130, 124-8, 104+1, 8+1, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Prefer Import", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int get_import_map_bias() +{ + import_map_bias_dlg[0].dp2=lfont; + + for(int i=0; i<3; i++) + { + import_map_bias_dlg[i+4].flags=0; + } + + import_map_bias_dlg[ImportMapBias+4].flags=D_SELECTED; + + if(is_large) + large_dialog(import_map_bias_dlg); + + if(zc_popup_dialog(import_map_bias_dlg,2)==2) + { + for(int i=0; i<3; i++) + { + if(import_map_bias_dlg[i+4].flags&D_SELECTED) + { + ImportMapBias=i; + break; + } + } + + return 0; + } + + return -1; +} + +int onImport_Map() +{ + if(Map.getCurrMap()>=Map.getMapCount()) + return D_O_K; + + if(get_import_map_bias()==-1) + { + return D_O_K; + } + + if(!getname("Import Map (.map)","map",NULL,datapath,false)) + return D_O_K; + + saved=false; + int ret=Map.load(temppath); + + if(ret) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,loaderror[ret],NULL,"O&K",NULL,'k',0,lfont); + + if(ret>1) + Map.clearmap(false); + } + else + { + bool willaffectlayers=false; + + for(int i=0; iMap.getMapCount()) + { + willaffectlayers=true; + break; + } + } + + fix_layers(&TheMaps[Map.getCurrMap()*MAPSCRS+i], false); + } + + if(willaffectlayers) + { + jwin_alert("Layers Changed", + "One or more screens in the imported map had", + "layers on maps that do not exist. The map numbers", + "of the affected layers will be reset to 0.", + "&OK", NULL, 'o', 0, lfont); + } + } + + refresh(rSCRMAP+rMAP+rMENU); + return D_O_K; +} + +int onExport_Map() +{ + if(Map.getCurrMap()>=Map.getMapCount()) + return D_O_K; + + if(!getname("Export Map (.map)","map",NULL,datapath,false)) + return D_O_K; + + int ret = Map.save(temppath); + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(!ret) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_DMaps() +{ + if(!getname("Import DMaps (.dmp)","dmp",NULL,datapath,false)) + return D_O_K; + + saved=false; + + if(!load_dmaps(temppath,0)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + else + { + int maxMap=0; + for(int i=0; imaxMap) + maxMap=DMaps[i].map; + } + + if(maxMap>map_count) + { + int ret=jwin_alert("Not enough maps", + "The imported DMaps use more maps than are", + " currently available. Do you want to add", + "more maps or change the DMaps' settings?", + "&Add maps","&Modify DMaps",'a','m',lfont); + if(ret==1) + setMapCount2(maxMap+1); + else + { + for(int i=0; i=map_count) + DMaps[i].map=0; + } + } + } + } + + return D_O_K; +} + +int onExport_DMaps() +{ + if(!getname("Export DMaps (.dmp)","dmp",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_dmaps(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Pals() +{ + if(!getname("Import Palettes (.zpl)","zpl",NULL,datapath,false)) + return D_O_K; + + saved=false; + + if(!load_pals(temppath,0)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + return D_O_K; +} + +int onExport_Pals() +{ + if(!getname("Export Palettes (.zpl)","zpl",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_pals(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Msgs() +{ + if(!getname("Import String Table (.zqs)","zqs",NULL,datapath,false)) + return D_O_K; + + saved=false; + + if(!load_msgstrs(temppath,0)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + return D_O_K; +} + +int onExport_Msgs() +{ + if(!getname("Export String Table (.zqs)","zqs",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_msgstrs(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + + +int onExport_MsgsText() +{ + if(!getname("Export Text Dump (.txt)","txt",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_msgstrs_text(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Combos() +{ + int ret=getnumber("Import Start Page",0); + + if(cancelgetnum) + { + return D_O_K; + } + + bound(ret,0,COMBO_PAGES-1); + + if(!getname("Import Combo Table (.cmb)","cmb",NULL,datapath,false)) + return D_O_K; + + if(!load_combos(temppath, ret*COMBOS_PER_PAGE)) + { + // if(!load_combos(temppath)) { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + else + saved=false; + + refresh(rALL); + return D_O_K; +} + +int onExport_Combos() +{ + if(!getname("Export Combo Table (.cmb)","cmb",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_combos(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Tiles() +{ + int ret=getnumber("Import Start Page",0); + + if(cancelgetnum) + { + return D_O_K; + } + + bound(ret,0,TILE_PAGES-1); + + if(!getname("Import Tiles (.til)","til",NULL,datapath,false)) + return D_O_K; + + saved=false; + + // usetiles=true; + if(!load_tiles(temppath, ret*TILES_PER_PAGE)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rALL); + return D_O_K; +} + +int onExport_Tiles() +{ + if(!getname("Export Tiles (.til)","til",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_tiles(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Guys() +{ + if(!getname("Import Enemies (.guy)","guy",NULL,datapath,false)) + return D_O_K; + + if(!load_guys(temppath)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rALL); + return D_O_K; +} + +int onExport_Guys() +{ + if(!getname("Export Enemies (.guy)","guy",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_guys(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + + +bool save_combo_alias(const char *path); +bool load_combo_alias(const char *path); +int onImport_ComboAlias() +{ + if(!getname("Import Combo Alias (.zca)","zca",NULL,datapath,false)) + return D_O_K; + + if(!load_combo_alias(temppath)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rALL); + return D_O_K; +} + +int onExport_ComboAlias() +{ + if(!getname("Export Combo Alias (.zca)","zca",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_combo_alias(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_ZGP() +{ + if(!getname("Import Graphics Pack (.zgp)","zgp",NULL,datapath,false)) + return D_O_K; + + saved=false; + + // usetiles=true; + if(!load_zgp(temppath)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rALL); + return D_O_K; +} + +int onExport_ZGP() +{ + if(!getname("Export Graphics Pack (.zgp)","zgp",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_zgp(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_Subscreen() +{ + if(!getname("Import Subscreen (.sub)","sub",NULL,datapath,false)) + return D_O_K; + + saved=false; + + // usetiles=true; + if(!load_subscreen(temppath)) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + refresh(rALL); + return D_O_K; +} + +int onExport_Subscreen() +{ + if(!getname("Export Subscreen (.sub)","sub",NULL,datapath,false)) + return D_O_K; + + bool cancel; + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_subscreen(temppath, &cancel)) + { + if(!cancel) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Did not save %s",name); + } + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_ZQT() +{ + if(!getname("Import Quest Template (.zqt)","zqt",NULL,datapath,false)) + return D_O_K; + + saved=false; + // usetiles=true; + int error = load_quest(temppath,true, false); + + if(error != qe_OK && error != qe_cancel) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + register_blank_tiles(); + loadlvlpal(Color); + setup_combo_animations(); + setup_combo_animations2(); + Map.setCurrMap(Map.getCurrMap()); // for bound checking + refresh(rALL); + refresh_pal(); + return D_O_K; +} + +int onExport_ZQT() +{ + if(!getname("Export Quest Template (.zqt)","zqt",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(!save_unencoded_quest(temppath, true)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onImport_UnencodedQuest() +{ + if(!getname("Import Unencoded Quest (.qsu)","qsu",NULL,datapath,false)) + return D_O_K; + + saved=false; + // usetiles=true; + int ret = load_quest(temppath,false,false); + + if(ret != qe_OK && ret != qe_cancel) + { + char buf[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + sprintf(buf,"Unable to load %s",name); + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + } + + register_blank_tiles(); + loadlvlpal(Color); + setup_combo_animations(); + setup_combo_animations2(); + Map.setCurrMap(Map.getCurrMap()); // for bound checking + refresh(rALL); + refresh_pal(); + return D_O_K; +} + +int onExport_UnencodedQuest() +{ + if(!getname("Export Unencoded Quest (.qsu)","qsu",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(!save_unencoded_quest(temppath, false)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +void center_zq_files_dialogs() +{ + jwin_center_dialog(editqt_dlg); + jwin_center_dialog(ruleset_dlg); + jwin_center_dialog(import_map_bias_dlg); + jwin_center_dialog(qtlist_dlg); +} + diff --git a/src/zq_files.h b/src/zq_files.h new file mode 100644 index 0000000000..a8d1d1514c --- /dev/null +++ b/src/zq_files.h @@ -0,0 +1,56 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_files.cc +// +// File support for ZQuest. +// +//-------------------------------------------------------- + +#ifndef _ZQ_FILES_H_ +#define _ZQ_FILES_H_ + +#include "zc_alleg.h" + +extern char qtbuf[31]; + +void reset_qt(int index); +void init_qts(); +void edit_qt(); //this is used to set the quest template for the current quest +void edit_qt(int index); +const char *qtlist(int index, int *list_size); +int qtlist_del(); +int onQuestTemplates(); +int NewQuestFile(int template_slot); +int onNew(); +int PickRuleset(); +int onSave(); +int onSaveAs(); +int onOpen(); +int onRevert(); +int get_import_map_bias(); +int onImport_Map(); +int onExport_Map(); +int onImport_DMaps(); +int onExport_DMaps(); +int onImport_Pals(); +int onExport_Pals(); +int onImport_Msgs(); +int onExport_Msgs(); +int onExport_MsgsText(); +int onImport_Combos(); +int onExport_Combos(); +int onImport_Tiles(); +int onExport_Tiles(); +int onImport_Subscreen(); +int onExport_Subscreen(); +int onImport_ZGP(); +int onExport_ZGP(); +int onImport_ZQT(); +int onExport_ZQT(); +int onImport_UnencodedQuest(); +int onExport_UnencodedQuest(); +void center_zq_files_dialogs(); +#endif + diff --git a/src/zq_init.cpp b/src/zq_init.cpp new file mode 100644 index 0000000000..fe9e1d1e1d --- /dev/null +++ b/src/zq_init.cpp @@ -0,0 +1,62 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "gui.h" +#include "init.h" +#include "zc_alleg.h" +#include "zdefs.h" +#include "jwin.h" +#include "zq_init.h" +#include "zsys.h" +#include "zquest.h" + +//#ifdef ALLEGRO_MACOSX +#define zc_min(a,b) ((a)<(b)?(a):(b)) +//#endif + +extern int dmap_list_size; +extern bool dmap_list_zero; +extern char *item_string[]; +extern const char *itype_names[]; + +extern int doInit(zinitdata *zinit); + +int onInit() +{ + char init_title[80]; + sprintf(init_title, "Initialization Data"); + init_dlg[0].dp=init_title; + + dmap_list_size=MAXDMAPS; + dmap_list_zero=true; + init_dlg[1656].d1 = zinit.start_dmap; + return doInit(&zinit); +} + +void center_zq_init_dialog() +{ + jwin_center_dialog(init_dlg); +} + +void onInitOK() +{ + saved=false; +} + diff --git a/src/zq_init.h b/src/zq_init.h new file mode 100644 index 0000000000..d91d19619f --- /dev/null +++ b/src/zq_init.h @@ -0,0 +1,18 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- + +#ifndef _ZQ_INIT_H_ +#define _ZQ_INIT_H_ + +int onInit(); +void center_zq_init_dialog(); +const char *familylist(int index, int *list_size); +#endif + diff --git a/src/zq_items.cpp b/src/zq_items.cpp new file mode 100644 index 0000000000..8f2527c03d --- /dev/null +++ b/src/zq_items.cpp @@ -0,0 +1,66 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +/**********************************/ +/********** Item Class **********/ +/**********************************/ + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include "zq_class.h" +#include "zdefs.h" + +void movefairy(fix&,fix&,int) +{ + return; +} + +void killfairy(int) +{ + return; +} + +bool addfairy(fix, fix, int, int) +{ + return false; +} + +bool can_drop(fix, fix) +{ + return false; +} + +int select_dropitem(int, int, int) +{ + return 0; +} + +bool is_side_view() +{ + return (Map.CurrScr()->flags7&fSIDEVIEW) != 0; +} + +void getitem(int, bool) +{ + return; +} +/*** end of sprite.cc ***/ + + diff --git a/src/zq_misc.cpp b/src/zq_misc.cpp new file mode 100644 index 0000000000..149be2a696 --- /dev/null +++ b/src/zq_misc.cpp @@ -0,0 +1,1573 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_misc.cc +// +// Misc. stuff for ZQuest. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +//INLINE void SCRFIX() { putpixel(screen,0,0,getpixel(screen,0,0)); } +//INLINE void SCRFIX() {} + +#include "precompiled.h" //always first + +#include "zq_misc.h" +#include "zquestdat.h" +#include "zquest.h" +#include "colors.h" +#include "qst.h" +#include "zsys.h" +#include "zq_class.h" +#include +#include + +#ifdef _MSC_VER +#define strupr _strupr +#define stricmp _stricmp +#endif + +extern int prv_mode; +extern void dopreview(); + + +const char *imgstr[ftMAX] = +{ + "Not loaded", "Binary/ROM", "Image", "ZC Tiles", + "ZC Tiles", "ZC Tiles", "ZC Tiles", "ZC Tiles" +}; + +int filetype(const char *path) +{ + if(path==NULL || strlen(get_filename(path))==0) + return 0; + + char ext[40]; + strcpy(ext,get_extension(path)); + strupr(ext); + + for(int i=0; i>4,((i&63)<<2)+3,((i&0xFC0)>>4)+3,i); +} + +int wrap(int x,int low,int high) +{ + while(xhigh) + x-=high-low+1; + + return x; +} + +bool readfile(const char *path,void *buf,int count) +{ + PACKFILE *f=pack_fopen_password(path,F_READ,""); + + if(!f) + return 0; + + bool good=pfread(buf,count,f,true); + pack_fclose(f); + return good; +} + +bool writefile(const char *path,void *buf,int count) +{ + PACKFILE *f=pack_fopen_password(path,F_WRITE,""); + + if(!f) + return 0; + + bool good=pfwrite(buf,count,f); + pack_fclose(f); + return good; +} + +/* dotted_rect: (from allegro's guiproc.c) + * Draws a dotted rectangle, for showing an object has the input focus. + */ +void dotted_rect(int x1, int y1, int x2, int y2, int fg, int bg) +{ + int x = ((x1+y1) & 1) ? 1 : 0; + int c; + + /* two loops to avoid bank switches */ + for(c=x1; c<=x2; c++) + { + putpixel(screen, c, y1, (((c+y1) & 1) == x) ? fg : bg); + } + + for(c=x1; c<=x2; c++) + { + putpixel(screen, c, y2, (((c+y2) & 1) == x) ? fg : bg); + } + + for(c=y1+1; c> 6; + x.g = (g1*(64-ratio) + g2*ratio) >> 6; + x.b = (b1*(64-ratio) + b2*ratio) >> 6; + x.filler=0; + return x; +} + +void reset_pal_cycling(); +void cycle_palette(); + +void load_cset(RGB *pal,int cset_index,int dataset) +{ + byte *si = colordata + CSET(dataset)*3; + + for(int i=0; i<16; i++) + { + pal[CSET(cset_index)+i] = _RGB(si); + si+=3; + } +} + +void set_pal() +{ + set_palette_range(RAMpal,0,192,true); +} + +void loadlvlpal(int level) +{ + Color=level; + + // full pal + for(int i=0; i<192; i++) + RAMpal[i] = _RGB(colordata+i*3); + + // level pal + byte *si = colordata + CSET(level*pdLEVEL+poLEVEL)*3; + + for(int i=0; i<16*3; i++) + { + RAMpal[CSET(2)+i] = _RGB(si); + si+=3; + } + + for(int i=0; i<16; i++) + { + RAMpal[CSET(9)+i] = _RGB(si); + si+=3; + } + + reset_pal_cycling(); + set_pal(); +} + +void loadfadepal(int dataset) +{ + byte *si = colordata + CSET(dataset)*3; + + for(int i=0; i<16*3; i++) + { + RAMpal[CSET(2)+i] = _RGB(si); + si+=3; + } + + set_pal(); +} + +void setup_lcolors() +{ + for(int i=0; i<14; i++) + { + RAMpal[lc1(i)] = _RGB(colordata+(CSET(i*pdLEVEL+poLEVEL)+2)*3); + RAMpal[lc2(i)] = _RGB(colordata+(CSET(i*pdLEVEL+poLEVEL)+16+1)*3); + } + + set_palette(RAMpal); +} + +void refresh_pal() +{ + loadlvlpal(Color); + setup_lcolors(); +} + +char ns_string[4]; + +// Mirrored in Link.cpp +const char *roomtype_string[MAXROOMTYPES] = +{ + "(None)","Special Item","Pay for Info","Secret Money","Gamble", + "Door Repair","Red Potion or Heart Container","Feed the Goriya","Level 9 Entrance", + "Potion Shop","Shop","More Bombs","Leave Money or Life","10 Rupees", + "3-Stair Warp","Ganon","Zelda", "-", "1/2 Magic Upgrade", "Learn Slash", "More Arrows","Take One Item" +}; + +const char *catchall_string[MAXROOMTYPES] = +{ + " ","Special Item","Info Type","Amount"," ","Repair Fee"," "," "," ","Shop Type", + "Shop Type","Price","Price"," ","Warp Ring"," "," ", " ", " ", + " ", "Price","Shop Type" +}; + +const char *warptype_string[MAXWARPTYPES] = +{ + "Cave/Item Cellar","Passageway","Entrance/Exit","Scrolling Warp","Insta-Warp","Insta-Warp with Blackout","Insta-Warp with Opening Wipe","Insta-Warp with Zap Effects", "Insta-Warp with Wave Effects", "Cancel Warp" + // "Cave/Item Cellar","Passageway","Entrance/Exit","Scrolling Warp","Standard","Cancel Warp"," "," ", " ", " " +}; + +const char *warpeffect_string[MAXWARPEFFECTS] = +{ + "Instant", "Circle", "Oval", "Triangle", "Super Mario All-Stars", "Curtains (Smooth)", "Curtains (Stepped)", "Mosaic", + "Wave White", "Wave Black", "Fade White", "Fade Black", "Global Opening/Closing", "Destination Default" +}; + +const char *flag_string[MAXFLAGS] = +{ + " 0 (None)", + " 1 Push Block (Vertical, Trigger)", + " 2 Push Block (4-Way, Trigger)", + " 3 Whistle Trigger", + " 4 Burn Trigger (Any)", + " 5 Arrow Trigger (Any)", + " 6 Bomb Trigger (Any)", + " 7 Fairy Ring (Life)", + " 8 Raft Path", + " 9 Armos -> Secret", + " 10 Armos/Chest -> Item", + " 11 Bomb (Super)", + " 12 Raft Branch", + " 13 Dive -> Item", + " 14 Lens Marker", + " 15 Zelda (Win Game)", + " 16 Secret Tile 0", + " 17 Secret Tile 1", + " 18 Secret Tile 2", + " 19 Secret Tile 3", + " 20 Secret Tile 4", + " 21 Secret Tile 5", + " 22 Secret Tile 6", + " 23 Secret Tile 7", + " 24 Secret Tile 8", + " 25 Secret Tile 9", + " 26 Secret Tile 10", + " 27 Secret Tile 11", + " 28 Secret Tile 12", + " 29 Secret Tile 13", + " 30 Secret Tile 14", + " 31 Secret Tile 15", + " 32 Trap (Horizontal, Line of Sight)", + " 33 Trap (Vertical, Line of Sight)", + " 34 Trap (4-Way, Line of Sight)", + " 35 Trap (Horizontal, Constant)", + " 36 Trap (Vertical, Constant)", + " 37 Enemy 0", + " 38 Enemy 1", + " 39 Enemy 2", + " 40 Enemy 3", + " 41 Enemy 4", + " 42 Enemy 5", + " 43 Enemy 6", + " 44 Enemy 7", + " 45 Enemy 8", + " 46 Enemy 9", + " 47 Push Block (Horiz, Once, Trigger)", + " 48 Push Block (Up, Once, Trigger)", + " 49 Push Block (Down, Once, Trigger)", + " 50 Push Block (Left, Once, Trigger)", + " 51 Push Block (Right, Once, Trigger)", + " 52 Push Block (Vert, Once)", + " 53 Push Block (Horizontal, Once)", + " 54 Push Block (4-Way, Once)", + " 55 Push Block (Up, Once)", + " 56 Push Block (Down, Once)", + " 57 Push Block (Left, Once)", + " 58 Push Block (Right, Once)", + " 59 Push Block (Vertical, Many)", + " 60 Push Block (Horizontal, Many)", + " 61 Push Block (4-Way, Many)", + " 62 Push Block (Up, Many)", + " 63 Push Block (Down, Many)", + " 64 Push Block (Left, Many)", + " 65 Push Block (Right, Many)", + " 66 Block Trigger", + " 67 No Push Blocks", + " 68 Boomerang Trigger (Any)", + " 69 Boomerang Trigger (Magic +)", + " 70 Boomerang Trigger (Fire)", + " 71 Arrow Trigger (Silver +)", + " 72 Arrow Trigger (Golden)", + " 73 Burn Trigger (Red Candle +)", + " 74 Burn Trigger (Wand Fire)", + " 75 Burn Trigger (Din's Fire)", + " 76 Magic Trigger (Wand)", + " 77 Magic Trigger (Reflected)", + " 78 Fireball Trigger (Reflected)", + " 79 Sword Trigger (Any)", + " 80 Sword Trigger (White +)", + " 81 Sword Trigger (Magic +)", + " 82 Sword Trigger (Master)", + " 83 Sword Beam Trigger (Any)", + " 84 Sword Beam Trigger (White +)", + " 85 Sword Beam Trigger (Magic +)", + " 86 Sword Beam Trigger (Master)", + " 87 Hookshot Trigger", + " 88 Wand Trigger", + " 89 Hammer Trigger", + " 90 Strike Trigger", + " 91 Block Hole (Block -> Next)", + " 92 Fairy Ring (Magic)", + " 93 Fairy Ring (All)", + " 94 Trigger -> Self Only", + " 95 Trigger -> Self, Secret Tiles", + " 96 No Enemies", + " 97 No Ground Enemies", + " 98 General Purpose 1 (Scripts)", + " 99 General Purpose 2 (Scripts)", + "100 General Purpose 3 (Scripts)", + "101 General Purpose 4 (Scripts)", + "102 General Purpose 5 (Scripts)", + "103 Raft Bounce" +}; + +const char *itemclass_help_string[(itype_last-20)*3] = +{ + "Link's most versatile weapon. When wielded, it can","stab, slash and fire sword beams. It is used to","perform several Tiger Scroll techniques, too.", + "When wielded, it flies out, hurting enemies, and","collecting items, before returning to Link. Can be","thrown diagonally. Can optionally drop damaging sparkles.", + "When wielded, it flies and collects items before","hitting an enemy. Requires the Bow. Expends either 1 rupee","or 1 arrow ammo. Can drop damaging sparkles.", + "When wielded, a damaging flame drifts out, which","lights dark screens until it expires. Can optionally","have wand-style stab and slash sprites.", + "When wielded, plays strange music and summons a","whirlwind that warps you to the Warp Ring locations.","Can also dry Water combos on specific screens.", + "When wielded, drops bait that attracts Walking Enemies","depending on their Hunger stat. Removed when used","in 'Feed The Goriya' room types.", + "When wielded in 'Potion Shop' room types, activates","the shop and all other Potion Shops in the quest.","Is overridden by Potions if you have them.", + "When wielded, Link regains hearts and/or magic.","Can also cure jinxes, depending on the Quest Rules.","", + "When wielded, shoots damaging magic. The magic","is affected by your current Magic Book item. Can also","damage enemies by stabbing and slashing.", + "Divides the damage that Link takes, and changes his palette.","If a magic cost is set, Link loses magic when he takes","damage, and the item is disabled without magic.", + "Can provide infinite rupees to Link,","or provide a regenerating supply of rupees.","Typically also set to increase his Rupee max.", + "Also called the Cross, this makes invisible","enemies visible. Currently does not affect Ganon.","", + "When Link isn't wielding an item, this deflects or","reflects enemy projectiles from the front.","The Block Flags are listed on the Wiki.", + "Required to wield the Arrow. This affects the speed of","the arrow fired. The Action settings are not used.","", + "Allows Link to traverse Raft Paths. When at a Raft","Branch combo flag, hold the arrow keys to","decide which path the raft will take.", + "Used to cross Water combos and certain combo types.","If Four-Way > 1, Link can step sideways off the ladder.","", + "Affects the sprite and damage of the magic shot","by the Wand. If 'Fire Magic' is set, a 1-damage flame is","created at the place where the magic stops.", + "Provides unlimited keys in a specific dungeon","level, or all dungeon levels up to a point.","The Action settings are not used.", + "Allows Link to push Heavy or Very Heavy push block","combos. Can be limited to one push per screen.","The Action settings are not used.", + "Allows Link to swim in Water combos. The Power","and Action settings are not used.","", + "Prevents damage from certain Damage combos. Can","require magic to use, which is drained as","Link touches the combos.", + "When wielded, shoots a hook and chain that collects","items and hurt enemies, before retracting back to","Link. Best used with the Hookshot Grab combo type.", + "When wielded, restricts your vision and reveals","certain combo flags, as well as hiding or","showing certain layers on a screen.", + "When wielded, pounds and breaks Walking Enemies'","shields. It is used to perform the Quake Hammer","and Super Quake techniques, too.", + "When wielded, casts a spell which sends out","a wide ring of flames from Link's body.","Link is invincible while casting the spell.", + "When wielded, teleports Link to the","Continue screen of the current DMap.","", + "When wielded, casts a spell which surrounds Link","with a magic shield that nullifies all","damage taken until it expires.", + "When wielded, places a bomb which explodes to","momentarily hurt foes. Expends 1 bomb ammo. Remote bombs only","explode when you press the button again after placing.", + "Similar to Bomb, but has a much larger blast","radius, and expends 1 super bomb ammo.","", + "When collected, freezes most enemies and makes","Link invincible for a limited time.","", + "No built-in effect, but is typically set to","increase your Key count by 1 when collected.","", + "No built-in effect, but is typically set to","increase your maximum Magic by 32 when collected.","", + "When collected, enables the Triforce for the","current dungeon level and plays a cutscene. May warp","Link out using the current screen's Side Warp A.", + "When collected, enables the Subscreen Map","for the current dungeon level.","", + "When collected, enables the Compass","for the current dungeon level.","", + "When collected, enables the Boss Key","for the current dungeon level, letting Link unlock","Boss Lock Blocks, Boss Chest combos and Boss doors.", + "Can provide infinite arrow ammo to Link,","or provide a regenerating supply of ammo.","Typically also set to increase his arrow ammo max.", + "When collected, increases the Level-Specific","Key count for the current dungeon level. These","keys are used in place of normal keys if possible.", + "When wielded, creates one or more beams that circle Link.","Beams can be dismissed by pressing the button again.","Can optionally have wand-style stab and slash sprites.", + "No built-in effect, but is typically set to","increase your Rupee count when collected.","", + "No built-in effect, but is typically set to","increase your Arrow ammo when collected.","", + "Flies around the screen at a certain speed.","When collected, Link regains hearts and/or magic.","Can also cure jinxes, depending on the Quest Rules.", + "No built-in effect, but is typically set to","increase your Magic when collected.","", + "No built-in effect, but is typically set to","restore Link's hearts when collected.","", + "No built-in effect, but is typically set to","increase Link's max. health when collected.","", + "When collected, increases Link's Heart Piece count by 1.","If the 'Per HC' amount (in Init Data) is reached,","Link's max. health is increased by 1 heart.", + "When collected, all beatable enemies on the","screen are instantly and silently killed.","", + "No built-in effect, but is typically set to","increase Link's bomb ammo when collected.","", + "Can provide infinite bomb ammo to Link,","or provide a regenerating supply of ammo.","Typically also set to increase his bomb ammo max.", + "When wielded, Link jumps into the air through","the 'Z-axis', with an initial Jump speed","of 0.8 times the Height Multiplier.", + "When Link is at the apex of a jump, he hovers","in the air for a specified time. In sideview,","can be dismissed by pressing Down.", + "When wielding the Sword, Link can hold the button","to tap solid combos to find bombable locations","and release to spin the sword around him.", + "When performing a Spin Attack with a sword that","can fire beams, four beams are released","from the sword during each spin.", + "When wielding the Hammer, Link can hold the","button and release to pound for extra damage,","and stunning most nearby ground enemies.", + "Reduces the duration of jinxes given by certain","enemies, or (if Divisor is 0) prevents them entirely.","The Action settings are not used.", + "Reduces the time it takes to charge the","Spin Attack/Quake Hammer (Charging) and","Hurricane Spin/Super Quake (Magic C.) abilities.", + "Enables the Sword to fire sword beams","when Link's health is below a certain amount.","The Action settings are not used.", + "In Shop room types, shop prices are multiplied","by the Discount Amount, making the items cheaper.","", + "Gradually restores Link's health in certain","quantities over a certain duration.","The Action settings are not used.", + "Gradually restores Link's magic in certain quantities","over a certain duration. Can also provide","infinite magic to Link. The Action settings are unused.", + "After charging the Spin Attack, holding down the","button longer enables a stronger attack","with faster and more numerous spins.", + "After charging the Quake Hammer, holding down the","button longer enables a stronger attack","which stuns more enemies for longer.", + "Link's sprite faintly vibrates when he stands","on or near secret-triggering combo flags.","Sensitivity increases the distance at which it works.", + "If Link, while jumping, lands on an enemy,","that enemy takes a certain amount of","damage, instead of damaging Link.", + "The Sword, Wand and Hammer will occasionally do","increased damage in a single strike.","", + "Divides the damage that Link takes when his","health is below a certain level.","", + "These items have no built-in effect.","They will not be dropped in an Item Drop Set.","", + "Displays the bow and arrow together as a single item.","No item should use this class; it is intended","for use in subscreens only.", + "Represents either the letter or a potion, whichever is","available at the moment. No item should use this class;","It is intended for use in subscreens only." +}; + +const char *combotype_help_string[cMAX*3] = +{ + "","","", + "Link is warped via Tile Warp A if he steps on","the bottom half of this combo.","", + "Link marches down into this combo and is warped","via Tile Warp A if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Water can contain Zora enemies and can be","crossed with various weapons and items.","If the matching quest rule is set, Link can drown in it.", + "When touched, this combo produces an Armos","and changes to the screen's Under Combo.","", + "When touched, this combo produces one Ghini.","","", + "Raft paths must begin on a Dock-type combo.","(Use the Raft combo flag to create raft paths.)","", + "","","", + "A Bracelet is not needed to push this combo,", "but it can't be pushed until the", "enemies are cleared from the screen.", + "A Bracelet is needed to push this combo.","The screen's Under Combo will appear beneath","it when it is pushed aside.", + "A Bracelet is needed to push this combo,","and it can't be pushed until the", "enemies are cleared from the screen.", + "If the 'Statues Shoot Fire' Screen Data","flag is checked, an invisible fireball","shooting enemy is spawned on this combo.", + "If the 'Statues Shoot Fire' Screen Data","flag is checked, an invisible fireball","shooting enemy is spawned on this combo.", + "Link's movement speed is reduced","while he walks on this combo.","Enemies will not be affected.", + // Conveyors + "","","", + "","","", + "","","", + "","","", + // Anyway... + "Link is warped via Tile Warp A if he swims on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp A if he dives on","this combo. Otherwise, this is identical to Water.","", + "If this combo is solid, the Ladder and Hookshot","can be used to cross over it.","It only permits the Ladder if it's on Layer 0.", + "This triggers Screen Secrets when the bottom half","of this combo is stepped on, but it does not set","the screen's 'Secret' Screen State.", + "This triggers Screen Secrets when the bottom half","of this combo is stepped on, and sets the screen's","'Secret' Screen State, making the secrets permanent.", + "","","", // Unused + "When stabbed or slashed with a Sword, this", "combo changes into the screen's Under Combo.","", + "Identical to Slash, but an item","from Item Drop Set 10 is created","when this combo is slashed.", + "A Bracelet with a Push Combo Level of 2","is needed to push this combo. Otherwise,","this is identical to Push (Heavy).", + "A Bracelet with a Push Combo Level of 2","is needed to push this combo. Otherwise,","this is identical to Push (Heavy, Wait).", + "When hit by a Hammer, this combo changes","into the next combo in the list.","", + "If this combo is struck by the Hookshot,", "Link is pulled towards the combo.","", + // Damage Combos + "","","", + "","","", + "","","", + "","","", + "","","", + // Anyway... + "If the 'Statues Shoot Fire' Screen Data","flag is checked, an invisible fireball","shooting enemy is spawned on this combo.", + "This flag is obsolete. It behaves identically to","Combo Flag 32, Trap (Horizontal, Line of Sight).","", + "This flag is obsolete. It behaves identically to","Combo Flag 33, Trap (Vertical, Line of Sight).","", + "This flag is obsolete. It behaves identically to","Combo Flag 34, Trap (4-Way, Line of Sight).","", + "This flag is obsolete. It behaves identically to","Combo Flag 35, Trap (Horizontal, Constant).","", + "This flag is obsolete. It behaves identically to","Combo Flag 36, Trap (Vertical Constant).","", + "Link is warped via Tile Warp A if he touches","any part of this combo, but his on-screen","position remains the same. Ground enemies can't enter.", + "If this combo is solid, the Hookshot","can be used to cross over it.","", + "This combo's tile is drawn between layers","3 and 4, even if it is placed on layer 0.","", + "Flying enemies (Keese, Peahats, Moldorms,","Patras, Fairys, Digdogger, Manhandla, Ghinis,","Gleeok heads) can't fly over or appear on this combo.", + "Wand magic and enemy magic that hits"," this combo is reflected 180 degrees,","and becomes 'reflected magic'.", + "Wand magic and enemy magic that hits"," this combo is reflected 90 degrees,","and become 'reflected magic'.", + "Wand magic and enemy magic that hits"," this combo is reflected 90 degrees,","and become 'reflected magic'.", + "Wand magic and enemy magic that hits"," this combo is duplicated twice, causing","three shots to be fired in three directions.", + "Wand magic and enemy magic that hits"," this combo is duplicated thrice, causing","four shots to be fired from each direction.", + "Wand magic and enemy magic that hits","this combo is destroyed.","", + "Link marches up into this combo and is warped","via Tile Warp A if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "The combo's tile changes depending on","Link's position relative to the combo.","It uses eight tiles per animation frame.", + "Identical to Eyeball (8-Way A), but the","angles at which the tile will change are","offset by 22.5 degrees (pi/8 radians).", + "Tektites cannot jump through or","appear on this combo.","", + "Identical to Slash->Item, but when it is","slashed, Bush Leaves sprites are drawn and","the 'Tall Grass slashed' sound plays.", + "Identical to Slash->Item, but when it is","slashed, Flower Clippings sprites are","drawn and the 'Tall Grass slashed' sound plays.", + "Identical to Slash->Item, but when it is","slashed, Grass Clippings sprites are","drawn and the 'Tall Grass slashed' sound plays.", + "Ripples sprites are drawn on Link when","he walks on this combo. Also, Quake","Hammer pounds are nullified by this combo.", + "If the combo is solid and Link pushes it with at","least one Key, it changes to the next combo, the 'Lock Blocks'","Screen State is set, and one key is used up.", + "Identical to Lock Block, but if any other","Lock Blocks are opened on the same screen,","this changes to the next combo.", + "If the combo is solid and Link pushes it with the","Boss Key, it changes to the next combo and","the 'Boss Lock Blocks' Screen State is set.", + "Identical to Lock Block (Boss), but if any other","Boss Lock Blocks are opened on the same","screen, this changes to the next combo.", + "If this combo is solid, the Ladder","can be used to cross over it.","Only works on layer 0.", + "When touched, this combo produces a Ghini","and changes to the next combo in the list.","", + "If Link pushes the bottom of this solid combo,","it changes to the next combo in the list.","Best used with the Armos/Chest->Item combo flag.", + "Identical to Treasure Chest (Normal), but if any","other Normal Treasure Chests are opened on the","same screen, this changes to the next combo.", + "Identical to Treasure Chest (Normal), but if Link","doesn't have a Key, it can't be opened.","Otherwise, a key is used up when it opens.", + "Identical to Treasure Chest (Locked), but if any","other Locked Treasure Chests are opened on the","same screen, this changes to the next combo.", + "Identical to Treasure Chest (Normal), but if Link","doesn't have the Boss Key, it can't be opened.","", + "Identical to Treasure Chest (Boss), but if any","other Boss Treasure Chests are opened on the","same screen, this changes to the next combo.", + "If Link touches this, the Screen States are cleared,","and Link is re-warped back into the screen,","effectively resetting the screen entirely.", + "Press the 'Start' button when Link is standing on","the bottom of this combo, and the Save menu appears. Best","used with the Save Point->Continue Here Screen Flag.", + "Identical to Save Point, but the Quit option","is also available in the menu.","", + "Link marches down into this combo and is warped","via Tile Warp B if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link marches down into this combo and is warped","via Tile Warp C if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link marches down into this combo and is warped","via Tile Warp D if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link is warped via Tile Warp B if he steps on","the bottom half of this combo.","", + "Link is warped via Tile Warp C if he steps on","the bottom half of this combo.","", + "Link is warped via Tile Warp D if he steps on","the bottom half of this combo.","", + "Link is warped via Tile Warp B if he touches","any part of this combo, but his on-screen","position remains the same. Ground enemies can't enter.", + "Link is warped via Tile Warp C if he touches","any part of this combo, but his on-screen","position remains the same. Ground enemies can't enter.", + "Link is warped via Tile Warp D if he touches","any part of this combo, but his on-screen","position remains the same. Ground enemies can't enter.", + "Link marches up into this combo and is warped","via Tile Warp B if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link marches up into this combo and is warped","via Tile Warp C if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link marches up into this combo and is warped","via Tile Warp D if he steps on this. The combo's tile","will be drawn above Link during this animation.", + "Link is warped via Tile Warp B if he swims on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp C if he swims on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp D if he swims on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp B if he dives on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp C if he dives on","this combo. Otherwise, this is identical to Water.","", + "Link is warped via Tile Warp D if he dives on","this combo. Otherwise, this is identical to Water.","", + "Identical to Stairs [A], but the Tile Warp","used (A, B, C, or D) is chosen at random. Use this only","in screens where all four Tile Warps are defined.", + "Identical to Direct Warp [A], but the Tile Warp","used (A, B, C, or D) is chosen at random. Use this only","in screens where all four Tile Warps are defined.", + "As soon as this combo appears on the screen,","Side Warp A is triggered. This is best used with","secret combos or combo cycling.", + "As soon as this combo appears on the screen,","Side Warp B is triggered. This is best used with","secret combos or combo cycling.", + "As soon as this combo appears on the screen,","Side Warp C is triggered. This is best used with","secret combos or combo cycling.", + "As soon as this combo appears on the screen,","Side Warp D is triggered. This is best used with","secret combos or combo cycling.", + "Identical to Auto Side Warp [A], but the Side Warp","used (A, B, C, or D) is chosen at random. Use this only","in screens where all four Side Warps are defined.", + "Identical to Stairs [A], but Link will be warped","as soon as he touches the edge of this combo.","", + "Identical to Stairs [B], but Link will be warped","as soon as he touches the edge of this combo.","", + "Identical to Stairs [C], but Link will be warped","as soon as he touches the edge of this combo.","", + "Identical to Stairs [D], but Link will be warped","as soon as he touches the edge of this combo.","", + "Identical to Stairs [Random], but Link will be","warped as soon as he touches the edge of this combo.","", + "Identical to Step->Secrets (Temporary), but","Screen Secrets are triggered as soon as","Link touches the edge of this combo.", + "Identical to Step->Secrets (Permanent), but","Screen Secrets are triggered as soon as","Link touches the edge of this combo.", + "When Link steps on this combo, it will","change into the next combo in the list.","", + "Identical to Step->Next, but if other instances","of this particular combo are stepped on, this","also changes to the next combo in the list.", + "When Link steps on this combo, each of","the Step->Next combos on screen will change","to the next combo after them in the list.", + "When Link steps on a Step->Next (All) type combo,","this will change into the next combo in the list.","", + "Enemies cannot enter or","appear on this combo.","", + "Level 1 Link arrows that hit this combo","are destroyed. Enemy arrows are unaffected.","", + "Level 1 or 2 Link arrows that hit this combo","are destroyed. Enemy arrows are unaffected.","", + "All Link arrows that hit this combo","are destroyed. Enemy arrows are unaffected.","", + "Level 1 Link boomerangs bounce off","this combo. Enemy boomerangs are unaffected.","", + "Level 1 or 2 Link boomerangs bounce off","this combo. Enemy boomerangs are unaffected.","", + "All Link boomerangs bounce off","this combo. Enemy boomerangs are unaffected.","", + "Link sword beams or enemy sword beams","that hit this combo are destroyed.","", + "All weapons that hit this combo are","either destroyed, or bounce off.","", + "Enemy fireballs and reflected fireballs","that hit this combo are destroyed.","", + // More damage + "","","", + "","","", + "","","", + "","","", // Unused + "A Spinning Tile immediately appears on this combo,","using the combo's tile to determine its sprite.","The combo then changes to the next in the list.", + "","","", // Unused + "While this combo is on the screen, all action is frozen,","except for FFC animation and all scripts. Best used","in conjunction with Changer FFCs or scripts.", + "While this combo is on the screen, FFCs and FFC scripts","will be frozen. Best used in conjunction","with combo cycling, screen secrets or global scripts.", + "Enemies that don't fly or jump","cannot enter or appear on","this combo.", + "Identical to Slash, but instead of changing","into the Under Combo when slashed, this","changes to the next combo in the list.", + "Identical to Slash (Item), but instead of changing","into the Under Combo when slashed, this","changes to the next combo in the list.", + "Identical to Bush, but instead of changing","into the Under Combo when slashed, this","changes to the next combo in the list.", + // Continuous variation + "Slash","","", + "Slash->Item","","", + "Bush","","", + "Flowers","","", + "Tall Grass","","", + "Slash->Next","","", + "Slash->Next (Item)","","", + "Bush->Next","","", + "Identical to Eyeball (8-Way A), but only the four","cardinal directions/sets of tiles are used","(up, down, left and right, respectively).", + "Identical to Tall Grass, but instead of changing","into the Under Combo when slashed, this","changes to the next combo in the list.", + // Script types + "","","", + "","","", + "","","", + "","","", + "","","" +}; + +const char *flag_help_string[(mfMAX)*3] = +{ + "","","", + "Allows Link to push the combo up or down once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Allows Link to push the combo in any direction once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Triggers Screen Secrets when Link plays the Whistle on it.","Is replaced with the 'Whistle' Secret Combo.","Doesn't interfere with Whistle related Screen Flags.", + "Triggers Screen Secrets when Link touches it with", "fire from any source (Candle, Wand, Din's Fire, etc.)", "Is replaced with the 'Blue Candle' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with one of his Arrows.", "Is replaced with the 'Wooden Arrow' Secret Combo.", + "Triggers Screen Secrets when the middle", "part of a Bomb explosion touches it.", "Is replaced with the 'Bomb' Secret Combo.", + "Makes a heart circle appear on screen", "when Link steps on it, and refills his life.", "See also the Heart Circle-related Quest Rules.", + "Place in paths to define the path Link travels", "when using the Raft. Use with Dock-type combos.", "If a path branches, Link takes the clockwise-most path.", + "When placed on an Armos-type combo, causes the 'Stairs'"," Secret Combo to appear when the Armos is triggered,","instead of the screen's Under Combo.", + "When placed on an Armos or treasure chest, causes","the room's Special Item to appear when the combo is activated.","Requires the 'Special Item' Room Type.", + "Triggers Screen Secrets when the middle", "part of a Super Bomb explosion touches it.", "Is replaced with the 'Super Bomb' Secret Combo.", + "Place at intersections of Raft flag paths to define", "points where the player may change directions.","Change directions by holding down a directional key.", + "When Link dives on a flagged water-type combo","he will recieve the screen's Special Item.","Requires the 'Special Item' Room Type.", + "Combos with this flag will flash white when", "viewed with the Lens of Truth item.","", + "When Link steps on this flag, the quest will", "end, and the credits will roll.","", + // 16-31 + "","","", + "","","", + "","","",//18 + "","","", + "","","", + "","","",//21 + "","","", + "","","", + "","","",//24 + "","","", + "","","", + "","","",//27 + "","","", + "","","", + "","","",//30 + "","","", + // Anyway... + "Creates the lowest-numbered enemy with the","'Spawned by 'Horz Trap' Combo Type/Flag' enemy","data flag on the flagged combo.", + "Creates the lowest-numbered enemy with the","'Spawned by 'Vert Trap' Combo Type/Flag' enemy","data flag on the flagged combo.", + "Creates the lowest-numbered enemy with the","'Spawned by '4-Way Trap' Combo Type/Flag' enemy","data flag on the flagged combo.", + "Creates the lowest-numbered enemy with the","'Spawned by 'LR Trap' Combo Type/Flag' enemy","data flag on the flagged combo.", + "Creates the lowest-numbered enemy with the","'Spawned by 'UD Trap' Combo Type/Flag' enemy","data flag on the flagged combo.", + // Enemy 0-9 + "","","", + "","","", + "","","",//2 + "","","", + "","","", + "","","",//5 + "","","", + "","","", + "","","",//8 + "","","", + //Anyway... + "Allows Link to push the combo left or right once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Allows Link to push the combo up once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Allows Link to push the combo down once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Allows Link to push the combo left once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + "Allows Link to push the combo right once,","triggering Screen Secrets (or just the 'Stairs',","secret combo) as well as Block->Shutters.", + // Push Silent + "","","",//52 + "","","", + "","","", + "","","", + "","","", + "","","", + "","","", + "","","",//59 + "","","", + "","","", + "","","", + "","","", + "","","", + "","","", + //Anyway... + "Pushing blocks onto ALL Block Triggers will trigger","Screen Secrets (or just the 'Stairs' secret combo)","as well as Block->Shutters.", + "Prevents push blocks from being pushed onto the","flagged combo, even if it is not solid.","", + "Triggers Screen Secrets when Link", "touches it with one of his Boomerangs.", "Is replaced with the 'Wooden Boomerang' Secret Combo.", + "Triggers Screen Secrets when Link touches", "it with a level 2 or higher Boomerang.", "Is replaced with the 'Magic Boomerang' Secret Combo.", + "Triggers Screen Secrets when Link touches", "it with a level 3 or higher Boomerang.", "Is replaced with the 'Fire Boomerang' Secret Combo.", + "Triggers Screen Secrets when Link touches", "it with a level 2 or higher Arrow.", "Is replaced with the 'Silver Arrow' Secret Combo.", + "Triggers Screen Secrets when Link touches", "it with a level 3 or higher Arrow.", "Is replaced with the 'Golden Arrow' Secret Combo.", + "Triggers Screen Secrets when Link touches it with", "fire from a level 2 Candle, a Wand, or Din's Fire.", "Is replaced with the 'Red Candle' Secret Combo.", + "Triggers Screen Secrets when Link touches it with", "fire from a Wand, or Din's Fire.", "Is replaced with the 'Wand Fire' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with Din's Fire. Is replaced", "with the 'Din's Fire' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with Wand magic, be it fire or not.", "Is replaced with the 'Wand Magic' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with reflected Wand magic.", "Is replaced with the 'Reflected Magic' Secret Combo.", + "Triggers Screen Secrets when Link touches", "it with a Shield-reflected fireball.", "Is replaced with the 'Reflected Fireball' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with one of his Swords.", "Is replaced with the 'Wooden Sword' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 2 or higher Sword.", "Is replaced with the 'White Sword' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 3 or higher Sword.", "Is replaced with the 'Magic Sword' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 4 or higher Sword.", "Is replaced with the 'Master Sword' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with one of his Sword beams.", "Is replaced with the 'Sword Beam' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 2 or higher Sword's beam.", "Is replaced with the 'White Sword Beam' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 3 or higher Sword's beam.", "Is replaced with the 'Magic Sword Beam' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with a level 4 or higher Sword's beam.", "Is replaced with the 'Master Sword Beam' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with one of his Hookshot hooks.", "Is replaced with the 'Hookshot' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with one of his Wands.", "Is replaced with the 'Wand' Secret Combo.", + "Triggers Screen Secrets when Link", "pounds it with one of his Hammers.", "Is replaced with the 'Hammer' Secret Combo.", + "Triggers Screen Secrets when Link", "touches it with any weapon or projectile.", "Is replaced with the 'Any Weapon' Secret Combo.", + "A push block pushed onto this flag","will cycle to the next combo in the list,","and lose the Push flag that was presumably on it.", + "Makes a heart circle appear on screen", "when Link steps on it, and refills his magic.", "See also the Heart Circle-related Quest Rules.", + "Makes a heart circle appear on screen when", "Link steps on it, and refills his life and magic.", "See also the Heart Circle-related Quest Rules.", + "When stacked with a Trigger Combo Flag, it","prevents the triggered Secrets process from","changing all other flagged combos on-screen.", + "Similar to 'Trigger->Self Only', but the","Secret Tile (16-31) flagged combos will still change.","(The 'Hit All Triggers->16-31' Screen Flag overrides this.)", + "Enemies cannot enter or appear","on the flagged combo.","", + "Enemies that don't fly or jump","cannot enter or appear on","the flagged combo.", + //Script Flags follow. + "", "", "", + "", "", "", + "", "", "", + "", "", "", + "", "", "", + //Raft bounce flag! ^_^ + "When Link is rafting, and hits","this flag, he will be turned around.", "" +}; + +// eMAXGUYS is defined in zdefs.h +const char *old_guy_string[OLDMAXGUYS] = +{ + "(None)","Abei","Ama","Merchant","Moblin","Fire","Fairy","Goriya","Zelda","Abei 2","Empty","","","","","","","","","", + // 020 + "Octorok (L1, Slow)","Octorok (L2, Slow)","Octorok (L1, Fast)","Octorok (L2, Fast)","Tektite (L1)", + // 025 + "Tektite (L2)","Leever (L1)","Leever (L2)","Moblin (L1)","Moblin (L2)", + // 030 + "Lynel (L1)","Lynel (L2)","Peahat (L1)","Zora","Rock", + // 035 + "Ghini (L1, Normal)","Ghini (L1, Phantom)","Armos","Keese (CSet 7)","Keese (CSet 8)", + // 040 + "Keese (CSet 9)","Stalfos (L1)","Gel (L1, Normal)","Zol (L1, Normal)","Rope (L1)", + // 045 + "Goriya (L1)","Goriya (L2)","Trap (4-Way)","Wall Master","Darknut (L1)", + // 050 + "Darknut (L2)","Bubble (Sword, Temporary Disabling)","Vire (Normal)","Like Like","Gibdo", + // 055 + "Pols Voice (Arrow)","Wizzrobe (Teleporting)","Wizzrobe (Floating)","Aquamentus (Facing Left)","Moldorm", + // 060 + "Dodongo","Manhandla (L1)","Gleeok (1 Head)","Gleeok (2 Heads)","Gleeok (3 Heads)", + // 065 + "Gleeok (4 Heads)","Digdogger (1 Kid)","Digdogger (3 Kids)","Digdogger Kid (1)","Digdogger Kid (2)", + // 070 + "Digdogger Kid (3)","Digdogger Kid (4)","Gohma (L1)","Gohma (L2)","Lanmola (L1)", + // 075 + "Lanmola (L2)","Patra (L1, Big Circle)","Patra (L1, Oval)","Ganon","Stalfos (L2)", + // 080 + "Rope (L2)","Bubble (Sword, Permanent Disabling)","Bubble (Sword, Re-enabling)","Shooter (Fireball)","Item Fairy ", + // 085 + "Fire","Octorok (Magic)", "Darknut (Death Knight)", "Gel (L1, Tribble)", "Zol (L1, Tribble)", + // 090 + "Keese (Tribble)", "Vire (Tribble)", "Darknut (Splitting)", "Aquamentus (Facing Right)", "Manhandla (L2)", + // 095 + "Trap (Horizontal, Line of Sight)", "Trap (Vertical, Line of Sight)", "Trap (Horizontal, Constant)", "Trap (Vertical, Constant)", "Wizzrobe (Fire)", + // 100 + "Wizzrobe (Wind)", "Ceiling Master ", "Floor Master ", "Patra (BS Zelda)", "Patra (L2)", + // 105 + "Patra (L3)", "Bat", "Wizzrobe (Bat)", "Wizzrobe (Bat 2) ", "Gleeok (Fire, 1 Head)", + // 110 + "Gleeok (Fire, 2 Heads)", "Gleeok (Fire, 3 Heads)","Gleeok (Fire, 4 Heads)", "Wizzrobe (Mirror)", "Dodongo (BS Zelda)", + // 115 + "Dodongo (Fire) ","Trigger", "Bubble (Item, Temporary Disabling)", "Bubble (Item, Permanent Disabling)", "Bubble (Item, Re-enabling)", + // 120 + "Stalfos (L3)", "Gohma (L3)", "Gohma (L4)", "NPC 1 (Standing) ", "NPC 2 (Standing) ", + // 125 + "NPC 3 (Standing) ", "NPC 4 (Standing) ", "NPC 5 (Standing) ", "NPC 6 (Standing) ", "NPC 1 (Walking) ", + // 130 + "NPC 2 (Walking) ", "NPC 3 (Walking) ", "NPC 4 (Walking) ", "NPC 5 (Walking) ", "NPC 6 (Walking) ", + // 135 + "Boulder", "Goriya (L3)", "Leever (L3)", "Octorok (L3, Slow)", "Octorok (L3, Fast)", + // 140 + "Octorok (L4, Slow)", "Octorok (L4, Fast)", "Trap (8-Way) ", "Trap (Diagonal) ", "Trap (/, Constant) ", + // 145 + "Trap (/, Line of Sight) ", "Trap (\\, Constant) ", "Trap (\\, Line of Sight) ", "Trap (CW, Constant) ", "Trap (CW, Line of Sight) ", + // 150 + "Trap (CCW, Constant) ", "Trap (CCW, Line of Sight) ", "Wizzrobe (Summoner)", "Wizzrobe (Ice) ", "Shooter (Magic)", + // 155 + "Shooter (Rock)", "Shooter (Spear)", "Shooter (Sword)", "Shooter (Fire)", "Shooter (Fire 2)", + // 160 + "Bombchu", "Gel (L2, Normal)", "Zol (L2, Normal)", "Gel (L2, Tribble)", "Zol (L2, Tribble)", + // 165 + "Tektite (L3) ", "Spinning Tile (Combo)", "Spinning Tile (Enemy Sprite)", "Lynel (L3) ", "Peahat (L2) ", + // 170 + "Pols Voice (Magic)", "Pols Voice (Whistle) ", "Darknut (Mirror) ", "Ghini (L2, Fire) ", "Ghini (L2, Magic) ", + // 175 + "Grappler Bug (HP) ", "Grappler Bug (MP) " +}; + +char *guy_string[eMAXGUYS]; + +const char *enetype_string[eeMAX] = +{ + "-Guy", + "Walking Enemy", + "-Unused", + "Tektite", + "Leever", + "Peahat", + "Zora", + "Rock", + "Ghini", + "-Unused", + "Keese", + "-Unused", + "-Unused", + "-Unused", + "-Unused", + "Trap", + "Wall Master", + "-Unused", + "-Unused", + "-Unused", + "-Unused", + "Wizzrobe", + "Aquamentus", + "Moldorm", + "Dodongo", + "Manhandla", + "Gleeok", + "Digdogger", + "Gohma", + "Lanmola", + "Patra", + "Ganon", + "Projectile Shooter", + "-Unused", + "-Unused", + "-Unused", + "-Unused", + "Spin Tile", + "(None)", + "-Fairy", + "Other (Floating)", + "Other" +}; + +const char *eneanim_string[aMAX] = +{ + "(None)", + "Flip", + "-Unused", + "2-Frame", + "-Unused", + "Octorok (NES)", + "Tektite (NES)", + "Leever (NES)", + "Walker", + "Zora (NES)", + "Zora (4-Frame)", + "Ghini", + "Armos (NES)", + "Rope", + "Wall Master (NES)", + "Wall Master (4-Frame)", + "Darknut (NES)", + "Vire", + "3-Frame", + "Wizzrobe (NES)", + "Aquamentus", + "Dodongo (NES)", + "Manhandla", + "Gleeok", + "Digdogger", + "Gohma", + "Lanmola", + "2-Frame Flying", + "4-Frame 4-Dir + Tracking", + "4-Frame 8-Dir + Tracking", + "4-Frame 4-Dir + Firing", + "4-Frame 4-Dir", + "4-Frame 8-Dir + Firing", + "Armos (4-Frame)", + "4-Frame Flying 4-Dir", + "4-Frame Flying 8-Dir", + "-Unused", + "4-Frame 8-Dir Big", + "Tektite (4-Frame)", + "3-Frame 4-Dir", + "2-Frame 4-Dir", + "Leever (4-Frame)", + "2-Frame 4-Dir + Tracking", + "Wizzrobe (4-Frame)", + "Dodongo (4-Frame)", + "Dodongo BS (4-Frame)", + "4-Frame Flying 8-Dir + Firing", + "4-Frame Flying 4-Dir + Firing", + "4-Frame", + "Ganon", + "2-Frame Big" +}; + +/* +char *itemset_string[isMAX] = +{ + "(None)", + "Default", + "Bombs", + "Rupees", + "Life", + "Bombs 100%", + "Super Bombs 100%", + "Magic", + "Magic + Bombs", + "Magic + Rupees", + "Magic + Life", + "Magic 2" +}; +*/ + +const char *eweapon_string[wMax-wEnemyWeapons] = +{ + "(None)", + "Fireball", + "Arrow", + "Boomerang", + "Sword", + "Rock", + "Magic", + "Bomb Blast", + "Super Bomb Blast", + "Lit Bomb", + "Lit Super Bomb", + "Fire Trail", + "Flame", + "Wind", + "Flame 2", + "-Flame 2 Trail ", + "-Ice ", + "Fireball (Rising)" +}; + +const char *walkmisc1_string[e1tLAST] = +{ + "1 Shot", "1 (End-Halt)", "Rapid-Fire", "1 (Fast)", "1 (Slanted)", "3 Shots", "4 Shots", "5 Shots", "3 (Fast)", "Breath", "8 Shots", "Summon", "Summon (Layer)" +}; +const char *walkmisc2_string[e2tTRIBBLE+1] = +{ + "Normal", "Split On Hit", "Split On Death", "8 Shots", "Explode", "Tribble" +}; + +const char *walkmisc7_string[e7tEATHURT+1] = +{ + "None", "Temp. Jinx", "Perm. Jinx", "Cure Jinx", "Lose Magic", "Lose Rupees", "Drunk", "Eat (Items)", "Eat (Magic)", "Eat (Rupees)", "Eat (Damage)" +}; + +const char *walkmisc9_string[e9tARMOS+1] = +{ + "Normal", "Rope", "Vire", "Pols Voice", "Armos" +}; + +const char *pattern_string[MAXPATTERNS] = +{ + "Spawn (Classic)", "Enter from Sides (Consecutive)", "Enter from Sides (Random)", "Fall From Ceiling (Classic)", "Fall From Ceiling (Random)", "Spawn (Random)" +}; + +const char *short_pattern_string[MAXPATTERNS] = +{ + "Spawn (C)", "Sides", "Sides (R)", "Ceiling (C)", "Ceiling (R)", "Spawn (R)" +}; + +const char *midi_string[MAXCUSTOMMIDIS_ZQ] = +{ + "(None)", + "Overworld", + "Dungeon", + "Level 9", +}; + +const char *screen_midi_string[MAXCUSTOMMIDIS_ZQ+1] = +{ + "Use DMap MIDI", + "(None)", + "Overworld", + "Dungeon", + "Level 9", +}; + +void refresh(int flags); +void domouse(); +void init_doorcombosets(); + +int onNew(); +int onOpen(); +int onOpen2(); +int onRevert(); +int onSave(); +int onSaveAs(); +int onQuestTemplates(); + +int onUndo(); +int onCopy(); +int onPaste(); +int onPasteAll(); +int onPasteToAll(); +int onPasteAllToAll(); +int onDelete(); +int onDeleteMap(); + +int onTemplate(); +int onDoors(); +int onCSetFix(); +int onFlags(); +int onShowPal(); +int onReTemplate(); + +int playTune(); +int playMIDI(); +int stopMIDI(); +int onKeyFile(); + +int onUp(); +int onDown(); +int onLeft(); +int onRight(); +int onPgUp(); +int onPgDn(); +int onIncreaseCSet(); +int onDecreaseCSet(); + +int onHelp(); +void doHelp(int bg,int fg); + +int onScrData(); +int onGuy(); +int onEndString(); +int onString(); +int onRType(); +int onCatchall(); +int onItem(); +int onWarp(); +int onWarp2(); +int onPath(); +int onEnemies(); +int onEnemyFlags(); +int onUnderCombo(); +int onSecretCombo(); + +int onHeader(); +int onAnimationRules(); +int onComboRules(); +int onItemRules(); +int onEnemyRules(); +int onFixesRules(); +int onMiscRules(); +int onCompatRules(); +int onRules2(); +int onCheats(); +int onStrings(); +int onDmaps(); +int onTiles(); +int onCombos(); +int onMidis(); +int onShopTypes(); +int onInfoTypes(); +int onWarpRings(); +int onWhistle(); +int onMiscColors(); +int onMapStyles(); +int onTemplates(); +int onDoorCombos(); +int onTriPieces(); +int onIcons(); +int onInit(); +int onLayers(); +int onScreenPalette(); +int xtoi(char *hexstr); + +int onColors_Main(); +int onColors_Levels(); +int onColors_Sprites(); + +int onImport_Map(); +int onImport_DMaps(); +int onImport_Msgs(); +int onImport_Combos(); +int onImport_Tiles(); +int onImport_Subscreen(); +int onImport_Pals(); +int onImport_ZGP(); +int onImport_ZQT(); +int onImport_UnencodedQuest(); + +int onExport_Map(); +int onExport_DMaps(); +int onExport_Msgs(); +int onExport_MsgsText(); +int onExport_Combos(); +int onExport_Tiles(); +int onExport_Subscreen(); +int onExport_Pals(); +int onExport_ZGP(); +int onExport_ZQT(); +int onExport_UnencodedQuest(); + +int onGotoMap(); +int onMapCount(); + +int onViewPic(); +int onViewMap(); +int onComboPage(); + +int onDefault_Pals(); +int onDefault_Tiles(); +int onDefault_Combos(); +int onDefault_Sprites(); +int onDefault_MapStyles(); + +int onCustomItems(); +int onCustomWpns(); +int onCustomLink(); +int onCustomGuys(); + +int onTest(); +int onTestOptions(); + +int onOptions(); + +void draw_checkbox(BITMAP *dest,int x,int y,int bg,int fg,bool value); +void draw_layerradio(BITMAP *dest,int x,int y,int bg,int fg,int value); +void KeyFileName(char *kfname); + + +extern int draw_mode; +extern int alias_origin; + +int onSpacebar() +{ + if(draw_mode==3) + { + alias_origin=(alias_origin+1)%4; + return D_O_K; + } + + combo_cols=!combo_cols; + return D_O_K; +} + +int onSnapshot() +{ + char buf[26]; + int num=0; + + do + { +#ifdef ALLEGRO_MACOSX + sprintf(buf, "../../../zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#else + sprintf(buf, "zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#endif + } + while(num<999 && exists(buf)); + + blit(screen,screen2,0,0,0,0,zq_screen_w,zq_screen_h); + PALETTE RAMpal2; + get_palette(RAMpal2); + save_bitmap(buf,screen2,RAMpal2); + return D_O_K; +} + +int gocnt=0; + +void go() +{ + switch(gocnt) + { + case 0: + scare_mouse(); + blit(screen,menu1,0,0,0,0,zq_screen_w,zq_screen_h); + unscare_mouse(); + break; + + case 1: + scare_mouse(); + blit(screen,menu3,0,0,0,0,zq_screen_w,zq_screen_h); + unscare_mouse(); + break; + + default: + return; + } + + ++gocnt; +} + +void comeback() +{ + switch(gocnt) + { + case 1: + scare_mouse(); + blit(menu1,screen,0,0,0,0,zq_screen_w,zq_screen_h); + unscare_mouse(); + break; + + case 2: + scare_mouse(); + blit(menu3,screen,0,0,0,0,zq_screen_w,zq_screen_h); + unscare_mouse(); + break; + + default: + return; + } + + --gocnt; +} + +int checksave() +{ + if(saved) + return 1; + + char buf[80]; + char *name = get_filename(filepath); + + if(name[0]==0) + sprintf(buf,"Save this quest file?"); + else + sprintf(buf,"Save changes to %s?",name); + + switch(jwin_alert3("ZQuest",buf,NULL,NULL,"&Yes","&No","Cancel",'y','n',27,lfont)) + { + case 1: + onSave(); + return 1; + + case 2: + return 1; + } + + return 0; +} + +int onExit() +{ + restore_mouse(); + + if(checksave()==0) + return D_O_K; + + if(jwin_alert("ZQuest","Really want to quit?", NULL, NULL, "&Yes", "&No", 'y', 'n', lfont) == 2) + return D_O_K; + + return D_CLOSE; +} + +int onAbout() +{ + char buf1[80]; + char buf2[80]; + char buf3[80]; + + if(get_debug()) + { +#if IS_BETA + { + sprintf(buf1,"ZQuest %s Beta Build %d - DEBUG",VerStr(ZELDA_VERSION), VERSION_BUILD); + } +#else + { + sprintf(buf1,"ZQuest %s Build %d - DEBUG",VerStr(ZELDA_VERSION), VERSION_BUILD); + } +#endif + sprintf(buf2,"ZQuest Editor: %04X",INTERNAL_VERSION); + sprintf(buf3,"This qst file: %04X",header.internal&0xFFFF); + jwin_alert("About ZQuest",buf1,buf2,buf3,"OK", NULL, 13, 27, lfont); + } + else + { + switch(IS_BETA) + { + case -1: + sprintf(buf1,"ZQuest %s Alpha Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case 1: + sprintf(buf1,"ZQuest %s Beta Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + + case 0: + default: + sprintf(buf1,"ZQuest %s Build %d",VerStr(ZELDA_VERSION), VERSION_BUILD); + break; + } + + sprintf(buf3,"'The Travels of Link' sequenced by Jeff Glenen."); + jwin_alert("About ZQuest",buf1,NULL,buf3,"OK", NULL, 13, 27, lfont); + } + + return D_O_K; +} + +int onShowWalkability() +{ + Flags^=cWALK; + refresh(rMAP+rMENU); + return D_O_K; +} + +int onPreviewMode() +{ + prv_mode=(prv_mode+1)%2; + + if(prv_mode) + { + Map.set_prvscr(Map.getCurrMap(),Map.getCurrScr()); + } + + bool tempcb=ComboBrush!=0; + ComboBrush=0; + restore_mouse(); + dopreview(); + ComboBrush=tempcb; + return D_O_K; +} + +int onShowFlags() +{ + Flags^=cFLAGS; + refresh(rMAP); + return D_O_K; +} + +int onP() +{ + if(prv_mode) + { + Map.set_prvfreeze(((Map.get_prvfreeze()+1)%2)); + } + + return D_O_K; +} + +int onShowComboInfoCSet() +{ + if(Flags&cCSET) + { + Flags ^= cCSET; + Flags |= cCTYPE; + } + else if(Flags&cCTYPE) + { + Flags ^= cCTYPE; + } + else + { + Flags |= cCSET; + } + + refresh(rMAP); + return D_O_K; +} + +int onShowCSet() +{ + Flags^=cCSET; + Flags&=~cCTYPE; + refresh(rMAP); + return D_O_K; +} + +int onShowCType() +{ + Flags^=cCTYPE; + Flags&=~cCSET; + refresh(rMAP); + return D_O_K; +} + +int onShowDarkness() +{ + if(get_bit(quest_rules,qr_FADE)) + { + int last = CSET(5)-1; + + if(get_bit(quest_rules,qr_FADECS5)) + last += 16; + + byte *si = colordata + CSET(Color*pdLEVEL+poFADE1)*3; + + for(int i=0; i<16; i++) + { + int light = si[0]+si[1]+si[2]; + si+=3; + fade_interpolate(RAMpal,black_palette,RAMpal,light?32:64,CSET(2)+i,CSET(2)+i); + } + + fade_interpolate(RAMpal,black_palette,RAMpal,64,CSET(3),last); + set_palette(RAMpal); + + readkey(); + + load_cset(RAMpal,5,5); + loadlvlpal(Color); + } + else + { + loadfadepal(Color*pdLEVEL+poFADE3); + readkey(); + loadlvlpal(Color); + } + + return D_O_K; +} + +int onM() +{ + return D_O_K; +} + +int onJ() +{ + return D_O_K; +} + +void setFlagColor() +{ + RAMpal[dvc(0)]=RAMpal[vc(Flag%16)]; + set_palette_range(RAMpal,dvc(0),dvc(0),false); +} + +int onIncreaseFlag() +{ + Flag=(Flag+1); + + if(Flag==mfMAX) + { + Flag=0; + } + + setFlagColor(); + refresh(rMENU); + return D_O_K; +} + +int onDecreaseFlag() +{ + if(Flag==0) + { + Flag=mfMAX; + } + + Flag=(Flag-1); + setFlagColor(); + refresh(rMENU); + return D_O_K; +} + +int on0(); +int on1(); +int on2(); +int on3(); +int on4(); +int on5(); +int on6(); +int on7(); +int on8(); +int on9(); +int on10(); +int on11(); +int on12(); +int on13(); +int on14(); + +int onToggleDarkness(); +int onIncMap(); +int onDecMap(); + +int onDumpScr(); + +// these are here so that copy_dialog won't choke when compiling zquest +int d_jbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_kbutton_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_listen_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_savemidi_proc(int, DIALOG*, int) +{ + return D_O_K; +} + + + + diff --git a/src/zq_misc.h b/src/zq_misc.h new file mode 100644 index 0000000000..e37ebde45e --- /dev/null +++ b/src/zq_misc.h @@ -0,0 +1,333 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_misc.cc +// +// Misc. stuff for ZQuest. +// +//-------------------------------------------------------- + +//INLINE void SCRFIX() { putpixel(screen,0,0,getpixel(screen,0,0)); } +//INLINE void SCRFIX() {} + +#ifndef _ZQ_MISC_H_ +#define _ZQ_MISC_H_ + +#include "zc_alleg.h" +#include "zdefs.h" +#include "jwin.h" +#include "sfx.h" + +#define MAXSCREENS 128 +#define MAXROOMTYPES rMAX +#define MAXWARPTYPES wtMAX-1 // minus whistle +#define MAXWARPEFFECTS weMAX +#define MAXCOMBOTYPES cMAX +#define MAXFLAGS mfMAX +#define MAXPATTERNS 6 +#define MAXCUSTOMMIDIS_ZQ (4+MAXCUSTOMMIDIS) + +#define cWALK 1 +#define cFLAGS 2 +#define cDARK 4 +#define cCSET 8 +#define cNODARK 16 +#define cNOITEM 32 +#define cCTYPE 64 +#define cDEBUG 128 + +#define rMAP 1 +#define rCOMBOS 2 +#define rSCRMAP 4 +#define rMENU 8 +#define rCOMBO 16 +#define rFAVORITES 32 +#define rCOMMANDS 64 +#define rOTHER 128 +#define rALL 0x0FFF +#define rCLEAR 0x1000 +#define rNOCURSOR 0x2000 + +#define C(x) ((x)-'a'+1) + +INLINE int popup_menu(MENU *menu,int x,int y) +{ + while(gui_mouse_b()) + { + /* do nothing */ + } + + return jwin_do_menu(menu,x,y); +} + +INLINE int bit(int val,int b) +{ + return (val>>b)&1; +} + +enum { ftBIN=1, ftBMP, ftTIL, ftZGP, ftQSU, ftZQT, ftQST, ftMAX }; +extern const char *imgstr[ftMAX]; +extern char ns_string[4]; +extern const char *old_item_string[iLast]; +extern const char *old_weapon_string[wLast]; +extern const char *old_sfx_string[Z35]; +extern char *item_string[ITEMCNT]; +extern char *weapon_string[WPNCNT]; +extern char *sfx_string[WAV_COUNT]; +extern const char *roomtype_string[MAXROOMTYPES]; +extern const char *catchall_string[MAXROOMTYPES]; +extern const char *warptype_string[MAXWARPTYPES]; +extern const char *warpeffect_string[MAXWARPEFFECTS]; +//extern const char *combotype_string[MAXCOMBOTYPES]; +extern const char *flag_string[MAXFLAGS]; +extern const char *flag_help_string[(mfMAX)*3]; +extern const char *itemclass_help_string[(itype_last-20)*3]; +extern const char *combotype_help_string[cMAX*3]; +extern const char *old_guy_string[OLDMAXGUYS]; +extern char *guy_string[eMAXGUYS]; +extern const char *pattern_string[MAXPATTERNS]; +extern const char *short_pattern_string[MAXPATTERNS]; +extern const char *walkmisc1_string[e1tLAST]; +extern const char *walkmisc2_string[e2tTRIBBLE+1]; +extern const char *walkmisc7_string[e7tEATHURT+1]; +extern const char *walkmisc9_string[e9tARMOS+1]; +extern const char *midi_string[MAXCUSTOMMIDIS_ZQ]; +extern const char *screen_midi_string[MAXCUSTOMMIDIS_ZQ+1]; +extern const char *enetype_string[eeMAX]; +extern const char *eneanim_string[aMAX]; +//extern char *itemset_string[isMAX]; +extern const char *eweapon_string[wMax-wEnemyWeapons]; +extern int gocnt; + +int filetype(const char *path); +void load_mice(); +void load_icons(); +void load_panel_button_icons(); +void load_selections(); +void load_arrows(); +void dump_pal(); + +int wrap(int x,int low,int high); +bool readfile(const char *path,void *buf,int count); +bool writefile(const char *path,void *buf,int count); + +/*** from allegro's guiproc.c ***/ +void dotted_rect(int x1, int y1, int x2, int y2, int fg, int bg); + +RGB _RGB(byte *si); +RGB _RGB(int r,int g,int b); +RGB invRGB(RGB s); +RGB mixRGB(int r1,int g1,int b1,int r2,int g2,int b2,int ratio); + +void reset_pal_cycling(); +void cycle_palette(); +void load_cset(RGB *pal,int cset_index,int dataset); +void set_pal(); +void loadlvlpal(int level); +void loadfadepal(int dataset); + +void setup_lcolors(); +void refresh_pal(); + +void refresh(int flags); +void domouse(); +void init_doorcombosets(); + +int onNew(); +int onOpen(); +int onOpen2(); +int onRevert(); +int onSave(); +int onSaveAs(); +int onQuestTemplates(); + +int onUndo(); +int onCopy(); +int onPaste(); +int onPasteAll(); +int onPasteToAll(); +int onPasteAllToAll(); +int onDelete(); +int onDeleteMap(); + +int onPasteUnderCombo(); +int onPasteSecretCombos(); +int onPasteFFCombos(); +int onPasteWarps(); +int onPasteScreenData(); +int onPasteWarpLocations(); +int onPasteDoors(); +int onPasteLayers(); +int onPasteRoom(); +int onPasteGuy(); +int onPasteEnemies(); + +int onTemplate(); +int onDoors(); +int onCSetFix(); +int onFlags(); +int onShowPal(); +int onReTemplate(); + +int playTune(); +int playMIDI(); +int stopMIDI(); +int onKeyFile(); + +int onUp(); +int onDown(); +int onLeft(); +int onRight(); +int onPgUp(); +int onPgDn(); +int onIncreaseCSet(); +int onDecreaseCSet(); + +int onHelp(); +void doHelp(int bg,int fg); + +int onScrData(); +int onGuy(); +int onEndString(); +int onString(); +int onRType(); +int onCatchall(); +int onItem(); +int onWarp(); +int onWarp2(); +int onPath(); +int onEnemies(); +int onEnemyFlags(); +int onUnderCombo(); +int onSecretCombo(); + +int onHeader(); +int onAnimationRules(); +int onComboRules(); +int onItemRules(); +int onEnemyRules(); +int onFixesRules(); +int onMiscRules(); +int onCompatRules(); +int onRules2(); +int onCheats(); +int onStrings(); +int onDmaps(); +int onTiles(); +int onCombos(); +int onMidis(); +int onShopTypes(); +int onInfoTypes(); +int onWarpRings(); +int onWhistle(); +int onMiscColors(); +int onMapStyles(); +int onTemplates(); +int onDoorCombos(); +int onTriPieces(); +int onIcons(); +int onInit(); +int onLayers(); +int onScreenPalette(); +int xtoi(char *hexstr); + +int onColors_Main(); +int onColors_Levels(); +int onColors_Sprites(); + +int onImport_Map(); +int onImport_DMaps(); +int onImport_Msgs(); +int onImport_Combos(); +int onImport_Tiles(); +int onImport_Guys(); +int onImport_Subscreen(); +int onImport_Pals(); +int onImport_ZGP(); +int onImport_ZQT(); +int onImport_UnencodedQuest(); + +int onExport_Map(); +int onExport_DMaps(); +int onExport_Msgs(); +int onExport_MsgsText(); +int onExport_Combos(); +int onExport_Tiles(); +int onExport_Guys(); +int onExport_Subscreen(); +int onExport_Pals(); +int onExport_ZGP(); +int onExport_ZQT(); +int onExport_UnencodedQuest(); + +int onGotoMap(); +int onMapCount(); + +int onViewPic(); +int onViewMap(); +int onComboPage(); + +int onDefault_Pals(); +int onDefault_Tiles(); +int onDefault_Combos(); +int onDefault_Sprites(); +int onDefault_MapStyles(); + +int onCustomItems(); +int onCustomWpns(); +int onCustomLink(); +int onCustomGuys(); + +int onTest(); +int onTestOptions(); + +int onOptions(); + +bool edit_combo(int c,bool freshen,int cs); + +void draw_checkbox(BITMAP *dest,int x,int y,int bg,int fg,bool value); +void draw_layerradio(BITMAP *dest,int x,int y,int bg,int fg,int value); +void KeyFileName(char *kfname); + +int onSpacebar(); +int onSnapshot(); +void go(); +void comeback(); +int checksave(); +int onExit(); +int onAbout(); +int onShowCSet(); +int onShowCType(); +int onShowWalkability(); +int onPreviewMode(); +int onShowFlags(); +int onP(); +int onShowComboInfoCSet(); +int onShowDarkness(); +int onJ(); +int onM(); +void setFlagColor(); +int onIncreaseFlag(); +int onDecreaseFlag(); +int on0(); +int on1(); +int on2(); +int on3(); +int on4(); +int on5(); +int on6(); +int on7(); +int on8(); +int on9(); +int on10(); +int on11(); +int on12(); +int on13(); +int on14(); +int onToggleDarkness(); +int onIncMap(); +int onDecMap(); +int onDumpScr(); +#endif + diff --git a/src/zq_sprite.cpp b/src/zq_sprite.cpp new file mode 100644 index 0000000000..76d02a4183 --- /dev/null +++ b/src/zq_sprite.cpp @@ -0,0 +1,52 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// sprite.cc +// +// Sprite classes: +// - sprite: base class for the guys and enemies in zelda.cc +// - movingblock: the moving block class +// - sprite_list: main container class for different groups of sprites +// - item: items class +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#include "precompiled.h" //always first + +#include "sprite.h" + +int fadeclk=-1; +int frame=8; +bool BSZ=false; +int conveyclk=0; +bool freeze_guys=false; + +#define SLMAX 255 + +void sprite::check_conveyor() +{ + return; +} + +void movingblock::push(fix bx,fix by,int d2,int f) +{ + //these are here to bypass compiler warnings about unused arguments + bx=bx; + by=by; + d2=d2; + f=f; + + return; +} + +bool movingblock::animate(int index) +{ + //these are here to bypass compiler warnings about unused arguments + index=index; + + return false; +} + diff --git a/src/zq_strings.cpp b/src/zq_strings.cpp new file mode 100644 index 0000000000..d411a9945b --- /dev/null +++ b/src/zq_strings.cpp @@ -0,0 +1,1669 @@ +#include "zq_strings.h" +#include "editbox.h" +#include "EditboxNew.h" +#include "gui.h" +#include "jwin.h" +#include "qst.h" +#include "tiles.h" +#include "zc_alleg.h" +#include "zc_malloc.h" +#include "zdefs.h" +#include "zq_custom.h" +#include "zq_misc.h" +#include "zq_tiles.h" +#include "zqscale.h" +#include "zquest.h" +#include "zsys.h" +#include +#include + +void editmsg(int index, int addAfter); +int strlist_del(); +int addtomsglist(int index); +void build_bistringcat_list(); +const char *stringcatlist(int index, int *list_size); +char *parse_msg_str(char *s); +int msg_code_operands(int cc); +int d_msg_preview_proc(int msg,DIALOG *d,int c); +int d_msg_edit_proc(int msg,DIALOG *d,int c); +int d_msgtile_proc(int msg,DIALOG *d,int c); +void strlist_rclick_func(int index, int x, int y); + + +std::map msglistcache; + +static ListData strlist_dlg_list(msgslist, &font); +static ListData stringcat_dlg_list(stringcatlist, &font); +MsgStr *curmsgstr = NULL; +int msg_x = 0; +int msg_y = 0; +int msgtile = 0; +int msgcset = 0; +char msgbuf[MSGSIZE*3]; + +int bistringcat[256]; // A dropdown menu containing all strings which begin with '--', which serves as a quick shortcut to large string blocks. +int bistringcat_cnt=-1; + +extern int zqwin_scale; + +// Dialogs + +static int editmsg_string_list[] = +{ 2, 3, 4, 5, 8, 17, 18, 29, 32, -1 }; + +static int editmsg_attributes_list[] = +{ 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1 }; + +static TABPANEL editmsg_tabs[] = +{ + // (text) + { (char*)"String", D_SELECTED, editmsg_string_list, 0, NULL }, + { (char*)"Attributes", 0, editmsg_attributes_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +DIALOG strlist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 20, 0, 200+72, 148+76, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Edit Message String", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_list_proc, 34, 21+8, 176+49, 131+3,jwin_pal[jcTEXTFG],jwin_pal[jcTEXTBG],0,D_EXIT|(D_USER<<1),0, 0, (void *)&strlist_dlg_list, NULL, (void *) &strlist_rclick_func }, + { jwin_button_proc, 40, 163+36, 71, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 200, 163+36, 71, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, 0, (void *) strlist_del, NULL, NULL }, + + { jwin_text_proc, 32, 165+4, 128, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Message More X, Y: ", NULL, NULL }, + { jwin_edit_proc, 128, 165, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 158, 165, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 32, 165+22, 128, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Default Text Speed: ", NULL, NULL }, + { jwin_edit_proc, 128, 165+18, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + + { jwin_button_proc, 266, 74, 16, 16, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { jwin_button_proc, 266, 99, 16, 16, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + { jwin_button_proc, 266, 44, 16, 16, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { jwin_button_proc, 266, 129, 16, 16, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + //15 + { jwin_check_proc, 188, 168, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Y is Offset", NULL, NULL }, + { jwin_button_proc, 120, 163+36, 71, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Add New Here", NULL, NULL }, + //17 + { jwin_droplist_proc, 34, 16, 161, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG],0,D_EXIT,0, 0, (void *) &stringcat_dlg_list, NULL, NULL }, + { jwin_button_proc, 34+161+2, 18, 12, 12, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "?", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'c', 0, 0, 0, (void *) close_dlg, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'v', 0, 0, 0, (void *) close_dlg, NULL, NULL }, + //21 + { jwin_text_proc, 158, 165+22, 128, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Template: ", NULL, NULL }, + { jwin_edit_proc, 204, 165+18, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +DIALOG editmsg_dlg[] = +{ + + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 44, 0, 296, 220, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_tab_proc, 50, 24, 284, 164, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) editmsg_tabs, NULL, (void *)editmsg_dlg }, + { jwin_frame_proc, 53, 89-9, 278, 54, vc(14), vc(1), 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_msg_edit_proc, 61, 48, 240, 16, vc(12), vc(1), 0, 0, MSGSIZE*3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 52, 158, 168, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Next string:", NULL, NULL }, + // 5 + { jwin_droplist_proc, 110, 154, 158, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 187+6, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 187+6, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_msg_preview_proc, 56, 92-9, 272, 48, jwin_pal[jcTEXTBG], jwin_pal[jcTEXTFG], 0, 0, 0, 0, msgbuf, NULL, NULL }, + { jwin_edit_proc, 80, 66, 28+1, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + // 10 + { jwin_ctext_proc, 64, 70, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "Y:", NULL, NULL }, + { jwin_frame_proc, 58, 102, 20, 20, vc(14), vc(1), 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_msgtile_proc, 60, 104, 16, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 80, 84, 28+1, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 64, 88, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "SFX:", NULL, NULL }, + // 15 + { jwin_edit_proc, 80, 48, 28+1, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 64, 52, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "X:", NULL, NULL }, + { jwin_text_proc, 52, 140, 168, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "String font:", NULL, NULL }, + { jwin_droplist_proc, 110, 136, 158, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 160, 48, 28+1, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + // 20 + { jwin_ctext_proc, 136, 52, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "Width:", NULL, NULL }, + { jwin_edit_proc, 160, 66, 28+1, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 136, 70, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "Height:", NULL, NULL }, + { jwin_edit_proc, 160, 84, 28+1, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 136, 88, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "H Spacing:", NULL, NULL }, + // 25 + { jwin_edit_proc, 160, 102, 28+1, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 136, 106, 192, 8, vc(9), vc(1), 0, 0, 0, 0, (void *) "V Spacing:", NULL, NULL }, + { jwin_check_proc, 56, 126, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is continuation of previous string", NULL, NULL }, + { jwin_check_proc, 56, 136, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Text wraps around bounding box", NULL, NULL }, + { jwin_button_proc, 270, 152, 56, 16, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Next in List", NULL, NULL }, + // 30 + { jwin_button_proc, 250, 187+6, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Help", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { jwin_check_proc, 52, 176, 0, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Set previous string's \"Next string\" to this", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +DIALOG editmsg_help_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ +// { jwin_textbox_proc, 4, 2+21, 320-8, 240-6-21, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_win_proc, 0, 0, 320, 240, 0, vc(15), 0, D_EXIT, 0, 0, (void *) "String Control Codes", NULL, NULL }, + { jwin_frame_proc, 4, 23, 320-8, 240-27, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_editbox_proc, 6, 25, 320-8-4, 240-27-4, 0, 0, 0, 0/*D_SELECTED*/, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *) close_dlg, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, (void *) onSnapshot, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static MENU strlist_rclick_menu[] = +{ + { (char *)"Copy Properties", NULL, NULL, 0, NULL }, + { (char *)"Paste Properties", NULL, NULL, 0, NULL }, + { (char *)"Set As Template", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static int g_strPropCopySrc=-1; +void strlist_rclick_func(int index, int x, int y) +{ + // Don't do anything on (none) or + if(index==0 || index==msg_count-1) + return; + + // Disable "Paste Properties" if the copy source is invalid + if(g_strPropCopySrc<=0 || g_strPropCopySrc>=msg_count) + strlist_rclick_menu[1].flags|=D_DISABLED; + else + strlist_rclick_menu[1].flags&=~D_DISABLED; + + int ret=popup_menu(strlist_rclick_menu, x, y); + + switch(ret) + { + case 0: // Copy properties + g_strPropCopySrc=msg_at_pos(index); + break; + + case 1: // Paste properties + MsgStrings[msg_at_pos(index)].copyStyle(MsgStrings[g_strPropCopySrc]); + break; + + case 2: // Set as template + sprintf(static_cast(strlist_dlg[22].dp), "%d", msg_at_pos(index)); + strlist_dlg[22].flags|=D_DIRTY; + break; + } +} + +// Don't actually use this to strip spaces. +char *strip_extra_spaces(char *string) +{ + int len=(int)strlen(string); + char *src=(char *)zc_malloc(len+1); + char *tmpsrc=src; + memcpy(src,string,len+1); + memset(src,0,len+1); + + for(unsigned int i=0; string[i]&&i 126)) + { + for(int numops=msg_code_operands(*tmpsrc-1); numops>0; numops--) + { + tmpsrc++; + + if((byte)(*tmpsrc)==255) + { + tmpsrc+=2; + } + } + } + + tmpsrc++; + } + + *tmpsrc=0; + // memcpy(string,src,len); + strcpy(string,src); + zc_free(src); + return string; +} + +char *MsgString(int index, bool show_number, bool pad_number) +{ + bound(index,0,msg_strings_size-1); + static char u[80]; + bool indent = is_large && index>0 && MsgStrings[addtomsglist(MsgStrings[index].listpos-1)].nextstring==index; + sprintf(u, pad_number?"%s%3d":"%s%d",indent?"--> ":"",index); + char *s=strcat(u,": "); + + char *t = new char[71]; + memset(t, 0, 71); + int i=0; + int length=strlen(MsgStrings[index].s); + //return s; + + //remove preceding spaces; + for(; i126); ++i) + { + if(MsgStrings[index].s[i]!=' ') // Is it a control code? + { + for(int numops=msg_code_operands(MsgStrings[index].s[i]-1); numops>0; numops--) + { + i++; + + if((byte)(MsgStrings[index].s[i])==255) + i+=2; + } + } + } + + int msgptr=0; + + for(; msgptr<70 && i=32 && MsgStrings[index].s[i]<=126) + { + t[msgptr++]=MsgStrings[index].s[i]; + } + else if(i0; numops--) + { + i++; + + if((byte)(MsgStrings[index].s[i])==255) + i+=2; + } + } + } + + for(; msgptr<=70; msgptr++) + t[msgptr]=0; + + strip_extra_spaces(t); + + if(show_number) + strcat(s, t); + else + strcpy(s, t); + + delete[] t; + return s; +} + +const char *msgslistImpl(int index, int *list_size, bool numbered) +{ + static char buf[80]; + memset(buf, 0, 80); + + if(index>=0) + { + if(index>=msg_count) + { + index=msg_count-1; + } + + // Find the listpos corresponding to the index + int pos = 0; + + std::map::iterator res = msglistcache.find(index); + + if(res != msglistcache.end()) + pos = res->second; + else + { + pos = addtomsglist(index); + } + + memcpy(buf,MsgString(pos, numbered, numbered),80); + return buf; + } + + *list_size=msg_count; + return NULL; +} + +const char *msgslist(int index, int *list_size) +{ + return msgslistImpl(index, list_size, true); +} + +//same as above, but without the numbers +const char *msgslist2(int index, int *list_size) +{ + return msgslistImpl(index, list_size, false); +} + +FONT* getfont(int fonta) +{ + switch(fonta) + { + default: + return zfont; + + case font_z3font: + return z3font; + + case font_z3smallfont: + return z3smallfont; + + case font_deffont: + return deffont; + + case font_lfont: + return lfont; + + case font_lfont_l: + return lfont_l; + + case font_pfont: + return pfont; + + case font_mfont: + return mfont; + + case font_ztfont: + return ztfont; + + case font_sfont: + return sfont; + + case font_sfont2: + return sfont2; + + case font_spfont: + return spfont; + + case font_ssfont1: + return ssfont1; + + case font_ssfont2: + return ssfont2; + + case font_ssfont3: + return ssfont3; + + case font_ssfont4: + return ssfont4; + + case font_gblafont: + return gblafont; + + case font_goronfont: + return goronfont; + + case font_zoranfont: + return zoranfont; + + case font_hylian1font: + return hylian1font; + + case font_hylian2font: + return hylian2font; + + case font_hylian3font: + return hylian3font; + + case font_hylian4font: + return hylian4font; + + case font_gboraclefont: + return gboraclefont; + + case font_gboraclepfont: + return gboraclepfont; + + case font_dsphantomfont: + return dsphantomfont; + + case font_dsphantompfont: + return dsphantompfont; + } +} + +void fix_string(word &str, word index) +{ + if(str == index) + str = 0; + else if(str > index) + --str; +} + +int strlist_del() +{ + if(msglistcache[strlist_dlg[2].d1]>0 && msglistcache[strlist_dlg[2].d1]= msg_strings_size) + { + Z_message("Reallocating string buffer...\n"); + MsgStrings=(MsgStr*)_al_sane_realloc(MsgStrings,sizeof(MsgStr)*MAXMSGS); + memset((void*)(&MsgStrings[msg_strings_size]), 0, sizeof(MsgStr)*(MAXMSGS-msg_strings_size)); + msg_strings_size = MAXMSGS; + init_msgstrings(msg_count, msg_strings_size); + } + + for(int i=0; i"); + MsgStrings[msg_count].x=24; + MsgStrings[msg_count].y=32; + MsgStrings[msg_count].w=24*8; + MsgStrings[msg_count].h=3*8; + MsgStrings[msg_count].hspace=0; + MsgStrings[msg_count].vspace=0; + MsgStrings[msg_count].stringflags=0; + MsgStrings[msg_count].listpos=msg_count; + } + + strlist_dlg[7].dp=msgmore_xstring; + strlist_dlg[8].dp=msgmore_ystring; + strlist_dlg[10].dp=msgspeed_string; + strlist_dlg[22].dp=template_string; + + int ret=zc_popup_dialog(strlist_dlg,2); + index=msglistcache[strlist_dlg[2].d1]; + + bool doedit=false; + int addAfter = -1; + + switch(ret) + { + case 18: + jwin_alert("String Index","Create a string beginning with two hyphens '--'", + "and it will be listed in this index, serving as a", + "shortcut to a location in your string list.","O&K",NULL,'k',0,lfont); + break; + + case 17: // Go to category + { + strlist_dlg[2].d1 = MsgStrings[bistringcat[strlist_dlg[17].d1]].listpos; + break; + } + + case 11: // Move string up + { + if(index==0 || index==msg_count-1) + break; + + // Find the string with index's listpos - 1, and increment it + int nextlistpos = MsgStrings[index].listpos-1; + + if(nextlistpos<0) + break; + + std::map::iterator res = msglistcache.find(nextlistpos); + + if(res == msglistcache.end()) + (void)addtomsglist(nextlistpos); + + int otherindex = msglistcache[nextlistpos]; + + if(otherindex==0) + break; // It's obviously not in here... + + MsgStrings[index].listpos--; + MsgStrings[otherindex].listpos++; + + // Fix msglistcache + (void)addtomsglist(MsgStrings[index].listpos); + (void)addtomsglist(MsgStrings[index].listpos+1); + + strlist_dlg[2].d1--; + saved=false; + break; + } + + case 12: // Move string down + { + if(index==0 || index==msg_count-1) + break; + + // Find the string with index's listpos + 1, and decrement it + int nextlistpos = MsgStrings[index].listpos+1; + + if(nextlistpos>=msg_count-1) + break; + + std::map::iterator res = msglistcache.find(nextlistpos); + + if(res == msglistcache.end()) + (void)addtomsglist(nextlistpos); + + int otherindex = msglistcache[nextlistpos]; + + if(otherindex==0) + break; // It's obviously not in here... + + MsgStrings[index].listpos++; + MsgStrings[otherindex].listpos--; + + // Fix msglistcache + (void)addtomsglist(MsgStrings[index].listpos); + (void)addtomsglist(MsgStrings[index].listpos-1); + + strlist_dlg[2].d1++; + saved=false; + break; + } + + case 13: // Move string up - 12 + case 14: // Move string down - 12 + { + if(index==0 || index==msg_count-1) + break; + + int diff = (ret == 13) ? zc_max(MsgStrings[index].listpos-12, 1) : zc_min(MsgStrings[index].listpos+12, msg_count-2); + int sign = (ret == 13) ? -1 : 1; + + int nextindex; + + // For all strings above or below, de/increment + for(int i=MsgStrings[index].listpos; i!=diff+sign; i+=sign) + { + std::map::iterator res = msglistcache.find(i); + + if(res == msglistcache.end()) + (void)addtomsglist(i); + + int otherindex = msglistcache[i]; + + if(otherindex==0) + break; // It's obviously not in here... + + if(i==diff) + { + nextindex = index; + } + else + { + res = msglistcache.find(i+sign); + + if(res == msglistcache.end()) + (void)addtomsglist(i+sign); + + nextindex = msglistcache[i+sign]; + } + + MsgStrings[otherindex].listpos+=sign; + MsgStrings[nextindex].listpos-=sign; + (void)addtomsglist(MsgStrings[otherindex].listpos); + (void)addtomsglist(MsgStrings[nextindex].listpos); + } + + //MsgStrings[index].listpos=diff; + //(void)addtomsglist(MsgStrings[index].listpos); + strlist_dlg[2].d1=diff; + saved=false; + break; + } + + case 16: + addAfter=zc_min(index, msg_count-2); + index=msg_count-1; + strlist_dlg[2].d1 = index; + + case 2: + case 3: + doedit=true; + break; + + case 0: // ??? + case 4: + + index=-1; + zinit.msg_more_x=atoi(msgmore_xstring); + zinit.msg_more_y=atoi(msgmore_ystring); + zinit.msg_speed=atoi(msgspeed_string); + zinit.msg_more_is_offset=(strlist_dlg[15].flags&D_SELECTED)?1:0; + + if(morex!=zinit.msg_more_x||morey!=zinit.msg_more_y||msgspeed!=zinit.msg_speed) + { + saved=false; + } + + break; + + case 5: // Delete + char buf[73], shortbuf[73]; + memset(buf, 0, 73); + memset(shortbuf, 0, 73); + strncpy(buf,MsgString(index, true, false),72); + strip_extra_spaces(buf); + shorten_string(shortbuf, buf, font, 72, 288); + + if(jwin_alert("Confirm Clear","Clear this message string?"," ",shortbuf,"Yes","No",'y',27,lfont)==1) + { + saved=false; + word pos=MsgStrings[index].listpos; + memset((void*)(&MsgStrings[index]), 0, sizeof(MsgStr)); + MsgStrings[index].x=24; + MsgStrings[index].y=32; + MsgStrings[index].w=24*8; + MsgStrings[index].h=3*8; + MsgStrings[index].listpos=pos; // Since the stuff below isn't being run, do this instead + + + /*// Go through strings with higher listpos and decrement listpos + for(int j=MsgStrings[index].listpos; j0) + { + if(index==msg_count-1) + msg_count++; + + MsgStrings[index]=MsgStrings[copysrc]; + } + + break; + } + + if(hasroom) + { + --msg_count; + } + + if(index>0 && doedit) + { + int lp = MsgStrings[addAfter].listpos; + editmsg(index, addAfter); + + if(MsgStrings[index].listpos!=msg_count) // Created new string + { + // Select the new message + strlist_dlg[2].d1 = MsgStrings[index].listpos; + if((editmsg_dlg[32].flags&D_SELECTED)!=0) + { + int prev=msg_at_pos(MsgStrings[index].listpos-1); + MsgStrings[prev].nextstring=index; + } + editmsg_dlg[27].flags=(MsgStrings[index].stringflags&STRINGFLAG_CONT)?D_SELECTED:0; + } + else // Canceled or edited an existing string + // Select previously selected message + strlist_dlg[2].d1 = lp; + + // Fix the quick-category menu + strlist_dlg[17].d1=0; + build_bistringcat_list(); + refresh(rMENU); + } + } + + //if(smsg!=NULL) delete [] smsg; + return D_O_K; +} + +void editmsg(int index, int addAfter) +{ + char setitle[80]; + sprintf(setitle, "String Editor (%d)", index); + + encode_msg_str(index); + + if(index==msg_count) // Adding a new message + { + int templateID=atoi(static_cast(strlist_dlg[22].dp)); + if(templateID>0 && templateIDdoHelp(); // This deletes the EditboxModel too. + } + } + while(ret==-1); + + if(ret==6) + { + saved=false; + char *tempstr_ = parse_msg_str(msgbuf); + sprintf(MsgStrings[index].s, "%s", tempstr_); + delete [] tempstr_; + + MsgStrings[index].nextstring = addtomsglist(editmsg_dlg[5].d1); + MsgStrings[index].font = editmsg_dlg[18].d1; + MsgStrings[index].trans = editmsg_dlg[9].flags != 0; + MsgStrings[index].tile = editmsg_dlg[12].d1; + MsgStrings[index].cset = editmsg_dlg[12].fg; + MsgStrings[index].x = vbound((int)strtol(msg_xbuf, (char **)NULL, 10),-512,512); + MsgStrings[index].y = vbound((int)strtol(msg_ybuf, (char **)NULL, 10),-512,512); + MsgStrings[index].w = vbound((int)strtol(msg_wbuf, (char **)NULL, 10),8,512); + MsgStrings[index].h = vbound((int)strtol(msg_hbuf, (char **)NULL, 10),8,512); + MsgStrings[index].hspace = vbound((int)strtol(msg_hsbuf, (char **)NULL, 10),0,128); + MsgStrings[index].vspace = vbound((int)strtol(msg_vsbuf, (char **)NULL, 10),0,128); + MsgStrings[index].sfx = (int)strtol(msg_sfxbuf, (char **)NULL, 10); + MsgStrings[index].stringflags = editmsg_dlg[27].flags & D_SELECTED ? MsgStrings[index].stringflags | STRINGFLAG_CONT : MsgStrings[index].stringflags & ~STRINGFLAG_CONT; + MsgStrings[index].stringflags = editmsg_dlg[28].flags & D_SELECTED ? MsgStrings[index].stringflags | STRINGFLAG_WRAP : MsgStrings[index].stringflags & ~STRINGFLAG_WRAP; + + if(index==msg_count) + { + if(addAfter!=-1) + { + MsgStrings[index].listpos = MsgStrings[addAfter].listpos+1; + + // Go through strings with higher listpos and increment listpos + for(int j=msg_count-1; j>=MsgStrings[index].listpos; j--) + { + MsgStrings[addtomsglist(j)].listpos++; + } + + msglistcache.clear(); + } + + ++msg_count; + MsgStrings[msg_count].sfx=18; + MsgStrings[msg_count].listpos=msg_count; + } + } + else if(ret==7 && addAfter!=-1) + { + MsgStrings[index].listpos = msg_count; + } +} + +// Returns the actual string of a given listpos +int addtomsglist(int index) +{ + if(index==0) + return 0; // '(None)' is always at the top + + if(index==msg_count) + return msg_count; // '' is always at the bottom + + int pos = 0; + // Easy heuristic: + // - Search backwards if index>(msg_count/2) + int increment = 1; + int i = 0; + + if(index > (msg_count/2)) + { + increment = -1; + i = msg_count-1; + } + + for(; i=0; i+=increment) + { + if(MsgStrings[i].listpos==index) + { + msglistcache[index] = pos = i; + break; + } + } + + return pos; +} + +const char *msgfont_str[font_max] = +{ + "Zelda NES", "Link to the Past", "LttP Small", "Allegro Default", "GUI Font Bold", "GUI Font", "GUI Font Narrow", "Zelda NES (Matrix)", "BS Time (Incomplete)", "Small", "Small 2", + "S. Proportional", "SS 1 (Numerals)", "SS 2 (Incomplete)", "SS 3", "SS 4 (Numerals)", "Link's Awakening", "Goron", "Zoran", "Hylian 1", "Hylian 2", + "Hylian 3", "Hylian 4", "Oracle", "Oracle Proportional", "Phantom", "Phantom Proportional" +}; + +const char *msgfontlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = font_max; + return NULL; + } + + return msgfont_str[index]; +} + +void strip_trailing_spaces(char *str) +{ + for(int i=0; str[i]; i++) + { + if(str[i]==' ') + { + for(int k=i+1; true; k++) + { + // End of the string, just spaces so far; end at i + if(str[k]=='\0') + { + str[i]='\0'; + return; + } + // Found a non-space character + else if(str[k]!=' ') + { + i=k; + break; + } + } + } + } +} + +//Not really the right usage of "parse"... +char *parse_msg_str(char *s) +{ + //if(smsg!=NULL) delete [] smsg; + char *smsg = new char[MSGSIZE+1]; + memset(smsg, 0, MSGSIZE+1); + int msgptr=0; + + for(int i=0; msgptr='0' && *(s+i+1)<='9' && ++digits <= 5) + { + i++; + msgcc*=10; // Move the current number one decimal place right. + msgcc+=(*(s+i)-'0'); + + // A hack to allow multi-byte numbers. + if(msgcc >= 254) + { + twofiftyfives = (msgcc/254)<<0; + } + + smsg[msgptr] = (unsigned char)((msgcc % 254) + 1); // As 0 is null, we must store codes 1 higher than their actual value... + } + + // A hack to allow multi-byte numbers, continued + if(twofiftyfives > 0 && i+2= 32 && *(s+i) <=126) ? *(s+i) : ' '; + } + } + + smsg[msgptr] = '\0'; + return smsg; +} + +//Make sure this is synchronised with parsemsgcode in guys.cpp! +void put_msg_str(char *s,int x,int y,int, int ,int, int start_x, int start_y) +{ + int cursor_x = 0; + int cursor_y = 0; + int w = vbound((int)strtol((char*)editmsg_dlg[19].dp, (char **)NULL, 10),0,512); + int h = vbound((int)strtol((char*)editmsg_dlg[21].dp, (char **)NULL, 10),0,512); + int fonta = editmsg_dlg[18].d1; + int flags = 0; + flags |= (int)editmsg_dlg[27].flags & D_SELECTED ? STRINGFLAG_CONT : 0; + flags |= (int)editmsg_dlg[28].flags & D_SELECTED ? STRINGFLAG_WRAP : 0; + int vspace = vbound((int)strtol((char*)editmsg_dlg[25].dp, (char **)NULL, 10),0,128); + int hspace = vbound((int)strtol((char*)editmsg_dlg[23].dp, (char **)NULL, 10),0,128); + int nextstring = addtomsglist(editmsg_dlg[5].d1); + + int i=0; + int msgcolour=misc.colors.msgtext; + + FONT *workfont = getfont(fonta); + + char *s2 = parse_msg_str(s); + strip_trailing_spaces(s2); + + BITMAP *buf = create_bitmap_ex(8,zc_max(w+16,256+16),zc_max(h+16,32+16)); + clear_bitmap(buf); + + if(buf) + { + clear_bitmap(buf); + + if(msgtile) + frame2x2(buf,&misc,0,0,msgtile,msgcset,(w/8)+2,(h/8)+2,0,0,0); + + bool space=true; + int tlength=0; + + for(; ;) + { + i=0; + + while((*(s2+i))) + { + char s3[145]; // Stores a complete word + int j; + int s3length = 1; + int hjump=0; + + if(flags & STRINGFLAG_WRAP) + { + if(space) + { + // Control codes and spaces are like one-character words + if((*(s2+i)) == ' ' || (*(s2+i)) < 32 || (*(s2+i)) > 126) + { + s3[0] = (*(s2+i)); + s3[1] = 0; + hjump = hspace; + i++; + } + else space = false; + } + + if(!space) + { + // Complete words finish at spaces or control codes. + for(j=i; (*(s2+j)) != ' ' && (*(s2+j)) >= 32 && (*(s2+j)) <= 126 && (*(s2+j)); j++) + { + s3[j-i] = (*(s2+j)); + hjump += hspace; + + if(s3[j-i]-1 == MSGC_NEWLINE) + { + j++; + break; + } + } + + space = true; + s3[j-i] = 0; + s3length = j-i; + i=j; + } + } + else + { + space=false; + /*for(j=i; (*(s2+j)) < 32 || (*(s2+j)) > 126 && (*(s2+j)); j++) + { + s3[j-i] = (*(s2+j)); + if(s3[j-i]-1 == MSGC_NEWLINE) {j++; break;} + } + s3[j-i] + s3[j-i+1] = 0; + i=j;*/ + s3[0] = (*(s2+i)); + + if(s3[0] >= 32 && s3[0] <= 126) hjump = hspace; + + s3[1] = 0; + i++; + } + + tlength = text_length(workfont, s3); + + if(cursor_x+tlength+hjump > w && ((cursor_x > w || !(flags & STRINGFLAG_WRAP)) ? 1 : strcmp(s3," ")!=0)) + { + cursor_y += text_height(workfont) + vspace; + cursor_x=0; + //if(space) s3[0]=0; + } + + // Evaluate what control code the character is, and skip over the CC's arguments by incrementing i (NOT k). + // Interpret the control codes which affect text display (currently just MSGC_COLOR). -L + for(int k=0; k < s3length; k++) + { + switch(s3[k]-1) + { + case MSGC_NEWLINE: + { + if(cursor_x>0 || (cursor_y==0 && cursor_x==0)) // If the newline's already at the end of a line, ignore it + { + cursor_y += text_height(workfont) + vspace; + cursor_x=0; + } + + //No i++ here - s3 terminates at newlines. + break; + } + + case MSGC_COLOUR: + { + // Read the CC arguments directly from s2, while skipping over them. + // (Yes, i++ and not ++i) -L + int cset = (*(s2+(i++)))-1; + msgcolour = CSET(cset)+(*(s2+(i++)))-1; + break; + } + + default: + if(s3[k] >= 32 && s3[k] <= 126) + { + textprintf_ex(buf,workfont,cursor_x+8,cursor_y+8,msgcolour,-1,"%c",s3[k]); + cursor_x += workfont->vtable->char_length(workfont, s3[k]); + cursor_x += hspace; + } + else + { + for(int numops=msg_code_operands(s3[k]-1); numops>0; numops--) + { + i++; + + if((byte)s2[i]==255) + i+=2; + } + } + + break; + } + } + } + + if(nextstring && MsgStrings[nextstring].stringflags & STRINGFLAG_CONT) + { + workfont = getfont(MsgStrings[nextstring].font); + flags = MsgStrings[nextstring].stringflags; + hspace = MsgStrings[nextstring].hspace; + vspace = MsgStrings[nextstring].vspace; + + if(s2!=NULL) delete [] s2; + + s2 = new char[MSGSIZE+1]; + strcpy(s2, MsgStrings[nextstring].s); + strip_trailing_spaces(s2); + + // Prevent an infinite loop... + if(MsgStrings[nextstring].nextstring!=nextstring) + nextstring = MsgStrings[nextstring].nextstring; + else + nextstring=0; + } + else + { + break; + } + } + + stretch_blit(buf,screen,start_x,start_y,256+16,32+16,x,y,(256+16)*(is_large?2:1),(32+16)*(is_large?2:1)); + destroy_bitmap(buf); + } + + if(s2!=NULL) delete [] s2; +} + +int mprvfont=0; +int mprvflags=0; +int mprvvspace=0; +int mprvhspace=0; +int mprvnextstring=0; +int mprvw=0; +int mprvh=0; + +// Load a stored string into msgbuf for editing. +void encode_msg_str(int index) +{ + memset(msgbuf, 0, MSGSIZE*3); + + // Adding a new string? + if(index==msg_count) + return; + + char *str=MsgStrings[index].s; + int strPos=0; + int msgbufPos=0; + byte nextChar; + char sccBuf[30]; // For string control codes + char sccArgBuf[10]; + word sccArg; + int sccNumArgs; + + while(msgbufPos=32 && nextChar<=126 && nextChar!='\\') + { + msgbuf[msgbufPos]=nextChar; + msgbufPos++; + strPos++; + } + + // String control codes... + else + { + // Backslash is a special case + if(nextChar=='\\') + { + sprintf(sccBuf, "\\91"); + strPos++; + } + else + { + // Load the code into sccBuf. The code is stored one higher + // than its actual value to ensure that it's not null. + nextChar--; + sprintf(sccBuf, "\\%hu", (word)nextChar); + strPos++; + + // One at a time, read arguments and append them to sccBuf + for(sccNumArgs=msg_code_operands(nextChar); sccNumArgs>0; sccNumArgs--) + { + // If strPos hasn't gone past the end of the string, + // just drop the control code. + if(strPos>MSGSIZE) + return; + + // If the argument is 253 or less, it's stored in one byte + // with one added so that it's not null. + nextChar=str[strPos]; + sccArg=nextChar-1; + strPos++; + + // If there are at least two more bytes to read, they may + // be part of the same argument. + if(strPos<=MSGSIZE-2) + { + // If the next byte is 255, add the byte after that + // times 254 to the argument. + nextChar=str[strPos]; + + if(nextChar==255) + { + nextChar=str[strPos+1]; + sccArg+=254*nextChar; + strPos+=2; + } + } + + // Append the argument to sccBuf. + sprintf(sccArgBuf, "\\%hu", sccArg); + strcat(sccBuf, sccArgBuf); + } + } + + // Finally, copy the control code into msgbuf + strcat(msgbuf, sccBuf); + msgbufPos+=strlen(sccBuf); + } + } +} + +// Fix the strings if they were broken +void fix_string_list() +{ + int found[MAXMSGS]; + bool corrupted = false; + memset(found, 0, MAXMSGS); + + for(int i=0; i=0) + { + memcpy(buf,MsgString(bistringcat[index], true, true),80); + return buf; + } + + *list_size=bistringcat_cnt; + return NULL; +} + + +// Dialog procs + // + + +int d_msg_preview_proc(int msg,DIALOG *d,int c) +{ + c=c; + char *s=(char*)(d->dp); + int w = vbound((int)strtol((char *)editmsg_dlg[19].dp, (char **) NULL, 10),8,512); + int h = vbound((int)strtol((char *)editmsg_dlg[21].dp, (char **) NULL, 10),8,512); + + if(msg_x > zc_max(w-256,0)) msg_x = zc_max(w-256,0); + + if(msg_y > zc_max(h-32,0)) msg_y = zc_max(h-32,0); + + if(mprvfont != editmsg_dlg[18].d1 || + mprvflags != ((editmsg_dlg[27].flags & D_SELECTED ? STRINGFLAG_CONT : 0) | (editmsg_dlg[28].flags & D_SELECTED ? STRINGFLAG_WRAP : 0)) || + mprvvspace != vbound((int)strtol((char*)editmsg_dlg[25].dp, (char **)NULL, 10),0,128) || + mprvhspace != vbound((int)strtol((char*)editmsg_dlg[23].dp, (char **)NULL, 10),0,128) || + mprvnextstring != addtomsglist(editmsg_dlg[5].d1) || + mprvw != vbound((int)strtol((char*)editmsg_dlg[25].dp, (char **)NULL, 10),0,128) || + mprvh != vbound((int)strtol((char*)editmsg_dlg[23].dp, (char **)NULL, 10),0,128)) + { + + mprvfont = editmsg_dlg[18].d1; + mprvflags = 0; + mprvflags |= (int)editmsg_dlg[27].flags & D_SELECTED ? STRINGFLAG_CONT : 0; + mprvflags |= (int)editmsg_dlg[28].flags & D_SELECTED ? STRINGFLAG_WRAP : 0; + mprvvspace = vbound((int)strtol((char*)editmsg_dlg[25].dp, (char **)NULL, 10),0,128); + mprvhspace = vbound((int)strtol((char*)editmsg_dlg[23].dp, (char **)NULL, 10),0,128); + mprvnextstring = addtomsglist(editmsg_dlg[5].d1); + mprvw = vbound((int)strtol((char*)editmsg_dlg[25].dp, (char **)NULL, 10),0,128); + mprvh = vbound((int)strtol((char*)editmsg_dlg[23].dp, (char **)NULL, 10),0,128); + + msg = MSG_DRAW; + } + + + switch(msg) + { + case MSG_CLICK: + { + /*{ + int pos = (((gui_mouse_x())-(d->x+8))>>3)+(((gui_mouse_y())-(d->y+16))>>3)*24; + int i = 0; + while (pos>0 && i<(int)strlen(msgbuf)) { + while (msgbuf[i] == '\\') { + do { + i++; + } + while(i<(int)strlen(msgbuf) && msgbuf[i] >= '0' && msgbuf[i] <= '9'); + } + pos--; + i++; + } + editmsg_dlg[3].d2 = i; + (void)jwin_edit_proc(MSG_DRAW,&editmsg_dlg[3],c);*/ + int ox = gui_mouse_x(); + int oy = gui_mouse_y(); + int cmx = msg_x; + int cmy = msg_y; + int omx = cmx; + int omy = cmy; + + while(gui_mouse_b()) + { + if(cmx != msg_x || cmy != msg_y) + { + cmx = msg_x; + cmy = msg_y; + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + } + + msg_x = vbound(omx+(ox-gui_mouse_x()),0,zc_max(0,w-256)); + msg_y = vbound(omy+(oy-gui_mouse_y()),0,zc_max(0,h-32)); + + broadcast_dialog_message(MSG_IDLE, 0); +#ifdef _ZQUEST_SCALE_ + + if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + +#endif + } + + break; + } + + case MSG_DRAW: + if(!(d->flags & D_GOTFOCUS)) + { + d->d2=-1; + } + + rectfill(screen, d->x, d->y, d->x+d->w, d->y+d->h, 0); + put_msg_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2,msg_x,msg_y); + break; + } + + return D_O_K; +} + +int d_msg_edit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_CHAR) + (void)d_msg_preview_proc(MSG_DRAW,&editmsg_dlg[8],c); + else if(msg==MSG_START) + { + //hack to counteract jwin_edit_proc's automatic setting of the cursor to the far right + d->d2=0; + } + + return ret; +} + +int d_msgtile_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + if(select_tile(d->d1,d->d2,1,d->fg,true)) + { + msgtile = d->d1; + msgcset = d->fg; + return D_REDRAW; + } + + break; + + case MSG_DRAW: + { + int dw = d->w; + int dh = d->h; + + if(is_large) + { + dw /= 2; + dh /= 2; + } + + BITMAP *buf = create_bitmap_ex(8,dw,dh); + + if(buf) + { + clear_bitmap(buf); + + if(d->d1) + puttile16(buf,d->d1,0,0,d->fg,0); + + stretch_blit(buf,screen,0,0,dw,dh,d->x-is_large,d->y-is_large,dw*(is_large?2:1),dh*(is_large?2:1)); + destroy_bitmap(buf); + } + } + } + + return D_O_K; +} diff --git a/src/zq_strings.h b/src/zq_strings.h new file mode 100644 index 0000000000..cc5566f123 --- /dev/null +++ b/src/zq_strings.h @@ -0,0 +1,22 @@ +#ifndef _ZQ_STRINGS_H_ +#define _ZQ_STRINGS_H_ + +#include +struct DIALOG; + +int onStrings(); +char *MsgString(int index, bool show_number, bool pad_number); +const char *msgfontlist(int index, int *list_size); +const char *msgslist(int index, int *list_size); +const char *msgslist2(int index, int *list_size); +int msg_at_pos(int pos); +char *strip_extra_spaces(char *string); +void encode_msg_str(int index); + +extern DIALOG strlist_dlg[]; +extern DIALOG editmsg_dlg[]; +extern DIALOG editmsg_help_dlg[]; + +extern std::map msglistcache; + +#endif diff --git a/src/zq_subscr.cpp b/src/zq_subscr.cpp new file mode 100644 index 0000000000..3e89a02f10 --- /dev/null +++ b/src/zq_subscr.cpp @@ -0,0 +1,7405 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// subscr.cc +// +// Subscreen code for zelda.cc +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include + +#include "gui.h" +#include "subscr.h" +#include "zq_subscr.h" +#include "jwin.h" +#include "zquest.h" +#include "zsys.h" +#include "zq_misc.h" +#include "tiles.h" +#include "qst.h" +#include "init.h" +#include +#include "mem_debug.h" + +#ifndef _MSC_VER +#include +#endif +#include + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +extern void large_dialog(DIALOG *d); +extern void large_dialog(DIALOG *d, float RESIZE_AMT); + +using namespace std; + +int curr_subscreen_object; +char *str_oname; +subscreen_group *css; +bool sso_selection[MAXSUBSCREENITEMS]; +static int g_ssPropCopySrc=-1; + +void replacedp(DIALOG &d, const char *newdp, size_t size=256); + +gamedata *game; + +//extern char *itemlist(int index, int *list_size) +extern int bii_cnt; + +void delete_subscreen(int subscreenidx); + + +const char *colortype_str[14] = +{ + "Misc. Color", "Sys. Color", "CSet 0", "CSet 1", "CSet 2", "CSet 3", "CSet 4", "CSet 5", "CSet 6", "CSet 7", "CSet 8", "CSet 9", "CSet 10", "CSet 11" +}; + +const char *colortypelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 14; + return NULL; + } + + return colortype_str[index]; +} + +int d_cs_color_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int w=(d->w-4)/16; + + switch(msg) + { + case MSG_DRAW: + //rectfill(screen, d->x+2, d->y+2, d->x+d->w-3, d->y+d->h-3, jwin_pal[jcBOX]); + //top blank part + rectfill(screen, d->x, d->y, d->x+(w*16)+3, d->y+1, jwin_pal[jcBOX]); + jwin_draw_frame(screen,d->x,d->y+2,w*16+4, d->h-4, FR_DEEP); + + for(int i=0; i<16; ++i) + { + rectfill(screen, d->x+2+(w*i), d->y+4, d->x+2+(w*(i+1))-1, d->y+d->h-5, ((d-2)->d1-2)*16+i); + } + + // right end + rectfill(screen, d->x+(w*16)+4, d->y, d->x+d->w-1, d->y+d->h-1, jwin_pal[jcBOX]); + // bottom part + rectfill(screen, d->x, d->y+d->h-2, d->x+(w*16)+3, d->y+d->h-1, jwin_pal[jcBOX]); + + //indicator lines + hline(screen, d->x+2+(w*d->d1), d->y, d->x+2+(w*(d->d1+1))-1, jwin_pal[jcBOXFG]); + hline(screen, d->x+2+(w*d->d1), d->y+d->h-1, d->x+2+(w*(d->d1+1))-1, jwin_pal[jcBOXFG]); + + break; + + case MSG_CLICK: + d->d1=vbound((gui_mouse_x()-d->x-2)/w,0,15); + d->flags|=D_DIRTY; + break; + } + + return D_O_K; +} + +int d_sys_color_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int w=(d->w-4)/17; + + switch(msg) + { + case MSG_DRAW: + //rectfill(screen, d->x+2, d->y+2, d->x+d->w-3, d->y+d->h-3, jwin_pal[jcBOX]); + //top blank part + rectfill(screen, d->x, d->y, d->x+(w*17)+3, d->y+1, jwin_pal[jcBOX]); + jwin_draw_frame(screen,d->x,d->y+2,w*17+4, d->h-4, FR_DEEP); + + for(int i=0; i<17; ++i) + { + rectfill(screen, d->x+2+(w*i), d->y+4, d->x+2+(w*(i+1))-1, d->y+d->h-5, vc(zc_max(0,i-1))); + } + + line(screen, d->x+2, d->y+4, d->x+2+w-1, d->y+d->h-5, vc(15)); + line(screen, d->x+2, d->y+d->h-5, d->x+2+w-1, d->y+4, vc(15)); + // right end + rectfill(screen, d->x+(w*17)+4, d->y, d->x+d->w-1, d->y+d->h-1, jwin_pal[jcBOX]); + // bottom part + rectfill(screen, d->x, d->y+d->h-2, d->x+(w*17)+3, d->y+d->h-1, jwin_pal[jcBOX]); + + //indicator lines + hline(screen, d->x+2+(w*(d->d1+1)), d->y, d->x+2+(w*(d->d1+2))-1, jwin_pal[jcBOXFG]); + hline(screen, d->x+2+(w*(d->d1+1)), d->y+d->h-1, d->x+2+(w*(d->d1+2))-1, jwin_pal[jcBOXFG]); + + break; + + case MSG_CLICK: + d->d1=vbound((gui_mouse_x()-d->x-2)/w,0,16)-1; + d->flags|=D_DIRTY; + break; + } + + return D_O_K; +} + +void update_ctl_proc(DIALOG *d, int ct) +{ + switch(ct) + { + case 0: + d->proc=jwin_droplist_proc; + break; + + case 1: + d->proc=d_sys_color_proc; + break; + + default: + d->proc=d_cs_color_proc; + break; + } + + d->flags|=D_DIRTY; +} + +int d_ctl_proc(int msg,DIALOG *d,int c) +{ + int old_d1=d->d1; + int ret=jwin_droplist_proc(msg, d, c); + + if(d->d1!=old_d1) + { + update_ctl_proc(d+2, d->d1); + } + + return ret; +} + +int d_csl2_proc(int msg,DIALOG *d,int c); + +void update_csl_proc(DIALOG *d, int cs) +{ + switch(cs) + { + case 0: + d->proc=jwin_text_proc; + d->fg=jwin_pal[jcBOXFG]; + d->bg=jwin_pal[jcBOX]; + (d+1)->proc=d_csl2_proc; + (d+1)->fg=0; + (d+1)->bg=0; + //(d+59)->fg=subscreen_cset(&misc,(d-1)->d1?(d-1)->d1-1:ssctMISC, (d+1)->d1); + break; + + default: + d->proc=d_box_proc; + d->fg=jwin_pal[jcBOX]; + d->bg=jwin_pal[jcBOX]; + (d+1)->proc=d_box_proc; + (d+1)->fg=jwin_pal[jcBOX]; + (d+1)->bg=jwin_pal[jcBOX]; + break; + } + + d->flags|=D_DIRTY; + (d+1)->flags|=D_DIRTY; +} + +int d_csl_proc(int msg,DIALOG *d,int c) +{ + int old_d1=d->d1; + int ret=jwin_droplist_proc(msg, d, c); + + if(d->d1!=old_d1) + { + update_csl_proc(d+1, d->d1); + (d+60)->fg=subscreen_cset(&misc,d->d1?d->d1-1:ssctMISC, (d+2)->d1); + } + + return ret; +} + +int d_csl2_proc(int msg,DIALOG *d,int c) +{ + int old_d1=d->d1; + int ret=jwin_droplist_proc(msg, d, c); + + if(d->d1!=old_d1) + { + (d+58)->fg=subscreen_cset(&misc,(d-2)->d1?(d-2)->d1-1:ssctMISC, d->d1); + } + + return ret; +} + +int jwin_fontdrop_proc(int msg,DIALOG *d,int c) +{ + int old_d1=d->d1; + int ret=jwin_droplist_proc(msg, d, c); + + if(d->d1!=old_d1) + { + (d+3)->dp2=ss_font(d->d1); + (d+3)->flags|=D_DIRTY; + + if((d+3)->proc!=d_dummy_proc) + { + rectfill(screen, (d+3)->x, (d+3)->y, (d+3)->x+(d+3)->w-1, (d+3)->y+(d+3)->h-1, jwin_pal[jcBOX]); + } + + (d+3)->h=text_height(ss_font(d->d1))+8; + (d+49)->dp2=ss_font(d->d1); + (d+49)->flags|=D_DIRTY; + + if((d+49)->proc!=d_dummy_proc) + { + rectfill(screen, (d+49)->x, (d+49)->y, (d+49)->x+(d+49)->w-1, (d+49)->y+(d+49)->h-1, jwin_pal[jcBOX]); + } + + (d+49)->h=text_height(ss_font(d->d1))+8; + } + + return ret; +} + +const char *misccolor_str[ssctMAX] = +{ + "Text", "Caption", "Overworld BG", "Dungeon BG", "Dungeon FG", "Cave FG", "BS Dark", "BS Goal", "Compass (Lt)", "Compass (Dk)", + "SS BG", "SS Shadow", "Tri. Frame", "Big Map BG", "Big Map FG", "Link's Pos", "Message Text" +}; + +const char *misccolorlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = ssctMAX; + return NULL; + } + + return misccolor_str[index]; +} + +const char *csettype_str[13] = +{ + "Misc. CSet", "CSet 0", "CSet 1", "CSet 2", "CSet 3", "CSet 4", "CSet 5", "CSet 6", "CSet 7", "CSet 8", "CSet 9", "CSet 10", "CSet 11" +}; + +const char *csettypelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 13; + return NULL; + } + + return csettype_str[index]; +} + +const char *misccset_str[sscsMAX] = +{ + "Triforce", "Tri. Frame", "Overworld Map", "Dungeon Map", "Blue Frame", "HC Piece", "SS Vine" +}; + +const char *misccsetlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = sscsMAX; + return NULL; + } + + return misccset_str[index]; +} + +const char *spectile_str[ssmstMAX+1] = +{ + "None", "SS Vine", "Magic Meter" +}; + +const char *spectilelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = ssmstMAX+1; + return NULL; + } + + return spectile_str[index]; +} + +const char *ssfont_str[ssfMAX] = +{ + "Zelda NES", "SS 1", "SS 2", "SS 3", "SS 4", "BS Time", "Small", "Small Prop.", "LttP Small", "Link's Awakening", "Link to the Past", + "Goron", "Zoran", "Hylian 1", "Hylian 2", "Hylian 3", "Hylian 4", "Proportional", "Oracle", "Oracle Proportional", "Phantom", "Phantom Proportional" +}; + +const char *ssfontlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = ssfMAX; + return NULL; + } + + return ssfont_str[index]; +} + +const char *shadowstyle_str[sstsMAX] = +{ + "None", "Shadow", "Shadow (U)", "Shadow (O)", "Shadow (+)", "Shadow (X)", "Shadowed", "Shadowed (U)", "Shadowed (O)", "Shadowed (+)", "Shadowed (X)" +}; + +const char *shadowstylelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = sstsMAX; + return NULL; + } + + return shadowstyle_str[index]; +} + +const char *alignment_str[3] = +{ + "Left", "Center", "Right" +}; + +const char *alignmentlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 3; + return NULL; + } + + return alignment_str[index]; +} + +const char *wrapping_str[2] = +{ + "Character", "Word" +}; + +const char *wrappinglist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 2; + return NULL; + } + + return wrapping_str[index]; +} + +const char *gaugeshow_str[3] = +{ + "Always", "1/2", "Normal" +}; + +const char *rows_str[2] = +{ + "Two", "Three" +}; + +const char *gaugeshowlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 3; + return NULL; + } + + return gaugeshow_str[index]; +} + +const char *rowslist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 2; + return NULL; + } + + return rows_str[index]; +} + +const char *button_str[2] = +{ + "A", "B" +}; + +const char *buttonlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 2; + return NULL; + } + + return button_str[index]; +} + +const char *icounter_str[sscMAX] = +{ + "Rupees", "Bombs", "Super Bombs", "Arrows", "Gen. Keys w/Magic", "Gen. Keys w/o Magic", "Level Keys w/Magic", + "Level Keys w/o Magic", "Any Keys w/Magic", "Any Keys w/o Magic", "Script 1", "Script 2", "Script 3", "Script 4", + "Script 5", "Script 6", "Script 7", "Script 8", "Script 9", "Script 10", "Script 11", "Script 12", "Script 13", + "Script 14", "Script 15", "Script 16", "Script 17", "Script 18", "Script 19", "Script 20", "Script 21", + "Script 22", "Script 23", "Script 24", "Script 25" +}; + +const char *icounterlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = sscMAX; + return NULL; + } + + return icounter_str[index]; +} + + +int d_stilelist_proc(int msg,DIALOG *d,int c) +{ + int old_d1=d->d1; + int ret=jwin_droplist_proc(msg, d, c); + + if(d->d1!=old_d1) + { + (d-14)->h=is_large?32:16; + (d-15)->h=(d-14)->h+4; + + switch(d->d1-1) + { + case ssmstSSVINETILE: + (d-15)->w=52; + (d-14)->w=48; + (d-14)->d1=wpnsbuf[iwSubscreenVine].tile; + break; + + case ssmstMAGICMETER: + (d-15)->w=148; + (d-14)->w=144; + (d-14)->d1=wpnsbuf[iwMMeter].tile; + break; + + case -1: + default: + (d-15)->w=20; + (d-14)->w=16; + break; + } + + (d-14)->w*=is_large?2:1; + (d-15)->w=(d-14)->w+4; + (d-14)->bg=vbound((d-14)->bg,0,((d-14)->w-1)>>2); + (d-17)->flags|=D_DIRTY; + (d-15)->flags|=D_DIRTY; + (d-14)->flags|=D_DIRTY; + (d-1)->flags|=D_DIRTY; + d->flags|=D_DIRTY; + } + + return ret; +} + + + +static int ssop_location_list[] = +{ + // dialog control number + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,212,213, -1 +}; + +static int ssop_color_list[] = +{ + // dialog control number + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, -1 +}; + +static int ssop_attributes_list[] = +{ + // dialog control number + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, -1 +}; + +static TABPANEL sso_properties_tabs[] = +{ + // (text) + { (char *)"Location", D_SELECTED, ssop_location_list, 0, NULL }, + { (char *)"Color", 0, ssop_color_list, 0, NULL }, + { (char *)"Attributes", 0, ssop_attributes_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +DIALOG *sso_properties_dlg; + +int jwin_tflpcheck_proc(int msg,DIALOG *d,int c) +{ + bool selected=(d->flags&D_SELECTED)!=0; + int ret= is_large ? jwin_checkfont_proc(msg,d,c) : jwin_check_proc(msg, d, c); + bool new_selected=(d->flags&D_SELECTED)!=0; + + if(new_selected!=selected) + { + (d-3)->w=(new_selected?32:16)*(is_large+1); + (d-3)->h=(new_selected?48:16)*(is_large+1); + (d-4)->w=(d-3)->w+4; + (d-4)->h=(d-3)->h+4; +// (d-5)->x=((d-4)->x)+(((d-4)->w)/2); + (d-6)->w=(new_selected?112:96)*(is_large+1); + (d-6)->h=(new_selected?112:48)*(is_large+1); + (d-7)->w=(d-6)->w+4; + (d-7)->h=(d-6)->h+4; +// (d-8)->x=((d-7)->x)+(((d-7)->w)/2); + (d-3)->flags|=D_DIRTY; + (d-4)->flags|=D_DIRTY; + (d-5)->flags|=D_DIRTY; + (d-6)->flags|=D_DIRTY; + (d-7)->flags|=D_DIRTY; + (d-8)->flags|=D_DIRTY; + (d-9)->flags|=D_DIRTY; + } + + return ret; +} + +int jwin_lscheck_proc(int msg,DIALOG *d,int c) +{ + bool selected=(d->flags&D_SELECTED)!=0; + int ret=is_large ? jwin_checkfont_proc(msg,d,c) : jwin_check_proc(msg, d, c); + bool new_selected=(d->flags&D_SELECTED)!=0; + + if(new_selected!=selected || msg==MSG_START) + { + (d-6)->w=(new_selected?32:16)*(is_large+1); + (d-6)->h=(new_selected?48:16)*(is_large+1); + (d-7)->w=(d-6)->w+4; + (d-7)->h=(d-6)->h+4; + (d-6)->flags|=D_DIRTY; + (d-7)->flags|=D_DIRTY; + (d-8)->flags|=D_DIRTY; + (d-9)->flags|=D_DIRTY; + } + + return ret; +} + +int d_qtile_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_DRAW: + { + int dw = d->w; + int dh = d->h; + + if(is_large) + { + dw /= 2; + dh /= 2; + } + + BITMAP *buf = create_bitmap_ex(8,dw,dh); + + if(buf) + { + clear_bitmap(buf); + + for(int y=0; yd1+(y>>4)*20+(x>>4),x,y,d->fg,d->d2); + } + } + + int t=d->bg>>2; + int t2=d->bg-(t<<2); + rect(buf, + (t<<4)+((t2&1)<<3) , + ((t2&2)<<2), + (t<<4)+((t2&1)<<3)+7, + ((t2&2)<<2)+7, jwin_pal[jcTITLER]); + stretch_blit(buf,screen,0,0,dw,dh,d->x-is_large,d->y-is_large,dw*(is_large?2:1),dh*(is_large?2:1)); + destroy_bitmap(buf); + } + + //textprintf_ex(screen, pfont, d->x,d->y, vc(15), -1, "%d", d->bg); + return D_O_K; + } + break; + + case MSG_CLICK: + { + int old_fg=d->fg; + + if(gui_mouse_b()&2) //right mouse button + { + int old_bg=d->bg; + int mx=vbound(gui_mouse_x()-d->x,0,d->w-1); + int my=vbound(gui_mouse_y()-d->y,0,d->h-1); + + if(is_large) + { + mx/=2; + my/=2; + } + + int t=mx>>4; + d->bg=(t<<2)+((my>>3)<<1)+((mx-(t<<4))>>3); + + if(d->bg!=old_bg) + { + d->flags|=D_DIRTY; + } + + return D_O_K; + } + + int ret=d_maptile_proc(msg, d, c); + + if(d->fg!=old_fg) + { + (d-60)->d1=d->fg+1; + (d-60)->d2=(d-60)->d1; + update_csl_proc(d-59, d->fg+1); + } + + d->flags|=D_DIRTY; + return ret; + } + break; + } + + return d_maptile_proc(msg, d, c); +} + +int d_spectile_proc(int msg,DIALOG *d,int c) +{ + int d1=d->d1; + int ret=d_qtile_proc(msg,d,c); + + if(d1!=d->d1) + { + (d+14)->d1=0; + (d+14)->d2=0; + (d+14)->flags|=D_DIRTY; + d->w=16*(is_large+1); + (d-1)->w=d->w+4; + d->flags|=D_DIRTY; + (d-1)->flags|=D_DIRTY; + (d-3)->flags|=D_DIRTY; + } + + return ret; +} + +int d_tileblock_proc(int msg,DIALOG *d,int c) +{ + int old_fg=d->fg; + int ret=d_maptile_proc(msg, d, c); + + switch(msg) + { + case MSG_CLICK: + if(d->fg!=old_fg) + { + (d-60)->d1=d->fg+1; + (d-60)->d2=(d-60)->d1; + update_csl_proc(d-59, d->fg+1); + } + + d->flags|=D_DIRTY; + break; + } + + return ret; +} + + +extern int d_alltriggerbutton_proc(int msg,DIALOG *d,int c); +extern int d_comboa_radio_proc(int msg,DIALOG *d,int c); +extern int d_comboabutton_proc(int msg,DIALOG *d,int c); +extern int d_jbutton_proc(int msg,DIALOG *d,int c); +extern int d_kbutton_proc(int msg,DIALOG *d,int c); +extern int d_listen_proc(int msg,DIALOG *d,int c); +extern int d_savemidi_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn3_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn4_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn2_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn3_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn4_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn3_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn4_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn3_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn4_proc(int msg,DIALOG *d,int c); +extern int d_triggerbutton_proc(int msg,DIALOG *d,int c); + +void dummy_dialog_proc(DIALOG *d) +{ + replacedp(*d,NULL); + d->proc=d_dummy_proc; + d->x=-1; + d->y=-1; + d->w=0; + d->h=0; +} + + +void extract_colortype(DIALOG *d, subscreen_object *tempsso, int ct) +{ + switch(ct) + { + case 3: + switch(tempsso->colortype3) + { + case ssctMISC: + d->d1=0; + break; + + case ssctSYSTEM: + d->d1=1; + break; + + default: + d->d1=tempsso->colortype3+2; + break; + } + + break; + + case 2: + switch(tempsso->colortype2) + { + case ssctMISC: + d->d1=0; + break; + + case ssctSYSTEM: + d->d1=1; + break; + + default: + d->d1=tempsso->colortype2+2; + break; + } + + break; + + case 1: + default: + switch(tempsso->colortype1) + { + case ssctMISC: + d->d1=0; + break; + + case ssctSYSTEM: + d->d1=1; + break; + + default: + d->d1=tempsso->colortype1+2; + break; + } + + break; + } +} + +void insert_colortype(DIALOG *d, subscreen_object *tempsso, int ct) +{ + switch(ct) + { + case 3: + switch(d->d1) + { + case 0: + tempsso->colortype3=ssctMISC; + break; + + case 1: + tempsso->colortype3=ssctSYSTEM; + break; + + default: + tempsso->colortype3=d->d1-2; + break; + } + + break; + + case 2: + switch(d->d1) + { + case 0: + tempsso->colortype2=ssctMISC; + break; + + case 1: + tempsso->colortype2=ssctSYSTEM; + break; + + default: + tempsso->colortype2=d->d1-2; + break; + } + + break; + + case 1: + default: + switch(d->d1) + { + case 0: + tempsso->colortype1=ssctMISC; + break; + + case 1: + tempsso->colortype1=ssctSYSTEM; + break; + + default: + tempsso->colortype1=d->d1-2; + break; + } + + break; + } +} + +void extract_cset(DIALOG *d, subscreen_object *tempsso, int ct) +{ + switch(ct) + { + case 3: + switch(tempsso->colortype3) + { + case ssctMISC: + d->d1=0; + break; + + default: + d->d1=tempsso->colortype3+1; + break; + } + + break; + + case 2: + switch(tempsso->colortype2) + { + case ssctMISC: + d->d1=0; + break; + + default: + d->d1=tempsso->colortype2+1; + break; + } + + break; + + case 1: + default: + switch(tempsso->colortype1) + { + case ssctMISC: + d->d1=0; + break; + + default: + d->d1=tempsso->colortype1+1; + break; + } + + break; + } +} + +void insert_cset(DIALOG *d, subscreen_object *tempsso, int ct) +{ + switch(ct) + { + case 3: + switch(d->d1) + { + case 0: + tempsso->colortype3=ssctMISC; + break; + + default: + tempsso->colortype3=d->d1-1; + break; + } + + break; + + case 2: + switch(d->d1) + { + case 0: + tempsso->colortype2=ssctMISC; + break; + + default: + tempsso->colortype2=d->d1-1; + break; + } + + break; + + case 1: + default: + switch(d->d1) + { + case 0: + tempsso->colortype1=ssctMISC; + break; + + default: + tempsso->colortype1=d->d1-1; + break; + } + + break; + } +} + +static DIALOG sso_raw_data_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Raw Data", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_textbox_proc, 72-12, 60+4, 176+24+1, 92+4, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 130, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static ListData gaugeshow_list(gaugeshowlist, &font); +static ListData rows_list(rowslist, &font); +static ListData itemclass_list(item_class_list, &font); + +int sso_raw_data(subscreen_object *tempsso) +{ + char raw_text[65535]; + char title[80]; + sprintf(title, "Raw Data for Object #%d", curr_subscreen_object); + sprintf(raw_text, "Type: %d\nPosition: %d\nX: %d\nY: %d\nW: %d\nH: %d\nColor Type 1: %d\nColor 1: %d\nColor Type 2: %d\nColor 2: %d\nColor Type 3: %d\nColor 3: %d\nD1: %d\nD2: %d\nD3: %d\nD4: %d\nD5: %d\nD6: %d\nD7: %d\nD8: %d\nD9: %d\nD10: %d\nFrames: %d\nSpeed: %d\nDelay: %d\nFrame: %d\nDp1: %s", + tempsso->type, tempsso->pos, tempsso->x, tempsso->y, tempsso->w, tempsso->h, tempsso->colortype1, tempsso->color1, tempsso->colortype2, tempsso->color2, tempsso->colortype3, tempsso->color3, tempsso->d1, tempsso->d2, tempsso->d3, tempsso->d4, tempsso->d5, tempsso->d6, tempsso->d7, tempsso->d8, tempsso->d9, tempsso->d10, tempsso->frames, tempsso->speed, tempsso->delay, tempsso->frame, tempsso->dp1!=NULL?(char *)tempsso->dp1:"NULL"); + sso_raw_data_dlg[0].dp2=lfont; + sso_raw_data_dlg[2].dp=raw_text; + sso_raw_data_dlg[2].d2=0; + + if(is_large) + large_dialog(sso_raw_data_dlg); + + zc_popup_dialog(sso_raw_data_dlg,2); + return D_O_K; +} + +static ListData wrapping_list(wrappinglist, &font); +static ListData alignment_list(alignmentlist, &font); +static ListData shadowstyle_list(shadowstylelist, &font); +static ListData misccolor_list(misccolorlist, &font); +static ListData spectile_list(spectilelist, &font); +static ListData ssfont_list(ssfontlist, &font); +static ListData colortype_list(colortypelist, &font); +static ListData item_list(itemlist, &font); + +static DIALOG sso_master_properties_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 320, 240, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Invalid Object Properties", NULL, NULL }, + { jwin_button_proc, 90, 215, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 215, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_tab_proc, 4, 25, 312, 185, 0, 0, 0, 0, 0, 0, (void *) sso_properties_tabs, NULL, (void *)sso_properties_dlg }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 5 + { jwin_text_proc, 8, 49, 42, 16, 0, 0, 0, 0, 0, 0, (void *) "Display:", NULL, NULL }, + //{ jwin_droplist_proc, 45, 45, 150, 16, 0, 0, 0, 0, 0, 0, (void *) displaylist, NULL, NULL }, + { jwin_check_proc, 50, 48, 60, 9, 0, 0, 0, 0, 0, 0, (void *) "Active Up", NULL, NULL }, + { jwin_text_proc, 8, 67, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "X:", NULL, NULL }, + { jwin_edit_proc, 23, 63, 31, 16, 0, 0, 0, 0, 4, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 85, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Y:", NULL, NULL }, + // 10 + { jwin_edit_proc, 23, 81, 31, 16, 0, 0, 0, 0, 4, 0, NULL, NULL, NULL }, + { jwin_text_proc, 68, 67, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "W:", NULL, NULL }, + { jwin_edit_proc, 83, 63, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 68, 85, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "H:", NULL, NULL }, + { jwin_edit_proc, 83, 81, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + // 15 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 20 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 25 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 30 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 35 + { jwin_frame_proc, 8, 48, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 12, 45, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Foreground Color ", NULL, NULL }, + { jwin_text_proc, 16, 59, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { d_ctl_proc, 46, 55, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + { jwin_text_proc, 16, 77, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + // 40 + { jwin_droplist_proc, 46, 73, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + + { jwin_frame_proc, 8, 103, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 12, 100, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Background Color ", NULL, NULL }, + { jwin_text_proc, 16, 114, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { d_ctl_proc, 46, 110, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + // 45 + { jwin_text_proc, 16, 132, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + { jwin_droplist_proc, 46, 128, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + + { jwin_frame_proc, 8, 158, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 12, 155, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Shadow Color ", NULL, NULL }, + { jwin_text_proc, 16, 169, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + // 50 + { d_ctl_proc, 46, 165, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + { jwin_text_proc, 16, 187, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + { jwin_droplist_proc, 46, 183, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + + { jwin_frame_proc, 168, 48, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 172, 45, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Foreground Color ", NULL, NULL }, + // 55 + { jwin_text_proc, 176, 59, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { d_ctl_proc, 206, 55, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + { jwin_text_proc, 176, 77, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + { jwin_droplist_proc, 206, 73, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + + { jwin_frame_proc, 168, 103, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + // 60 + { jwin_text_proc, 172, 100, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Background Color ", NULL, NULL }, + { jwin_text_proc, 176, 114, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { d_ctl_proc, 206, 110, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + { jwin_text_proc, 176, 132, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + { jwin_droplist_proc, 206, 128, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + + // 65 + { jwin_frame_proc, 168, 158, 144, 48, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 172, 155, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Shadow Color ", NULL, NULL }, + { jwin_text_proc, 176, 169, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { d_ctl_proc, 206, 165, 88, 16, 0, 0, 0, 0, 0, 0, (void *) &colortype_list, NULL, NULL }, + { jwin_text_proc, 176, 187, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + // 70 + { jwin_droplist_proc, 206, 183, 98, 16, 0, 0, 0, 0, 0, 0, (void *) &misccolor_list, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 75 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 80 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 85 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 90 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 160, 122, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_DISABLED, 0, 0, (void *) "Part of Attributes", NULL, NULL }, + // 95 + { d_box_proc, 8, 45, 156, 122, vc(4), vc(4), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 45, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "TILE", NULL, NULL }, + { jwin_frame_proc, 8, 51, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_maptile_proc, 10, 53, 16, 16, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, + { jwin_text_proc, 128, 45, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "TILE", NULL, NULL }, + // 100 + { jwin_frame_proc, 128, 51, 36, 52, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_maptile_proc, 130, 53, 32, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, + { jwin_check_proc, 166, 109, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Overlay", NULL, NULL }, + { jwin_check_proc, 166, 119, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Transparent", NULL, NULL }, + { jwin_tflpcheck_proc, 166, 129, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Large Pieces", NULL, NULL }, + // 105 + { jwin_text_proc, 166, 55, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Frames:", NULL, NULL }, + { jwin_text_proc, 166, 73, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Speed:", NULL, NULL }, + { jwin_text_proc, 166, 91, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Delay:", NULL, NULL }, + { jwin_edit_proc, 215, 51, 35, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 215, 69, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + // 110 + { jwin_edit_proc, 215, 87, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 79, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Special Tile:", NULL, NULL }, + { d_stilelist_proc, 65, 75, 92, 16, 0, 0, 0, 0, 0, 0, (void *) &spectile_list, NULL, NULL }, + { jwin_text_proc, 8, 97, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Offset:", NULL, NULL }, + { jwin_edit_proc, 65, 93, 69, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 115 + { jwin_text_proc, 8, 55, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Font:", NULL, NULL }, + { jwin_text_proc, 8, 73, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Style:", NULL, NULL }, + { jwin_text_proc, 8, 91, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Alignment:", NULL, NULL }, + { jwin_text_proc, 8, 105, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Text:", NULL, NULL }, + { jwin_fontdrop_proc, 55, 51, 110, 16, 0, 0, 0, 0, 0, 0, (void *) &ssfont_list, NULL, NULL }, + // 120 + { jwin_droplist_proc, 55, 69, 110, 16, 0, 0, 0, 0, 0, 0, (void *) &shadowstyle_list, NULL, NULL }, + { jwin_droplist_proc, 55, 87, 110, 16, 0, 0, 0, 0, 0, 0, (void *) &alignment_list, NULL, NULL }, + { jwin_edit_proc, 8, 115, 146, 16, 0, 0, 0, 0, 255, 0, NULL, NULL, NULL }, + { jwin_text_proc, 166, 55, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Wrapping:", NULL, NULL }, + { jwin_text_proc, 166, 73, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Tab Size:", NULL, NULL }, + // 125 + { jwin_droplist_proc, 212, 51, 83, 16, 0, 0, 0, 0, 0, 0, (void *) &wrapping_list, NULL, NULL }, + { jwin_edit_proc, 212, 69, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 8, 55, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Item Class:", NULL, NULL }, + { jwin_text_proc, 8, 73, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Position:", NULL, NULL }, + { jwin_text_proc, 8, 91, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Up Select:", NULL, NULL }, + // 130 + { jwin_text_proc, 8, 109, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Down Select:", NULL, NULL }, + { jwin_text_proc, 8, 127, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Left Select:", NULL, NULL }, + { jwin_text_proc, 8, 145, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Right Select:", NULL, NULL }, + { jwin_droplist_proc, 68, 51, 101, 16, 0, 0, 0, 0, 0, 0, (void *) &itemclass_list, NULL, NULL }, + { jwin_edit_proc, 68, 69, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + // 135 + { jwin_edit_proc, 68, 87, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 68, 105, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 68, 123, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 68, 141, 83, 16, 0, 0, 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 68, 177, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Invisible", NULL, NULL }, + // 140 + { jwin_check_proc, 166, 139, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show Compass", NULL, NULL }, + { jwin_check_proc, 166, 149, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Large", NULL, NULL }, + { jwin_ctext_proc, 18, 45, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "NOT", NULL, NULL }, + { jwin_ctext_proc, 18, 51, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "LAST", NULL, NULL }, + { jwin_frame_proc, 8, 57, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + // 145 + { d_qtile_proc, 10, 59, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 56, 51, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "LAST", NULL, NULL }, + { jwin_frame_proc, 46, 57, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_qtile_proc, 48, 59, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 150 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 18, 101, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "CAP", NULL, NULL }, + { jwin_frame_proc, 8, 107, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_qtile_proc, 10, 109, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 56, 95, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "AFTER", NULL, NULL }, + // 155 + { jwin_ctext_proc, 56, 101, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "CAP", NULL, NULL }, + { jwin_frame_proc, 46, 107, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_qtile_proc, 48, 109, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_check_proc, 8, 78, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Mod", NULL, NULL }, + { jwin_check_proc, 46, 78, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Mod", NULL, NULL }, + // 160 + { jwin_check_proc, 8, 128, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Mod", NULL, NULL }, + { jwin_check_proc, 46, 128, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Mod", NULL, NULL }, + { jwin_text_proc, 166, 109, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Show:", NULL, NULL }, + { jwin_droplist_proc, 215, 105, 68, 16, 0, 0, 0, 0, 0, 0, (void *) &gaugeshow_list, NULL, NULL }, + { jwin_text_proc, 166, 133, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Container:", NULL, NULL }, + // 165 + { jwin_edit_proc, 215, 129, 35, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_check_proc, 166, 147, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Unique Last", NULL, NULL }, + { jwin_text_proc, 166, 91, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Infinite Character:", NULL, NULL }, + { jwin_edit_proc, 253, 87, 58, 16, 0, 0, 0, 0, 1, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 170 + { jwin_ctext_proc, 160, 122, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_DISABLED, 0, 0, (void *) "Part of Attributes", NULL, NULL }, + { jwin_check_proc, 8, 51, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show 1", NULL, NULL }, + { jwin_check_proc, 8, 63, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show 2", NULL, NULL }, + { jwin_check_proc, 8, 75, 128, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show 3", NULL, NULL }, + { jwin_text_proc, 8, 51, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Rows:", NULL, NULL }, + // 175 + { jwin_droplist_proc, 57, 47, 68, 16, 0, 0, 0, 0, 0, 0, (void *) &rows_list, NULL, NULL }, + { jwin_droplist_proc, 68, 159, 128, 16, 0, 0, 0, 0, 3, 0, (void *) &item_list, NULL, NULL }, + { jwin_text_proc, 8, 163, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Item Override:", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 180 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 185 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 190 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 195 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 200 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 205 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 210 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_check_proc, 115, 48, 70, 9, 0, 0, 0, 0, 0, 0, (void *) "Active Down", NULL, NULL }, + { jwin_check_proc, 190, 48, 70, 9, 0, 0, 0, 0, 0, 0, (void *) "Active Scrolling", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void replacedp(DIALOG &d, const char *newdp, size_t size) +{ + if((d.proc==d_alltriggerbutton_proc)|| + (d.proc==d_button_proc)|| + (d.proc==d_check_proc)|| + (d.proc==d_comboa_radio_proc)|| + (d.proc==d_comboabutton_proc)|| + (d.proc==d_ctext_proc)|| + (d.proc==d_edit_proc)|| + (d.proc==d_jbutton_proc)|| + (d.proc==d_kbutton_proc)|| + (d.proc==d_listen_proc)|| + (d.proc==d_savemidi_proc)|| + (d.proc==d_ssdn_btn_proc)|| + (d.proc==d_ssdn_btn2_proc)|| + (d.proc==d_ssdn_btn3_proc)|| + (d.proc==d_ssdn_btn4_proc)|| + (d.proc==d_sslt_btn_proc)|| + (d.proc==d_sslt_btn2_proc)|| + (d.proc==d_sslt_btn3_proc)|| + (d.proc==d_sslt_btn4_proc)|| + (d.proc==d_ssrt_btn_proc)|| + (d.proc==d_ssrt_btn2_proc)|| + (d.proc==d_ssrt_btn3_proc)|| + (d.proc==d_ssrt_btn4_proc)|| + (d.proc==d_ssup_btn_proc)|| + (d.proc==d_ssup_btn2_proc)|| + (d.proc==d_ssup_btn3_proc)|| + (d.proc==d_ssup_btn4_proc)|| + (d.proc==d_text_proc)|| + (d.proc==d_tri_edit_proc)|| + (d.proc==d_triggerbutton_proc)|| + (d.proc==jwin_button_proc)|| + (d.proc==jwin_check_proc)|| + (d.proc==jwin_ctext_proc)|| + (d.proc==jwin_radio_proc)|| + (d.proc==jwin_rtext_proc)|| + (d.proc==jwin_text_proc)|| + (d.proc==jwin_win_proc) || + (d.proc==jwin_edit_proc)) + { + if(d.dp != NULL) + zc_free(d.dp); + + if(newdp != NULL) + { + size = zc_max(size, strlen((char *)newdp)+1); + d.dp = zc_malloc(size); + strcpy((char*)d.dp, newdp); + } + else + d.dp = NULL; + } + else + { + d.dp = (void *)newdp; + } +} + +int sso_properties(subscreen_object *tempsso) +{ + copy_dialog(&sso_properties_dlg, sso_master_properties_dlg); + char title[256], x_str[256],y_str[256],w_str[256],h_str[256],f_str[256],s_str[256],d_str[256]; + int x_stri=0, y_stri=0, w_stri=0, h_stri=0,f_stri=0,s_stri=0,d_stri=0; + char buf[256], buf2[256], buf3[256], buf4[256], buf5[256]; + int bufi=0, buf2i=0, buf3i=0,buf4i=0,buf5i=0; + memset(title, 0, 256); + memset(x_str, 0, 256); + memset(y_str, 0, 256); + memset(w_str, 0, 256); + memset(h_str, 0, 256); + memset(f_str, 0, 256); + memset(s_str, 0, 256); + memset(d_str, 0, 256); + memset(buf, 0, 256); + memset(buf2, 0, 256); + memset(buf3, 0, 256); + memset(buf4, 0, 256); + memset(buf5, 0, 256); + sprintf(title, "%s Properties (Object #%d)", sso_name(tempsso->type), curr_subscreen_object); + sprintf(x_str, "invalid"); + sprintf(y_str, "invalid"); + sprintf(w_str, "invalid"); + sprintf(h_str, "invalid"); + int ret=-1; + + replacedp(sso_properties_dlg[0],title); + sso_properties_dlg[0].dp2=lfont; + + //for everything + sso_properties_dlg[6].flags = (tempsso->pos & sspUP) != 0 ? D_SELECTED : 0; + sso_properties_dlg[212].flags = (tempsso->pos & sspDOWN) != 0 ? D_SELECTED : 0; + sso_properties_dlg[213].flags = (tempsso->pos & sspSCROLLING) != 0 ? D_SELECTED : 0; + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + sso_properties_dlg[95].bg=jwin_pal[jcBOX]; + sso_properties_dlg[95].fg=jwin_pal[jcBOX]; + sso_properties_dlg[96].dp2=spfont; + sso_properties_dlg[99].dp2=spfont; + replacedp(sso_properties_dlg[108],x_str); + x_stri=108; + replacedp(sso_properties_dlg[109],x_str); + x_stri=109; + replacedp(sso_properties_dlg[110],x_str); + x_stri=110; + replacedp(sso_properties_dlg[114],x_str); + x_stri=114; + replacedp(sso_properties_dlg[122],x_str); + x_stri=112; + sso_properties_dlg[122].dp2=ss_font(ssfZELDA); + sso_properties_dlg[122].h=text_height(ss_font(ssfZELDA))+8; + replacedp(sso_properties_dlg[126],x_str); + x_stri=126; + replacedp(sso_properties_dlg[134],x_str); + x_stri=134; + replacedp(sso_properties_dlg[135],x_str); + x_stri=134; + replacedp(sso_properties_dlg[136],x_str); + x_stri=136; + replacedp(sso_properties_dlg[137],x_str); + x_stri=137; + replacedp(sso_properties_dlg[138],x_str); + x_stri=138; + sso_properties_dlg[142].dp2=spfont; + sso_properties_dlg[143].dp2=spfont; + sso_properties_dlg[147].dp2=spfont; + sso_properties_dlg[151].dp2=spfont; + sso_properties_dlg[154].dp2=spfont; + sso_properties_dlg[155].dp2=spfont; + replacedp(sso_properties_dlg[165],x_str); + x_stri=165; + sso_properties_dlg[168].dp2=ss_font(ssfZELDA); + sso_properties_dlg[168].h=text_height(ss_font(ssfZELDA))+8; + replacedp(sso_properties_dlg[168],x_str); + x_stri=168; + + if(biic_cnt==-1) + build_biic_list(); + + if(is_large && !sso_properties_dlg[0].d1) + { + sso_properties_dlg[126].proc = sso_properties_dlg[136].proc = sso_properties_dlg[137].proc = + sso_properties_dlg[138].proc = jwin_droplist_proc; // jwin_edit_proc, but sometimes jwin_droplist_proc + large_dialog(sso_properties_dlg); + sso_properties_dlg[126].proc = sso_properties_dlg[136].proc = sso_properties_dlg[137].proc = + sso_properties_dlg[138].proc = jwin_edit_proc; + + sso_properties_dlg[95].w=(156*2)+1; // d_box_proc + sso_properties_dlg[95].h=(122*2)+1; + + sso_properties_dlg[97].x = sso_properties_dlg[98].x-2; // d_frame_proc + sso_properties_dlg[97].y = sso_properties_dlg[98].y-2; + + for(int i = 99; i <= 104; i++) + sso_properties_dlg[i].x += (i >=102 ? 80:64); + + for(int i = 158; i <= 162; i++) + sso_properties_dlg[i].y += 8; + + sso_properties_dlg[100].x = sso_properties_dlg[101].x-2; // d_frame_proc + sso_properties_dlg[100].y = sso_properties_dlg[101].y-2; + } + + //item specific + switch(tempsso->type) + { + case ssoNONE: + { + // I'd just disable it entirely if I knew how... + dummy_dialog_proc(sso_properties_dlg+6); + + for(int i=11; i<=213; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + } + break; + + case sso2X2FRAME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=99; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + +// draw_block_flip(dest,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3,css->objects[i].d4); + char cset_caption1[80]; + char cset_caption2[80]; + char scset_caption[80]; + sprintf(cset_caption1, " CSet "); + sprintf(cset_caption2, "CSet:"); + sprintf(scset_caption, "Type:"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + + replacedp(sso_properties_dlg[36],cset_caption1); + replacedp(sso_properties_dlg[37],cset_caption2); + + ListData csettype_list(csettypelist, is_large ? &lfont_l : &font); + sso_properties_dlg[38].proc=d_csl_proc; + //A dubious cast, but I think correct -DD + replacedp(sso_properties_dlg[38],(char *)&csettype_list); + + replacedp(sso_properties_dlg[39],scset_caption); + + extract_cset(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].proc=d_csl2_proc; + ListData misccset_list(misccsetlist, is_large? &lfont_l : &font); + replacedp(sso_properties_dlg[40],(char *)&misccset_list); + sso_properties_dlg[40].d1=tempsso->color1; + update_csl_proc(sso_properties_dlg+39, sso_properties_dlg[38].d1); + //sso_properties_dlg[98].fg=sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:sso_properties_dlg[40].d1; + sso_properties_dlg[98].fg=subscreen_cset(&misc,sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:ssctMISC, sso_properties_dlg[40].d1); + + sso_properties_dlg[98].d1=tempsso->d1; + sso_properties_dlg[98].d2=tempsso->d2; + sso_properties_dlg[98].proc=d_tileblock_proc; + sso_properties_dlg[98].w=is_large?64:32; + sso_properties_dlg[98].h=is_large?64:32; + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[102].flags=tempsso->d3?D_SELECTED:0; + sso_properties_dlg[103].flags=tempsso->d4?D_SELECTED:0; + } + break; + + case ssoTEXT: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=123; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + buf[0]=0; + + if(tempsso->dp1!=NULL) + { + strcpy(buf, (char *)tempsso->dp1); + } + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + replacedp(sso_properties_dlg[122],buf); + bufi=122; + sso_properties_dlg[122].dp2=ss_font(tempsso->d1); + sso_properties_dlg[122].h=text_height(ss_font(tempsso->d1))+8; + } + break; + + case ssoLINE: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char lc_color_caption[80]; + sprintf(lc_color_caption, " Line Color "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],lc_color_caption); + + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + sso_properties_dlg[102].flags|=(tempsso->d3)?D_SELECTED:0; + sso_properties_dlg[103].flags|=(tempsso->d4)?D_SELECTED:0; + } + break; + + case ssoRECT: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=47; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char ol_color_caption[80]; + char f_color_caption[80]; + char filled_caption[80]; + sprintf(ol_color_caption, " Outline Color "); + sprintf(f_color_caption, " Fill Color "); + sprintf(filled_caption, "Filled"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],ol_color_caption); + replacedp(sso_properties_dlg[42],f_color_caption); + + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + sso_properties_dlg[102].flags|=(tempsso->d1)?D_SELECTED:0; + replacedp(sso_properties_dlg[102],filled_caption); + sso_properties_dlg[103].flags|=(tempsso->d2)?D_SELECTED:0; + } + break; + + case ssoBSTIME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+118); + + for(int i=122; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + } + break; + + case ssoTIME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+118); + + for(int i=122; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + } + break; + + case ssoSSTIME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+118); + + for(int i=122; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + } + break; + + case ssoMAGICMETER: + { + for(int i=11; i<=93; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=95; i<=169; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=171; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char no_prop[80]; + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(no_prop, "No Properties Available"); + + //Bad! You must use replacedp or you will run into major pointer problems... -DD + //sso_properties_dlg[8].dp=x_str; + //sso_properties_dlg[10].dp=y_str; + //sso_properties_dlg[94].dp=no_prop; + //sso_properties_dlg[170].dp=no_prop; + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[94],no_prop); + replacedp(sso_properties_dlg[170],no_prop); + + } + break; + + case ssoLIFEMETER: + { + for(int i=11; i<=93; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=95; i<=138; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=140; i<=173; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=176; i<=210; i++) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char bs_style[80]; + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(bs_style, "BS-Zelda Style"); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[139],bs_style); + sso_properties_dlg[139].flags=tempsso->d2?D_SELECTED:0; + sso_properties_dlg[175].d1 = tempsso->d3; + } + break; + + case ssoBUTTONITEM: + { + for(int i=15; i<=102; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=116; i<=118; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=120; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char button_caption[80]; + sprintf(button_caption, "Button:"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + sso_properties_dlg[103].flags|=(tempsso->d2)?D_SELECTED:0; + + replacedp(sso_properties_dlg[115],button_caption); + ListData button_list(buttonlist, is_large? &lfont_l : &font); + replacedp(sso_properties_dlg[119],(char *)&button_list); + + sso_properties_dlg[119].d1=tempsso->d1; + } + break; + + case ssoICON: + { + } + break; + + case ssoCOUNTER: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+118); + dummy_dialog_proc(sso_properties_dlg+122); + + for(int i=127; i<=129; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=133; i<=135; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+139); + + for(int i=142; i<=166; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=169; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + char item_1_caption[80]; + char item_2_caption[80]; + char item_3_caption[80]; + char digits_caption[80]; + char zero_caption[80]; + char selected_caption[80]; + char infinite_caption[80]; + + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + + sprintf(item_1_caption, "Item 1:"); + sprintf(item_2_caption, "Item 2:"); + sprintf(item_3_caption, "Item 3:"); + sprintf(infinite_caption, "Infinite:"); + sprintf(digits_caption, "Digits:"); + sprintf(zero_caption, "Show Zero"); + sprintf(selected_caption, "Only Selected"); + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + + sprintf(buf, "%d", tempsso->d4); + sprintf(buf2, "%c", tempsso->d5); + + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + replacedp(sso_properties_dlg[123],digits_caption); + replacedp(sso_properties_dlg[124],infinite_caption); + + //why, guys, why?!?? :( + sso_properties_dlg[125].dp = NULL; + sso_properties_dlg[125].proc=jwin_edit_proc; + replacedp(sso_properties_dlg[125],buf); + bufi = 125; + sso_properties_dlg[125].d1 = 255; + sso_properties_dlg[125].x-=8; + sso_properties_dlg[125].w+=24; + + //Infinite Item + if(bii_cnt==-1) + { + build_bii_list(true); + } + + int index=tempsso->d10; + int itemid = 0; + + for(int i=0; id7; + sso_properties_dlg[136].x-=13; + sso_properties_dlg[136].w+=56; + sso_properties_dlg[137].proc=jwin_droplist_proc; + replacedp(sso_properties_dlg[137],(char *)&icounter_list); + sso_properties_dlg[137].d1=tempsso->d8; + sso_properties_dlg[137].x-=13; + sso_properties_dlg[137].w+=56; + sso_properties_dlg[138].proc=jwin_droplist_proc; + replacedp(sso_properties_dlg[138],(char *)&icounter_list); + sso_properties_dlg[138].d1=tempsso->d9; + sso_properties_dlg[138].x-=13; + sso_properties_dlg[138].w+=56; + replacedp(sso_properties_dlg[168],buf2); + buf2i=168; + sso_properties_dlg[168].dp2=ss_font(tempsso->d1); + sso_properties_dlg[168].h=text_height(ss_font(tempsso->d1))+8; + replacedp(sso_properties_dlg[140],zero_caption); + sso_properties_dlg[140].flags=tempsso->d6&1?D_SELECTED:0; + sso_properties_dlg[140].x += 40; + replacedp(sso_properties_dlg[141],selected_caption); + sso_properties_dlg[141].flags=tempsso->d6&2?D_SELECTED:0; + sso_properties_dlg[141].x += 40; + + } + break; + + case ssoCOUNTERS: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+117); + dummy_dialog_proc(sso_properties_dlg+118); + dummy_dialog_proc(sso_properties_dlg+121); + dummy_dialog_proc(sso_properties_dlg+122); + dummy_dialog_proc(sso_properties_dlg+123); + dummy_dialog_proc(sso_properties_dlg+125); + + for(int i=127; i<=139; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=141; i<=166; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=169; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + char item_caption[80]; + char digits_caption[80]; + char x_caption[80]; + + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + + sprintf(item_caption, "Item:"); + sprintf(digits_caption, "Digits:"); + sprintf(x_caption, "Use X"); + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + + sprintf(buf, "%d", tempsso->d4); + sprintf(buf2, "%c", tempsso->d5); + + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + replacedp(sso_properties_dlg[124],digits_caption); + replacedp(sso_properties_dlg[126],buf); + bufi=126; + sso_properties_dlg[126].x-=8; + sso_properties_dlg[126].w+=24; + replacedp(sso_properties_dlg[168],buf2); + buf2i=168; + sso_properties_dlg[168].dp2=ss_font(tempsso->d1); + sso_properties_dlg[168].h=text_height(ss_font(tempsso->d1))+8; + replacedp(sso_properties_dlg[140],x_caption); + sso_properties_dlg[140].flags=tempsso->d2?D_SELECTED:0; + + } + break; + + case ssoMINIMAPTITLE: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + dummy_dialog_proc(sso_properties_dlg+118); + + for(int i=122; i<=210; ++i) + { + if(i!=139) dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + char map_rule_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + sprintf(map_rule_caption, "Invisible w/o Dungeon Map"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + replacedp(sso_properties_dlg[139],map_rule_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + sso_properties_dlg[139].flags=tempsso->d4?D_SELECTED:0; + } + break; + + case ssoMINIMAP: + { + for(int i=11; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=170; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=174; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + char show1[80]; + char show2[80]; + char show3[80]; + sprintf(t_color_caption, " Link Color "); + sprintf(s_color_caption, " C. Blink Color "); + sprintf(b_color_caption, " C. Const Color "); + sprintf(show1, " Show Map "); + sprintf(show2, " Show Link "); + sprintf(show3, " Show Compass "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + replacedp(sso_properties_dlg[171],show1); + replacedp(sso_properties_dlg[172],show2); + replacedp(sso_properties_dlg[173],show3); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[171].flags=tempsso->d1?D_SELECTED:0; + sso_properties_dlg[172].flags=tempsso->d2?D_SELECTED:0; + sso_properties_dlg[173].flags=tempsso->d3?D_SELECTED:0; + } + break; + + case ssoLARGEMAP: + { + for(int i=11; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=47; i<=138; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=140; i<=170; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=174; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char show1[80]; + char show2[80]; + char show3[80]; + char bs_style[80]; + sprintf(t_color_caption, " Room Color "); + sprintf(s_color_caption, " Link Color "); + sprintf(show1, " Show Map "); + sprintf(show2, " Show Rooms "); + sprintf(show3, " Show Link "); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(bs_style, "Large"); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[139],bs_style); + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[171],show1); + replacedp(sso_properties_dlg[172],show2); + replacedp(sso_properties_dlg[173],show3); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + sso_properties_dlg[171].flags=tempsso->d1?D_SELECTED:0; + sso_properties_dlg[172].flags=tempsso->d2?D_SELECTED:0; + sso_properties_dlg[173].flags=tempsso->d3?D_SELECTED:0; + + sso_properties_dlg[139].flags=tempsso->d10?D_SELECTED:0; + } + break; + + case ssoCLEAR: + { + for(int i=7; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char ss_color_caption[80]; + sprintf(ss_color_caption, " Subscreen Color "); + replacedp(sso_properties_dlg[36],ss_color_caption); + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + } + break; + + case ssoCURRENTITEM: + { + for(int i=15; i<=93; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=95; i<=126; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=140; i<=175; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=178; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + + sprintf(buf, "%d", tempsso->d3); + sprintf(buf2, "%d", tempsso->d4); + sprintf(buf3, "%d", tempsso->d5); + sprintf(buf4, "%d", tempsso->d6); + sprintf(buf5, "%d", tempsso->d7); + + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + replacedp(sso_properties_dlg[134],buf); + bufi=134; + replacedp(sso_properties_dlg[135],buf2); + buf2i=135; + replacedp(sso_properties_dlg[136],buf3); + buf3i=136; + replacedp(sso_properties_dlg[137],buf4); + buf4i=137; + replacedp(sso_properties_dlg[138],buf5); + buf5i=138; + // Item Override droplist + + build_bii_list(true); + int index=tempsso->d8-1; + int itemid = 0; + + for(int i=0; id1) + sso_properties_dlg[133].d1 = j; + } + + sso_properties_dlg[139].flags=tempsso->d2?0:D_SELECTED; + } + break; + + case ssoITEM: + { + } + break; + + case ssoTRIFRAME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=47; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=105; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char fo_color_caption[80]; + char n_color_caption[80]; + char show_frame_caption[80]; + char show_pieces_caption[80]; + sprintf(fo_color_caption, " Frame Outline Color "); + sprintf(n_color_caption, " Number Color "); + sprintf(show_frame_caption, "Show Frame"); + sprintf(show_pieces_caption, "Show Pieces"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],fo_color_caption); + replacedp(sso_properties_dlg[42],n_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + sso_properties_dlg[98].w=(tempsso->d7?112:96)*(is_large+1); + sso_properties_dlg[98].h=(tempsso->d7?112:48)*(is_large+1); + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[98].d1=tempsso->d1; + sso_properties_dlg[98].fg=tempsso->d2; + sso_properties_dlg[101].w=(tempsso->d7?32:16)*(is_large+1); + sso_properties_dlg[101].h=(tempsso->d7?48:16)*(is_large+1); + sso_properties_dlg[100].w=sso_properties_dlg[101].w+4; + sso_properties_dlg[100].h=sso_properties_dlg[101].h+4; + sso_properties_dlg[101].d1=tempsso->d3; + sso_properties_dlg[101].fg=tempsso->d4; + replacedp(sso_properties_dlg[102],show_frame_caption); + sso_properties_dlg[102].flags=tempsso->d5?D_SELECTED:0; + replacedp(sso_properties_dlg[103],show_pieces_caption); + sso_properties_dlg[103].flags=tempsso->d6?D_SELECTED:0; + sso_properties_dlg[104].flags=tempsso->d7?D_SELECTED:0; + } + break; + + case ssoTRIFORCE: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=99; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=163; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=166; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char cset_caption1[80]; + char cset_caption2[80]; + char scset_caption[80]; + char piece_caption[80]; + sprintf(cset_caption1, " CSet "); + sprintf(cset_caption2, "CSet:"); + sprintf(scset_caption, "Type:"); + sprintf(piece_caption, "Piece #:"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + sprintf(buf, "%d", tempsso->d5); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + replacedp(sso_properties_dlg[36],cset_caption1); + replacedp(sso_properties_dlg[37],cset_caption2); + sso_properties_dlg[38].proc=d_csl_proc; + ListData csettype_list(csettypelist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[38],(char *)&csettype_list); + replacedp(sso_properties_dlg[39],scset_caption); + + extract_cset(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].proc=d_csl2_proc; + ListData misccset_list(misccsetlist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[40],(char *)&misccset_list); + sso_properties_dlg[40].d1=tempsso->color1; + update_csl_proc(sso_properties_dlg+39, sso_properties_dlg[38].d1); + //sso_properties_dlg[98].fg=sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:sso_properties_dlg[40].d1; + sso_properties_dlg[98].fg=subscreen_cset(&misc,sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:ssctMISC, sso_properties_dlg[40].d1); + + sso_properties_dlg[98].d1=tempsso->d1; + sso_properties_dlg[98].d2=tempsso->d2; + sso_properties_dlg[98].w=is_large?32:16; + sso_properties_dlg[98].h=is_large?32:16; + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[98].proc=d_tileblock_proc; + sso_properties_dlg[102].flags=tempsso->d3?D_SELECTED:0; + sso_properties_dlg[103].flags=tempsso->d4?D_SELECTED:0; + replacedp(sso_properties_dlg[164],piece_caption); + replacedp(sso_properties_dlg[165],buf); + bufi=165; + } + break; + + case ssoTILEBLOCK: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=99; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + +// draw_block_flip(dest,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3,css->objects[i].d4); + char cset_caption1[80]; + char cset_caption2[80]; + char scset_caption[80]; + sprintf(cset_caption1, " CSet "); + sprintf(cset_caption2, "CSet:"); + sprintf(scset_caption, "Type:"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + sso_properties_dlg[38].proc=d_csl_proc; + ListData csettype_list(csettypelist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[36],cset_caption1); + replacedp(sso_properties_dlg[37],cset_caption2); + replacedp(sso_properties_dlg[38],(char *)&csettype_list); + replacedp(sso_properties_dlg[39],scset_caption); + + extract_cset(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].proc=d_csl2_proc; + ListData misccset_list(misccsetlist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[40],(char *)&misccset_list); + sso_properties_dlg[40].d1=tempsso->color1; + update_csl_proc(sso_properties_dlg+39, sso_properties_dlg[38].d1); + sso_properties_dlg[98].fg=subscreen_cset(&misc,sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:ssctMISC, sso_properties_dlg[40].d1); + + sso_properties_dlg[98].d1=tempsso->d1; + sso_properties_dlg[98].d2=tempsso->d2; + sso_properties_dlg[98].w=is_large?32:16; + sso_properties_dlg[98].h=is_large?32:16; + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[98].proc=d_tileblock_proc; + sso_properties_dlg[102].flags=tempsso->d3?D_SELECTED:0; + sso_properties_dlg[103].flags=tempsso->d4?D_SELECTED:0; + } + break; + + case ssoMINITILE: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=99; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=104; i<=110; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=113; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + +// draw_block_flip(dest,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3,css->objects[i].d4); + char cset_caption1[80]; + char cset_caption2[80]; + char scset_caption[80]; + sprintf(cset_caption1, " CSet "); + sprintf(cset_caption2, "CSet:"); + sprintf(scset_caption, "Type:"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + sso_properties_dlg[38].proc=d_csl_proc; + ListData csettype_list(csettypelist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[36],cset_caption1); + replacedp(sso_properties_dlg[37],cset_caption2); + replacedp(sso_properties_dlg[38],(char *)&csettype_list); + replacedp(sso_properties_dlg[39],scset_caption); + + + extract_cset(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].proc=d_csl2_proc; + ListData misccset_list(misccsetlist, is_large ? &lfont_l : &font); + replacedp(sso_properties_dlg[40],(char *)&misccset_list); + sso_properties_dlg[40].d1=tempsso->color1; + update_csl_proc(sso_properties_dlg+39, sso_properties_dlg[38].d1); + //sso_properties_dlg[98].fg=sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:sso_properties_dlg[40].d1; + sso_properties_dlg[98].fg=subscreen_cset(&misc,sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:ssctMISC, sso_properties_dlg[40].d1); + + if(tempsso->d1!=-1) + { + sso_properties_dlg[98].d1=tempsso->d1>>2; + sso_properties_dlg[98].bg=vbound(tempsso->d1-(sso_properties_dlg[98].d1<<2)+tempsso->d3,0,3); + sso_properties_dlg[112].d1=0; + sso_properties_dlg[112].d2=0; + sso_properties_dlg[97].w=20; + sso_properties_dlg[98].w=16; + } + else + { + switch(tempsso->d2) + { + case ssmstSSVINETILE: + sso_properties_dlg[98].d1=wpnsbuf[iwSubscreenVine].tile; + sso_properties_dlg[97].w=52; + sso_properties_dlg[98].w=48; + break; + + case ssmstMAGICMETER: + sso_properties_dlg[98].d1=wpnsbuf[iwMMeter].tile; + sso_properties_dlg[97].w=148; + sso_properties_dlg[98].w=144; + break; + + default: + sso_properties_dlg[97].w=20; + sso_properties_dlg[98].w=16; + } + + sso_properties_dlg[98].bg=tempsso->d3; + sso_properties_dlg[112].d1=tempsso->d2+1; + sso_properties_dlg[112].d2=sso_properties_dlg[112].d1; + } + + sso_properties_dlg[98].w*=(is_large?2:1); + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[98].h=is_large?32:16; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[98].d2=tempsso->d4; + sso_properties_dlg[98].proc=d_spectile_proc; + sso_properties_dlg[102].flags=tempsso->d5?D_SELECTED:0; + sso_properties_dlg[103].flags=tempsso->d6?D_SELECTED:0; + } + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + { + for(int i=11; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=41; i<=94; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=99; i<=101; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=105; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + +// draw_block_flip(dest,x,y,css->objects[i].d1,subscreen_cset(misc, css->objects[i].colortype1, css->objects[i].color1),css->objects[i].w,css->objects[i].h,css->objects[i].d2,css->objects[i].d3,css->objects[i].d4); + char cset_caption1[80]; + char cset_caption2[80]; + char scset_caption[80]; + char large_caption[80]; + sprintf(cset_caption1, " CSet "); + sprintf(cset_caption2, "CSet:"); + sprintf(scset_caption, "Type:"); + sprintf(large_caption, "Large"); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + + ListData csettype_list(csettypelist, is_large ? &lfont_l : &font); + sso_properties_dlg[38].proc=d_csl_proc; + replacedp(sso_properties_dlg[36],cset_caption1); + replacedp(sso_properties_dlg[37],cset_caption2); + replacedp(sso_properties_dlg[38],(char *)&csettype_list); + replacedp(sso_properties_dlg[39],scset_caption); + + extract_cset(sso_properties_dlg+38, tempsso, 1); + ListData misccset_list(misccsetlist,is_large ? &lfont_l : &font); + sso_properties_dlg[40].proc=d_csl2_proc; + replacedp(sso_properties_dlg[40],(char *)&misccset_list); + sso_properties_dlg[40].d1=tempsso->color1; + update_csl_proc(sso_properties_dlg+39, sso_properties_dlg[38].d1); + //sso_properties_dlg[98].fg=sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:sso_properties_dlg[40].d1; + sso_properties_dlg[98].fg=subscreen_cset(&misc,sso_properties_dlg[38].d1?sso_properties_dlg[38].d1-1:ssctMISC, sso_properties_dlg[40].d1); + + sso_properties_dlg[98].d1=tempsso->d1; + sso_properties_dlg[98].d2=tempsso->d2; + sso_properties_dlg[98].proc=d_tileblock_proc; + sso_properties_dlg[98].w=is_large?64:32; + sso_properties_dlg[98].h=is_large?64:32; + sso_properties_dlg[97].w=sso_properties_dlg[98].w+4; + sso_properties_dlg[97].h=sso_properties_dlg[98].h+4; + sso_properties_dlg[102].flags=tempsso->d3?D_SELECTED:0; + sso_properties_dlg[103].flags=tempsso->d4?D_SELECTED:0; + replacedp(sso_properties_dlg[104],large_caption); + sso_properties_dlg[104].proc=jwin_lscheck_proc; + sso_properties_dlg[104].flags=tempsso->d5?D_SELECTED:0; + } + break; + + case ssoMAGICGAUGE: + { + for(int i=15; i<=93; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=95; i<=104; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=111; i<=141; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=167; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + + sprintf(f_str, "%d", tempsso->d6); + sprintf(s_str, "%d", tempsso->d7); + sprintf(d_str, "%d", tempsso->d8); + // container + sprintf(buf, "%d", tempsso->d1); + + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + replacedp(sso_properties_dlg[108],f_str); + f_stri=108; + replacedp(sso_properties_dlg[109],s_str); + s_stri=109; + replacedp(sso_properties_dlg[110],d_str); + d_stri=110; + + sso_properties_dlg[145].d1=(tempsso->d2)>>2; + sso_properties_dlg[145].d2=0; + sso_properties_dlg[145].fg=tempsso->colortype1; + sso_properties_dlg[145].bg=(tempsso->d2)%4; + sso_properties_dlg[144].w = sso_properties_dlg[145].w+4; + sso_properties_dlg[144].h = sso_properties_dlg[145].h+4; + sso_properties_dlg[144].x = sso_properties_dlg[145].x-3; + sso_properties_dlg[144].y = sso_properties_dlg[145].y-3; + + sso_properties_dlg[149].d1=(tempsso->d3)>>2; + sso_properties_dlg[149].d2=0; + sso_properties_dlg[149].fg=tempsso->color1; + sso_properties_dlg[149].bg=(tempsso->d3)%4; + sso_properties_dlg[148].w = sso_properties_dlg[149].w+4; + sso_properties_dlg[148].h = sso_properties_dlg[149].h+4; + sso_properties_dlg[148].x = sso_properties_dlg[149].x-3; + sso_properties_dlg[148].y = sso_properties_dlg[149].y-3; + + sso_properties_dlg[153].d1=(tempsso->d4)>>2; + sso_properties_dlg[153].d2=0; + sso_properties_dlg[153].fg=tempsso->colortype2; + sso_properties_dlg[153].bg=(tempsso->d4)%4; + sso_properties_dlg[152].w = sso_properties_dlg[153].w+4; + sso_properties_dlg[152].h = sso_properties_dlg[153].h+4; + sso_properties_dlg[152].x = sso_properties_dlg[153].x-3; + sso_properties_dlg[152].y = sso_properties_dlg[153].y-3; + + sso_properties_dlg[157].d1=(tempsso->d5)>>2; + sso_properties_dlg[157].d2=0; + sso_properties_dlg[157].fg=tempsso->color2; + sso_properties_dlg[157].bg=(tempsso->d5)%4; + sso_properties_dlg[156].w = sso_properties_dlg[157].w+4; + sso_properties_dlg[156].h = sso_properties_dlg[157].h+4; + sso_properties_dlg[156].x = sso_properties_dlg[157].x-3; + sso_properties_dlg[156].y = sso_properties_dlg[157].y-3; + + sso_properties_dlg[158].flags=((tempsso->d10)&1)?D_SELECTED:0; + sso_properties_dlg[159].flags=((tempsso->d10)&2)?D_SELECTED:0; + sso_properties_dlg[160].flags=((tempsso->d10)&4)?D_SELECTED:0; + sso_properties_dlg[161].flags=((tempsso->d10)&8)?D_SELECTED:0; + sso_properties_dlg[163].d1=tempsso->d9; + replacedp(sso_properties_dlg[165],buf); + bufi=165; + sso_properties_dlg[166].flags=((tempsso->d10)&16)?D_SELECTED:0; + } + break; + + case ssoLIFEGAUGE: + { + for(int i=15; i<=93; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=95; i<=104; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=111; i<=141; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=167; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + + sprintf(f_str, "%d", tempsso->d6); + sprintf(s_str, "%d", tempsso->d7); + sprintf(d_str, "%d", tempsso->d8); + // container + sprintf(buf, "%d", tempsso->d1); + + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + + replacedp(sso_properties_dlg[108],f_str); + f_stri=108; + replacedp(sso_properties_dlg[109],s_str); + s_stri=109; + replacedp(sso_properties_dlg[110],d_str); + d_stri=110; + + sso_properties_dlg[145].d1=(tempsso->d2)>>2; + sso_properties_dlg[145].d2=0; + sso_properties_dlg[145].fg=tempsso->colortype1; + sso_properties_dlg[145].bg=(tempsso->d2)%4; + sso_properties_dlg[144].w = sso_properties_dlg[145].w+4; + sso_properties_dlg[144].h = sso_properties_dlg[145].h+4; + sso_properties_dlg[144].x = sso_properties_dlg[145].x-3; + sso_properties_dlg[144].y = sso_properties_dlg[145].y-3; + + sso_properties_dlg[149].d1=(tempsso->d3)>>2; + sso_properties_dlg[149].d2=0; + sso_properties_dlg[149].fg=tempsso->color1; + sso_properties_dlg[149].bg=(tempsso->d3)%4; + sso_properties_dlg[148].w = sso_properties_dlg[149].w+4; + sso_properties_dlg[148].h = sso_properties_dlg[149].h+4; + sso_properties_dlg[148].x = sso_properties_dlg[149].x-3; + sso_properties_dlg[148].y = sso_properties_dlg[149].y-3; + + sso_properties_dlg[153].d1=(tempsso->d4)>>2; + sso_properties_dlg[153].d2=0; + sso_properties_dlg[153].fg=tempsso->colortype2; + sso_properties_dlg[153].bg=(tempsso->d4)%4; + sso_properties_dlg[152].w = sso_properties_dlg[153].w+4; + sso_properties_dlg[152].h = sso_properties_dlg[153].h+4; + sso_properties_dlg[152].x = sso_properties_dlg[153].x-3; + sso_properties_dlg[152].y = sso_properties_dlg[153].y-3; + + sso_properties_dlg[157].d1=(tempsso->d5)>>2; + sso_properties_dlg[157].d2=0; + sso_properties_dlg[157].fg=tempsso->color2; + sso_properties_dlg[157].bg=(tempsso->d5)%4; + sso_properties_dlg[156].w = sso_properties_dlg[157].w+4; + sso_properties_dlg[156].h = sso_properties_dlg[157].h+4; + sso_properties_dlg[156].x = sso_properties_dlg[157].x-3; + sso_properties_dlg[156].y = sso_properties_dlg[157].y-3; + + sso_properties_dlg[158].flags=((tempsso->d10)&1)?D_SELECTED:0; + sso_properties_dlg[159].flags=((tempsso->d10)&2)?D_SELECTED:0; + sso_properties_dlg[160].flags=((tempsso->d10)&4)?D_SELECTED:0; + sso_properties_dlg[161].flags=((tempsso->d10)&8)?D_SELECTED:0; + sso_properties_dlg[163].d1=tempsso->d9; + replacedp(sso_properties_dlg[165],buf); + bufi=165; + sso_properties_dlg[166].flags=((tempsso->d10)&16)?D_SELECTED:0; + } + break; + + case ssoTEXTBOX: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=127; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + strcpy(buf, (char *)tempsso->dp1); + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", tempsso->w); + sprintf(h_str, "%d", tempsso->h); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + replacedp(sso_properties_dlg[122],buf); + bufi=122; + sso_properties_dlg[122].dp2=ss_font(tempsso->d1); + sso_properties_dlg[122].h=text_height(ss_font(tempsso->d1))+8; + sso_properties_dlg[125].d1=tempsso->d4; + sprintf(buf2, "%d", tempsso->d5); + replacedp(sso_properties_dlg[126],buf2); + buf2i=126; + } + break; + + case ssoCURRENTITEMTILE: + { + } + break; + + case ssoSELECTEDITEMTILE: + { + } + break; + + case ssoCURRENTITEMTEXT: + { + } + break; + + case ssoCURRENTITEMNAME: + { + } + break; + + case ssoSELECTEDITEMNAME: + { + for(int i=15; i<=34; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=53; i<=114; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + for(int i=127; i<=210; ++i) + { + dummy_dialog_proc(sso_properties_dlg+i); + } + + char t_color_caption[80]; + char s_color_caption[80]; + char b_color_caption[80]; + sprintf(t_color_caption, " Text Color "); + sprintf(s_color_caption, " Shadow Color "); + sprintf(b_color_caption, " Background Color "); + buf[0]=0; + sprintf(x_str, "%d", tempsso->x); + sprintf(y_str, "%d", tempsso->y); + sprintf(w_str, "%d", sso_w(tempsso)); + sprintf(h_str, "%d", sso_h(tempsso)); + replacedp(sso_properties_dlg[8],x_str); + x_stri=8; + replacedp(sso_properties_dlg[10],y_str); + y_stri=10; + replacedp(sso_properties_dlg[12],w_str); + w_stri=12; + replacedp(sso_properties_dlg[14],h_str); + h_stri=14; + replacedp(sso_properties_dlg[36],t_color_caption); + replacedp(sso_properties_dlg[42],s_color_caption); + replacedp(sso_properties_dlg[48],b_color_caption); + + extract_colortype(sso_properties_dlg+38, tempsso, 1); + sso_properties_dlg[40].d1=tempsso->color1; + update_ctl_proc(sso_properties_dlg+40, sso_properties_dlg[38].d1); + + extract_colortype(sso_properties_dlg+44, tempsso, 2); + sso_properties_dlg[46].d1=tempsso->color2; + update_ctl_proc(sso_properties_dlg+46, sso_properties_dlg[44].d1); + + extract_colortype(sso_properties_dlg+50, tempsso, 3); + sso_properties_dlg[52].d1=tempsso->color3; + update_ctl_proc(sso_properties_dlg+52, sso_properties_dlg[50].d1); + + sso_properties_dlg[119].d1=tempsso->d1; + sso_properties_dlg[120].d1=tempsso->d3; + sso_properties_dlg[121].d1=tempsso->d2; + replacedp(sso_properties_dlg[122],buf); + bufi=122; + sso_properties_dlg[122].dp2=ss_font(tempsso->d1); + sso_properties_dlg[122].h=text_height(ss_font(tempsso->d1))+8; + sso_properties_dlg[125].d1=tempsso->d4; + sprintf(buf2, "%d", tempsso->d5); + replacedp(sso_properties_dlg[126],buf2); + buf2i=126; + } + break; + + case ssoCURRENTITEMCLASSTEXT: + { + } + break; + + case ssoCURRENTITEMCLASSNAME: + { + } + break; + + case ssoSELECTEDITEMCLASSNAME: + { + } + break; + + default: + { + } + break; + } + + ret=zc_popup_dialog(sso_properties_dlg,2); + + //Bad idea + //leaks memory -DD + /*if (ret==2) + { + return -1; + }*/ + + if(ret != 2) + { + //for everything + tempsso->pos = 0; + + if((sso_properties_dlg[6].flags & D_SELECTED) != 0) + tempsso->pos |= sspUP; + + if((sso_properties_dlg[212].flags & D_SELECTED) != 0) + tempsso->pos |= sspDOWN; + + if((sso_properties_dlg[213].flags & D_SELECTED) != 0) + tempsso->pos |= sspSCROLLING; + + //item specific + switch(tempsso->type) + { + case ssoNONE: + { + } + break; + + case sso2X2FRAME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + + insert_cset(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + tempsso->d1=sso_properties_dlg[98].d1; + tempsso->d2=sso_properties_dlg[98].d2; + tempsso->d3=sso_properties_dlg[102].flags&D_SELECTED?1:0; + tempsso->d4=sso_properties_dlg[103].flags&D_SELECTED?1:0; + } + break; + + case ssoTEXT: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + + if(tempsso->dp1!=NULL) + { + //zc_free((char *)(tempsso->dp1)); + delete[]((char *)(tempsso->dp1)); + } + + //(tempsso->dp1)=(char *)zc_malloc(strlen((char *)sso_properties_dlg[bufi].dp)+1); + tempsso->dp1 = new char[strlen((char *)sso_properties_dlg[bufi].dp)+1]; + strcpy((char *)tempsso->dp1, (char *)sso_properties_dlg[bufi].dp); + } + break; + + case ssoLINE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + tempsso->d1=(sso_properties_dlg[102].flags&D_SELECTED)?1:0; + tempsso->d2=(sso_properties_dlg[103].flags&D_SELECTED)?1:0; + } + break; + + case ssoRECT: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + tempsso->d1=(sso_properties_dlg[102].flags&D_SELECTED)?1:0; + tempsso->d2=(sso_properties_dlg[103].flags&D_SELECTED)?1:0; + } + break; + + case ssoBSTIME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + } + break; + + case ssoTIME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + } + break; + + case ssoSSTIME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + } + break; + + case ssoMAGICMETER: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + } + break; + + case ssoLIFEMETER: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->d2=(sso_properties_dlg[139].flags&D_SELECTED)?1:0; + tempsso->d3= sso_properties_dlg[175].d1; + } + break; + + case ssoBUTTONITEM: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + tempsso->d2=(sso_properties_dlg[103].flags&D_SELECTED)?1:0; + tempsso->d1=sso_properties_dlg[119].d1; + } + break; + + case ssoICON: + { + } + break; + + case ssoCOUNTER: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + + tempsso->d4=atoi((char *)sso_properties_dlg[bufi].dp); + tempsso->d5=((char *)sso_properties_dlg[buf2i].dp)[0]; + tempsso->d6=(sso_properties_dlg[140].flags&D_SELECTED?1:0)+(sso_properties_dlg[141].flags&D_SELECTED?2:0); + tempsso->d7=sso_properties_dlg[136].d1; + tempsso->d8=sso_properties_dlg[137].d1; + tempsso->d9=sso_properties_dlg[138].d1; + tempsso->d10=bii[sso_properties_dlg[126].d1].i; + } + break; + + case ssoCOUNTERS: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + + tempsso->d4=atoi((char *)sso_properties_dlg[bufi].dp); + tempsso->d5=((char *)sso_properties_dlg[buf2i].dp)[0]; + tempsso->d2=sso_properties_dlg[140].flags&D_SELECTED?1:0; + } + break; + + case ssoMINIMAPTITLE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + tempsso->d4=(sso_properties_dlg[139].flags&D_SELECTED)?1:0; + } + break; + + case ssoMINIMAP: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=(sso_properties_dlg[171].flags&D_SELECTED)?1:0; + tempsso->d2=(sso_properties_dlg[172].flags&D_SELECTED)?1:0; + tempsso->d3=(sso_properties_dlg[173].flags&D_SELECTED)?1:0; + } + break; + + case ssoLARGEMAP: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + tempsso->d1=(sso_properties_dlg[171].flags&D_SELECTED)?1:0; + tempsso->d2=(sso_properties_dlg[172].flags&D_SELECTED)?1:0; + tempsso->d3=(sso_properties_dlg[173].flags&D_SELECTED)?1:0; + tempsso->d10=(sso_properties_dlg[139].flags&D_SELECTED)?1:0; + } + break; + + case ssoCLEAR: + { + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + } + break; + + case ssoCURRENTITEM: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + tempsso->d3=atoi((char *)sso_properties_dlg[bufi].dp); + tempsso->d4=atoi((char *)sso_properties_dlg[buf2i].dp); + tempsso->d5=atoi((char *)sso_properties_dlg[buf3i].dp); + tempsso->d6=atoi((char *)sso_properties_dlg[buf4i].dp); + tempsso->d7=atoi((char *)sso_properties_dlg[buf5i].dp); + tempsso->d8=vbound(bii[sso_properties_dlg[176].d1].i+1, 0, 255); + + tempsso->d1=vbound(biic[sso_properties_dlg[133].d1].i, 0, 255); + tempsso->d2=sso_properties_dlg[139].flags&D_SELECTED?0:1; + tempsso->d8=vbound(tempsso->d8,0,256); + } + break; + + case ssoITEM: + { + } + break; + + case ssoTRIFRAME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + tempsso->d1=sso_properties_dlg[98].d1; + tempsso->d2=sso_properties_dlg[98].fg; + tempsso->d3=sso_properties_dlg[101].d1; + tempsso->d4=sso_properties_dlg[101].fg; + tempsso->d5=(sso_properties_dlg[102].flags&D_SELECTED)?1:0; + tempsso->d6=(sso_properties_dlg[103].flags&D_SELECTED)?1:0; + tempsso->d7=(sso_properties_dlg[104].flags&D_SELECTED)?1:0; + } + break; + + case ssoTRIFORCE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + + insert_cset(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + tempsso->d1=sso_properties_dlg[98].d1; + tempsso->d2=sso_properties_dlg[98].d2; + tempsso->d3=sso_properties_dlg[102].flags&D_SELECTED?1:0; + tempsso->d4=sso_properties_dlg[103].flags&D_SELECTED?1:0; + tempsso->d5=atoi((char *)sso_properties_dlg[bufi].dp); + } + break; + + case ssoTILEBLOCK: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + + insert_cset(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + tempsso->d1=sso_properties_dlg[98].d1; + tempsso->d2=sso_properties_dlg[98].d2; + tempsso->d3=sso_properties_dlg[102].flags&D_SELECTED?1:0; + tempsso->d4=sso_properties_dlg[103].flags&D_SELECTED?1:0; + } + break; + + case ssoMINITILE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_cset(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + switch(sso_properties_dlg[112].d1-1) + { + case ssmstSSVINETILE: + case ssmstMAGICMETER: + tempsso->d1=-1; + tempsso->d2=sso_properties_dlg[112].d1-1; + tempsso->d3=sso_properties_dlg[98].bg; + break; + + case -1: + default: + tempsso->d1=(sso_properties_dlg[98].d1<<2)+sso_properties_dlg[98].bg; + tempsso->d2=0; + tempsso->d3=0; + break; + } + + tempsso->d4=sso_properties_dlg[98].d2; + tempsso->d5=sso_properties_dlg[102].flags&D_SELECTED?1:0; + tempsso->d6=sso_properties_dlg[103].flags&D_SELECTED?1:0; + } + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + //tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + //tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + + insert_cset(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + tempsso->d1=sso_properties_dlg[98].d1; + tempsso->d2=sso_properties_dlg[98].d2; + tempsso->d3=sso_properties_dlg[102].flags&D_SELECTED?1:0; + tempsso->d4=sso_properties_dlg[103].flags&D_SELECTED?1:0; + tempsso->d5=sso_properties_dlg[104].flags&D_SELECTED?1:0; + } + break; + + case ssoMAGICGAUGE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + tempsso->d6=atoi((char *)sso_properties_dlg[f_stri].dp); + tempsso->d7=atoi((char *)sso_properties_dlg[s_stri].dp); + tempsso->d8=atoi((char *)sso_properties_dlg[d_stri].dp); + + tempsso->d2=(sso_properties_dlg[145].d1<<2)+sso_properties_dlg[145].bg; + tempsso->colortype1=sso_properties_dlg[145].fg; + + tempsso->d3=(sso_properties_dlg[149].d1<<2)+sso_properties_dlg[149].bg; + tempsso->color1=sso_properties_dlg[149].fg; + + tempsso->d4=(sso_properties_dlg[153].d1<<2)+sso_properties_dlg[153].bg; + tempsso->colortype2=sso_properties_dlg[153].fg; + + tempsso->d5=(sso_properties_dlg[157].d1<<2)+sso_properties_dlg[157].bg; + tempsso->color2=sso_properties_dlg[157].fg; + + tempsso->d10=((sso_properties_dlg[158].flags&D_SELECTED)?1:0)+ + ((sso_properties_dlg[159].flags&D_SELECTED)?2:0)+ + ((sso_properties_dlg[160].flags&D_SELECTED)?4:0)+ + ((sso_properties_dlg[161].flags&D_SELECTED)?8:0)+ + ((sso_properties_dlg[166].flags&D_SELECTED)?16:0); + + tempsso->d9=sso_properties_dlg[163].d1; + tempsso->d1=atoi((char *)sso_properties_dlg[bufi].dp); + } + break; + + case ssoLIFEGAUGE: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + tempsso->d6=atoi((char *)sso_properties_dlg[f_stri].dp); + tempsso->d7=atoi((char *)sso_properties_dlg[s_stri].dp); + tempsso->d8=atoi((char *)sso_properties_dlg[d_stri].dp); + + tempsso->d2=(sso_properties_dlg[145].d1<<2)+sso_properties_dlg[145].bg; + tempsso->colortype1=sso_properties_dlg[145].fg; + + tempsso->d3=(sso_properties_dlg[149].d1<<2)+sso_properties_dlg[149].bg; + tempsso->color1=sso_properties_dlg[149].fg; + + tempsso->d4=(sso_properties_dlg[153].d1<<2)+sso_properties_dlg[153].bg; + tempsso->colortype2=sso_properties_dlg[153].fg; + + tempsso->d5=(sso_properties_dlg[157].d1<<2)+sso_properties_dlg[157].bg; + tempsso->color2=sso_properties_dlg[157].fg; + + tempsso->d10=((sso_properties_dlg[158].flags&D_SELECTED)?1:0)+ + ((sso_properties_dlg[159].flags&D_SELECTED)?2:0)+ + ((sso_properties_dlg[160].flags&D_SELECTED)?4:0)+ + ((sso_properties_dlg[161].flags&D_SELECTED)?8:0)+ + ((sso_properties_dlg[166].flags&D_SELECTED)?16:0); + + tempsso->d9=sso_properties_dlg[163].d1; + tempsso->d1=atoi((char *)sso_properties_dlg[bufi].dp); + } + break; + + case ssoTEXTBOX: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + + if(tempsso->dp1!=NULL) + { + //zc_free((char *)(tempsso->dp1)); + delete[]((char *)(tempsso->dp1)); + } + + //(tempsso->dp1)=(char *)zc_malloc(strlen((char *)sso_properties_dlg[bufi].dp)+1); + tempsso->dp1 = new char[strlen((char *)sso_properties_dlg[bufi].dp)+1]; + strcpy((char *)tempsso->dp1, (char *)sso_properties_dlg[bufi].dp); + tempsso->d4=sso_properties_dlg[125].d1; + tempsso->d5=atoi((char *)sso_properties_dlg[buf2i].dp); + } + break; + + case ssoCURRENTITEMTILE: + { + } + break; + + case ssoSELECTEDITEMTILE: + { + } + break; + + case ssoCURRENTITEMTEXT: + { + } + break; + + case ssoCURRENTITEMNAME: + { + } + break; + + case ssoSELECTEDITEMNAME: + { + tempsso->x=atoi((char *)sso_properties_dlg[x_stri].dp); + tempsso->y=atoi((char *)sso_properties_dlg[y_stri].dp); + tempsso->w=atoi((char *)sso_properties_dlg[w_stri].dp); + tempsso->h=atoi((char *)sso_properties_dlg[h_stri].dp); + + insert_colortype(sso_properties_dlg+38, tempsso, 1); + tempsso->color1=sso_properties_dlg[40].d1; + + insert_colortype(sso_properties_dlg+44, tempsso, 2); + tempsso->color2=sso_properties_dlg[46].d1; + + insert_colortype(sso_properties_dlg+50, tempsso, 3); + tempsso->color3=sso_properties_dlg[52].d1; + + tempsso->d1=sso_properties_dlg[119].d1; + tempsso->d3=sso_properties_dlg[120].d1; + tempsso->d2=sso_properties_dlg[121].d1; + tempsso->d4=sso_properties_dlg[125].d1; + tempsso->d5=atoi((char *)sso_properties_dlg[buf2i].dp); + } + break; + + case ssoCURRENTITEMCLASSTEXT: + { + } + break; + + case ssoCURRENTITEMCLASSNAME: + { + } + break; + + case ssoSELECTEDITEMCLASSNAME: + { + } + break; + + default: + { + } + break; + } + + } + + free_dialog(&sso_properties_dlg); + //for(map::iterator it = itemclassnames.begin(); it != itemclassnames.end(); it++) + // delete[] it->second; + //itemclassnames.clear(); + return (ret==2) ? -1 : 0; +} + +int onBringToFront(); +int onBringForward(); +int onSendBackward(); +int onSendToBack(); +int onReverseArrangement(); +int onAlignLeft(); +int onAlignCenter(); +int onAlignRight(); +int onAlignTop(); +int onAlignMiddle(); +int onAlignBottom(); +int onDistributeLeft(); +int onDistributeCenter(); +int onDistributeRight(); +int onDistributeTop(); +int onDistributeMiddle(); +int onDistributeBottom(); +int onGridSnapLeft(); +int onGridSnapCenter(); +int onGridSnapRight(); +int onGridSnapTop(); +int onGridSnapMiddle(); +int onGridSnapBottom(); +void copySSOProperties(subscreen_object& src, subscreen_object& dest); + +int onSubscreenObjectProperties() +{ + if(curr_subscreen_object >= 0) + { + if(sso_properties(&(css->objects[curr_subscreen_object]))!=-1) + { + for(int i=0; iobjects[curr_subscreen_object], css->objects[i]); + } + } + } + + return D_O_K; +} + +int onSubscreenObjectRawProperties() +{ + if(curr_subscreen_object >= 0) + { + sso_raw_data(&(css->objects[curr_subscreen_object])); + } + + return D_O_K; +} + +int onNewSubscreenObject(); + +int onDeleteSubscreenObject() +{ + int objs=ss_objects(css); + + if(objs==0) + { + return D_O_K; + } + + for(int i=curr_subscreen_object; iobjects[i]=css->objects[i+1]; + sso_selection[i]=sso_selection[i+1]; + } + + if(css->objects[objs-1].dp1!=NULL) + { + //No, don't do this. css->objects[objs-2] is pointing at this. Leave it be. + //delete [] (char *)css->objects[objs-1].dp1; + css->objects[objs-1].dp1=NULL; + } + + css->objects[objs-1].type=ssoNULL; + sso_selection[objs-1]=false; + + if(g_ssPropCopySrc==curr_subscreen_object) + g_ssPropCopySrc=-1; + else if(g_ssPropCopySrc>curr_subscreen_object) + g_ssPropCopySrc--; + + if(curr_subscreen_object==objs-1) + { + --curr_subscreen_object; + } + + update_sso_name(); + update_up_dn_btns(); + + return D_O_K; +} + +int onAddToSelection() +{ + if(curr_subscreen_object >= 0) + { + sso_selection[curr_subscreen_object]=true; + } + + return D_O_K; +} + +int onRemoveFromSelection() +{ + if(curr_subscreen_object >= 0) + { + sso_selection[curr_subscreen_object]=false; + } + + return D_O_K; +} + +int onInvertSelection() +{ + for(int i=0; iobjects[c].dp1!=NULL) + { + delete [](char *)css->objects[c].dp1; + } + + css->objects[c]=css->objects[i]; + + if(css->objects[c].dp1!=NULL) + { + //No, don't do this. css->objects[i] is pointing at this. Leave it be. + //delete [] (char *)css->objects[c].dp1; + css->objects[c].dp1=NULL; + } + + if(css->objects[i].dp1!=NULL) + { + //css->objects[c].dp1=zc_malloc(strlen((char *)css->objects[i].dp1)+1); + css->objects[c].dp1= new char[strlen((char *)css->objects[i].dp1)+1]; + strcpy((char *)css->objects[c].dp1,(char *)css->objects[i].dp1); + } + else + { + //css->objects[c].dp1=zc_malloc(2); + css->objects[c].dp1 = new char[2]; + ((char *)css->objects[c].dp1)[0]=0; + } + + css->objects[c].x+=zc_max(zinit.ss_grid_x>>1,4); + css->objects[c].y+=zc_max(zinit.ss_grid_y>>1,4); + ++counter; + } + } + + update_sso_name(); + update_up_dn_btns(); + + return D_O_K; +} + +int onEditGrid(); +int onSelectionOptions(); +int onShowHideGrid(); + + +static MENU subscreen_rc_menu[] = +{ + { (char *)"Properties ", NULL, NULL, 0, NULL }, + { (char *)"Inspect ", NULL, NULL, 0, NULL }, + { (char *)"Copy Properties ", NULL, NULL, 0, NULL }, + { (char *)"Paste Properties ", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +int d_subscreen_proc(int msg,DIALOG *d,int) +{ + switch(msg) + { + case MSG_CLICK: + { + for(int i=ss_objects(css)-1; i>=0; --i) + { + int x=sso_x(&css->objects[i])*(1+is_large); + int y=sso_y(&css->objects[i])*(1+is_large); + int w=sso_w(&css->objects[i])*(1+is_large); + int h=sso_h(&css->objects[i])*(1+is_large); + + switch(get_alignment(&css->objects[i])) + { + case sstaCENTER: + x-=(w/2); + break; + + case sstaRIGHT: + x-=w; + break; + + case sstaLEFT: + default: + break; + } + + if(isinRect(gui_mouse_x(),gui_mouse_y(),d->x+x, d->y+y, d->x+x+w-1, d->y+y+h-1)) + { + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + if(sso_selection[i]==true) + { + sso_selection[i]=false; + } + else + { + sso_selection[curr_subscreen_object]=true; + curr_subscreen_object=i; + update_sso_name(); + update_up_dn_btns(); + } + } + else + { + onClearSelection(); + curr_subscreen_object=i; + update_sso_name(); + update_up_dn_btns(); + } + + break; + } + } + + if(gui_mouse_b()&2) //right mouse button + { + object_message(d,MSG_DRAW,0); + + // Disable "Paste Properties" if the copy source is invalid + if(g_ssPropCopySrc<0 || css->objects[g_ssPropCopySrc].type==ssoNULL) + subscreen_rc_menu[3].flags|=D_DISABLED; + else + subscreen_rc_menu[3].flags&=~D_DISABLED; + + int m = popup_menu(subscreen_rc_menu,gui_mouse_x(),gui_mouse_y()); + + switch(m) + { + case 0: // Properties + onSubscreenObjectProperties(); + break; + + case 1: // Inspect + onSubscreenObjectRawProperties(); + break; + + case 2: // Copy Properties + g_ssPropCopySrc=curr_subscreen_object; + break; + + case 3: // Paste Properties + if(g_ssPropCopySrc>=0) // Hopefully unnecessary) + { + copySSOProperties(css->objects[g_ssPropCopySrc], css->objects[curr_subscreen_object]); + for(int i=0; iobjects[g_ssPropCopySrc], css->objects[i]); + } + } + break; + } + } + + return D_O_K; + } + break; + + case MSG_VSYNC: + d->flags|=D_DIRTY; + break; + + case MSG_DRAW: + { + Sitems.animate(); + BITMAP *buf = create_bitmap_ex(8,d->w,d->h);//In Large Mode, this is actually 2x as large as needed, but whatever. + + if(buf) + { + clear_bitmap(buf); + show_custom_subscreen(buf, &misc, (subscreen_group *)(d->dp), 0, 0, true, sspUP | sspDOWN | sspSCROLLING); + + for(int i=0; iw; x+=zinit.ss_grid_x) + { + for(int y=zinit.ss_grid_yofs; yh; y+=zinit.ss_grid_y) + { + buf->line[y][x]=vc(zinit.ss_grid_color); + } + } + } + + if(is_large) + { + stretch_blit(buf,screen,0,0,d->w/(1+is_large),d->h/(1+is_large),d->x,d->y,d->w,d->h); + } + else + { + blit(buf,screen,0,0,d->x,d->y,d->w,d->h); + } + + destroy_bitmap(buf); + } + } + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + break; + } + + return D_O_K; +} + +int onSSUp(); +int onSSDown(); +int onSSLeft(); +int onSSRight(); +int onSSPgDn(); +int onSSPgUp(); + +int d_ssup_btn_proc(int msg,DIALOG *d,int c); +int d_ssdn_btn_proc(int msg,DIALOG *d,int c); +int d_sslt_btn_proc(int msg,DIALOG *d,int c); +int d_ssrt_btn_proc(int msg,DIALOG *d,int c); + +int onSSUp() +{ + int delta=(key[KEY_LSHIFT]||key[KEY_RSHIFT])?-zinit.ss_grid_y:-1; + + for(int i=0; iobjects[i].h+=delta; + } + else + { + css->objects[i].y+=delta; + } + } + } + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + css->objects[curr_subscreen_object].h+=delta; + } + else + { + css->objects[curr_subscreen_object].y+=delta; + } + + return D_O_K; +} + +int onSSDown() +{ + int delta=(key[KEY_LSHIFT]||key[KEY_RSHIFT])?zinit.ss_grid_y:1; + + for(int i=0; iobjects[i].h+=delta; + } + else + { + css->objects[i].y+=delta; + } + } + } + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + css->objects[curr_subscreen_object].h+=delta; + } + else + { + css->objects[curr_subscreen_object].y+=delta; + } + + return D_O_K; +} + +int onSSLeft() +{ + int delta=(key[KEY_LSHIFT]||key[KEY_RSHIFT])?-zinit.ss_grid_x:-1; + + for(int i=0; iobjects[i].w+=delta; + } + else + { + css->objects[i].x+=delta; + } + } + } + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + css->objects[curr_subscreen_object].w+=delta; + } + else + { + css->objects[curr_subscreen_object].x+=delta; + } + + return D_O_K; +} + +int onSSRight() +{ + int delta=(key[KEY_LSHIFT]||key[KEY_RSHIFT])?zinit.ss_grid_x:1; + + for(int i=0; iobjects[i].w+=delta; + } + else + { + css->objects[i].x+=delta; + } + } + } + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + css->objects[curr_subscreen_object].w+=delta; + } + else + { + css->objects[curr_subscreen_object].x+=delta; + } + + return D_O_K; +} + +int d_ssup_btn2_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSUp(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssdn_btn2_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSDown(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_sslt_btn2_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSLeft(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssrt_btn2_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSRight(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssup_btn3_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + + for(int i=0; iobjects[i].h; + } + } + + --css->objects[curr_subscreen_object].h; + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssdn_btn3_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + + for(int i=0; iobjects[i].h; + } + } + + ++css->objects[curr_subscreen_object].h; + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_sslt_btn3_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + + for(int i=0; iobjects[i].w; + } + } + + --css->objects[curr_subscreen_object].w; + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssrt_btn3_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + + for(int i=0; iobjects[i].w; + } + } + + ++css->objects[curr_subscreen_object].w; + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int Bweapon(int pos) +{ + int p=-1; + + for(int i=0; css->objects[i].type!=ssoNULL; ++i) + { + if(css->objects[i].type==ssoCURRENTITEM && css->objects[i].d3==pos) + { + p=i; + break; + } + } + + if(p==-1) + { + return 0; + } + + int family = 0; + bool bow = false; + + switch(css->objects[p].d1) + { + case itype_arrow: + case itype_bowandarrow: + if(current_item(itype_bow) && current_item(itype_arrow)) + { + bow=(css->objects[p].d1==itype_bowandarrow); + family=itype_arrow; + } + + break; + + case itype_letterpotion: + if(current_item(itype_potion)) + family=itype_potion; + else if(current_item(itype_letter)) + family=itype_letter; + + break; + + case itype_sword: + { + if(!get_bit(quest_rules,qr_SELECTAWPN)) + break; + + family=itype_sword; + } + break; + + default: + family=css->objects[p].d1; + } + + for(int i=0; iobjects[i].type!=ssoNULL; ++i) + { + if(css->objects[i].type==ssoCURRENTITEM) + { + if(css->objects[i].d3==Bpos) + { + p=i; + break; + } + } + } + + if(p!=-1) + { + if(xstep!=0) + { + Bpos=xstep<0?css->objects[p].d6:css->objects[p].d7; + } + else + { + Bpos=ystep<0?css->objects[p].d4:css->objects[p].d5; + } + } + + Bwpn = Bweapon(Bpos); + update_subscr_items(); + + if(Bwpn) + { + return; + } + } + while(Bpos!=pos && ++tries<0x100); + + if(!Bwpn) + Bpos=0; +} + + +int d_ssup_btn4_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + selectBwpn(0, -1); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssdn_btn4_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + selectBwpn(0, 1); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_sslt_btn4_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + selectBwpn(-1, 0); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssrt_btn4_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + selectBwpn(1, 0); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +const char *sso_type[ssoMAX]= +{ + "ssoNULL", "ssoNONE", "sso2X2FRAME", "ssoTEXT", "ssoLINE", "ssoRECT", "ssoBSTIME", "ssoTIME", "ssoSSTIME", "ssoMAGICMETER", "ssoLIFEMETER", "ssoBUTTONITEM", "ssoICON", "ssoCOUNTER", + "ssoCOUNTERS", "ssoMINIMAPTITLE", "ssoMINIMAP", "ssoLARGEMAP", "ssoCLEAR", "ssoCURRENTITEM", "ssoITEM", "ssoTRIFRAME", "ssoTRIFORCE", "ssoTILEBLOCK", "ssoMINITILE", "ssoSELECTOR1", "ssoSELECTOR2", + "ssoMAGICGAUGE", "ssoLIFEGAUGE", "ssoTEXTBOX", "ssoCURRENTITEMTILE", "ssoSELECTEDITEMTILE", "ssoCURRENTITEMTEXT", "ssoCURRENTITEMNAME", "ssoSELECTEDITEMNAME", "ssoCURRENTITEMCLASSTEXT", + "ssoCURRENTITEMCLASSNAME", "ssoSELECTEDITEMCLASSNAME" +}; + +const char *sso_textstyle[sstsMAX]= +{ + "sstsNORMAL", "sstsSHADOW", "sstsSHADOWU", "sstsOUTLINE8", "sstsOUTLINEPLUS", "sstsOUTLINEX", "sstsSHADOWED", "sstsSHADOWEDU", "sstsOUTLINED8", "sstsOUTLINEDPLUS", "sstsOUTLINEDX" +}; + +const char *sso_fontname[ssfMAX]= +{ + "ssfZELDA", "ssfSS1", "ssfSS2", "ssfSS3", "ssfSS4", "ssfZTIME", "ssfSMALL", "ssfSMALLPROP", "ssfZ3SMALL", "ssfGBLA", "ssfZ3", + "ssfGORON", "ssfZORAN", "ssfHYLIAN1", "ssfHYLIAN2", "ssfHYLIAN3", "ssfHYLIAN4", "ssfPROP", "ssfGBORACLE", "ssfGBORACLEP", + "ssfDSPHANTOM", "ssfDSPHANTOMP" +}; + +const char *sso_colortype[2]= +{ + "ssctSYSTEM", "ssctMISC" +}; + +const char *sso_specialcolor[ssctMAX]= +{ + "ssctTEXT", "ssctCAPTION", "ssctOVERWBG", "ssctDNGNBG", "ssctDNGNFG", "ssctCAVEFG", "ssctBSDK", "ssctBSGOAL", "ssctCOMPASSLT", "ssctCOMPASSDK", "ssctSUBSCRBG", "ssctSUBSCRSHADOW", + "ssctTRIFRAMECOLOR", "ssctBMAPBG", "ssctBMAPFG", "ssctLINKDOT", "ssctMSGTEXT" +}; + +const char *sso_specialcset[sscsMAX]= +{ + "sscsTRIFORCECSET", "sscsTRIFRAMECSET", "sscsOVERWORLDMAPCSET", "sscsDUNGEONMAPCSET", "sscsBLUEFRAMECSET", "sscsHCPIECESCSET", "sscsSSVINECSET" +}; + +const char *sso_specialtile[ssmstMAX]= +{ + "ssmstSSVINETILE", "ssmstMAGICMETER" +}; + +const char *sso_counterobject[sscMAX]= +{ + "sscRUPEES", "sscBOMBS", "sscSBOMBS", "sscARROWS", "sscGENKEYMAGIC", "sscGENKEYNOMAGIC", "sscLEVKEYMAGIC", + "sscLEVKEYNOMAGIC", "sscANYKEYMAGIC", "sscANYKEYNOMAGIC", "sscSCRIPT1", "sscSCRIPT2", "sscSCRIPT3", "sscSCRIPT4", + "sscSCRIPT5", "sscSCRIPT6", "sscSCRIPT7", "sscSCRIPT8", "sscSCRIPT9", "sscSCRIPT10" +}; + +const char *sso_alignment[3]= +{ + "sstaLEFT", "sstaCENTER", "sstaRIGHT" +}; + + +bool save_subscreen_code(char *path) +{ + PACKFILE *f = pack_fopen_password(path,F_WRITE,""); + + if(!f) + { + return false; + } + + int ssobjs=ss_objects(css); + char buf[512]; + memset(buf,0,512); + sprintf(buf, "subscreen_object exported_subscreen[%d]=\n", ssobjs); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + pack_fputs("{\n", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + for(int i=0; iobjects[i].type], css->objects[i].pos, css->objects[i].x, css->objects[i].y, css->objects[i].w, css->objects[i].h); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + if(css->objects[i].colortype1>=ssctSYSTEM) + { + sprintf(buf, "%s, ", sso_colortype[css->objects[i].colortype1==ssctSYSTEM?0:1]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + if(css->objects[i].colortype1==ssctMISC) + { + int t=css->objects[i].type; + + if(t==sso2X2FRAME||t==ssoCURRENTITEMTILE||t==ssoICON||t==ssoMINITILE||t==ssoSELECTEDITEMTILE||t==ssoSELECTOR1||t==ssoSELECTOR2||t==ssoTRIFORCE||t==ssoTILEBLOCK) + { + sprintf(buf, "%s, ", sso_specialcset[css->objects[i].color1]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + else + { + sprintf(buf, "%s, ", sso_specialcolor[css->objects[i].color1]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, ", css->objects[i].color1); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, %d, ", css->objects[i].colortype1, css->objects[i].color1); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + + if(css->objects[i].colortype2>=ssctSYSTEM) + { + sprintf(buf, "%s, ", sso_colortype[css->objects[i].colortype2==ssctSYSTEM?0:1]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + if(css->objects[i].colortype2==ssctMISC) + { + int t=css->objects[i].type; + + if(t==sso2X2FRAME||t==ssoCURRENTITEMTILE||t==ssoICON||t==ssoMINITILE||t==ssoSELECTEDITEMTILE||t==ssoSELECTOR1||t==ssoSELECTOR2||t==ssoTRIFORCE||t==ssoTILEBLOCK) + { + sprintf(buf, "%s, ", sso_specialcset[css->objects[i].color2]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + else + { + sprintf(buf, "%s, ", sso_specialcolor[css->objects[i].color2]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, ", css->objects[i].color2); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, %d, ", css->objects[i].colortype2, css->objects[i].color2); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + + if(css->objects[i].colortype3>=ssctSYSTEM) + { + sprintf(buf, "%s, ", sso_colortype[css->objects[i].colortype3==ssctSYSTEM?0:1]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + if(css->objects[i].colortype3==ssctMISC) + { + int t=css->objects[i].type; + + if(t==sso2X2FRAME||t==ssoCURRENTITEMTILE||t==ssoICON||t==ssoMINITILE||t==ssoSELECTEDITEMTILE||t==ssoSELECTOR1||t==ssoSELECTOR2||t==ssoTRIFORCE||t==ssoTILEBLOCK) + { + sprintf(buf, "%s, ", sso_specialcset[css->objects[i].color3]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + else + { + sprintf(buf, "%s, ", sso_specialcolor[css->objects[i].color3]); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, ", css->objects[i].color3); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + } + else + { + sprintf(buf, "%d, %d, ", css->objects[i].colortype3, css->objects[i].color3); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + + switch(css->objects[i].type) + { + case ssoCURRENTITEM: + sprintf(buf, "%s, ", itype_names[css->objects[i].d1]); + break; + + case ssoCOUNTER: + case ssoCOUNTERS: + case ssoTEXT: + case ssoTEXTBOX: + case ssoMINIMAPTITLE: + case ssoSELECTEDITEMNAME: + case ssoTIME: + case ssoSSTIME: + case ssoBSTIME: + sprintf(buf, "%s, ", sso_fontname[css->objects[i].d1]); + break; + + default: + sprintf(buf, "%d, ", css->objects[i].d1); + break; + } + + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + switch(css->objects[i].type) + { + case ssoCOUNTER: + case ssoTEXT: + case ssoTEXTBOX: + case ssoMINIMAPTITLE: + case ssoSELECTEDITEMNAME: + case ssoTIME: + case ssoSSTIME: + case ssoBSTIME: + sprintf(buf, "%s, ", sso_alignment[css->objects[i].d2]); + break; + + case ssoMINITILE: + if(css->objects[i].d1==-1) + { + sprintf(buf, "%s, ", sso_specialtile[css->objects[i].d2]); + } + else + { + sprintf(buf, "%d, ", css->objects[i].d2); + } + + break; + + default: + sprintf(buf, "%d, ", css->objects[i].d2); + break; + } + + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + switch(css->objects[i].type) + { + case ssoCOUNTER: + case ssoCOUNTERS: + case ssoTEXT: + case ssoTEXTBOX: + case ssoMINIMAPTITLE: + case ssoSELECTEDITEMNAME: + case ssoTIME: + case ssoSSTIME: + case ssoBSTIME: + sprintf(buf, "%s, ", (char *)sso_textstyle[css->objects[i].d3]); + break; + + default: + sprintf(buf, "%d, ", css->objects[i].d3); + break; + } + + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].d4); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + switch(css->objects[i].type) + { + case ssoCOUNTER: + case ssoCOUNTERS: + sprintf(buf, "\'%c\', ", css->objects[i].d5); + break; + + default: + sprintf(buf, "%d, ", css->objects[i].d5); + break; + } + + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].d6); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + switch(css->objects[i].type) + { + case ssoCOUNTER: + sprintf(buf, "%s, ", sso_counterobject[css->objects[i].d7]); + break; + + default: + sprintf(buf, "%d, ", css->objects[i].d7); + break; + } + + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].d8); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].d9); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].d10); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].frames); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].speed); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].delay); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + sprintf(buf, "%d, ", css->objects[i].frame); + pack_fputs(buf, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + + if(!css->objects[i].dp1) + { + pack_fputs("NULL", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + else + { + pack_fputs("(void *)\"", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + pack_fputs((char *)css->objects[i].dp1, f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + pack_fputs("\"", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + + pack_fputs(" },\n", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + } + + pack_fputs(" { ssoNULL }\n", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + pack_fputs("};\n", f); + + if(pack_ferror(f)) + { + pack_fclose(f); + return false; + } + + pack_fclose(f); + return true; +} + + + +int onExport_Subscreen_Code() +{ + if(!getname("Export Subscreen Code (.zss)","zss",NULL,datapath,false)) + return D_O_K; + + char buf[80],buf2[80],name[13]; + extract_name(temppath,name,FILENAME8_3); + + if(save_subscreen_code(temppath)) + { + sprintf(buf,"ZQuest"); + sprintf(buf2,"Saved %s",name); + } + else + { + sprintf(buf,"Error"); + sprintf(buf2,"Error saving %s",name); + } + + jwin_alert(buf,buf2,NULL,NULL,"O&K",NULL,'k',0,lfont); + return D_O_K; +} + +int onActivePassive(); + +static MENU ss_arrange_menu[] = +{ + { (char *)"Bring to Front", onBringToFront, NULL, 0, NULL }, + { (char *)"Bring Forward", onBringForward, NULL, 0, NULL }, + { (char *)"Send Backward", onSendBackward, NULL, 0, NULL }, + { (char *)"Send to Back", onSendToBack, NULL, 0, NULL }, + { (char *)"Reverse", onReverseArrangement, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_grid_snap_menu[] = +{ + { (char *)"Left Edges", onGridSnapLeft, NULL, 0, NULL }, + { (char *)"Horizontal Centers", onGridSnapCenter, NULL, 0, NULL }, + { (char *)"Right Edges", onGridSnapRight, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Top Edges", onGridSnapTop, NULL, 0, NULL }, + { (char *)"Vertical Centers", onGridSnapMiddle, NULL, 0, NULL }, + { (char *)"Bottom Edges", onGridSnapBottom, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_align_menu[] = +{ + { (char *)"Left Edges", onAlignLeft, NULL, 0, NULL }, + { (char *)"Horizontal Centers", onAlignCenter, NULL, 0, NULL }, + { (char *)"Right Edges", onAlignRight, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Top Edges", onAlignTop, NULL, 0, NULL }, + { (char *)"Vertical Centers", onAlignMiddle, NULL, 0, NULL }, + { (char *)"Bottom Edges", onAlignBottom, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"To Grid", NULL, ss_grid_snap_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_distribute_menu[] = +{ + { (char *)"Left Edges", onDistributeLeft, NULL, 0, NULL }, + { (char *)"Horizontal Centers", onDistributeCenter, NULL, 0, NULL }, + { (char *)"Right Edges", onDistributeRight, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Top Edges", onDistributeTop, NULL, 0, NULL }, + { (char *)"Vertical Centers", onDistributeMiddle, NULL, 0, NULL }, + { (char *)"Bottom Edges", onDistributeBottom, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_edit_menu[] = +{ + { (char *)"&New\tIns", onNewSubscreenObject, NULL, 0, NULL }, + { (char *)"&Delete\tDel", onDeleteSubscreenObject, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Duplicate", onDuplicateSubscreenObject, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Properties", onSubscreenObjectProperties, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Arrange", NULL, ss_arrange_menu, 0, NULL }, + { (char *)"Al&ign", NULL, ss_align_menu, 0, NULL }, + { (char *)"Dis&tribute", NULL, ss_distribute_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Switch Active/Passive", onActivePassive, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Take Snapshot\tZ", onSnapshot, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"E&xport as Code\tX", onExport_Subscreen_Code, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_grid_menu[] = +{ + { (char *)"&Edit", onEditGrid, NULL, 0, NULL }, + { (char *)"&Show", onShowHideGrid, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU ss_selection_menu[] = +{ + { (char *)"&Add to Selection\tA", onAddToSelection, NULL, 0, NULL }, + { (char *)"&Remove from Selection\tR", onRemoveFromSelection, NULL, 0, NULL }, + { (char *)"&Invert Selection\tI", onInvertSelection, NULL, 0, NULL }, + { (char *)"&Clear Selection\tC", onClearSelection, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Options", onSelectionOptions, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU subscreen_menu[] = +{ + { (char *)"&Edit", NULL, ss_edit_menu, 0, NULL }, + { (char *)"&Grid", NULL, ss_grid_menu, 0, NULL }, + { (char *)"&Selection", NULL, ss_selection_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + + +static DIALOG subscreen_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 320, 240, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Subscreen Editor", NULL, NULL }, + { jwin_button_proc, 192, 215, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 255, 215, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_frame_proc, 4, 37, 260, 172, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_subscreen_proc, 6, 39, 256, 168, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 5 + { d_box_proc, 11, 211, 181, 8, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 11, 211, 181, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 4, 225, 30, 16, 0, 0, 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 34, 221, 155, 16, 0, 0, 0, 0, 64, 0, NULL, NULL, NULL }, + + { d_ssup_btn_proc, 284, 23, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { d_ssdn_btn_proc, 284, 53, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + { d_sslt_btn_proc, 269, 38, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8A", NULL, NULL }, + { d_ssrt_btn_proc, 299, 38, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8B", NULL, NULL }, + + { d_ssup_btn2_proc, 284, 70, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { d_ssdn_btn2_proc, 284, 100, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + { d_sslt_btn2_proc, 269, 85, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8A", NULL, NULL }, + { d_ssrt_btn2_proc, 299, 85, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8B", NULL, NULL }, + + { d_ssup_btn3_proc, 284, 117, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x98", NULL, NULL }, + { d_ssdn_btn3_proc, 284, 147, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x99", NULL, NULL }, + { d_sslt_btn3_proc, 269, 132, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x9A", NULL, NULL }, + { d_ssrt_btn3_proc, 299, 132, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x9B", NULL, NULL }, + + { d_ssup_btn4_proc, 284, 164, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x88", NULL, NULL }, + { d_ssdn_btn4_proc, 284, 194, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x89", NULL, NULL }, + { d_sslt_btn4_proc, 269, 179, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8A", NULL, NULL }, + { d_ssrt_btn4_proc, 299, 179, 15, 15, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "\x8B", NULL, NULL }, + + { jwin_menu_proc, 4, 23, 0, 13, 0, 0, 0, 0, 0, 0, (void *) subscreen_menu, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_UP, 0, (void *) onSSUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DOWN, 0, (void *) onSSDown, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_LEFT, 0, (void *) onSSLeft, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, 0, (void *) onSSRight, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGUP, 0, (void *) onSSPgUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGDN, 0, (void *) onSSPgDn, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'a', 0, 0, 0, (void *) onAddToSelection, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'r', 0, 0, 0, (void *) onRemoveFromSelection, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'i', 0, 0, 0, (void *) onInvertSelection, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'c', 0, 0, 0, (void *) onClearSelection, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_INSERT, 0, (void *) onNewSubscreenObject, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, 0, (void *) onDeleteSubscreenObject, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'd', 0, 0, 0, (void *) onDuplicateSubscreenObject, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'e', 0, 0, 0, (void *) onSubscreenObjectProperties, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'z', 0, 0, 0, (void *) onSnapshot, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'x', 0, 0, 0, (void *) onExport_Subscreen_Code, NULL, NULL }, + { d_vsync_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onActivePassive() +{ + if(css->ss_type == sstACTIVE) + { + css->ss_type = sstPASSIVE; + subscreen_dlg[3].h=60*(1+is_large)-(is_large?4:0); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + else if(css->ss_type == sstPASSIVE) + { + css->ss_type = sstACTIVE; + subscreen_dlg[3].h=172*(1+is_large)-(is_large?4:0); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + + return D_REDRAW; +} + + +const char *color_str[16] = +{ + "Black", "Blue", "Green", "Cyan", "Red", "Magenta", "Brown", "Light Gray", + "Dark Gray", "Light Blue", "Light Green", "Light Cyan", "Light Red", "Light Magenta", "Yellow", "White" +}; + +const char *colorlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 16; + return NULL; + } + + return color_str[index]; +} + +static ListData color_list(colorlist, &font); + +static DIALOG grid_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 158, 120, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Edit Grid Properties", NULL, NULL }, + { jwin_button_proc, 18, 95, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 81, 95, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 6, 29, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "X Size:", NULL, NULL }, + { jwin_edit_proc, 42, 25, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + // 5 + { jwin_text_proc, 6, 49, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Y Size:", NULL, NULL }, + { jwin_edit_proc, 42, 45, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 78, 29, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "X Offset:", NULL, NULL }, + { jwin_edit_proc, 126, 25, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 78, 49, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Y Offset:", NULL, NULL }, + // 10 + { jwin_edit_proc, 126, 45, 26, 16, 0, 0, 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 6, 69, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + { jwin_droplist_proc, 36, 65, 116, 16, 0, 0, 0, 0, 0, 0, (void *) &color_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG sel_options_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 225, 120, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Selection Options", NULL, NULL }, + { jwin_button_proc, 51, 95, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 114, 95, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_frame_proc, 6, 28, 213, 51, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 10, 25, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Selection Outlines ", NULL, NULL }, + // 5 + { jwin_text_proc, 14, 41, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Primary Color:", NULL, NULL }, + { jwin_droplist_proc, 94, 37, 116, 16, 0, 0, 0, 0, 0, 0, (void *) &color_list, NULL, NULL }, + { jwin_text_proc, 14, 61, 186, 16, 0, 0, 0, 0, 0, 0, (void *) "Secondary Color:", NULL, NULL }, + { jwin_droplist_proc, 94, 57, 116, 16, 0, 0, 0, 0, 0, 0, (void *) &color_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +const char *sso_str[ssoMAX]= +{ + "NULL", "(None)", "2x2 Frame", "Text", "Line", "Rectangle", "BS-Zelda Time", "Game Time", "Game Time (Quest Rule)", "Magic Meter", "Life Meter", + "Button Item", "-Icon (Not Implemented)", "Counter", "Counter Block", "Minimap Title", "Minimap", "Large Map", "Erase Subscreen", "Current Item", "-Item (Not Implemented)", + "Triforce Frame", "Triforce Piece", "Tile Block", "Minitile", "Selector 1", "Selector 2", "Magic Gauge Piece", "Life Gauge Piece", "Text Box", "-Current Item -> Tile (Not Implemented)", + "-Selected Item -> Tile (Not Implemented)", "-Current Item -> Text (Not Implemented)", "-Current Item Name (Not Implemented)", "Selected Item Name", + "-Current Item Class -> Text (Not Implemented)", "-Current Item Class Name (Not Implemented)", "-Selected Item Class Name (Not Implemented)" +}; + +char *sso_name(int type) +{ + char *tempname; + tempname=(char*)zc_malloc(255); + + if(type>=0 && type 0) + { + std::swap(bisso[i],bisso[j]); + } + } + } +} + +const char *ssolist(int index, int *list_size) +{ + if(index<0) + { + *list_size = bisso_cnt; + return NULL; + } + + return bisso[index].s; +} + +static ListData sso_list(ssolist, &font); + +static DIALOG ssolist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 255, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Object Type", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_abclist_proc, 4, 24, 247, 95, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &sso_list, NULL, NULL }, + { jwin_button_proc, 65, 123, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 128, 123, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onNewSubscreenObject() +{ + subscreen_object tempsso; + int ret=-1; + ssolist_dlg[0].dp2=lfont; + build_bisso_list(); + + if(is_large) + large_dialog(ssolist_dlg); + + ret=zc_popup_dialog(ssolist_dlg,2); + + if(ret!=0&&ret!=4) + { + memset(&tempsso,0,sizeof(subscreen_object)); + //tempsso.dp1=(char *)zc_malloc(2); + tempsso.dp1 = new char[2]; + ((char *)tempsso.dp1)[0]=0; + tempsso.type=bisso[ssolist_dlg[2].d1].i; + tempsso.pos = sspUP | sspDOWN | sspSCROLLING; + tempsso.w=1; + tempsso.h=1; + + if(tempsso.type==ssoCURRENTITEM) // Should not be invisible! + tempsso.d2 = 1; + + int temp_cso=curr_subscreen_object; + curr_subscreen_object=ss_objects(css); + + if(sso_properties(&tempsso)!=-1) + { + if(css->objects[curr_subscreen_object].dp1!=NULL) + { + delete [](char *)css->objects[curr_subscreen_object].dp1; + css->objects[curr_subscreen_object].dp1=NULL; + } + + css->objects[curr_subscreen_object]=tempsso; + update_sso_name(); + update_up_dn_btns(); + } + else + { + curr_subscreen_object=temp_cso; + } + } + + return D_O_K; +} + + +void align_objects(subscreen_group *tempss, bool *selection, int align_type) +{ + int l=sso_x(&tempss->objects[curr_subscreen_object]); + int t=sso_y(&tempss->objects[curr_subscreen_object]); + int w=sso_w(&tempss->objects[curr_subscreen_object]); + int h=sso_h(&tempss->objects[curr_subscreen_object]); + + switch(get_alignment(&tempss->objects[curr_subscreen_object])) + { + case sstaCENTER: + l-=(w/2); + break; + + case sstaRIGHT: + l-=w; + break; + + case sstaLEFT: + default: + break; + } + + int r=l+w-1; + int b=t+h-1; + int c=l+w/2; + int m=t+h/2; + + for(int i=0; iobjects[i]); + int tt=sso_y(&tempss->objects[i]); + int tw=sso_w(&tempss->objects[i]); + int th=sso_h(&tempss->objects[i]); + + switch(get_alignment(&tempss->objects[i])) + { + case sstaCENTER: + tl-=(tw/2); + break; + + case sstaRIGHT: + tl-=tw; + break; + + case sstaLEFT: + default: + break; + } + + int tr=tl+tw-1; + int tb=tt+th-1; + int tc=tl+tw/2; + int tm=tt+th/2; + + switch(align_type) + { + case ssoaBOTTOM: + tempss->objects[i].y+=b-tb; + break; + + case ssoaMIDDLE: + tempss->objects[i].y+=m-tm; + break; + + case ssoaTOP: + tempss->objects[i].y+=t-tt; + break; + + case ssoaRIGHT: + tempss->objects[i].x+=r-tr; + break; + + case ssoaCENTER: + tempss->objects[i].x+=c-tc; + break; + + case ssoaLEFT: + default: + tempss->objects[i].x+=l-tl; + break; + } + } + } +} + +void grid_snap_objects(subscreen_group *tempss, bool *selection, int snap_type) +{ + for(int i=0; iobjects[i]); + int tt=sso_y(&tempss->objects[i]); + int tw=sso_w(&tempss->objects[i]); + int th=sso_h(&tempss->objects[i]); + + switch(get_alignment(&tempss->objects[i])) + { + case sstaCENTER: + tl-=(tw/2); + break; + + case sstaRIGHT: + tl-=tw; + break; + + case sstaLEFT: + default: + break; + } + + int tr=tl+tw-1; + int tb=tt+th-1; + int tc=tl+tw/2; + int tm=tt+th/2; + int l1=(tl-zinit.ss_grid_xofs)/zinit.ss_grid_x*zinit.ss_grid_x+zinit.ss_grid_xofs; + int l2=l1+zinit.ss_grid_x; + int c1=(tc-zinit.ss_grid_xofs)/zinit.ss_grid_x*zinit.ss_grid_x+zinit.ss_grid_xofs; + int c2=c1+zinit.ss_grid_x; + int r1=(tr-zinit.ss_grid_xofs)/zinit.ss_grid_x*zinit.ss_grid_x+zinit.ss_grid_xofs; + int r2=r1+zinit.ss_grid_x; + + int t1=(tt-zinit.ss_grid_yofs)/zinit.ss_grid_y*zinit.ss_grid_y+zinit.ss_grid_yofs; + int t2=t1+zinit.ss_grid_y; + int m1=(tm-zinit.ss_grid_yofs)/zinit.ss_grid_y*zinit.ss_grid_y+zinit.ss_grid_yofs; + int m2=m1+zinit.ss_grid_y; + int b1=(tb-zinit.ss_grid_yofs)/zinit.ss_grid_y*zinit.ss_grid_y+zinit.ss_grid_yofs; + int b2=b1+zinit.ss_grid_y; + + switch(snap_type) + { + case ssosBOTTOM: + tempss->objects[i].y+=(abs(b1-tb)>abs(b2-tb))?(b2-tb):(b1-tb); + break; + + case ssosMIDDLE: + tempss->objects[i].y+=(abs(m1-tm)>abs(m2-tm))?(m2-tm):(m1-tm); + break; + + case ssosTOP: + tempss->objects[i].y+=(abs(t1-tt)>abs(t2-tt))?(t2-tt):(t1-tt); + break; + + case ssosRIGHT: + tempss->objects[i].x+=(abs(r1-tr)>abs(r2-tr))?(r2-tr):(r1-tr); + break; + + case ssosCENTER: + tempss->objects[i].x+=(abs(c1-tc)>abs(c2-tc))?(c2-tc):(c1-tc); + break; + + case ssosLEFT: + default: + tempss->objects[i].x+=(abs(l1-tl)>abs(l2-tl))?(l2-tl):(l1-tl); + break; + } + } + } +} + +typedef struct dist_obj +{ + int index; + int l; + int t; + int w; + int h; + int r; + int b; + int c; + int m; +} dist_obj; + +void distribute_objects(subscreen_group *tempss, bool *selection, int distribute_type) +{ + //these are here to bypass compiler warnings about unused arguments + selection=selection; + + int count=0; + dist_obj temp_do[MAXSUBSCREENITEMS]; + + for(int i=0; iobjects[i]); + temp_do[count].t=sso_y(&tempss->objects[i]); + temp_do[count].w=sso_w(&tempss->objects[i]); + temp_do[count].h=sso_h(&tempss->objects[i]); + + switch(get_alignment(&tempss->objects[i])) + { + case sstaCENTER: + temp_do[count].l-=(temp_do[count].w/2); + break; + + case sstaRIGHT: + temp_do[count].l-=temp_do[count].w; + break; + + case sstaLEFT: + default: + break; + } + + temp_do[count].r=temp_do[count].l+temp_do[count].w-1; + temp_do[count].b=temp_do[count].t+temp_do[count].h-1; + temp_do[count].c=temp_do[count].l+temp_do[count].w/2; + temp_do[count].m=temp_do[count].t+temp_do[count].h/2; + ++count; + } + } + + if(count<3) + { + return; + } + + //sort all objects in order of position, then index (yeah, bubble sort; sue me) + dist_obj tempdo2; + + for(int j=0; jobjects[temp_do[i].index].y+=bd*i/(count-1)-temp_do[i].b+temp_do[0].b; + break; + + case ssodMIDDLE: + tempss->objects[temp_do[i].index].y+=md*i/(count-1)-temp_do[i].m+temp_do[0].m; + break; + + case ssodTOP: + tempss->objects[temp_do[i].index].y+=td*i/(count-1)-temp_do[i].t+temp_do[0].t; + break; + + case ssodRIGHT: + tempss->objects[temp_do[i].index].x+=rd*i/(count-1)-temp_do[i].r+temp_do[0].r; + break; + + case ssodCENTER: + tempss->objects[temp_do[i].index].x+=cd*i/(count-1)-temp_do[i].c+temp_do[0].c; + break; + + case ssodLEFT: + default: + tempss->objects[temp_do[i].index].x+=ld*i/(count-1)-temp_do[i].l+temp_do[0].l; + break; + } + } + +} + +int onBringToFront() +{ + while(curr_subscreen_object0) + { + onSendBackward(); + } + + return D_O_K; +} + +int onReverseArrangement() +{ + int i=0; + int j=MAXSUBSCREENITEMS-1; + subscreen_object tempsso; + + sso_selection[curr_subscreen_object]=true; + + while(true) + { + while(i=0 && !sso_selection[j]) + j--; + + if(i>=j) + { + sso_selection[curr_subscreen_object]=false; + return D_O_K; + } + + if(curr_subscreen_object==i) + curr_subscreen_object=j; + else if(curr_subscreen_object==j) + curr_subscreen_object=i; + + tempsso=css->objects[i]; + css->objects[i]=css->objects[j]; + css->objects[j]=tempsso; + + i++; + j--; + } +} + +int onAlignLeft() +{ + align_objects(css, sso_selection, ssoaLEFT); + return D_O_K; +} + +int onAlignCenter() +{ + align_objects(css, sso_selection, ssoaCENTER); + return D_O_K; +} + +int onAlignRight() +{ + align_objects(css, sso_selection, ssoaRIGHT); + return D_O_K; +} + +int onAlignTop() +{ + align_objects(css, sso_selection, ssoaTOP); + return D_O_K; +} + +int onAlignMiddle() +{ + align_objects(css, sso_selection, ssoaMIDDLE); + return D_O_K; +} + +int onAlignBottom() +{ + align_objects(css, sso_selection, ssoaBOTTOM); + return D_O_K; +} + +int onDistributeLeft() +{ + distribute_objects(css, sso_selection, ssodLEFT); + return D_O_K; +} + +int onDistributeCenter() +{ + distribute_objects(css, sso_selection, ssodCENTER); + return D_O_K; +} + +int onDistributeRight() +{ + distribute_objects(css, sso_selection, ssodRIGHT); + return D_O_K; +} + +int onDistributeTop() +{ + distribute_objects(css, sso_selection, ssodTOP); + return D_O_K; +} + +int onDistributeMiddle() +{ + distribute_objects(css, sso_selection, ssodMIDDLE); + return D_O_K; +} + +int onDistributeBottom() +{ + distribute_objects(css, sso_selection, ssodBOTTOM); + return D_O_K; +} + +int onGridSnapLeft() +{ + grid_snap_objects(css, sso_selection, ssosLEFT); + return D_O_K; +} + +int onGridSnapCenter() +{ + grid_snap_objects(css, sso_selection, ssosCENTER); + return D_O_K; +} + +int onGridSnapRight() +{ + grid_snap_objects(css, sso_selection, ssosRIGHT); + return D_O_K; +} + +int onGridSnapTop() +{ + grid_snap_objects(css, sso_selection, ssosTOP); + return D_O_K; +} + +int onGridSnapMiddle() +{ + grid_snap_objects(css, sso_selection, ssosMIDDLE); + return D_O_K; +} + +int onGridSnapBottom() +{ + grid_snap_objects(css, sso_selection, ssosBOTTOM); + return D_O_K; +} + +int onEditGrid() +{ + grid_dlg[0].dp2=lfont; + char xsize[4]; + char ysize[4]; + char xoffset[4]; + char yoffset[4]; + sprintf(xsize, "%d", zc_max(zinit.ss_grid_x,1)); + sprintf(ysize, "%d", zc_max(zinit.ss_grid_y,1)); + sprintf(xoffset, "%d", zinit.ss_grid_xofs); + sprintf(yoffset, "%d", zinit.ss_grid_yofs); + grid_dlg[4].dp=xsize; + grid_dlg[6].dp=ysize; + grid_dlg[8].dp=xoffset; + grid_dlg[10].dp=yoffset; + grid_dlg[12].d1=zinit.ss_grid_color; + + if(is_large) + large_dialog(grid_dlg); + + int ret = zc_popup_dialog(grid_dlg,2); + + if(ret==1) + { + zinit.ss_grid_x=zc_max(atoi(xsize),1); + zinit.ss_grid_xofs=atoi(xoffset); + zinit.ss_grid_y=zc_max(atoi(ysize),1); + zinit.ss_grid_yofs=atoi(yoffset); + zinit.ss_grid_color=grid_dlg[12].d1; + } + + return D_O_K; +} + +int onShowHideGrid() +{ + bool show=!(zinit.ss_flags&ssflagSHOWGRID); + zinit.ss_flags&=~ssflagSHOWGRID; + zinit.ss_flags|=(show?ssflagSHOWGRID:0); + ss_grid_menu[1].flags=zinit.ss_flags&ssflagSHOWGRID?D_SELECTED:0; + return D_O_K; +} + +int onSelectionOptions() +{ + sel_options_dlg[0].dp2=lfont; + sel_options_dlg[6].d1=zinit.ss_bbox_1_color; + sel_options_dlg[8].d1=zinit.ss_bbox_2_color; + + if(is_large) + large_dialog(sel_options_dlg); + + int ret = zc_popup_dialog(sel_options_dlg,2); + + if(ret==1) + { + zinit.ss_bbox_1_color=sel_options_dlg[6].d1; + zinit.ss_bbox_2_color=sel_options_dlg[8].d1; + } + + return D_O_K; +} + + +void update_up_dn_btns() +{ + if(curr_subscreen_object<1) + { + subscreen_dlg[10].flags|=D_DISABLED; + } + else + { + subscreen_dlg[10].flags&=~D_DISABLED; + } + + if(curr_subscreen_object>=ss_objects(css)-1) + { + subscreen_dlg[9].flags|=D_DISABLED; + } + else + { + subscreen_dlg[9].flags&=~D_DISABLED; + } + + subscreen_dlg[9].flags|=D_DIRTY; + subscreen_dlg[10].flags|=D_DIRTY; +} + +int onSSCtrlPgUp() +{ + return onBringForward(); +} + +int onSSCtrlPgDn() +{ + return onSendBackward(); +} + +int onSendBackward() +{ + subscreen_object tempsso; + bool tempsel; + + if(curr_subscreen_object>0) + { + tempsso=css->objects[curr_subscreen_object]; + tempsel=sso_selection[curr_subscreen_object]; + + css->objects[curr_subscreen_object]=css->objects[curr_subscreen_object-1]; + sso_selection[curr_subscreen_object]=sso_selection[curr_subscreen_object-1]; + + css->objects[curr_subscreen_object-1]=tempsso; + sso_selection[curr_subscreen_object-1]=tempsel; + + --curr_subscreen_object; + update_sso_name(); + } + + update_up_dn_btns(); + return D_O_K; +} + +int onSSPgDn() +{ + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + return onSSCtrlPgDn(); + } + else + { + --curr_subscreen_object; + + if(curr_subscreen_object<0) + { + curr_subscreen_object=ss_objects(css)-1; + } + + update_sso_name(); + update_up_dn_btns(); + } + + return D_O_K; +} + +// Send forward +int onBringForward() +{ + subscreen_object tempsso; + bool tempsel; + + if(curr_subscreen_objectobjects[curr_subscreen_object]; + tempsel=sso_selection[curr_subscreen_object]; + + css->objects[curr_subscreen_object]=css->objects[curr_subscreen_object+1]; + sso_selection[curr_subscreen_object]=sso_selection[curr_subscreen_object+1]; + + css->objects[curr_subscreen_object+1]=tempsso; + sso_selection[curr_subscreen_object+1]=tempsel; + + ++curr_subscreen_object; + update_sso_name(); + } + + update_up_dn_btns(); + return D_O_K; +} + + +int onSSPgUp() +{ + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + return onSSCtrlPgUp(); + } + else + { + if(ss_objects(css)>0) + { + ++curr_subscreen_object; + + if(curr_subscreen_object>=ss_objects(css)) + { + curr_subscreen_object=0; + } + } + + update_sso_name(); + update_up_dn_btns(); + } + + return D_O_K; +} + +int d_ssup_btn_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + return onSSCtrlPgUp(); + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssdn_btn_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + return onSSCtrlPgDn(); + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_sslt_btn_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSPgDn(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + +int d_ssrt_btn_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_CLICK: + { + jwin_button_proc(msg, d, c); + onSSPgUp(); + return D_O_K; + } + break; + } + + return jwin_button_proc(msg, d, c); +} + + + +void edit_subscreen() +{ + game = new gamedata; + game->Clear(); + game->set_time(0); + resetItems(game,&zinit,true); + + //so that these will show up on the subscreen -DD + if(game->get_bombs() == 0) + game->set_bombs(1); + + if(game->get_sbombs() == 0) + game->set_sbombs(1); + + if(game->get_arrows() == 0) + game->set_arrows(1); + + subscreen_dlg[0].dp2=lfont; + load_Sitems(&misc); + curr_subscreen_object=0; + g_ssPropCopySrc=-1; + subscreen_group tempss; + memset(&tempss, 0, sizeof(subscreen_group)); + int i; + + for(i=0; iobjects[i],sizeof(subscreen_object)); + + switch(css->objects[i].type) + { + case ssoTEXT: + case ssoTEXTBOX: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMCLASSTEXT: + tempss.objects[i].dp1 = NULL; + tempss.objects[i].dp1 = new char[strlen((char*)css->objects[i].dp1)+1]; + strcpy((char*)tempss.objects[i].dp1,(char*)css->objects[i].dp1); + break; + + default: + break; + } + } + + tempss.ss_type=css->ss_type; + sprintf(tempss.name, css->name); + + if(ss_objects(css)==0) + { + curr_subscreen_object=-1; + } + + onClearSelection(); + ss_grid_menu[1].flags=zinit.ss_flags&ssflagSHOWGRID?D_SELECTED:0; + + if(css->objects[0].type==ssoNULL) + { + css->objects[0].type=ssoNONE; + } + + subscreen_dlg[4].dp=(void *)css; + subscreen_dlg[5].fg=jwin_pal[jcBOX]; + subscreen_dlg[5].bg=jwin_pal[jcBOX]; + str_oname=(char *)zc_malloc(255); + subscreen_dlg[6].dp=(void *)str_oname; + subscreen_dlg[8].dp=(void *)(css->name); + update_sso_name(); + subscreen_dlg[10].flags|=D_DISABLED; + + if(css->ss_type==sstPASSIVE) + { + subscreen_dlg[21].flags|=D_DISABLED; + subscreen_dlg[22].flags|=D_DISABLED; + subscreen_dlg[23].flags|=D_DISABLED; + subscreen_dlg[24].flags|=D_DISABLED; + } + else + { + subscreen_dlg[21].flags&=~D_DISABLED; + subscreen_dlg[22].flags&=~D_DISABLED; + subscreen_dlg[23].flags&=~D_DISABLED; + subscreen_dlg[24].flags&=~D_DISABLED; + } + + selectBwpn(0, 0); + + if(is_large) + { + bool enlarge = subscreen_dlg[0].d1==0; + + if(enlarge) + { + large_dialog(subscreen_dlg,2); + subscreen_dlg[4].y-=32; + subscreen_dlg[3].y-=31; + subscreen_dlg[3].x+=1; + + if(css->ss_type == sstPASSIVE) + subscreen_dlg[3].h=60*(1+is_large)-(is_large?4:0); + else if(css->ss_type == sstACTIVE) + subscreen_dlg[3].h=172*(1+is_large)-(is_large?4:0); + + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + } + + int ret = zc_popup_dialog(subscreen_dlg,2); + + if(ret==1) + { + saved=false; + zinit.subscreen=ssdtMAX; + } + else + { + reset_subscreen(css); + int j; + + for(j=0; jobjects[j],&tempss.objects[j],sizeof(subscreen_object)); + + switch(tempss.objects[j].type) + { + case ssoTEXT: + case ssoTEXTBOX: + case ssoCURRENTITEMTEXT: + case ssoCURRENTITEMCLASSTEXT: + css->objects[j].dp1 = NULL; + css->objects[j].dp1 = new char[strlen((char*)tempss.objects[j].dp1)+1]; + strcpy((char*)css->objects[j].dp1,(char*)tempss.objects[j].dp1); + break; + + default: + break; + } + } + + css->ss_type=tempss.ss_type; + sprintf(css->name, tempss.name); + reset_subscreen(&tempss); + } + + delete game; + game=NULL; +} + +const char *allsubscrtype_str[30] = +{ + "Original (Top, Triforce)", "Original (Top, Map)", + "New Subscreen (Top, Triforce)", "New Subscreen (Top, Map)", + "Revision 2 (Top, Triforce)", "Revision 2 (Top, Map)", + "BS Zelda Original (Top, Triforce)", "BS Zelda Original (Top, Map)", + "BS Zelda Modified (Top, Triforce)", "BS Zelda Modified (Top, Map)", + "BS Zelda Enhanced (Top, Triforce)", "BS Zelda Enhanced (Top, Map)", + "BS Zelda Complete (Top, Triforce)", "BS Zelda Complete (Top, Map)", + "Zelda 3 (Top)", + "Original (Bottom, Magic)", "Original (Bottom, No Magic)", + "New Subscreen (Bottom, Magic)", "New Subscreen (Bottom, No Magic)", + "Revision 2 (Bottom, Magic)", "Revision 2 (Bottom, No Magic)", + "BS Zelda Original (Bottom, Magic)", "BS Zelda Original (Bottom, No Magic)", + "BS Zelda Modified (Bottom, Magic)", "BS Zelda Modified (Bottom, No Magic)", + "BS Zelda Enhanced (Bottom, Magic)", "BS Zelda Enhanced (Bottom, No Magic)", + "BS Zelda Complete (Bottom, Magic)", "BS Zelda Complete (Bottom, No Magic)", + "Zelda 3 (Bottom)" +}; + +const char *activesubscrtype_str[16] = +{ + "Blank", + "Original (Top, Triforce)", "Original (Top, Map)", + "New Subscreen (Top, Triforce)", "New Subscreen (Top, Map)", + "Revision 2 (Top, Triforce)", "Revision 2 (Top, Map)", + "BS Zelda Original (Top, Triforce)", "BS Zelda Original (Top, Map)", + "BS Zelda Modified (Top, Triforce)", "BS Zelda Modified (Top, Map)", + "BS Zelda Enhanced (Top, Triforce)", "BS Zelda Enhanced (Top, Map)", + "BS Zelda Complete (Top, Triforce)", "BS Zelda Complete (Top, Map)", + "Zelda 3 (Top)" +}; + +const char *activelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 16; + return NULL; + } + + return activesubscrtype_str[index]; +} + +const char *passivesubscrtype_str[16] = +{ + "Blank", + "Original (Bottom, Magic)", "Original (Bottom, No Magic)", + "New Subscreen (Bottom, Magic)", "New Subscreen (Bottom, No Magic)", + "Revision 2 (Bottom, Magic)", "Revision 2 (Bottom, No Magic)", + "BS Zelda Original (Bottom, Magic)", "BS Zelda Original (Bottom, No Magic)", + "BS Zelda Modified (Bottom, Magic)", "BS Zelda Modified (Bottom, No Magic)", + "BS Zelda Enhanced (Bottom, Magic)", "BS Zelda Enhanced (Bottom, No Magic)", + "BS Zelda Complete (Bottom, Magic)", "BS Zelda Complete (Bottom, No Magic)", + "Zelda 3 (Bottom)" +}; + +const char *passivelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = 16; + return NULL; + } + + return passivesubscrtype_str[index]; +} + +const char *activepassive_str[sstMAX] = +{ + "Active", "Passive" +}; + +const char *activepassivelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = sstMAX; + return NULL; + } + + return activepassive_str[index]; +} + +static ListData passive_list(passivelist, &font); +static ListData active_list(activelist, &font); + +int sstype_drop_proc(int msg,DIALOG *d,int c) +{ + int tempd1=d->d1; + int ret=jwin_droplist_proc(msg,d,c); + + if(tempd1!=d->d1) + { + (d+1)->dp=(d->d1)?(void*)&passive_list:(void*)&active_list; + object_message(d+1,MSG_START,0); + (d+1)->flags|=D_DIRTY; + } + + return ret; +} + +static ListData activepassive_list(activepassivelist, &font); + +static DIALOG sstemplatelist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 265, 87, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "New Subscreen", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 4, 28, 8, 8, 0, 0, 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 4, 46, 8, 8, 0, 0, 0, 0, 0, 0, (void *) "Template:", NULL, NULL }, + { sstype_drop_proc, 33, 24, 72, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &activepassive_list, NULL, NULL }, + { jwin_droplist_proc, 50, 42, 211, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &active_list, NULL, NULL }, + { jwin_button_proc, 61, 62, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 142, 62, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +bool show_new_ss=true; + +const char *subscreenlist(int index, int *list_size) +{ + if(index<0) + { + int j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL) + { + ++j; + } + + *list_size = j+(show_new_ss?1:0); + sprintf(custom_subscreen[j].name, ""); + return NULL; + } + + return custom_subscreen[index].name; +} + +const char *subscreenlist_a(int index, int *list_size) +{ + if(index<0) + { + int i=0, j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL) + { + if(custom_subscreen[j].ss_type==sstACTIVE) + { + ++i; + } + + ++j; + } + + *list_size = i; + return NULL; + } + +// return custsubscrtype_str[index]; + int i=-1, j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL&&i!=index) + { + if(custom_subscreen[j].ss_type==sstACTIVE) + { + ++i; + } + + ++j; + } + + return custom_subscreen[j-1].name; +} + +const char *subscreenlist_b(int index, int *list_size) +{ + if(index<0) + { + int i=0, j=0; + + while(custom_subscreen[j].objects[0].type!=ssoNULL) + { + if(custom_subscreen[j].ss_type==sstPASSIVE) + { + ++i; + } + + ++j; + } + + *list_size = i; + return NULL; + } + +// return custsubscrtype_str[index]; + int i=-1, j=0; + + while(custom_subscreen[j].name[0]&&i!=index) + { + if(custom_subscreen[j].ss_type==sstPASSIVE) + { + ++i; + } + + ++j; + } + + return custom_subscreen[j-1].name; +} + +static ListData subscreen_list(subscreenlist, &font); + +DIALOG sslist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 234, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Subscreen", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_abclist_proc, 12, 24, 211, 95, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &subscreen_list, NULL, NULL }, + { jwin_button_proc, 12, 123, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 85, 123, 61, 21, vc(14), vc(1), KEY_DEL, D_EXIT, 0, 0, (void *) "Delete", NULL, NULL }, + { jwin_button_proc, 158, 123, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onEditSubscreens() +{ + int ret=-1; + sslist_dlg[0].dp2=lfont; + sstemplatelist_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(sslist_dlg); + + while(ret!=0&&ret!=5) + { + ret=zc_popup_dialog(sslist_dlg,2); + + if(ret==4) + { + int confirm = jwin_alert("Confirm Delete", "You are about to delete the selected subscreen!", "Are you sure?", NULL, "OK", "Cancel", KEY_ENTER, KEY_ESC, lfont); + + if(confirm==1) + { + delete_subscreen(sslist_dlg[2].d1); + saved=false; + } + } + else if(ret==2 || ret ==3) + { + if(custom_subscreen[sslist_dlg[2].d1].ss_type==sstACTIVE) + { + subscreen_dlg[3].h=172*(1+is_large)-(is_large?4:0); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + else if(custom_subscreen[sslist_dlg[2].d1].ss_type==sstPASSIVE) + { + subscreen_dlg[3].h=60*(1+is_large)-(is_large?4:0); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + //iu;hukl;kh; + } + else + { + subscreen_dlg[3].h=20*(1+is_large); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + + css = &custom_subscreen[sslist_dlg[2].d1]; + bool edit_it=true; + + if(css->objects[0].type==ssoNULL) + { + if(is_large) + large_dialog(sstemplatelist_dlg); + + ret=zc_popup_dialog(sstemplatelist_dlg,4); + + if(ret==6) + { + if(sstemplatelist_dlg[5].d1<15) + { + if(sstemplatelist_dlg[5].d1 != 0) + { + subscreen_object *tempsub; + + if(sstemplatelist_dlg[4].d1==0) + { + tempsub = default_subscreen_active[(sstemplatelist_dlg[5].d1-1)/2][(sstemplatelist_dlg[5].d1-1)&1]; + } + else + { + tempsub = default_subscreen_passive[(sstemplatelist_dlg[5].d1-1)/2][(sstemplatelist_dlg[5].d1-1)&1]; + } + + int i; + + for(i=0; (iobjects[i].dp1 != NULL) delete [](char *)css->objects[i].dp1; + + memcpy(&css->objects[i],&tempsub[i],sizeof(subscreen_object)); + css->objects[i].dp1 = NULL; + css->objects[i].dp1 = new char[strlen((char*)tempsub[i].dp1)+1]; + strcpy((char*)css->objects[i].dp1,(char*)tempsub[i].dp1); + break; + + default: + memcpy(&css->objects[i],&tempsub[i],sizeof(subscreen_object)); + break; + } + } + } + + if(sstemplatelist_dlg[4].d1==0) + { + css->ss_type=sstACTIVE; + sprintf(css->name, activesubscrtype_str[sstemplatelist_dlg[5].d1]); + subscreen_dlg[3].h=172*(1+is_large); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + else + { + css->ss_type=sstPASSIVE; + sprintf(css->name, passivesubscrtype_str[sstemplatelist_dlg[5].d1]); + subscreen_dlg[3].h=60*(1+is_large); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + } + else //Z3 + { + subscreen_object *tempsub; + + if(sstemplatelist_dlg[4].d1==0) + { + tempsub = z3_active_a; + } + else + { + tempsub = z3_passive_a; + } + + int i; + + for(i=0; (iobjects[i].dp1 != NULL) delete [](char *)css->objects[i].dp1; + + memcpy(&css->objects[i],&tempsub[i],sizeof(subscreen_object)); + css->objects[i].dp1 = NULL; + css->objects[i].dp1 = new char[strlen((char*)tempsub[i].dp1)+1]; + strcpy((char*)css->objects[i].dp1,(char*)tempsub[i].dp1); + break; + + default: + memcpy(&css->objects[i],&tempsub[i],sizeof(subscreen_object)); + break; + } + } + + if(sstemplatelist_dlg[4].d1==0) + { + css->ss_type=sstACTIVE; + sprintf(css->name, activesubscrtype_str[sstemplatelist_dlg[5].d1]); + subscreen_dlg[3].h=172*(1+is_large); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + + } + else + { + css->ss_type=sstPASSIVE; + sprintf(css->name, passivesubscrtype_str[sstemplatelist_dlg[5].d1]); + subscreen_dlg[3].h=60*(1+is_large); + subscreen_dlg[4].h=subscreen_dlg[3].h-4; + } + } + } + else + { + edit_it=false; + } + } + + if(edit_it) + { + edit_subscreen(); + } + } + } + + position_mouse_z(0); + return D_O_K; +} + +void update_sso_name() +{ + if(curr_subscreen_object<0) + { + sprintf(str_oname, "No object selected"); + } + else + { + sprintf(str_oname, "%3d: %s", curr_subscreen_object, sso_name(css->objects, curr_subscreen_object)); + } + + subscreen_dlg[5].flags|=D_DIRTY; + subscreen_dlg[6].flags|=D_DIRTY; +} + +void center_zq_subscreen_dialogs() +{ + jwin_center_dialog(grid_dlg); + jwin_center_dialog(sel_options_dlg); + jwin_center_dialog(sslist_dlg); + jwin_center_dialog(ssolist_dlg); + jwin_center_dialog(sso_master_properties_dlg); + jwin_center_dialog(sstemplatelist_dlg); + jwin_center_dialog(subscreen_dlg); +} + +void delete_subscreen(int subscreenidx) +{ + if(custom_subscreen[subscreenidx].objects[0].type == ssoNULL) + return; + + //delete + reset_subscreen(&custom_subscreen[subscreenidx]); + + //and move all other subscreens up + for(int i=subscreenidx+1; i subscreenidx) + DMaps[i].active_subscreen--; + + if(DMaps[i].passive_subscreen > subscreenidx) + DMaps[i].passive_subscreen--; + } +} + +// These were defined in ffscript.h; no need for them here +#undef DELAY +#undef WIDTH +#undef HEIGHT + +#define D1 0x00000001 +#define D2 0x00000002 +#define D3 0x00000004 +#define D4 0x00000008 +#define D5 0x00000010 +#define D6 0x00000020 +#define D7 0x00000040 +#define D8 0x00000080 +#define D9 0x00000100 +#define D10 0x00000200 +#define D1_TO_D10 0x000002FF +#define COLOR1 0x00000400 +#define COLOR2 0x00000800 +#define COLOR3 0x00001000 +#define FRAMES 0x00002000 +#define FRAME 0x00004000 +#define SPEED 0x00008000 +#define DELAY 0x00010000 +#define WIDTH 0x00020000 +#define HEIGHT 0x00040000 + +// This function does the actual copying. Name sucks, but whatever. +// what controls which properties are copied. Type, x, y, and dp1 +// are never copied. The active up/down/scrolling flags from pos +// are always copied, but the rest of it is not. +void doCopySSOProperties(subscreen_object& src, subscreen_object& dest, int what) +{ + dest.pos&=~(sspUP|sspDOWN|sspSCROLLING); + dest.pos|=src.pos&(sspUP|sspDOWN|sspSCROLLING); + + // Actually, I think pos is nothing but those three flags... + + if(what&WIDTH) + dest.w=src.w; + if(what&HEIGHT) + dest.h=src.h; + + if(what&D1) + dest.d1=src.d1; + if(what&D2) + dest.d2=src.d2; + if(what&D3) + dest.d3=src.d3; + if(what&D4) + dest.d4=src.d4; + if(what&D5) + dest.d5=src.d5; + if(what&D6) + dest.d6=src.d6; + if(what&D7) + dest.d7=src.d7; + if(what&D8) + dest.d8=src.d8; + if(what&D9) + dest.d9=src.d9; + if(what&D10) + dest.d10=src.d10; + + if(what&COLOR1) + { + dest.colortype1=src.colortype1; + dest.color1=src.color1; + } + if(what&COLOR2) + { + dest.colortype2=src.colortype2; + dest.color2=src.color2; + } + if(what&COLOR3) + { + dest.colortype3=src.colortype3; + dest.color3=src.color3; + } + + if(what&FRAMES) + dest.frames=src.frames; + if(what&FRAME) + dest.frame=src.frame; + if(what&SPEED) + dest.speed=src.speed; + if(what&DELAY) + dest.delay=src.delay; +} + +// Copies one object's properties to another. Selects properties depending on +// the object type; some things are deliberately skipped, like which heart +// container a life gauge piece corresponds to. +void copySSOProperties(subscreen_object& src, subscreen_object& dest) +{ + if(src.type!=dest.type || &src==&dest) + return; + + switch(src.type) + { + case sso2X2FRAME: + doCopySSOProperties(src, dest, D1|D2|D3|D4|COLOR1); + break; + + case ssoTEXT: + doCopySSOProperties(src, dest, D1|D2|D3|COLOR1|COLOR2|COLOR3); + break; + + case ssoLINE: + doCopySSOProperties(src, dest, D1|D2|COLOR1|WIDTH|HEIGHT); + break; + + case ssoRECT: + doCopySSOProperties(src, dest, D1|D2|COLOR1|COLOR2|WIDTH|HEIGHT); + break; + + case ssoBSTIME: + case ssoTIME: + case ssoSSTIME: + doCopySSOProperties(src, dest, D1|D2|D3|COLOR1|COLOR2|COLOR3); + break; + + case ssoMAGICMETER: // Full meter + // No properties but pos + doCopySSOProperties(src, dest, 0); + break; + + case ssoLIFEMETER: + doCopySSOProperties(src, dest, D2|D3); + break; + + case ssoBUTTONITEM: + doCopySSOProperties(src, dest, D2); + break; + + case ssoCOUNTER: // Single counter + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|D6|COLOR1|COLOR2|COLOR3); + break; + + case ssoCOUNTERS: // Counter block + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|COLOR1|COLOR2|COLOR3); + break; + + case ssoMINIMAPTITLE: + doCopySSOProperties(src, dest, D1|D2|D3|D4|COLOR1|COLOR2|COLOR3); + break; + + case ssoMINIMAP: + doCopySSOProperties(src, dest, D1|D2|D3|COLOR1|COLOR2|COLOR3); + break; + + case ssoLARGEMAP: + doCopySSOProperties(src, dest, D1|D2|D3|D10|COLOR1|COLOR2); + break; + + case ssoCLEAR: + doCopySSOProperties(src, dest, COLOR1); + break; + + case ssoCURRENTITEM: + // Only the invisible flag + doCopySSOProperties(src, dest, D2); + break; + + case ssoTRIFRAME: + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|D6|D7|COLOR1|COLOR2); + break; + + case ssoTRIFORCE: // Single piece + doCopySSOProperties(src, dest, D1|D2|D3|D4|COLOR1); + break; + + case ssoTILEBLOCK: + doCopySSOProperties(src, dest, D1|D2|D3|D4|COLOR1|WIDTH|HEIGHT); + break; + + case ssoMINITILE: + // Does this one work at all? + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|D6|COLOR1|WIDTH|HEIGHT); + break; + + case ssoSELECTOR1: + case ssoSELECTOR2: + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|COLOR1); + break; + + case ssoMAGICGAUGE: // Single piece + // Skip magic container (d1) + doCopySSOProperties(src, dest, (D1_TO_D10&~D1)|COLOR1|COLOR2|WIDTH|HEIGHT); + break; + + case ssoLIFEGAUGE: // Single piece + // Skip heart container (d1) + doCopySSOProperties(src, dest, (D1_TO_D10&~D1)|COLOR1|COLOR2|WIDTH|HEIGHT); + break; + + case ssoTEXTBOX: + case ssoSELECTEDITEMNAME: + doCopySSOProperties(src, dest, D1|D2|D3|D4|D5|COLOR1|COLOR2|COLOR3|WIDTH|HEIGHT); + break; + } +} + +/*** end of subscr.cc ***/ + diff --git a/src/zq_subscr.h b/src/zq_subscr.h new file mode 100644 index 0000000000..3ffd8d473c --- /dev/null +++ b/src/zq_subscr.h @@ -0,0 +1,37 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// subscr.cc +// +// Subscreen code for zelda.cc +// +//-------------------------------------------------------- + +#ifndef _ZQ_SUBSCR_H_ +#define _ZQ_SUBSCR_H_ + +//subscreen object alignment +enum { ssoaLEFT, ssoaCENTER, ssoaRIGHT, ssoaTOP, ssoaMIDDLE, ssoaBOTTOM }; + +//subscreen object distribution +enum { ssodLEFT, ssodCENTER, ssodRIGHT, ssodTOP, ssodMIDDLE, ssodBOTTOM }; + +//subscreen object snapping +enum { ssosLEFT, ssosCENTER, ssosRIGHT, ssosTOP, ssosMIDDLE, ssosBOTTOM }; + +void edit_subscreen(); +int onEditSubscreens(); + +char *sso_name(int type); +char *sso_name(subscreen_object *tempss, int id); +void center_zq_subscreen_dialogs(); +void update_sso_name(); +void update_up_dn_btns(); +extern bool show_new_ss; +extern DIALOG sslist_dlg[]; + +#endif + +/*** end of subscr.cc ***/ + diff --git a/src/zq_tiles.cpp b/src/zq_tiles.cpp new file mode 100644 index 0000000000..d6851ec38e --- /dev/null +++ b/src/zq_tiles.cpp @@ -0,0 +1,11624 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_tiles.cc +// +// Tile editor stuff, etc., for ZQuest. +// +//-------------------------------------------------------- +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +#ifndef __GTHREAD_HIDE_WIN32API +#define __GTHREAD_HIDE_WIN32API 1 +#endif //prevent indirectly including windows.h + +#include "precompiled.h" //always first + +#include +#include + +#include "gui.h" +#include "zquestdat.h" +#include "zq_tiles.h" +#include "zquest.h" +#include "tiles.h" +#include "zq_misc.h" +#include "zq_class.h" +#include "zsys.h" +#include "colors.h" +#include "qst.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "zqscale.h" +#include "zc_custom.h" +#include "questReport.h" +#include "mem_debug.h" + +#include "dialog/zquest/tileSelector.h" +#include "gui/manager.h" + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +extern GUI::GUIManager* gui; + +extern void large_dialog(DIALOG *d); + +int ex=0; +int nextcombo_fake_click=0; +int invcol=0; + +tiledata *newundotilebuf; +newcombo *undocombobuf; + +BITMAP *selection_pattern; +byte selection_grid[18][18]; +byte selection_anchor=0; + +enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude}; +BITMAP *selecting_pattern; +int selecting_x1, selecting_x2, selecting_y1, selecting_y2; + +word combobufFoo[MAXCOMBOS] = {}; //No idea what this actually does... + + +BITMAP *intersection_pattern; + +byte relational_template[48][4]= +{ + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 1, 1, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 1 }, + { 0, 1, 0, 1 }, + { 1, 0, 0, 1 }, + { 1, 1, 0, 1 }, + { 0, 0, 1, 1 }, + { 0, 1, 1, 1 }, + { 1, 0, 1, 1 }, + { 1, 1, 1, 1 }, + { 0, 2, 0, 2 }, + { 1, 2, 0, 2 }, + { 0, 2, 1, 2 }, + { 1, 2, 1, 2 }, + { 3, 3, 0, 0 }, + { 3, 3, 1, 0 }, + { 3, 3, 0, 1 }, + { 3, 3, 1, 1 }, + { 3, 4, 0, 2 }, + { 3, 4, 1, 2 }, + { 2, 0, 2, 0 }, + { 2, 1, 2, 0 }, + { 2, 0, 2, 1 }, + { 2, 1, 2, 1 }, + { 2, 2, 2, 2 }, + { 4, 3, 2, 0 }, + { 4, 3, 2, 1 }, + { 4, 4, 2, 2 }, + { 0, 0, 3, 3 }, + { 0, 1, 3, 3 }, + { 1, 0, 3, 3 }, + { 1, 1, 3, 3 }, + { 0, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 3, 3, 3, 3 }, + { 3, 4, 3, 4 }, + { 2, 0, 4, 3 }, + { 2, 1, 4, 3 }, + { 2, 2, 4, 4 }, + { 4, 3, 4, 3 }, + { 4, 4, 4, 4 }, + { 5, 5, 5, 5 } +}; + +byte dungeon_carving_template[96][4]= +{ + { 0, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 1, 1, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 }, + { 0, 0, 0, 1 }, + { 0, 1, 0, 1 }, + { 1, 0, 0, 1 }, + { 1, 1, 0, 1 }, + { 0, 0, 1, 1 }, + { 0, 1, 1, 1 }, + { 1, 0, 1, 1 }, + { 1, 1, 1, 1 }, + { 0, 2, 0, 2 }, + { 1, 2, 0, 2 }, + { 0, 2, 1, 2 }, + { 1, 2, 1, 2 }, + { 3, 3, 0, 0 }, + { 3, 3, 1, 0 }, + { 3, 3, 0, 1 }, + { 3, 3, 1, 1 }, + { 3, 4, 0, 2 }, + { 3, 4, 1, 2 }, + { 2, 0, 2, 0 }, + { 2, 1, 2, 0 }, + { 2, 0, 2, 1 }, + { 2, 1, 2, 1 }, + { 2, 2, 2, 2 }, + { 4, 3, 2, 0 }, + { 4, 3, 2, 1 }, + { 4, 4, 2, 2 }, + { 0, 0, 3, 3 }, + { 0, 1, 3, 3 }, + { 1, 0, 3, 3 }, + { 1, 1, 3, 3 }, + { 0, 2, 3, 4 }, + { 1, 2, 3, 4 }, + { 3, 3, 3, 3 }, + { 3, 4, 3, 4 }, + { 2, 0, 4, 3 }, + { 2, 1, 4, 3 }, + { 2, 2, 4, 4 }, + { 4, 3, 4, 3 }, + { 4, 4, 4, 4 }, + { 5, 5, 5, 5 }, + + { 5, 5, 5, 5 }, + { 6, 6, 6, 6 }, + { 7, 7, 7, 7 }, + { 7, 6, 7, 6 }, + { 8, 8, 8, 8 }, + { 16, 6, 8, 15 }, + { 7, 7, 8, 8 }, + { 7, 6, 8, 15 }, + { 9, 9, 9, 9 }, + { 6, 6, 9, 9 }, + { 7, 17, 14, 9 }, + { 7, 6, 14, 9 }, + { 8, 9, 8, 9 }, + { 16, 6, 8, 9 }, + { 7, 17, 8, 9 }, + { 7, 6, 8, 9 }, + { 10, 10, 10, 10 }, + { 7, 10, 14, 10 }, + { 16, 10, 8, 10 }, + { 7, 10, 8, 10 }, + { 11, 11, 11, 11 }, + { 11, 11, 8, 15 }, + { 11, 11, 14, 9 }, + { 11, 11, 8, 9 }, + { 14, 14, 14, 14 }, + { 14, 14, 8, 14 }, + { 12, 12, 12, 12 }, + { 12, 6, 12, 15 }, + { 12, 17, 12, 9 }, + { 12, 6, 12, 9 }, + { 12, 10, 12, 10 }, + { 15, 15, 15, 15 }, + { 15, 15, 15, 9 }, + { 15, 14, 12, 10 }, + { 13, 13, 13, 13 }, + { 16, 6, 13, 13 }, + { 7, 17, 13, 13 }, + { 7, 6, 13, 13 }, + { 16, 16, 16, 16 }, + { 7, 16, 16, 16 }, + { 11, 11, 13, 13 }, + { 11, 14, 13, 16 }, + { 17, 17, 17, 17 }, + { 17, 6, 17, 17 }, + { 12, 10, 17, 16 }, + { 15, 11, 17, 13 }, + { 15, 14, 17, 16 }, + { 18, 18, 18, 18 } +}; + +/*********************************/ +/***** Tiles & Combos ******/ +/*********************************/ + +void merge_tiles(int dest_tile, int src_quarter1, int src_quarter2, int src_quarter3, int src_quarter4) +{ + int size=tilesize(newtilebuf[dest_tile].format)>>4; + int size2=size>>1; + + if(newtilebuf[dest_tile].data==NULL) + { + reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format); + } + + int i=0; + + if((dest_tile<<2)+i!=src_quarter1) + { + for(int j=0; j<8; ++j) + { + memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2); + } + } + + i=1; + + if((dest_tile<<2)+i!=src_quarter2) + { + for(int j=0; j<8; ++j) + { + memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2); + } + } + + i=2; + + if((dest_tile<<2)+i!=src_quarter3) + { + for(int j=0; j<8; ++j) + { + memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2); + } + } + + i=3; + + if((dest_tile<<2)+i!=src_quarter4) + { + for(int j=0; j<8; ++j) + { + memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2); + } + } +} + +int d_combo_proc(int msg,DIALOG *d,int c); + +void go_tiles() +{ + for(dword i=0; i>3, 0); + + for(int i=1; i<18; ++i) + { + for(int j=1; j<18; ++j) + { + // zoomtile16(screen2,tile,79,31,cs,flip,8); + if(selection_grid[i-1][j]!=selection_grid[i][j]) + { + _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255); + } + + if(selection_grid[i][j-1]!=selection_grid[i][j]) + { + _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255); + } + } + } + + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + // selection_anchor=(selection_anchor+1)%64; +} + +bool is_selecting() +{ + return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1); +} + +void draw_selecting_outline(BITMAP *dest, int x, int y, int scale2) +{ + int x1=zc_min(selecting_x1,selecting_x2); + int x2=zc_max(selecting_x1,selecting_x2); + int y1=zc_min(selecting_y1,selecting_y2); + int y2=zc_max(selecting_y1,selecting_y2); + +// rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255); + for(int i=1; i<18; ++i) + { + for(int j=1; j<18; ++j) + { + drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0); + + if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2))) + { + if(selection_grid[i-1][j]!=selection_grid[i][j]) + { + drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0); + } + + _allegro_vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255); + } + + if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2))) + { + if(selection_grid[i][j-1]!=selection_grid[i][j]) + { + drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0); + } + + _allegro_hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255); + } + } + } + + drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0); + // selection_anchor=(selection_anchor+1)%64; +} + +void add_color_to_selection(int color) +{ + for(int i=1; i<17; ++i) + { + for(int j=1; j<17; ++j) + { + if(unpackbuf[((j-1)<<4)+(i-1)]==color) + { + selection_grid[i][j]=1; + } + } + } +} + +void remove_color_from_selection(int color) +{ + for(int i=1; i<17; ++i) + { + for(int j=1; j<17; ++j) + { + if(unpackbuf[((j-1)<<4)+(i-1)]==color) + { + selection_grid[i][j]=0; + } + } + } +} + +void intersect_color_with_selection(int color) +{ + for(int i=1; i<17; ++i) + { + for(int j=1; j<17; ++j) + { + if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1)) + { + selection_grid[i][j]=1; + } + else + { + selection_grid[i][j]=0; + } + } + } +} + +bool is_in_selection(int x, int y) +{ + return (!has_selection()||(selection_grid[x+1][y+1]!=0)); +} + +void zoomtile16(BITMAP *dest,int tile,int x,int y,int cset,int flip,int m) +{ + // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]); + rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?vc(7):vc(8)); + cset <<= 4; + + if(newtilebuf[tile].format>tf4Bit) + { + cset=0; + } + + unpack_tile(newtilebuf, tile, 0, false); + byte *si = unpackbuf; + + for(int cy=0; cy<16; cy++) + { + for(int cx=0; cx<16; cx++) + { + int dx = ((flip&1)?15-cx:cx)*m; + int dy = ((flip&2)?15-cy:cy)*m; + rectfill(dest,x+dx+1,y+dy+1,x+dx+m-1,y+dy+m-1,*si+cset); + + if(*si==0) + { + little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2); + } + + ++si; + } + } + + if(has_selection()||is_selecting()) + { + selection_anchor=(selection_anchor+1)%64; + + if(has_selection()||is_selecting()) + { + draw_selection_outline(dest, x, y, m); + } + + if(is_selecting()) + { + draw_selecting_outline(dest, x, y, m); + } + } +} + +void draw_text_button(BITMAP *dest,int x,int y,int w,int h,const char *text,int bg,int fg,int flags,bool jwin) +{ + if(!jwin) + { + if(flags&D_SELECTED) + { + zc_swap(fg,bg); + } + + rect(dest,x+1,y+1,x+w-1,y+h-1,fg); + rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg); + rect(dest,x,y,x+w-2,y+h-2,fg); + textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1); + } + else + { + jwin_draw_text_button(dest, x, y, w, h, text, flags, true); + } +} + +bool do_text_button(int x,int y,int w,int h,const char *text,int bg,int fg,bool jwin) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_text_button(screen,x,y,w,h,text,fg,bg,D_SELECTED,jwin); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_text_button(screen,x,y,w,h,text,fg,bg,0,jwin); + unscare_mouse(); + over=false; + } + } + } + + return over; +} + +bool do_text_button_reset(int x,int y,int w,int h,const char *text,int bg,int fg,bool jwin) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_text_button(screen,x,y,w,h,text,fg,bg,D_SELECTED,jwin); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_text_button(screen,x,y,w,h,text,fg,bg,0,jwin); + unscare_mouse(); + over=false; + } + } + } + + if(over) + { + custom_vsync(); + scare_mouse(); + draw_text_button(screen,x,y,w,h,text,fg,bg,0,jwin); + unscare_mouse(); + } + + return over; +} + +void draw_graphics_button(BITMAP *dest,int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,int flags,bool jwin,bool overlay) +{ + if(!jwin) + { + if(flags&D_SELECTED) + { + zc_swap(fg,bg); + } + + rect(dest,x+1,y+1,x+w-1,y+h-1,fg); + rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg); + rect(dest,x,y,x+w-2,y+h-2,fg); + int g = (flags & D_SELECTED) ? 1 : 0; + + if(overlay) + { + masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w); + } + else + { + blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w); + } + } + else + { + jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay); + } +} + +bool do_graphics_button(int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,bool jwin,bool overlay) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay); + unscare_mouse(); + over=false; + } + } + } + + return over; +} + +bool do_graphics_button_reset(int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,bool jwin,bool overlay) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1)) + { + if(!over) + { + scare_mouse(); + draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay); + unscare_mouse(); + over=false; + } + } + } + + if(over) + { + custom_vsync(); + scare_mouse(); + draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay); + unscare_mouse(); + } + + return over; +} +// circle(BITMAP *bmp, int x, int y, int radius, int color); +// circlefill(BITMAP *bmp, int x, int y, int radius, int color); + +void draw_layerradio(BITMAP *dest,int x,int y,int bg,int fg, int value) +{ + //these are here to bypass compiler warnings about unused arguments + bg=bg; + fg=fg; + + int r, center; + + for(int k=0; k<7; k++) + { + if((k==0)||(Map.CurrScr()->layermap[k-1])) + { + // circle(dest, x+(k*25)+4, y+4, 4, fg); + // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg); + //* + r = 9/2; + + center = x+(k*25)+r; + rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]); + + circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]); + arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]); + circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]); + arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]); + circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]); + + if(value==k) + { + circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]); + } + + //*/ + } + } +} + +void do_layerradio(BITMAP *dest,int x,int y,int bg,int fg,int &value) +{ + while(gui_mouse_b()) + { + custom_vsync(); + + for(int k=0; k<7; k++) + { + if((k==0)||(Map.CurrScr()->layermap[k-1])) + { + //if on radio button + if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8)) + { + value=k; + scare_mouse(); + draw_layerradio(dest,x,y,bg,fg,value); + refresh(rMENU); + unscare_mouse(); + } + } + } + } +} + +void draw_checkbox(BITMAP *dest,int x,int y,int bg,int fg, bool value) +{ + //these are here to bypass compiler warnings about unused arguments + bg=bg; + fg=fg; + + // rect(dest,x, y, x+8, y+8, fg); + // line(dest,x+1,y+1,x+7,y+7,value?fg:bg); + // line(dest,x+1,y+7,x+7,y+1,value?fg:bg); + + jwin_draw_frame(dest, x, y, 9, 9, FR_DEEP); + rectfill(dest, x+2, y+2, x+9-3, y+9-3, jwin_pal[jcLIGHT]); + + if(value) + { + line(dest, x+2, y+2, x+9-3, y+9-3, jwin_pal[jcDARK]); + line(dest, x+2, y+9-3, x+9-3, y+2, jwin_pal[jcDARK]); + } + +} + + + +bool do_checkbox(BITMAP *dest,int x,int y,int bg,int fg,int &value) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+8,y+8)) //if on checkbox + { + if(!over) //if wasn't here before + { + scare_mouse(); + value=!value; + draw_checkbox(dest,x,y,bg,fg,value!=0); + refresh(rMENU); + unscare_mouse(); + over=true; + } + } + else //if not on checkbox + { + if(over) //if was here before + { + scare_mouse(); + value=!value; + draw_checkbox(dest,x,y,bg,fg,value!=0); + refresh(rMENU); + unscare_mouse(); + over=false; + } + } + } + + return over; +} + +//*************** tile flood fill stuff ************** + +byte tf_c; +byte tf_u; + +void tile_floodfill_rec(int x,int y) +{ + if(is_in_selection(x,y)) + { + while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u)) + --x; + + while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u)) + { + if(is_in_selection(x,y)) + { + unpackbuf[(y<<4)+x] = tf_c; + } + + if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u)) + tile_floodfill_rec(x,y-1); + + if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u)) + tile_floodfill_rec(x,y+1); + + ++x; + } + } +} + +void tile_floodfill(int tile,int x,int y,byte c) +{ + if(is_in_selection(x,y)) + { + unpack_tile(newtilebuf, tile, 0, false); + tf_c = c; + tf_u = unpackbuf[(y<<4)+x]; + + if(tf_u != tf_c) + tile_floodfill_rec(x,y); + + pack_tile(newtilebuf,unpackbuf,tile); + } +} + +//***************** tile editor stuff ***************** +int ok_button_x=224; +int ok_button_y=168; +int cancel_button_x=224; +int cancel_button_y=192; +int edit_button_x=24; +int edit_button_y=184; +//int palette_x=104; +//int palette_y=176; +int palette_x=94; +int palette_y=172; +int palette_scale=4; +//int fgbg_btn_x=144; +int fgbg_btn_x=168; +int fgbg_btn_y=172+14; +int fgbg_btn_w=42; +int fgbg_btn_h=39; +int fgbg_btn_size=25; +int fgbg_btn_offset=15; +int mouse_lb_x=5; +int mouse_lb_y=7; +int mouse_rb_x=15; +int mouse_rb_y=4; +int zoom_tile_x=80; +int zoom_tile_y=32; +int zoom_tile_scale=8; +int zoom_tile_size=1; +int preview_tiles_x=224; +int preview_tiles_y=48; +int preview_tiles_scale=1; +int status_info_x=224; +int status_info_y=112; + +int c1=1; +int c2=0; +//int bgc=dvc(4+5); +//int bgc=vc(1); +//enum { t_pen, t_fill, t_recolor, t_eyedropper, t_move, t_select, t_wand, t_max }; +int tool = t_pen; +int old_tool = -1; +int tool_cur = -1; +int select_mode = 0; +int drawing=0; + +int tool_buttons_left=22, tool_buttons_top=29, tool_buttons_columns=2; + +void update_tool_cursor() +{ +// int screen_xofs=(zq_screen_w-320)>>1; +// int screen_yofs=(zq_screen_h-240)>>1; +// int temp_mouse_x=gui_mouse_x()-screen_xofs; +// int temp_mouse_y=gui_mouse_y()-screen_yofs; + int temp_mouse_x=gui_mouse_x(); + int temp_mouse_y=gui_mouse_y(); + + int type=0; + + if(has_selection()) + { + switch(tool) + { + case t_select: + case t_wand: + type+=select_mode; + break; + } + } + +// if(isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) //inside the zoomed tile window + if(isinRect(temp_mouse_x,temp_mouse_y,zoom_tile_x,zoom_tile_y-(tool==t_fill ? (is_large ? 14 : 7) : 0),zoom_tile_x+(16*zoom_tile_scale/zoom_tile_size)-2,zoom_tile_y+(16*zoom_tile_scale/zoom_tile_size)-2-(tool==t_fill ? (is_large ? 14 : 7) : 0))) //inside the zoomed tile window + { + if(tool_cur==-1) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_SWORD+tool][type]); + + switch(tool) + { + case t_fill: + set_mouse_sprite_focus(1, 14); + break; + + case t_move: + set_mouse_sprite_focus(8, 8); + break; + + default: + set_mouse_sprite_focus(1, 1); + break; + } + } + + tool_cur=tool; + } + else if(tool_cur != -1) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + tool_cur = -1; + } +} + +void draw_edit_scr(int tile,int flip,int cs,byte *oldtile, bool create_tbar) +{ + if(is_large) + { + ok_button_x=268; + ok_button_y=562; + cancel_button_x=332; + cancel_button_y=562; + edit_button_x=637; + edit_button_y=562; + palette_x=604; + palette_y=416; + palette_scale=8; + fgbg_btn_x=626+2; + fgbg_btn_y=316; + fgbg_btn_w=83; + fgbg_btn_h=80; + fgbg_btn_size=50; + fgbg_btn_offset=30; + mouse_lb_x=11; + mouse_lb_y=19; + mouse_rb_x=34; + mouse_rb_y=12; + zoom_tile_x=80; + zoom_tile_y=32; + zoom_tile_scale=32; + zoom_tile_size=1; + preview_tiles_x=604; + preview_tiles_y=31; + preview_tiles_scale=4; + status_info_x=604; + status_info_y=268; + } + + PALETTE tpal; + static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18); + static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64); +// int screen_xofs=(zq_screen_w-320)>>1; +// int screen_yofs=(zq_screen_h-240)>>1; + jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN); + + /* + FONT *oldfont = font; + if (!create_tbar) + { + blit(tbar, screen2, 0, 0, 3, 3, 320-6, 18); + } + else + { + font = lfont; + char buf[80]; + sprintf(buf,"Tile Editor (%d)", tile); + jwin_draw_titlebar(tbar, 0, 0, 320-6, 18, buf, true); + font = oldfont; + blit(tbar, screen2, 0, 0, 3, 3, 320-6, 18); + } + */ + if(!create_tbar) + { + blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18); + } + else + { + jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true); + blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18); + } + + textprintf_ex(screen2,lfont,5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile); + //draw_x_button(screen2, 320 - 21, 5, 0); + + clear_to_color(preview_bmp, 0); + zc_swap(oldtile,newtilebuf[tile].data); +// jwin_draw_win(screen2, 222, 46, 20, 20, FR_DEEP); +// puttile16(screen2,tile,224,48,cs,flip); +// jwin_draw_win(screen2, 246, 46, 20, 20, FR_DEEP); +// overtile16(screen2,tile,248,48,cs,flip); + jwin_draw_win(screen2, preview_tiles_x-2,preview_tiles_y-2, (16*preview_tiles_scale)+4, (16*preview_tiles_scale)+4, FR_DEEP); +// puttile16(screen2,tile,preview_tiles_x,preview_tiles_y,cs,flip); + puttile16(preview_bmp,tile,0,0,cs,flip); + stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, preview_tiles_x, preview_tiles_y, 16*preview_tiles_scale, 16*preview_tiles_scale); + + clear_to_color(preview_bmp, 0); + jwin_draw_win(screen2, preview_tiles_x+(16*preview_tiles_scale)+8-2,preview_tiles_y-2, (16*preview_tiles_scale)+4, (16*preview_tiles_scale)+4, FR_DEEP); +// overtile16(screen2,tile,preview_tiles_x+(16*preview_tiles_scale)+8,preview_tiles_y,cs,flip); + overtile16(preview_bmp,tile,0,0,cs,flip); + masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, preview_tiles_x+(16*preview_tiles_scale)+8, preview_tiles_y, 16*preview_tiles_scale, 16*preview_tiles_scale); + zc_swap(oldtile,newtilebuf[tile].data); + +// jwin_draw_win(screen2, 222, 78, 20, 20, FR_DEEP); +// puttile16(screen2,tile,224,80,cs,flip); +// jwin_draw_win(screen2, 246, 78, 20, 20, FR_DEEP); +// overtile16(screen2,tile,248,80,cs,flip); + clear_to_color(preview_bmp, 0); +// jwin_draw_win(screen2, preview_tiles_x-2,preview_tiles_y+24-2, 20, 20, FR_DEEP); + jwin_draw_win(screen2, preview_tiles_x-2, preview_tiles_y+(16*preview_tiles_scale)+8-2, (16*preview_tiles_scale)+4, (16*preview_tiles_scale)+4, FR_DEEP); +// puttile16(screen2,tile,preview_tiles_x,preview_tiles_y+24,cs,flip); + puttile16(preview_bmp,tile,0,0,cs,flip); + stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, preview_tiles_x, preview_tiles_y+(16*preview_tiles_scale)+8, 16*preview_tiles_scale, 16*preview_tiles_scale); + + clear_to_color(preview_bmp, 0); +// jwin_draw_win(screen2, preview_tiles_x+24-2,preview_tiles_y+24-2, 20, 20, FR_DEEP); + jwin_draw_win(screen2, preview_tiles_x+(16*preview_tiles_scale)+8-2, preview_tiles_y+(16*preview_tiles_scale)+8-2, (16*preview_tiles_scale)+4, (16*preview_tiles_scale)+4, FR_DEEP); +// overtile16(screen2,tile,preview_tiles_x+24,preview_tiles_y+24,cs,flip); + overtile16(preview_bmp,tile,0,0,cs,flip); + masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, preview_tiles_x+(16*preview_tiles_scale)+8, preview_tiles_y+(16*preview_tiles_scale)+8, 16*preview_tiles_scale, 16*preview_tiles_scale); + + jwin_draw_win(screen2, zoom_tile_x-3, zoom_tile_y-3, (16*zoom_tile_scale)+5, (16*zoom_tile_scale)+5, FR_DEEP); +// zoomtile16(screen2,tile,79,31,cs,flip,zoom_scale); + zoomtile16(screen2,tile,zoom_tile_x-1,zoom_tile_y-1,cs,flip,zoom_tile_scale); + +// textprintf_ex(screen2,font,224,112,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile); +// textprintf_ex(screen2,font,224,120,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs); + textprintf_ex(screen2,font,status_info_x,status_info_y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile); + if(newtilebuf[tile].format==tf8Bit) + textprintf_ex(screen2,font,status_info_x,status_info_y+8,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit"); + else + textprintf_ex(screen2,font,status_info_x,status_info_y+8,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs); + + PALETTE temppal; + + //palette and mouse + switch(newtilebuf[tile].format) + { + case tf4Bit: + jwin_draw_win(screen2, palette_x-2, palette_y-2, (palette_scale*16)+4, (palette_scale*16)+4, FR_DEEP); + get_palette(temppal); + + for(int i=0; i<16; i++) + { + int x=((i&3)*palette_scale*4)+palette_x; + int y=((i>>2)*palette_scale*4)+palette_y; + int c=CSET(cs)+i; + rectfill(screen2,x,y,x+(palette_scale*4)-1,y+(palette_scale*4)-1,c); + } + + little_x(screen2,palette_x+palette_scale,palette_y+palette_scale,invcol,(palette_scale*2)-1); + break; + + case tf8Bit: + jwin_draw_win(screen2, palette_x-2, palette_y-2+palette_scale, (palette_scale*16)+4, (palette_scale*15)+4, FR_DEEP); + + for(int i=0; i<240; i++) + { + int x=((i&15)*palette_scale)+palette_x; + int y=(((i>>4)+1)*palette_scale)+palette_y; + rectfill(screen2,x,y,x+palette_scale-1,y+palette_scale-1,i); + } + +// little_x(screen2,94,172,210,2); + little_x(screen2,palette_x+1,palette_y+palette_scale+1,invcol,(palette_scale/2)-1); + break; + } + + rect(screen2, fgbg_btn_x+fgbg_btn_offset, fgbg_btn_y+fgbg_btn_offset, fgbg_btn_x+fgbg_btn_offset+fgbg_btn_size-1, fgbg_btn_y+fgbg_btn_offset+fgbg_btn_size-1, jwin_pal[jcTEXTFG]); + rectfill(screen2, fgbg_btn_x+fgbg_btn_offset+1, fgbg_btn_y+fgbg_btn_offset+1, fgbg_btn_x+fgbg_btn_offset+fgbg_btn_size-2, fgbg_btn_y+fgbg_btn_offset+fgbg_btn_size-2, jwin_pal[jcTEXTBG]); + rectfill(screen2, fgbg_btn_x+fgbg_btn_offset+1+2, fgbg_btn_y+fgbg_btn_offset+1+2, fgbg_btn_x+fgbg_btn_offset+fgbg_btn_size-2-2, fgbg_btn_y+fgbg_btn_offset+fgbg_btn_size-2-2, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0)); + + if(c2==0) + { + little_x(screen2, fgbg_btn_x+fgbg_btn_offset+fgbg_btn_size/4, fgbg_btn_y+fgbg_btn_offset+fgbg_btn_size/4, invcol, fgbg_btn_size/2); + } + + rect(screen2, fgbg_btn_x, fgbg_btn_y, fgbg_btn_x+fgbg_btn_size-1, fgbg_btn_y+fgbg_btn_size-1, jwin_pal[jcTEXTFG]); + rectfill(screen2, fgbg_btn_x+1, fgbg_btn_y+1, fgbg_btn_x+fgbg_btn_size-2, fgbg_btn_y+fgbg_btn_size-2, jwin_pal[jcTEXTBG]); + rectfill(screen2, fgbg_btn_x+1+2, fgbg_btn_y+1+2, fgbg_btn_x+fgbg_btn_size-2-2, fgbg_btn_y+fgbg_btn_size-2-2, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0)); + + if(c1==0) + { + little_x(screen2, fgbg_btn_x+fgbg_btn_size/4, fgbg_btn_y+fgbg_btn_size/4, invcol, fgbg_btn_size/2); + } + +// masked_blit((BITMAP *)zcdata[is_large?BMP_MOUSELARGE:BMP_MOUSESMALL].dat, screen2, 0, 0, mouse_pic_x, mouse_pic_y, mouse_pic_w, mouse_pic_h); +// little_x(screen2,mouse_pic_x+mouse_lb_x,mouse_pic_y+mouse_lb_y,c1==0?210:208,2); +// little_x(screen2,mouse_pic_x+mouse_rb_x,mouse_pic_y+mouse_rb_y,c2==0?210:209,2); + + //masked_blit((BITMAP *)zcdata[BMP_MOUSESMALL].dat, screen2, 0, 0, 144, 172, 42, 39); + //little_x(screen2,149,179,c1==0?210:208,2); + //little_x(screen2,159,176,c2==0?210:209,2); + + draw_text_button(screen2,ok_button_x,ok_button_y,61,21,"OK",vc(1),vc(14),0,true); + draw_text_button(screen2,cancel_button_x,cancel_button_y,61,21,"Cancel",vc(1),vc(14),0,true); + draw_text_button(screen2,edit_button_x,edit_button_y,61,21,"Edit",vc(1),vc(14),0,true); + + //tool buttons + for(int i=MOUSE_BMP_SWORD; i=0&&temp_x<=(16*zoom_tile_size)-1)&&(temp_y>=0&&temp_y<=(16*zoom_tile_size)-1)) + { + textprintf_ex(screen2,font,status_info_x,status_info_y+24,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"x: %d",temp_x); + textprintf_ex(screen2,font,status_info_x+40,status_info_y+24,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y); + unpack_tile(newtilebuf, tile, 0, false); + byte *si = unpackbuf; + si+=(temp_y*16+temp_x); + get_palette(tpal); + + if(newtilebuf[tile].format<=tf4Bit) + { + textprintf_ex(screen2,font,status_info_x,status_info_y+32,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%02d %02d %02d (%d)",tpal[CSET(cs)+(*si)].r,tpal[CSET(cs)+(*si)].g,tpal[CSET(cs)+(*si)].b,*si); + } + else + { + textprintf_ex(screen2,font,status_info_x,status_info_y+32,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%02d %02d %02d (%d)",tpal[(*si)].r,tpal[(*si)].g,tpal[(*si)].b,*si); + } + } + } + + custom_vsync(); + scare_mouse(); +// blit(screen2,screen,0,0,screen_xofs,screen_yofs,zq_screen_w,zq_screen_w); + blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w); + update_tool_cursor(); + unscare_mouse(); + SCRFIX(); +} + +void normalize(int tile,int tile2, bool rect_sel, int flip) +{ + if(tile>tile2) + { + zc_swap(tile, tile2); + } + + int left=zc_min(tile_col(tile), tile_col(tile2)); + int columns=zc_max(tile_col(tile), tile_col(tile2))-left+1; + + int start=tile; + int end=tile2; + + // Might have top-right and bottom-left corners selected... + if(rect_sel && tile_col(tile)>tile_col(tile2)) + { + start=tile-(tile_col(tile)-tile_col(tile2)); + end=tile2+(tile_col(tile)-tile_col(tile2)); + } + + for(int temptile=start; temptile<=end; temptile++) + { + if(!rect_sel || ((tile_col(temptile)>=left) && (tile_col(temptile)<=left+columns-1))) + { + unpack_tile(newtilebuf, temptile, 0, false); + + if(flip&1) + { + for(int y=0; y<16; y++) + { + for(int x=0; x<8; x++) + { + zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]); + } + } + } + + if(flip&2) + { + for(int y=0; y<8; y++) + { + for(int x=0; x<16; x++) + { + zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]); + } + } + } + + pack_tile(newtilebuf,unpackbuf,temptile); + } + } +} + +void rotate_tile(int tile, bool backward) +{ + unpack_tile(newtilebuf, tile, 0, false); + byte tempunpackbuf[256]; + byte tempx, tempy; + + for(tempx=0; tempx<16; tempx++) + { + for(tempy=0; tempy<16; tempy++) + { + if(!backward) + { + tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy]; + } + else + { + tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx]; + } + } + } + + pack_tile(newtilebuf,tempunpackbuf,tile); +} + +static int undocount=128; +byte undotile[256]; + +void wrap_tile(int tile, int vertical, int horizontal, bool clear) +{ + byte buf[256]; + + for(int i=0; i0?r:15-r)*16+c]=0; + } + } + + for(int r=0; r<16; r++) + { + for(int c=0; c0?c:15-c)]=0; + } + } + } + + pack_tile(newtilebuf,buf,tile); +} + +void shift_tile_colors(int tile, int amount, bool ignore_transparent) +{ + byte buf[256]; + + unpack_tile(newtilebuf, tile, 0, true); + + for(int i=0; i<256; i++) + { + buf[i]=unpackbuf[i]; + + if(!is_in_selection(i&0x0F, (i&0xF0)>>4)) + continue; + + if(ignore_transparent) + { + if(buf[i]==0) + continue; + + buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 191 : 15); + } + else // Don't ignore transparent + buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 191 : 15); + } + + pack_tile(newtilebuf,buf,tile); +} + +void clear_selection_grid() +{ + for(int x=0; x<18; ++x) + { + for(int y=0; y<18; ++y) + { + selection_grid[x][y]=0; + } + } +} + +void invert_selection_grid() +{ + for(int x=1; x<17; ++x) + { + for(int y=1; y<17; ++y) + { + selection_grid[x][y]=selection_grid[x][y]?0:1; + } + } +} + +void edit_tile(int tile,int flip,int &cs) +{ + go(); + undocount = tilesize(newtilebuf[tile].format); + clear_selection_grid(); + selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1; + + //PALETTE opal; + PALETTE tpal; + //get_palette(opal); + /* + //This causes a bug. Why? -L + get_palette(tpal); + for(int i=0; i<15; i++) + { + load_cset(tpal,i,i); + } + set_palette(tpal); + */ + byte oldtile[256]; + + memset(&tpal, 0, sizeof(PALETTE)); + memset(oldtile, 0, 256); + + for(int i=0; iline[y][x]=selection_pattern_source[x][y]?vc(0):vc(15); + } + } + + selecting_pattern=create_bitmap_ex(8, 8, 8); + + for(int x=0; x<8; ++x) + { + for(int y=0; y<8; ++y) + { + // rectfill(selection_pattern, x<<2, y<<2, (x<<2)+3, (y<<2)+3, (((x^y)&1)==0)?vc(15):vc(0)); + selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15); + } + } + + intersection_pattern=create_bitmap_ex(8, 8, 8); + + for(int x=0; x<8; ++x) + { + for(int y=0; y<8; ++y) + { + // rectfill(selection_pattern, x<<2, y<<2, (x<<2)+3, (y<<2)+3, (((x^y)&1)==0)?vc(15):vc(0)); + intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15); + } + } + +// int screen_xofs=(zq_screen_w-320)>>1; +// int screen_yofs=(zq_screen_h-240)>>1; + + do + { +// int temp_mouse_x=gui_mouse_x()-screen_xofs; +// int temp_mouse_y=gui_mouse_y()-screen_yofs; + int temp_mouse_x=gui_mouse_x(); + int temp_mouse_y=gui_mouse_y(); + rest(4); + bool redraw=false; + bool did_wand_select=false; + + if((tooltip_trigger.x>-1&&tooltip_trigger.y>-1)&&(!isinRect(temp_mouse_x,temp_mouse_y,tooltip_trigger.x,tooltip_trigger.y,tooltip_trigger.x+tooltip_trigger.w-1,tooltip_trigger.y+tooltip_trigger.h-1))) + { + clear_tooltip(); + redraw=true; + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_ENTER_PAD: + case KEY_ENTER: + done=2; + break; + + case KEY_ESC: + done=1; + break; + + case KEY_A: + clear_selection_grid(); + invert_selection_grid(); + redraw=true; + break; + + case KEY_D: + clear_selection_grid(); + redraw=true; + break; + + case KEY_I: + invert_selection_grid(); + redraw=true; + break; + + case KEY_H: + flip^=1; + normalize(tile,tile,0,flip); + flip=0; + redraw=true; + break; + + case KEY_V: + flip^=2; + normalize(tile,tile,0,flip); + flip=0; + redraw=true; + break; + + case KEY_F12: + onSnapshot(); + break; + + case KEY_R: + { + //if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])) + //{ + //do_recolor(tile); redraw=true; saved=false; + //} + //else + //{ + go_tiles(); + rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT])); + redraw=true; + saved=false; + //} + break; + } + + case KEY_EQUALS: + case KEY_PLUS_PAD: + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL] || + key[KEY_ALT] || key[KEY_ALTGR]) + { + for(int i=0; i0) ? cs-1:11; + + redraw=true; + break; + } + + case KEY_SPACE: + gridmode=(gridmode+1)%gm_max; + redraw=true; + break; + + case KEY_U: + for(int i=0; i>3; +// move_origin_y=prev_y=(temp_mouse_y-32)>>3; + move_origin_x=prev_x=(temp_mouse_x-zoom_tile_x)/zoom_tile_scale; + move_origin_y=prev_y=(temp_mouse_y-zoom_tile_y)/zoom_tile_scale; + } + + if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button + { +// if(isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) + if(isinRect(temp_mouse_x,temp_mouse_y,zoom_tile_x,zoom_tile_y-(tool==t_fill ? (is_large ? 14 : 7) : 0),zoom_tile_x+(16*zoom_tile_scale/zoom_tile_size)-2,zoom_tile_y+(16*zoom_tile_scale/zoom_tile_size)-2-(tool==t_fill ? (is_large ? 14 : 7) : 0))) //inside the zoomed tile window + { + if(tool==t_move || tool==t_fill) + { + scare_mouse(); + + if(tool==t_fill) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_SWORD+tool][0]); + set_mouse_sprite_focus(1, 14); + } + else + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_SWORD+tool][1]); + set_mouse_sprite_focus(8, 8); + } + + unscare_mouse(); + move_origin_x=prev_x=(temp_mouse_x-zoom_tile_x)/zoom_tile_scale; + move_origin_y=prev_y=(temp_mouse_y-zoom_tile_y)/zoom_tile_scale; +// move_origin_x=prev_x=(temp_mouse_x-80)>>3; +// move_origin_y=prev_y=(temp_mouse_y-32)>>3; + } + + for(int i=0; i>3; +// int y=(temp_mouse_y-176)>>3; + int x=(temp_mouse_x-palette_x)/(palette_scale*4); + int y=(temp_mouse_y-palette_y)/(palette_scale*4); + c1 = (y<<2)+x; + redraw=true; + } + + break; + + case tf8Bit: + +// if(isinRect(temp_mouse_x,temp_mouse_y,94,172,157,231)) + if(isinRect(temp_mouse_x,temp_mouse_y,palette_x, palette_y+palette_scale,palette_x+(palette_scale*16)-1,palette_y+(palette_scale*15)-1)) + { +// int x=(temp_mouse_x-94)>>2; +// int y=(temp_mouse_y-172)>>2; + int x=(temp_mouse_x-palette_x)/(palette_scale); + int y=(temp_mouse_y-palette_y-palette_scale)/(palette_scale); + c1 = (y<<4)+x; + redraw=true; + } + + break; + } + + + for(int i=0; i>3; +// move_origin_y=prev_y=(temp_mouse_y-32)>>3; + } + + for(int i=0; i>3; +// int y=(temp_mouse_y-176)>>3; + int x=(temp_mouse_x-palette_x)/(palette_scale*4); + int y=(temp_mouse_y-palette_y)/(palette_scale*4); + c2 = (y<<2)+x; + redraw=true; + } + + break; + + case tf8Bit: + +// if(isinRect(temp_mouse_x,temp_mouse_y,94,172,157,231)) + if(isinRect(temp_mouse_x,temp_mouse_y,palette_x, palette_y+palette_scale,palette_x+(palette_scale*16)-1,palette_y+(palette_scale*15)-1)) + { +// int x=(temp_mouse_x-94)>>2; +// int y=(temp_mouse_y-172)>>2; + int x=(temp_mouse_x-palette_x)/(palette_scale); + int y=(temp_mouse_y-palette_y-palette_scale)/(palette_scale); + c2 = (y<<4)+x; + redraw=true; + } + + break; + } + + bdown=true; + } + + if(bdown&&!gui_mouse_b()) //released the buttons + { +// if(isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) + if(isinRect(temp_mouse_x,temp_mouse_y,zoom_tile_x,zoom_tile_y-(tool==t_fill ? (is_large ? 14 : 7) : 0),zoom_tile_x+(16*zoom_tile_scale/zoom_tile_size)-2,zoom_tile_y+(16*zoom_tile_scale/zoom_tile_size)-2-(tool==t_fill ? (is_large ? 14 : 7) : 0))) //inside the zoomed tile window + { + if(tool==t_move || tool==t_fill) + { + scare_mouse(); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_SWORD+tool][0]); + + if(tool==t_fill) + { + set_mouse_sprite_focus(1, 14); + } + else + { + set_mouse_sprite_focus(8, 8); + } + + unscare_mouse(); + } + } + } + +// if(drawing && isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) + if(drawing && isinRect(temp_mouse_x,temp_mouse_y,zoom_tile_x,zoom_tile_y-(tool==t_fill ? (is_large ? 14 : 7) : 0),zoom_tile_x+(16*zoom_tile_scale/zoom_tile_size)-2,zoom_tile_y+(16*zoom_tile_scale/zoom_tile_size)-2-(tool==t_fill ? (is_large ? 14 : 7) : 0))) //inside the zoomed tile window + { + + int mx = gui_mouse_x(); + int my = gui_mouse_y(); + + if(tool==t_fill) //&& is_windowed_mode()) // Sigh... -L + { + mx += 1; + my += is_large ? 14 : 7; + } + + int x=(mx-zoom_tile_x)/(zoom_tile_scale/zoom_tile_size); + int y=(my-zoom_tile_y)/(zoom_tile_scale/zoom_tile_size); + + switch(tool) + { + case t_pen: + if(flip&1) x=15-x; + + if(flip&2) y=15-y; + + if(is_in_selection(x,y)) + { + unpack_tile(newtilebuf, tile, 0, false); + unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2; + pack_tile(newtilebuf, unpackbuf,tile); + } + + break; + + case t_fill: + if(is_in_selection(x,y)) + { + tile_floodfill(tile,x,y,(drawing==1)?c1:c2); + drawing=0; + } + + break; + + case t_recolor: + if(is_in_selection(x,y)) + { + unpack_tile(newtilebuf, tile, 0, false); + tf_u = unpackbuf[(y<<4)+x]; + + for(int i=0; i<256; i++) + { + if(is_in_selection(i&15,i>>4)) + { + if(unpackbuf[i]==tf_u) + { + unpackbuf[i]=(drawing==1)?c1:c2; + } + } + } + + pack_tile(newtilebuf, unpackbuf,tile); + drawing=0; + } + + break; + + case t_eyedropper: + unpack_tile(newtilebuf, tile, 0, false); + + if(gui_mouse_b()&1) + { + c1=unpackbuf[((y<<4)+x)]; + } + + if(gui_mouse_b()&2) + { + c2=unpackbuf[((y<<4)+x)]; + } + + break; + + case t_move: + if((prev_x!=x)||(prev_y!=y)) + { + wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2); + prev_x=x; + prev_y=y; + } + + break; + + case t_select: + if(flip&1) x=15-x; + + if(flip&2) y=15-y; + + if(selecting_x1==-1||selecting_y1==-1) + { + selecting_x1=x; + selecting_y1=y; + } + else + { + selecting_x2=x; + selecting_y2=y; + } + + break; + + case t_wand: + if(flip&1) x=15-x; + + if(flip&2) y=15-y; + + switch(select_mode) + { + case 0: + clear_selection_grid(); + add_color_to_selection(unpackbuf[((y<<4)+x)]); + break; + + case 1: + add_color_to_selection(unpackbuf[((y<<4)+x)]); + break; + + case 2: + remove_color_from_selection(unpackbuf[((y<<4)+x)]); + break; + + case 3: + intersect_color_with_selection(unpackbuf[((y<<4)+x)]); + break; + } + + drawing=0; + break; + } + + redraw=true; + } + + if(gui_mouse_b()==0) + { + bdown=false; + drawing=0; + } + +// temp_x=(temp_mouse_x-80)/8; +// temp_y=(temp_mouse_y-32)/8; + temp_x=zoom_tile_size*(gui_mouse_x()-zoom_tile_x)/zoom_tile_scale; + temp_y=zoom_tile_size*(gui_mouse_y()-zoom_tile_y)/zoom_tile_scale; + +// if(!isinRect(temp_mouse_x,temp_mouse_y,80,32,206,158)) + if(!isinRect(temp_mouse_x,temp_mouse_y,zoom_tile_x,zoom_tile_y,zoom_tile_x+(16*zoom_tile_scale/zoom_tile_size)-2,zoom_tile_y+(16*zoom_tile_scale/zoom_tile_size)-2)) //inside the zoomed tile window + { +// temp_x=-1; +// temp_y=-1; + } + +// if (temp_x!=tile_x||temp_y!=tile_y) + { + tile_x=temp_x; + tile_y=temp_y; + redraw=true; + } + + const char *toolnames[t_max]= + { + "Pencil", "Fill", "Replace Color", "Grab Color", "Move", "Select", "Select Color" + }; + + for(int i=0; i=tooltip_maxtimer)&&(tooltip_box.x>=0&&tooltip_box.y>=0)) + { + masked_blit(tooltipbmp, screen, 0, 0, tooltip_box.x, tooltip_box.y, tooltip_box.w, tooltip_box.h); + } + } + else + { + bool hs=has_selection(); + + if(hs) + { +// zoomtile16(screen2,tile,79,31,cs,flip,8); + zoomtile16(screen2,tile,zoom_tile_x-1,zoom_tile_y-1,cs,flip,zoom_tile_scale); + } + + custom_vsync(); + scare_mouse(); + + if(hs) + { +// blit(screen2, screen, 79, 31, 79, 31, 129, 129); + blit(screen2, screen, zoom_tile_x-1,zoom_tile_y-1, zoom_tile_x-1,zoom_tile_y-1, (16*zoom_tile_scale/zoom_tile_size)+1, (16*zoom_tile_scale/zoom_tile_size)+1); + } + + update_tool_cursor(); + unscare_mouse(); + SCRFIX(); + } + + } + while(!done); + + clear_selection_grid(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + if(done==1) + { + for(int i=0; icolor+1) * pdLEVEL + cs) + i) * 3; + else if(cs==9) + rgbByte = colordata + (CSET((Map.CurrScr()->color+1) * pdLEVEL + 5) + i) * 3; + else + rgbByte = colordata + (CSET(cs)+i)*3; + + int dr=r-*rgbByte; + int dg=g-*(rgbByte+1); + int db=b-*(rgbByte+2); + + // Track both the total color difference and the single greatest + // difference of R, G, B. The idea is that it's better to have + // two or three small differences than one big one. + // The differences are multiplied by different numbers to account + // for the differences in perceived brightness of the three colors. + float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068); + float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068)); + + // Perfect match? Just stop here. + if(totalDiff==0) + return i; + + if(totalDiff < bestTotalDiff || // Best match so far? + (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference? + { + bestMatch=i; + bestTotalDiff=totalDiff; + bestHighDiff=highDiff; + } + } + + return bestMatch; +} + +// Same as the above, but draws from all colors in CSets 0-11. +int bestfit_cset_color_8bit(int r, int g, int b) +{ + int bestMatch = 0; + float bestTotalDiff = 100000; + float bestHighDiff = 100000; + + for(int i = 0; i < 192; i++) // 192 colors in CSets 0-11 + { + byte *rgbByte; + RGB rgb; + + int cs=i>>4; + if(cs==2 || cs==3 || cs==4) + rgbByte = colordata + (CSET((Map.CurrScr()->color+1) * pdLEVEL + cs) + (i%16)) * 3; + else if(cs==9) + rgbByte = colordata + (CSET((Map.CurrScr()->color+1) * pdLEVEL + 5) + (i%16)) * 3; + else + rgbByte = colordata + i * 3; + + int dr=r-*rgbByte; + int dg=g-*(rgbByte+1); + int db=b-*(rgbByte+2); + + float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068); + float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068)); + + if(totalDiff==0) // Perfect match? + return i; + + if(totalDiff < bestTotalDiff || // Best match so far? + (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference? + { + bestMatch=i; + bestTotalDiff=totalDiff; + bestHighDiff=highDiff; + } + } + + return bestMatch; +} + +byte cset_reduce_table[PAL_SIZE]; + +void calc_cset_reduce_table(PALETTE pal, int cs) +{ + for(int i=0; i=0; --i) + { + buf[bx+i] = (b&1)+(cs<<4); + b>>=1; + } + } + + ++src; + + for(int p=1; p=0; --i) + { + if(nesmode) + { + buf[bx+8+i] = (b&1)+(cs<<4); + } + else + { + buf[bx+i] |= (b&1)<>=1; + } + } + + if(p&1) + { + src+=15; + } + else + { + ++src; + } + } + + + if(nesmode) + { + src=oldsrc; + + for(int counter=0; counter<2; ++counter, ++src) + { + //for 8 lines in the source image... + for(int line=0; line<4; line++) + { + //bx is the pixel at the start of a line in the storage buffer + int bx=line<<4; + //b is a byte in the source image (either an entire line in 1bp or the start of a line in others) + byte b=src[(line+4)<<1]; + + //fill the storage buffer with data from the source image + for(int i=7; i>=0; --i) + { + // buf[bx+i] = (b&1)+(cs<<4); + buf[bx+(counter<<3)+i] |= (b&1)<<1; + b>>=1; + } + } + } + } + + int c=0; + + switch(romtilemode) + { + case 0: + case 1: + case 2: + for(int j=0; j<8; j++) + { + for(int i=0; i<8; i++) + { + putpixel(dest,x+i,y+j,buf[c++]); + } + } + + break; + + case 3: + for(int j=0; j<4; j++) + { + for(int i=0; i<16; i++) + { + putpixel(dest,x+i,y+j,buf[c++]); + } + } + + break; + } +} + +const char *file_type[ftMAX]= +{ + "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST" +}; + +void draw_grab_window() +{ + int w = is_large?640:320; + int h = is_large?480:240; + int window_xofs=(zq_screen_w-w-12)>>1; + int window_yofs=(zq_screen_h-h-25-6)>>1; + scare_mouse(); + jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN); + jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(82*(is_large+1)), FR_DEEP); + + FONT *oldfont = font; + font = lfont; + jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true); + font=oldfont; + unscare_mouse(); + return; +} + +void draw_grab_scr(int tile,int cs,byte *newtile,int black,int white, int width, int height, byte *newformat) +{ + width=width; + height=height; + white=white; // happy birthday compiler + + int yofs=0; + //clear_to_color(screen2,bg); + rectfill(screen2, 0, 0, 319, 159, black); + //jwin_draw_win(screen2, 0, 160, 320, 80, FR_WIN); + + if(is_large) + { +// jwin_draw_frame(screen2,-2,-2,324,212,FR_DEEP); + rectfill(screen2,0,160,319,239,jwin_pal[jcBOX]); + _allegro_hline(screen2, 0, 158, 319, jwin_pal[jcMEDLT]); + _allegro_hline(screen2, 0, 159, 319, jwin_pal[jcLIGHT]); + yofs=3; + } + else + { + jwin_draw_win(screen2, 0, 160, 320, 80, FR_WIN); + } + + // text_mode(-1); + int tileromcolumns=20; + + switch(imagetype) + { + case ftBMP: + if(recolor==rcNone) + { + blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160); + } + else + { + int maxy=zc_min(160,((BITMAP*)imagebuf)->h); + int maxx=zc_min(320,((BITMAP*)imagebuf)->w); + + for(int y=0; y=((BITMAP*)imagebuf)->h) + { + break; + } + + for(int x=0; x=((BITMAP*)imagebuf)->w) + { + break; + } + + if(recolor==rc8Bit) + screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]]; + else + screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4); + } + } + } + + break; + + case ftZGP: + case ftQST: + case ftZQT: + case ftQSU: + case ftTIL: + { + tiledata *hold = newtilebuf; + newtilebuf = grabtilebuf; + //fixme + int t=imagey*TILES_PER_ROW; + + for(int i=0; i<200; i++) // 10 rows, down to y=160 + { + if(t <= tilecount) + { + puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0); + } + + ++t; + } + + newtilebuf = hold; + //fixme + } + break; + + case ftBIN: + { + int ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs; + byte *buf = (byte*)imagebuf; + + switch(romtilemode) + { + case 0: + for(int y=0; y<160; y+=8) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8) + { + puttileROM(screen2,x,y,buf+ofs,cs); + ofs+=8*bp; + } + } + + for(int y=0; y<160; y+=8) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8) + { + puttileROM(screen2,x+128,y,buf+ofs,cs); + ofs+=8*bp; + } + } + + break; + + case 1: + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8) + { + puttileROM(screen2,x,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x,y+8,buf+ofs,cs); + ofs+=8*bp; + } + } + + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8) + { + puttileROM(screen2,x+128,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+128,y+8,buf+ofs,cs); + ofs+=8*bp; + } + } + + break; + + case 2: + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16) + { + puttileROM(screen2,x,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+8,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x,y+8,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+8,y+8,buf+ofs,cs); + ofs+=8*bp; + } + } + + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16) + { + puttileROM(screen2,x+128,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+136,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+128,y+8,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+136,y+8,buf+ofs,cs); + ofs+=8*bp; + } + } + + break; + + case 3: + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16) + { + puttileROM(screen2,x,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x,y+4,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x,y+8,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x,y+12,buf+ofs,cs); + ofs+=8*bp; + } + } + + for(int y=0; y<160; y+=16) + { + for(int x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16) + { + puttileROM(screen2,x+128,y,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+128,y+4,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+128,y+8,buf+ofs,cs); + ofs+=8*bp; + puttileROM(screen2,x+128,y+12,buf+ofs,cs); + ofs+=8*bp; + } + } + + break; + } + } + break; + } + + tiledata hold; + + if(is_valid_format(newtilebuf[0].format)) + { + hold.format = newtilebuf[0].format; + hold.data = (byte *)zc_malloc(tilesize(hold.format)); + memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format)); + } + else + { + hold.format=tfInvalid; + hold.data=NULL; + } + + newtilebuf[0].format=newformat[0]; + + if(newtilebuf[0].data!=NULL) + { + zc_free(newtilebuf[0].data); + } + + if(is_valid_format(newtilebuf[0].format)) + { + newtilebuf[0].data = (byte *)zc_malloc(tilesize(newtilebuf[0].format)); + + for(int i=0; i>1; + window_yofs=(zq_screen_h-480-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + } + + custom_vsync(); + scare_mouse(); + + if(is_large) + stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480); + else blit(screen2,screen,0,0,screen_xofs,screen_yofs,320,240); + + // Suspend the current font while draw_text_button does its work + FONT* oldfont = font; + + if(is_large) + font = lfont_l; + + // Interface + switch(imagetype) + { + case 0: + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]); + break; + + case ftBMP: + { + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %dx%d",imgstr[imagetype],((BITMAP*)imagebuf)->w,((BITMAP*)imagebuf)->h); + draw_text_button(screen,window_yofs+141*mul,window_yofs+(192+yofs)*mul,int(61*(is_large?1.5:1)),int(20*(is_large?1.5:1)),"Recolor",vc(1),vc(14),0,true); + break; + } + + case ftZGP: + case ftQST: + case ftZQT: + case ftQSU: + case ftTIL: + case ftBIN: + textprintf_ex(screen,is_large? lfont_l : font,window_xofs+8*mul,window_yofs+(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %ld KB",imgstr[imagetype],imagesize>>10); + break; + } + + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely); + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey); + + if(bp==8) + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit"); + else + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs); + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode); + + if(imagetype==ftBIN) + { + textprintf_ex(screen,font,window_xofs+104*mul,window_yofs+(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":""); + textprintf_ex(screen,font,window_xofs+104*mul,window_yofs+(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs); + textprintf_ex(screen,font,window_xofs+104*mul,window_yofs+(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode); + } + + textprintf_ex(screen,font,window_xofs+8*mul,window_yofs+(224+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imagepath); +// rectfill(screen2,256,224,319,231,black); + draw_text_button(screen,window_xofs+255*mul,window_yofs+(168+yofs)*mul,int(61*(is_large?1.5:1)),int(20*(is_large?1.5:1)),"OK",vc(1),vc(14),0,true); + draw_text_button(screen,window_xofs+255*mul,window_yofs+(192+yofs)*mul,int(61*(is_large?1.5:1)),int(20*(is_large?1.5:1)),"Cancel",vc(1),vc(14),0,true); + draw_text_button(screen,window_xofs+255*mul,window_yofs+(216+yofs)*mul,int(61*(is_large?1.5:1)),int(20*(is_large?1.5:1)),"File",vc(1),vc(14),0,true); + draw_text_button(screen,window_xofs+117*mul,window_yofs+(166+yofs)*mul,int(61*(is_large?1.5:1)),int(20*(is_large?1.5:1)),"Leech",vc(1),vc(14),0,true); + + //int rectw = 16*mul; + //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white); + unscare_mouse(); + SCRFIX(); + font = oldfont; +} + +RGB_MAP rgb_table; +COLOR_MAP imagepal_table; + + +extern void return_RAMpal_color(AL_CONST PALETTE pal, int x, int y, RGB *rgb) +{ + //these are here to bypass compiler warnings about unused arguments + x=x; + + rgb->r = pal[y].r; + rgb->g = pal[y].g; + rgb->b = pal[y].b; +} + + +void load_imagebuf() +{ + PACKFILE *f; + bool compressed=false; + bool encrypted=false; + tiledata *hold=newtilebuf; + zquestheader tempheader; + memset(&tempheader, 0, sizeof(zquestheader)); + + if(imagebuf) + { + switch(imagetype) + { + case ftBMP: + destroy_bitmap((BITMAP*)imagebuf); + break; + + case ftZGP: + case ftQST: + case ftZQT: + case ftQSU: + case ftTIL: + clear_tiles(grabtilebuf); + break; + + case ftBIN: + zc_free(imagebuf); + break; + } + + imagebuf=NULL; + } + + selx=sely=romofs=0; + bp=4; + imagetype=filetype(imagepath); + + dword section_id; + dword section_version; + dword section_cversion; + + switch(imagetype) + { + case ftBMP: + imagebuf = load_bitmap(imagepath,imagepal); + imagesize = file_size_ex_password(imagepath,""); + tilecount=0; + create_rgb_table(&rgb_table, imagepal, NULL); + rgb_map = &rgb_table; + create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL); + + if(!imagebuf) + { + imagetype=0; + } + + break; + + case ftBIN: + imagesize = file_size_ex_password(imagepath, ""); + tilecount=0; + + if(imagesize) + { + imagebuf = zc_malloc(imagesize); + + if(!readfile(imagepath,imagebuf,imagesize)) + { + zc_free(imagebuf); + imagesize=0; + imagetype=0; + } + } + + break; + + case ftTIL: + imagesize = file_size_ex_password(imagepath,""); + f = pack_fopen_password(imagepath,F_READ,""); + + if(!f) + { + goto error; + } + + if(!p_mgetl(§ion_id,f,true)) + { + goto error; + } + + if(section_id==ID_TILES) + { + if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false, true)==0) + { + goto error; + } + } + +error: + pack_fclose(f); + tilecount=count_tiles(grabtilebuf); + break; + + case ftZGP: + imagesize = file_size_ex_password(imagepath, ""); + f=pack_fopen_password(imagepath,F_READ,""); + + if(!f) + { + goto error2; + } + + if(!p_mgetl(§ion_id,f,true)) + { + goto error2; + } + + if(section_id!=ID_GRAPHICSPACK) + { + goto error2; + } + + //section version info + if(!p_igetw(§ion_version,f,true)) + { + goto error2; + } + + if(!p_igetw(§ion_cversion,f,true)) + { + goto error2; + } + + //tiles + if(!p_mgetl(§ion_id,f,true)) + { + goto error2; + } + + if(section_id==ID_TILES) + { + if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false, true)!=0) + { + goto error2; + } + } + +error2: + pack_fclose(f); + tilecount=count_tiles(grabtilebuf); + break; + + case ftQST: + encrypted=true; + + case ftZQT: + compressed=true; + + case ftQSU: + imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : ""); + newtilebuf=grabtilebuf; + byte skip_flags[4]; + + for(int i=0; i=0) + { + bound(index,0,leeching_from_tiles?2:1); + + if(index==imported) + { + sprintf(bitstrbuf,"Imported"); + } + else + { + sprintf(bitstrbuf,"%d",4<w)+15)/16; + height=((((BITMAP*)imagebuf)->h)+15)/16; + break; + } + + if(currtile+(width*height)>NEWMAXTILES) + { + if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',lfont)==2) + { + delete[] testtile; + return false; + } + } + + go_tiles(); + saved=false; + + // usetiles=true; + for(int ty=0; ty=NEWMAXTILES) //if we've maxed out on our tiles... + { + delete[] testtile; + return true; + } + + switch(imagetype) + { + case ftBIN: + break; + + case ftZGP: + case ftQST: + case ftZQT: + case ftQSU: + case ftTIL: + memset(testtile, 0, tilesize(tf32Bit)); + imported_format=grabtilebuf[tx].format; + + switch(cdepth) + { + case 1: //4-bit + newformat=tf4Bit; + + switch(imported_format) + { + case tf4Bit: + memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format)); + break; + + case tf8Bit: + for(int y=0; y<16; y++) //snag a tile + { + for(int x=0; x<16; x+=2) + { + testtile[(y*8)+(x/2)]= + (grabtilebuf[tx].data[y*16+x]&15)+ + ((grabtilebuf[tx].data[y*16+x+1]&15)<<4); + } + } + + break; + } + + break; + + case 2: //8-bit + newformat=tf8Bit; + + switch(imported_format) + { + case tf4Bit: + unpack_tile(grabtilebuf, tx, 0, true); + cst = cs&15; + cst <<= CSET_SHFT; + + for(int i=0; i<256; i++) + { + if(!shift||unpackbuf[i]!=0) + { + unpackbuf[i]+=cst; + } + } + + pack_tiledata(testtile, unpackbuf, tf8Bit); + break; + + case tf8Bit: + memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format)); + break; + } + + break; + + case 3: //original tile's bit depth + newformat=imported_format; + memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format)); + break; + } + + break; + + case ftBMP: + newformat=cdepth; + + for(int y=0; y<16; y++) //snag a tile + { + for(int x=0; x<16; x+=2) + { + switch(cdepth) + { + case tf4Bit: + testtile[(y*8)+(x/2)]= + (getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y)&15)+ + ((getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y)&15)<<4); + break; + + case tf8Bit: + testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y); + testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y); + break; + } + } + } + + break; + } + + if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0) + { + temp_canadd=true; + + //check all tiles before this one + for(int checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile0) + { + if(keypressed()) + { + delete[] testtile; + return true; + } + + duplicate=(newformat==imported_format); + + if(duplicate) + { + switch(flipping) + { + case 0: //normal + if(dest[checktile].data!=NULL) + { + for(int y=0; ((duplicate==true)&&(y<16)); y++) + { + for(int x=0; ((duplicate==true)&&(x<16)); x+=3-newformat) + { + // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)])) + if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=(newformat==tf4Bit?(testtile[(y*8)+(x/2)]):(testtile[(y*16)+x]))) + { + duplicate=false; + } + } + } + } + + break; + + case 1: //horizontal + if(dest[checktile].data!=NULL) + { + for(int y=0; ((duplicate==true)&&(y<16)); y++) + { + for(int x=0; ((duplicate==true)&&(x<16)); x+=3-newformat) + { + // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15))) + if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=(newformat==tf4Bit?(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)):(testtile[(y*16)+x]))) + { + duplicate=false; + } + } + } + } + + break; + + case 2: //vertical + if(dest[checktile].data!=NULL) + { + for(int y=0; ((duplicate==true)&&(y<16)); y++) + { + for(int x=0; ((duplicate==true)&&(x<16)); x+=3-newformat) + { + // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)])) + if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=(newformat==tf4Bit?(testtile[(y*8)+(x/2)]):(testtile[(y*16)+x]))) + { + duplicate=false; + } + } + } + } + + break; + + case 3: //both + if(dest[checktile].data!=NULL) + { + for(int y=0; ((duplicate==true)&&(y<16)); y++) + { + for(int x=0; ((duplicate==true)&&(x<16)); x+=3-newformat) + { + // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15))) + if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=(newformat==tf4Bit?(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)):testtile[(y*16)+x])) + { + duplicate=false; + } + } + } + } + + break; + } + } + + if(duplicate==true) + { + ++duplicates_found[flipping]; + ++total_duplicates_found; + + if(DuplicateAction[flipping]>1) + { + ++total_duplicates_discarded; + temp_canadd=false; + } + } + } + + canadd=canadd&&temp_canadd; + } + } + } + +// dest[currtile].format=(cdepth==3?imported_format:cdepth); + dest[currtile].format=newformat; + + if(dest[currtile].data!=NULL) + { + zc_free(dest[currtile].data); + } + + dest[currtile].data=(byte *)zc_malloc(tilesize(dest[currtile].format)); + + if(dest[currtile].data==NULL) + { + Z_error("Unable to initialize tile #%d.\n", currtile); + } + + if(canadd==true) + { + /* + for(int y=0; y<16; y++) + { + for(int x=0; x<8; x++) + { + dest[currtile].data[(y*8)+x]=testtile[(y*8)+x]; + } + } + */ + memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format)); + ++currtile; + } + } + } + + destroy_bitmap(status); + delete[] testtile; + return true; +} + +void grab(byte(*dest)[256],byte *def, int width, int height, int oformat, byte *newformat) +{ + // Not too sure what's going on with the format stuff here... + byte defFormat=(bp==8) ? tf8Bit : tf4Bit; + byte format=defFormat; + int stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16)); + + switch(imagetype) + { + case ftZGP: + case ftQST: + case ftZQT: + case ftQSU: + case ftTIL: + case ftBIN: + case ftBMP: + for(int ty=0; ty>4; + break; + } + + break; + + case tf8Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=(def[(y*16)+(x)]&15)+(def[(y*16)+(x+1)]<<4); + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)]; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)]; + break; + } + + break; + } + } + else if(y<8 && x>7 && grabmask&2) + { + switch(oformat) + { + case tf4Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=def[(y*8)+(x/2)]; + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*8)+(x/2)]&15; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*8)+(x/2)]>>4; + break; + } + + break; + + case tf8Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=(def[(y*16)+(x)]&15)+(def[(y*16)+(x+1)]<<4); + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)]; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)]; + break; + } + + break; + } + } + else if(y>7 && x<8 && grabmask&4) + { + switch(oformat) + { + case tf4Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=def[(y*8)+(x/2)]; + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*8)+(x/2)]&15; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*8)+(x/2)]>>4; + break; + } + + break; + + case tf8Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=(def[(y*16)+(x)]&15)+(def[(y*16)+(x+1)]<<4); + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)]; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)]; + break; + } + + break; + } + } + else if(y>7 && x>7 && grabmask&8) + { + switch(oformat) + { + case tf4Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=def[(y*8)+(x/2)]; + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*8)+(x/2)]&15; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*8)+(x/2)]>>4; + break; + } + + break; + + case tf8Bit: + switch(format) + { + case tf4Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=(def[(y*16)+(x)]&15)+(def[(y*16)+(x+1)]<<4); + break; + + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)]; + dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)]; + break; + } + + break; + } + } + else + { + switch(format) + { + case tf8Bit: + dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely); + dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely); + newformat[(ty*TILES_PER_ROW)+tx] = tf8Bit; + break; + + case tf4Bit: + default: + dest[(ty*TILES_PER_ROW)+tx][(y*8)+(x/2)]=(getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely)&15)+((getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely)&15)<<4); + newformat[(ty*TILES_PER_ROW)+tx] = tf4Bit; + break; + } + } + } + } + } + } + + break; + + default: + for(int i=0; i<200; i++) + { + for(int j=0; j<256; j++) + { + dest[i][j]=0; + } + + newformat[i] = tf4Bit; + } + + break; + } +} + +void grab_tile(int tile,int &cs) +{ + int window_xofs=0; + int window_yofs=0; + int screen_xofs=0; + int screen_yofs=0; + int panel_yofs=0; + int mul = 1; + int bwidth = 61; + int bheight = 20; + int button_x = 255; + int grab_ok_button_y = 168; + int leech_button_x = 117; + int leech_button_y = 166; + int grab_cancel_button_y = 192; + int file_button_y = 216; + int rec_button_x = 141; + int rec_button_y = 192; + + if(is_large) + { + window_xofs=(zq_screen_w-640-12)>>1; + window_yofs=(zq_screen_h-480-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + mul=2; + button_x *= mul; + grab_ok_button_y *= mul; + leech_button_x *= mul; + leech_button_y *= mul; + grab_cancel_button_y *= mul; + file_button_y *= mul; + rec_button_y *= mul; + rec_button_x *= mul; + rec_button_x -= 30; + bwidth = int(bwidth*1.5); + bheight = int(bheight*1.5); + } + + byte newtile[200][256]; + BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h); + clear_bitmap(screen3); + byte newformat[200]; + + memset(newtile, 0, 200*256); + memset(newformat, 0, 200); + + static EXT_LIST list[] = + { + { (char *)"All Files (*.*)", NULL }, + { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" }, + { (char *)"GIF Image (*.gif)", (char *)"gif" }, + { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" }, + { (char *)"ZC Tile Export (*.til)", (char *)"til" }, + { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" }, + { (char *)"ZC Quest (*.qst)", (char *)"qst" }, + { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" }, + { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" }, + { (char *)"NES ROM Image (*.nes)", (char *)"nes" }, + { (char *)"SNES ROM Image (*.smc)", (char *)"smc" }, + { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" }, + { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" }, + { NULL, NULL } + }; + + + memset(cset_reduce_table, 0, 256); + memset(col_diff,0,3*128); + bool bdown=false; + int done=0; + int pal=0; + int f=0; + int black=vc(0),white=vc(15); + int selwidth=1, selheight=1; + int selx2=0, sely2=0; + bool xreversed=false, yreversed=false; + bool doleech=false, dofile=false, dopal=false; + + int jwin_pal2[jcMAX]; + memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX); + + + if(imagebuf==NULL) + load_imagebuf(); + + calc_cset_reduce_table(imagepal, cs); + calc_cset_reduce_table_8bit(imagepal); + draw_grab_window(); + draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat); + grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat); + draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + do + { + rest(4); + bool redraw=false; + + if(keypressed()) + { + redraw=true; + + switch(readkey()>>8) + { + case KEY_F: + dofile=true; + break; + + case KEY_L: + doleech=true; + break; + + case KEY_P: + if(imagetype==ftBMP) + { + dopal=true; + recolor=rcNone; + calc_cset_reduce_table(imagepal, cs); + } + + break; + + case KEY_ESC: + done=1; + break; + + case KEY_ENTER_PAD: + case KEY_ENTER: + done=2; + break; + + case KEY_DOWN: + if(key[KEY_ZC_LCONTROL]||key[KEY_ZC_LCONTROL]) sely=zc_min(sely+1,144); + else ++imagey; + + break; + + case KEY_UP: + if(key[KEY_ZC_LCONTROL]||key[KEY_ZC_LCONTROL]) sely=zc_max(sely-1,0); + else --imagey; + + break; + + case KEY_RIGHT: + if(key[KEY_ZC_LCONTROL]||key[KEY_ZC_LCONTROL]) selx=zc_min(selx+1,304); + else ++imagex; + + break; + + case KEY_LEFT: + if(key[KEY_ZC_LCONTROL]||key[KEY_ZC_LCONTROL]) selx=zc_max(selx-1,0); + else --imagex; + + break; + + case KEY_PGDN: + imagey+=10; + break; + + case KEY_PGUP: + imagey-=10; + break; + + case KEY_HOME: + imagex=imagey=0; + break; + + case KEY_EQUALS: + case KEY_PLUS_PAD: + cs = (cs<11) ? cs+1:0; + if(recolor==rc4Bit) + calc_cset_reduce_table(imagepal, cs); + break; + + case KEY_MINUS: + case KEY_MINUS_PAD: + cs = (cs>0) ? cs-1:11; + if(recolor==rc4Bit) + calc_cset_reduce_table(imagepal, cs); + break; + + case KEY_S: + if(grabmode==1) grabmode=8; + else if(grabmode==8) grabmode=16; + else grabmode=1; + + break; + + case KEY_1: + if(recolor==rc8Bit) + recolor=rcNone; + //imagex=(imagex*bp)>>3; + bp=1; + //imagex<<=3; + nesmode=false; + break; + + case KEY_2: + if(recolor==rc8Bit) + recolor=rcNone; + //imagex=(imagex*bp)>>3; + bp=2; + //imagex<<=2; + nesmode=false; + break; + + case KEY_N: + if(recolor==rc8Bit) + recolor=rcNone; + //imagex=(imagex*bp)>>3; + bp=2; + //imagex<<=2; + nesmode=true; + break; + + case KEY_4: + if(recolor==rc8Bit) + recolor=rcNone; + //imagex=(imagex*bp)>>3; + bp=4; + //imagex<<=1; + nesmode=false; + break; + + case KEY_8: + //imagex=(imagex*bp)>>3; + bp=8; + break; + + case KEY_B: + if(bp==2&&!nesmode) + { + nesmode=true; + } + else + { + nesmode=false; + bp<<=1; + + if(bp==16) + { + bp=1; + //imagex<<=3; + } + else + { + //imagex>>=1; + } + } + + break; + + case KEY_M: + romtilemode=(romtilemode+1)%4; + break; + + case KEY_Z: + if(romofs>0) --romofs; + + break; + + case KEY_X: + ++romofs; + break; + + case KEY_R: + if(pal) + { + dopal=true; + } + + if(recolor!=rcNone) + recolor=rcNone; + else if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + bp=8; + recolor=rc8Bit; + calc_cset_reduce_table_8bit(imagepal); + } + else + { + if(bp==8) + bp=4; + recolor=rc4Bit; + calc_cset_reduce_table(imagepal, cs); + } + break; + + default: + redraw=false; + } + + clear_keybuf(); + + if(imagex<0) imagex=0; + + if(imagey<0) imagey=0; + + draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat); + grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat); + } + + //boogie! + if(gui_mouse_b()==1 && !bdown) + { + if(is_large) + { + if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + 320 + 12 - 21, window_yofs + 5, window_xofs + 320 +12 - 21 + 15, window_yofs + 5 + 13)) + { + if(do_x_button(screen, 320+12+window_xofs - 21, 5+window_yofs)) + { + done=1; + } + } + } + + if(!bdown) + { + bool regrab=false; + bdown=true; + int x=gui_mouse_x()-window_xofs; + int y=gui_mouse_y()-window_xofs; + // Large Mode: change font temporarily + FONT* oldfont = font; + + if(is_large) + font = lfont_l; + + if(y>=0 && y<=160*mul) + { + while(gui_mouse_b()) + { + x=(gui_mouse_x()-screen_xofs) / mul; + y=(gui_mouse_y()-screen_yofs) / mul; + + if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT])) + { + selx=vbound((x/grabmode)*grabmode,0,304); + sely=vbound((y/grabmode)*grabmode,0,144); + selx2=selx; + sely2=sely; + selwidth=1; + selheight=1; + xreversed=false; + yreversed=false; + } + else + { + if(xreversed) + { + zc_swap(selx, selx2); + xreversed=false; + } + + if(yreversed) + { + zc_swap(sely, sely2); + yreversed=false; + } + + selx2=vbound((x/grabmode)*grabmode,0,304); + sely2=vbound((y/grabmode)*grabmode,0,144); + selwidth=1+(abs(selx2-selx))/16; + selheight=1+(abs(sely2-sely))/16; + + if(selx2line[dy+(y)][dx+(x)]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rect(screen2, (x)+1,(y)+1, (x)+l, (y)+l, vc(15)); + line(screen2, (x)+1,(y)+1, (x)+l, (y)+l, vc(15)); + line(screen2, (x)+1,(y)+l, (x)+l, (y)+1, vc(15)); + } + } + else + { + puttile16(buf,first+i,0,0,cs,0); + stretch_blit(buf,screen2,0,0,16,16,x,y,w,h); + } + + if((f%32)<=16 && is_large && newtilebuf[first+i].format==tf8Bit) + { + textprintf_ex(screen2,z3smallfont,(x)+l-3,(y)+l-3,vc(int((f%32)/6)+10),-1,"8"); + } + } + + destroy_bitmap(buf); +} + +void tile_info_0(int tile,int tile2,int cs,int copy,int copycnt,int page,bool rect_sel) +{ + int yofs=0; + BITMAP *buf = create_bitmap_ex(8,16,16); + int mul = is_large + 1; + FONT *tfont = pfont; + + if(is_large) + { +// jwin_draw_frame(screen2,-2,-2,324,212,FR_DEEP); + rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]); + _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]); + _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]); + yofs=3; + tfont = lfont_l; + } + else + { + jwin_draw_win(screen2,0, 208, 320, 32, FR_WIN); + } + + jwin_draw_frame(screen2,(36*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + int coldiff=tile_col(copy)-tile_col(copy+copycnt-1); + + if(copy>=0) + { + puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0); + stretch_blit(buf,screen2,0,0,16,16,36*mul,216*mul+yofs,16*mul,16*mul); + + if(copycnt>1) + { + textprintf_right_ex(screen2,tfont,30*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy); + textprintf_right_ex(screen2,tfont,26*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1); + } + else + { + textprintf_right_ex(screen2,tfont,26*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy); + } + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<16*mul; dy++) + { + for(int dx=0; dx<16*mul; dx++) + { + screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(screen2, 36*mul, (216*mul)+yofs, (36+15)*mul, ((216+15)*mul)+yofs, vc(0)); + rect(screen2, 36*mul, (216*mul)+yofs, (36+15)*mul, ((216+15)*mul)+yofs, vc(15)); + line(screen2, 36*mul, (216*mul)+yofs, (36+15)*mul, ((216+15)*mul)+yofs, vc(15)); + line(screen2, 36*mul, ((216+15)*mul)+yofs, (36+15)*mul, (216*mul)+yofs, vc(15)); + } + } + + + //current tile + jwin_draw_frame(screen2,(108*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + puttile16(buf,tile,0,0,cs,0); + stretch_blit(buf,screen2,0,0,16,16,108*mul,216*mul+yofs,16*mul,16*mul); + + jwin_draw_frame(screen2,(132*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,132*mul,216*mul+yofs,16*mul,16*mul); + + if(tile>tile2) + { + zc_swap(tile,tile2); + } + + char tbuf[8]; + tbuf[0]=0; + + if(tile2!=tile) + { + sprintf(tbuf,"-%d",tile2); + } + + textprintf_ex(screen2,tfont,58*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs); + textprintf_right_ex(screen2,tfont,102*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:"); + textprintf_right_ex(screen2,tfont,102*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf); + + FONT *tf = font; + font = tfont; + + draw_text_button(screen2,157*mul,213*mul+yofs,32*mul,21*mul,"Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + draw_text_button(screen2,(157+32)*mul,213*mul+yofs,32*mul,21*mul,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + draw_text_button(screen2,(157+32*2)*mul,213*mul+yofs,32*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + draw_text_button(screen2,(157+32*3)*mul,213*mul+yofs,32*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + + textprintf_ex(screen2,font,305*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x88"); + textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:"); + textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page); + textprintf_ex(screen2,font,305*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x89"); + + font = tf; + + int window_xofs=0; + int window_yofs=0; + int screen_xofs=0; + int screen_yofs=0; + int w = 320*mul; + int h = 240*mul; + + if(is_large) + { + window_xofs=(zq_screen_w-w-12)>>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + } + + custom_vsync(); + scare_mouse(); + blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h); + unscare_mouse(); + SCRFIX(); + destroy_bitmap(buf); +} + +void tile_info_1(int oldtile,int oldflip,int oldcs,int tile,int flip,int cs,int copy,int page, bool always_use_flip) +{ + int yofs=0; + BITMAP *buf = create_bitmap_ex(8,16,16); + int mul = is_large + 1; + FONT *tfont = pfont; + + if(is_large) + { +// jwin_draw_frame(screen2,-2,-2,324,212,FR_DEEP); + rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]); + _allegro_hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]); + _allegro_hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]); + yofs=3; + tfont = lfont_l; + } + else + { + jwin_draw_win(screen2,0, 208, 320, 32, FR_WIN); + } + + jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + + if(copy>=0) + { + puttile16(buf,copy,0,0,cs,flip); + stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul); + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<16*mul; dy++) + { + for(int dx=0; dx<16*mul; dx++) + { + screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0)); + rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15)); + line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15)); + line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15)); + } + } + + jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + puttile16(buf,oldtile,0,0, oldcs, oldflip); + stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul); + + textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:"); + textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile); + + textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:"); + textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs); + + if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage + { + textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:"); + textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip); + } + + jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + puttile16(buf,tile,0,0, cs, + (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage + stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul); + + textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:"); + textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile); + textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:"); + textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs); + + if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage + { + textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:"); + textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip); + } + + textprintf_ex(screen2,font,305*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x88"); + textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:"); + textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page); + textprintf_ex(screen2,font,305*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x89"); + + + int window_xofs=0; + int window_yofs=0; + int screen_xofs=0; + int screen_yofs=0; + int w = 320; + int h = 240; + + if(is_large) + { + w*=2; + h*=2; + window_xofs=(zq_screen_w-w-12)>>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + } + + custom_vsync(); + scare_mouse(); + blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h); + unscare_mouse(); + SCRFIX(); + destroy_bitmap(buf); +} +/* +void reset_tile(tiledata *buf, int t, int format=1) +{ + buf[t].format=format; + if (buf[t].data!=NULL) + { + zc_free(buf[t].data); + } + buf[t].data=(byte *)zc_malloc(tilesize(buf[t].format)); + if (buf[t].data==NULL) + { + Z_error("Unable to initialize tile #%d.\n", t); + } + for(int i=0; iselection_last)||(selection_first>check_last)) + { + return ti_none; + } + + // if selection envelopes check + if((selection_first<=check_first)&&(selection_last>=check_last)) + { + return ti_encompass; //encompass + } + + //everything else is a break + return ti_broken; //intersect +} + + + +//rectangular check and striped selection +int move_intersection_rs(int check_left, int check_top, int check_width, int check_height, int selection_first, int selection_last) +{ + int ret1=-1, ret2=-1; + + for(int i=0; i=(check_top+check_height-1))) + { + return ti_encompass; + } + else + { + return ti_broken; + } + } + + return ti_none; +} + + +//striped check and rectangular selection +int move_intersection_sr(int check_first, int check_last, int selection_left, int selection_top, int selection_width, int selection_height) +{ + if(selection_width < TILES_PER_ROW) + { + if((check_last-check_first+1<=selection_width) && + (tile_row(check_first)>=selection_top) && + (tile_row(check_last)<=selection_top+selection_height-1) && + (tile_col(check_first)>=selection_left) && + (tile_col(check_last)<=tile_col(selection_left+selection_width-1))) + { + return ti_encompass; + } + else if((check_last(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1)) + { + return ti_none; + } + + //else if (selection_top*TILES_PER_ROW+selection_leftcheck_last) + + //one last base case: the strip we're interested in only lies along one row + if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW) + { + int cfcol = check_first%TILES_PER_ROW; + int clcol = check_last%TILES_PER_ROW; + + if(clcol < selection_left || cfcol >= selection_left+selection_width) + return ti_none; + else + return ti_broken; + } + else + { + //recursively cut the strip into substrips which lie entirely on one row + int currow = check_first/TILES_PER_ROW; + int endrow = check_last/TILES_PER_ROW; + int accum = 0; + accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height); + + for(++currow; currow 0) + return ti_broken; + + return ti_none; + } + } + + return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1); +} + +//rectangular check and rectangular selection +int move_intersection_rr(int check_left, int check_top, int check_width, int check_height, int selection_left, int selection_top, int selection_width, int selection_height) +{ + if((check_left>=selection_left) && + (check_left+check_width<=selection_left+selection_width) && + (check_top>=selection_top) && + (check_top+check_height<=selection_top+selection_height)) + { + return ti_encompass; + } + else + { + for(int i=check_top; i2); + map_styles_items[0].tile=misc.colors.blueframe_tile; + map_styles_items[1].tile=misc.colors.HCpieces_tile; + map_styles_items[1].width=zinit.hcp_per_hc; + map_styles_items[2].tile=misc.colors.triforce_tile; + map_styles_items[2].width=BSZ2?2:1; + map_styles_items[2].height=BSZ2?3:1; + map_styles_items[3].tile=misc.colors.triframe_tile; + map_styles_items[3].width=BSZ2?7:6; + map_styles_items[3].height=BSZ2?7:3; + map_styles_items[4].tile=misc.colors.overworld_map_tile; + map_styles_items[5].tile=misc.colors.dungeon_map_tile; + + for(int u=0; u<6; u++) + { + for(int r=zc_max(tile_row(map_styles_items[u].tile),0); r2); + + for(int d=0; d=eGLEEOK1 && u<=eGLEEOK4) + { + gleeok=1; + } + else if(u>=eGLEEOK1F && u<=eGLEEOK4F) + { + gleeok=2; + } + + if(newtiles) + { + if(guysbuf[u].e_tile==0) + { + continue; + } + + if(guysbuf[u].e_height==0) + { + for(int t=zc_max(guysbuf[u].e_tile,0); t1?1:0),0); r1?1:0)+1,TILE_ROWS_PER_PAGE*TILE_PAGES); ++r) + { + for(int c=zc_max(tile_col(guysbuf[u].e_tile+(gleeok>1?-4:8)),0); c1?-4:8))+4,TILES_PER_ROW); ++c) + { + used_tile_table[(r*TILES_PER_ROW)+c]=true; + } + } + } + + int c3=tile_col(guysbuf[u].e_tile)+(gleeok>1?-12:0); + int r3=tile_row(guysbuf[u].e_tile)+(gleeok>1?17:8); + + for(int r=zc_max(r3,0); rtile2 then swap them + if(tile>tile2) + { + zc_swap(tile, tile2); + } + + // alt=copy from right + // shift=copy from bottom + + int copies=copycnt; + int dest_first=tile; + int dest_last=tile2; + int src_first=copy; + int src_last=copy+copies-1; + + int dest_top=0; + int dest_bottom=0; + int src_top=0; + int src_bottom=0; + int src_left=0, src_right=0; + int src_width=0, src_height=0; + int dest_left=0, dest_right=0; + int dest_width=0, dest_height=0; + int rows=0, cols=0; + + if(rect) + { + dest_top=tile_row(dest_first); + dest_bottom=tile_row(dest_last); + src_top=tile_row(src_first); + src_bottom=tile_row(src_last); + + src_left= zc_min(tile_col(src_first),tile_col(src_last)); + src_right=zc_max(tile_col(src_first),tile_col(src_last)); + src_first=(src_top * TILES_PER_ROW)+src_left; + src_last= (src_bottom*TILES_PER_ROW)+src_right; + + dest_left= zc_min(tile_col(dest_first),tile_col(dest_last)); + dest_right=zc_max(tile_col(dest_first),tile_col(dest_last)); + dest_first=(dest_top * TILES_PER_ROW)+dest_left; + dest_last= (dest_bottom*TILES_PER_ROW)+dest_right; + + //if no dest range set, then set one + if((dest_first==dest_last)&&(src_first!=src_last)) + { + if(alt) + { + dest_left=dest_right-(src_right-src_left); + } + else + { + dest_right=dest_left+(src_right-src_left); + } + + if(shift) + { + dest_top=dest_bottom-(src_bottom-src_top); + } + else + { + dest_bottom=dest_top+(src_bottom-src_top); + } + + dest_first=(dest_top * TILES_PER_ROW)+dest_left; + dest_last= (dest_bottom*TILES_PER_ROW)+dest_right; + } + else + { + if(dest_right-dest_leftsrc_right-src_left) //destination is longer than source + { + if(alt) //copy from right tile instead of left + { + dest_left=dest_right-(src_right-src_left); + } + else //copy from left tile + { + dest_right=dest_left+(src_right-src_left); + } + } + + if(dest_bottom-dest_topsrc_bottom-src_top) //destination is longer than source + { + if(shift) //copy from bottom tile instead of top + { + dest_top=dest_bottom-(src_bottom-src_top); + } + else //copy from top tile + { + dest_bottom=dest_top+(src_bottom-src_top); + } + } + + src_first=(src_top * TILES_PER_ROW)+src_left; + src_last= (src_bottom*TILES_PER_ROW)+src_right; + dest_first=(dest_top * TILES_PER_ROW)+dest_left; + dest_last= (dest_bottom*TILES_PER_ROW)+dest_right; + } + + cols=src_right-src_left+1; + rows=src_bottom-src_top+1; + + dest_width=dest_right-dest_left+1; + dest_height=dest_bottom-dest_top+1; + src_width=src_right-src_left+1; + src_height=src_bottom-src_top+1; + + } + else //!rect + { + //if no dest range set, then set one + if((dest_first==dest_last)&&(src_first!=src_last)) + { + if(alt) + { + dest_first=dest_last-(src_last-src_first); + } + else + { + dest_last=dest_first+(src_last-src_first); + } + } + else + { + if(dest_last-dest_firstsrc_last-src_first) //destination is longer than source + { + if(alt) //copy from last tile instead of first + { + dest_first=dest_last-(src_last-src_first); + } + else //copy from first tile + { + dest_last=dest_first+(src_last-src_first); + } + } + } + + copies=dest_last-dest_first+1; + } + + + + char buf[80], buf2[80], buf3[80], buf4[80]; + sprintf(buf, " "); + sprintf(buf2, " "); + sprintf(buf3, " "); + sprintf(buf4, " "); + + // warn if range extends beyond last tile + sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied."); + + if(dest_last>=NEWMAXTILES) + { + sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy"); + jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, lfont); + return false; +//fix this below to allow the operation to complete with a modified start or end instead of just cancelling + //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', lfont)==2) + //{ + // return false; + //} + } + + char *tile_move_list_text = new char[65535]; + char temptext[80]; + + sprintf(buf, "Destination Warning"); + tile_move_list_dlg[0].dp=buf; + tile_move_list_dlg[0].dp2=lfont; + bool found; + bool flood; + + int i; + bool *move_combo_list = new bool[MAXCOMBOS]; + bool *move_items_list = new bool[iMax]; + bool *move_weapons_list = new bool[wMAX]; + bool move_link_sprites_list[41]; + bool move_mapstyles_list[6]; + //bool move_subscreenobjects_list[MAXCUSTOMSUBSCREENS*MAXSUBSCREENITEMS]; + bool move_game_icons_list[4]; + bool move_dmap_maps_list[MAXDMAPS][4]; + // bool move_enemies_list[eMAXGUYS]; //to be implemented once custom enemies are in + + // warn if paste overwrites other defined tiles or + // if delete erases other defined tiles + int selection_first=0, selection_last=0, selection_left=0, selection_top=0, selection_width=0, selection_height=0; + bool done = false; + + for(int q=0; q<2 && !done; ++q) + { + + switch(q) + { + case 0: + selection_first=dest_first; + selection_last=dest_last; + selection_left=dest_left; + selection_top=dest_top; + selection_width=dest_width; + selection_height=dest_height; + break; + + case 1: + selection_first=src_first; + selection_last=src_last; + selection_left=src_left; + selection_top=src_top; + selection_width=src_width; + selection_height=src_height; + break; + } + + if(move||q==0) + { + //check combos + if(!done) + { + //this is here to allow this section to fold + tile_move_list_text[0]=0; + found=false; + flood=false; + + for(int u=0; u2); + map_styles_items[0].tile=misc.colors.blueframe_tile; + map_styles_items[1].tile=misc.colors.HCpieces_tile; + map_styles_items[1].width=zinit.hcp_per_hc; + map_styles_items[2].tile=misc.colors.triforce_tile; + map_styles_items[2].width=BSZ2?2:1; + map_styles_items[2].height=BSZ2?3:1; + map_styles_items[3].tile=misc.colors.triframe_tile; + map_styles_items[3].width=BSZ2?7:6; + map_styles_items[3].height=BSZ2?7:3; + map_styles_items[4].tile=misc.colors.overworld_map_tile; + map_styles_items[5].tile=misc.colors.dungeon_map_tile; + + for(int u=0; u<6; u++) + { + move_mapstyles_list[u]=false; + + if(rect) + { + i=move_intersection_rr(tile_col(map_styles_items[u].tile), tile_row(map_styles_items[u].tile), map_styles_items[u].width, map_styles_items[u].height, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(tile_col(map_styles_items[u].tile), tile_row(map_styles_items[u].tile), map_styles_items[u].width, map_styles_items[u].height, selection_first, selection_last); + } + + if((i!=ti_none)&&(map_styles_items[u].tile!=0)) + { + if(i==ti_broken || q==0) + { + sprintf(temptext, "%s\n", map_styles_items[u].name); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + else if(i==ti_encompass) + { + move_mapstyles_list[u]=true; + } + } + } + + if(found) + { + sprintf(buf2, "The tiles used by the following map style"); + + if(move) + { + sprintf(buf3, "items will be partially cleared by the move."); + sprintf(buf4, "Proceed?"); + } + else + { + sprintf(buf3, "items will be partially or completely"); + sprintf(buf4, "overwritten by this process. Proceed?"); + } + + tile_move_list_dlg[1].dp=buf2; + tile_move_list_dlg[2].dp=buf3; + tile_move_list_dlg[3].dp=buf4; + tile_move_list_dlg[4].dp=tile_move_list_text; + tile_move_list_dlg[4].d2=0; + + if(TileProtection) + { + if(is_large) + large_dialog(tile_move_list_dlg); + + int ret=zc_popup_dialog(tile_move_list_dlg,2); + position_mouse_z(0); + + if(ret!=5) + { + done = true; + } + } + } + } + + //check game icons + if(!done) + { + //this is here to allow this section to fold + tile_move_list_text[0]=0; + found=false; + flood=false; + const char *icon_title[4]= + { + "No Ring / Green Ring", "Blue Ring", "Red Ring", "Golden Ring" + }; + + for(int u=0; u<4; u++) + { + move_game_icons_list[u]=false; + + if(rect) + { + i=move_intersection_sr(misc.icons[u], misc.icons[u], selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_ss(misc.icons[u], misc.icons[u], selection_first, selection_last); + } + + if((i!=ti_none)&&(misc.icons[u]!=0)) + { + if(i==ti_broken || q==0) + { + sprintf(temptext, "%s\n", icon_title[u]); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + else if(i==ti_encompass) + { + move_game_icons_list[u]=true; + } + } + } + + if(rect) + { + i=move_intersection_sr(41, 41, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_ss(41, 41, selection_first, selection_last); + } + + if((i!=ti_none)) // &&(41!=0)) //this is for when the quest sword can change + { + sprintf(temptext, "Quest Sword"); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + + if(found) + { + sprintf(buf2, "The tiles used by the following quest icons"); + + if(move) + { + sprintf(buf3, "will be partially cleared by the move."); + sprintf(buf4, "Proceed?"); + } + else + { + sprintf(buf3, "will be overwritten by this process. Proceed?"); + sprintf(buf4, " "); + } + + tile_move_list_dlg[1].dp=buf2; + tile_move_list_dlg[2].dp=buf3; + tile_move_list_dlg[3].dp=buf4; + tile_move_list_dlg[4].dp=tile_move_list_text; + tile_move_list_dlg[4].d2=0; + + if(TileProtection) + { + if(is_large) + large_dialog(tile_move_list_dlg); + + int ret=zc_popup_dialog(tile_move_list_dlg,2); + position_mouse_z(0); + + if(ret!=5) + { + done = true; + } + } + } + } + + //check dmap maps + if(!done) + { + //this is here to allow this section to fold + tile_move_list_text[0]=0; + found=false; + flood=false; + bool BSZ2=(zinit.subscreen>2); + + for(int t=0; t=eGLEEOK1 && bie[u].i<=eGLEEOK4) + gleeok=1; + else if(bie[u].i>=eGLEEOK1F && bie[u].i<=eGLEEOK4F) + gleeok=2; + + // Unimplemented enemies, or enemies with no tiles. + if(bie[u].i>=eOCTO1S && bie[u].i1?-4:8)), tile_row(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0), 4, 1, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(tile_col(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)), tile_row(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0), 4, 1, selection_first, selection_last); + } + } + + if(i==ti_none) + { + int c=tile_col(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0); + int r=tile_row(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8); + + if(rect) + { + i=move_intersection_rr(c, r, 20, 3, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(c, r, 20, 3, selection_first, selection_last); + } + + if(i==ti_none) + { + if(rect) + { + i=move_intersection_rr(c, r+3, 16, 6, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(c, r+3, 16, 6, selection_first, selection_last); + } + } + } + + if(((q==1) && i==ti_broken) || (q==0 && i!=ti_none)) + { + sprintf(temptext, "%s\n", bie[u].s); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + } + } + else + { + if((guysbuf[bie[u].i].tile==0)) + { + continue; + } + else if(guysbuf[bie[u].i].height==0) + { + if(rect) + { + i=move_intersection_sr(guysbuf[bie[u].i].tile, guysbuf[bie[u].i].tile+zc_max(guysbuf[bie[u].i].width-1, 0), selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_ss(guysbuf[bie[u].i].tile, guysbuf[bie[u].i].tile+zc_max(guysbuf[bie[u].i].width-1, 0), selection_first, selection_last); + } + } + else + { + if(rect) + { + i=move_intersection_rr(tile_col(guysbuf[bie[u].i].tile), tile_row(guysbuf[bie[u].i].tile), guysbuf[bie[u].i].width, guysbuf[bie[u].i].height, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(tile_col(guysbuf[bie[u].i].tile), tile_row(guysbuf[bie[u].i].tile), guysbuf[bie[u].i].width, guysbuf[bie[u].i].height, selection_first, selection_last); + } + } + + if(((q==1) && i==ti_broken) || (q==0 && i!=ti_none)) + { + sprintf(temptext, "%s\n", bie[u].s); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + + if(guysbuf[bie[u].i].s_tile!=0) + { + if(guysbuf[bie[u].i].s_height==0) + { + if(rect) + { + i=move_intersection_sr(guysbuf[bie[u].i].s_tile, guysbuf[bie[u].i].s_tile+zc_max(guysbuf[bie[u].i].s_width-1, 0), selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_ss(guysbuf[bie[u].i].s_tile, guysbuf[bie[u].i].s_tile+zc_max(guysbuf[bie[u].i].s_width-1, 0), selection_first, selection_last); + } + } + else + { + if(rect) + { + i=move_intersection_rr(tile_col(guysbuf[bie[u].i].s_tile), tile_row(guysbuf[bie[u].i].s_tile), guysbuf[bie[u].i].s_width, guysbuf[bie[u].i].s_height, selection_left, selection_top, selection_width, selection_height); + } + else + { + i=move_intersection_rs(tile_col(guysbuf[bie[u].i].s_tile), tile_row(guysbuf[bie[u].i].s_tile), guysbuf[bie[u].i].s_width, guysbuf[bie[u].i].s_height, selection_first, selection_last); + } + } + + if(((q==1) && i==ti_broken) || (q==0 && i!=ti_none)) + { + sprintf(temptext, "%s (%s)\n", bie[u].s, darknut?"broken shield":"secondary tiles"); + + if(strlen(tile_move_list_text)<65000) + { + strcat(tile_move_list_text, temptext); + } + else + { + if(!flood) + { + strcat(tile_move_list_text, "...\n...\n...\nmany others"); + flood=true; + } + } + + found=true; + } + } + } + } + + if(found) + { + sprintf(buf2, "The tiles used by the following enemies"); + + if(move) + { + sprintf(buf3, "will be partially cleared by the move."); + sprintf(buf4, "Proceed?"); + } + else + { + sprintf(buf3, "will be partially or completely"); + sprintf(buf4, "overwritten by this process. Proceed?"); + } + + tile_move_list_dlg[1].dp=buf2; + tile_move_list_dlg[2].dp=buf3; + tile_move_list_dlg[3].dp=buf4; + tile_move_list_dlg[4].dp=tile_move_list_text; + tile_move_list_dlg[4].d2=0; + + if(TileProtection) + { + if(is_large) + large_dialog(tile_move_list_dlg); + + int ret=zc_popup_dialog(tile_move_list_dlg,2); + position_mouse_z(0); + + if(ret!=5) + { + done = true; + } + } + } + } + } + } + + // + // copy tiles and delete if needed (move) + + if(!done) + { + go_tiles(); + + int diff=dest_first-src_first; + + if(rect) + { + for(int r=0; r=NEWMAXTILES) + continue; + + reset_tile(newtilebuf, dt, newundotilebuf[st].format); + + for(int j=0; j((dest_first+cols-1)%TILES_PER_ROW))||(st(dest_first+((rows-1)*TILES_PER_ROW)+(cols-1)))) + reset_tile(newtilebuf, st, tf4Bit); + } + } + } + } + else + { + for(int c=0; c=NEWMAXTILES) + continue; + + reset_tile(newtilebuf, dt, newundotilebuf[st].format); + + for(int j=0; j(dest_first+c-1)) + reset_tile(newtilebuf, st, tf4Bit); + } + } + } + + if(move) + { + for(int u=0; u=0); (tile=0); (tile=copy)&&(TheMaps[i*MAPSCRS+j].data[k]=copy)&& (TheMaps[i*MAPSCRS+j].secretcombo[k]=copy)&&(TheMaps[i*MAPSCRS+j].undercombo= copy) && (TheMaps[i*MAPSCRS+j].ffcs[k].data < copy+copycnt) && (TheMaps[i*MAPSCRS+j].ffcs[k].data != 0)) + { + TheMaps[i*MAPSCRS+j].ffcs[k].data = TheMaps[i*MAPSCRS+j].ffcs[k].data-copy+tile; + } + } + } + } + + for(int i=0; i=copy)&&(DoorComboSets[i].walkthroughcombo[j]=copy)&&(DoorComboSets[i].bombdoorcombo_u[j]=copy)&&(DoorComboSets[i].bombdoorcombo_d[j]=copy)&&(DoorComboSets[i].bombdoorcombo_l[j]=copy)&&(DoorComboSets[i].bombdoorcombo_r[j]=copy)&&(DoorComboSets[i].doorcombo_u[j][k]=copy)&&(DoorComboSets[i].doorcombo_d[j][k]=copy)&&(DoorComboSets[i].doorcombo_l[j][k]=copy)&&(DoorComboSets[i].doorcombo_r[j][k]=copy)&&(combobuf[i].nextcombo=copy)&&(combo_aliases[i].combos[j]=copy && favorite_combos[i]tile_col(lasttile)) + { + coldiff=tile_col(firsttile)-tile_col(lasttile); + firsttile-=coldiff; + lasttile+=coldiff; + } + + go_tiles(); + + //if copying to an earlier tile, copy from left to right + //otherwise, copy from right to left + for(int t=firsttile; t<=lasttile; t++) + if(!rect_sel || + ((tile_col(t)>=tile_col(firsttile)) && + (tile_col(t)<=tile_col(lasttile)))) + reset_tile(newtilebuf, t, tf4Bit); + + tile=tile2=zc_min(tile,tile2); + saved=false; + register_blank_tiles(); + } +} + +void overlay_tile2(int dest,int src,int cs,bool backwards) +{ + byte buf[256]; + go_tiles(); + + unpack_tile(newtilebuf, dest, 0, false); + + for(int i=0; i<256; i++) + buf[i] = unpackbuf[i]; + + unpack_tile(newtilebuf, src, 0, false); + + if(newtilebuf[src].format>tf4Bit) + { + cs=0; + } + + cs &= 15; + cs <<= CSET_SHFT; + + for(int i=0; i<256; i++) + { + if(backwards) + { + if(!buf[i]) + { + buf[i] = unpackbuf[i]+cs; + } + } + else + { + if(unpackbuf[i]) + { + buf[i] = unpackbuf[i]+cs; + } + } + } + + pack_tile(newtilebuf, buf,dest); + saved=false; +} + +void mass_overlay_tile(int dest1, int dest2, int src, int cs, bool backwards, bool rect_sel) +{ + byte buf[256]; + go_tiles(); + + unpack_tile(newtilebuf, src, 0, false); + + for(int i=0; i<256; i++) + buf[i] = unpackbuf[i]; + + if(newtilebuf[src].format>tf4Bit) + { + cs=0; + } + + cs &= 15; + cs <<= CSET_SHFT; + + if(!rect_sel) + { + for(int d=dest1; d <= dest2; ++d) + { + unpack_tile(newtilebuf, d, 0, false); + + for(int i=0; i<256; i++) + { + if(!backwards) + { + if(!buf[i]) + { + buf[i] = unpackbuf[i] + cs; + } + } + else + { + if(unpackbuf[i]) + { + buf[i] = unpackbuf[i] + cs; + } + } + } + + pack_tile(newtilebuf, buf,d); + + if(!blank_tile_table[src]) + { + blank_tile_table[d]=false; + } + } + } + else + { + int rmin=zc_min(tile_row(dest1),tile_row(dest2)); + int rmax=zc_max(tile_row(dest1),tile_row(dest2)); + int cmin=zc_min(tile_col(dest1),tile_col(dest2)); + int cmax=zc_max(tile_col(dest1),tile_col(dest2)); + int d=0; + + for(int j=cmin; j<=cmax; ++j) + { + for(int k=rmin; k<=rmax; ++k) + { + d=j+TILES_PER_ROW*k; + unpack_tile(newtilebuf, d, 0, false); + + for(int i=0; i<256; i++) + { + if(!backwards) + { + if(!buf[i]) + { + buf[i] = unpackbuf[i] + cs; + } + } + else + { + if(unpackbuf[i]) + { + buf[i] = unpackbuf[i] + cs; + } + } + } + + pack_tile(newtilebuf, buf,d); + + if(!blank_tile_table[src]) + { + blank_tile_table[d]=false; + } + } + } + } + + return; +} + +void sel_tile(int &tile, int &tile2, int &first, int type, int s) +{ + tile+=s; + bound(tile,0,NEWMAXTILES-1); + + if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT])) + tile2 = tile; + + first = tile - (tile%TILES_PER_PAGE); +} + +void convert_tile(int t, int bp2, int cs, bool shift, bool alt) +{ + int cst; + + switch(bp2) + { + case tf4Bit: + switch(newtilebuf[t].format) + { + case tf4Bit: + //already in the right format + break; + + case tf8Bit: + unpack_tile(newtilebuf, t, 0, true); + + if(alt) //reduce + { + for(int i=0; i<256; i++) + { + if(!shift||unpackbuf[i]!=0) + { + unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]); + } + } + } + else //truncate + { + for(int i=0; i<256; i++) + { + unpackbuf[i]&=15; + } + } + + reset_tile(newtilebuf, t, tf4Bit); + pack_tile(newtilebuf, unpackbuf, t); + break; + } + + break; + + case tf8Bit: + switch(newtilebuf[t].format) + { + case tf4Bit: + unpack_tile(newtilebuf, t, 0, true); + cst = cs&15; + cst <<= CSET_SHFT; + + for(int i=0; i<256; i++) + { + if(!shift||unpackbuf[i]!=0) + { + unpackbuf[i]+=cst; + } + } + + reset_tile(newtilebuf, t, tf8Bit); + pack_tile(newtilebuf, unpackbuf, t); + break; + + case tf8Bit: + //already in the right format + break; + } + + break; + } +} + +static DIALOG create_relational_tiles_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL }, + { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL }, + { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL }, + { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL }, + { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void draw_tile_list_window() +{ + int w = 320; + int h = 240; + + if(is_large) + { + w *= 2; + h *= 2; + } + + int window_xofs=(zq_screen_w-w-12)>>1; + int window_yofs=(zq_screen_h-h-25-6)>>1; + scare_mouse(); + jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN); + jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP); + + FONT *oldfont = font; + font = lfont; + jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true); + font=oldfont; + unscare_mouse(); + return; +} + +void show_blank_tile(int t) +{ + char tbuf[80], tbuf2[80], tbuf3[80]; + sprintf(tbuf, "Tile is %s blank.", blank_tile_table[t]?"":"not"); + sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-'); + sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-'); + jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,lfont); +} + +void do_convert_tile(int tile, int tile2, int cs, bool rect_sel, bool fourbit, bool shift, bool alt) +{ + char buf[80]; + sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",fourbit?4:8); + + if(jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + go_tiles(); + saved=false; + + if(fourbit) + { + memset(cset_reduce_table, 0, 256); + memset(col_diff,0,3*128); + calc_cset_reduce_table(RAMpal, cs); + } + + int firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0; + + if(rect_sel && tile_col(firsttile)>tile_col(lasttile)) + { + coldiff=tile_col(firsttile)-tile_col(lasttile); + firsttile-=coldiff; + lasttile+=coldiff; + } + + for(int t=firsttile; t<=lasttile; t++) + if(!rect_sel || + ((tile_col(t)>=tile_col(firsttile)) && + (tile_col(t)<=tile_col(lasttile)))) + convert_tile(t, fourbit?tf4Bit:tf8Bit, cs, shift, alt); + + tile=tile2=zc_min(tile,tile2); + } +} + +int select_tile(int &tile,int &flip,int type,int &cs,bool edit_cs,int exnow, bool always_use_flip) +{ + reset_combo_animations(); + reset_combo_animations2(); + bound(tile,0,NEWMAXTILES-1); + ex=exnow; + int done=0; + int oflip=flip; + int otile=tile; + int ocs=cs; + int first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page + int copy=-1; + int tile2=tile,copycnt=0; + int tile_clicked=-1; + bool rect_sel=true; + bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1); + position_mouse_z(0); + + go(); + + register_used_tiles(); + int window_xofs=0; + int window_yofs=0; + int screen_xofs=0; + int screen_yofs=0; + int panel_yofs=0; + int w = 320; + int h = 240; + int mul = 1; + FONT *tfont = pfont; + + if(is_large) + { + w *= 2; + h *= 2; + mul = 2; // multiply dimensions by 2 + window_xofs=(zq_screen_w-w-12)>>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + panel_yofs=3; + tfont = lfont_l; + } + + draw_tile_list_window(); + int f=0; + draw_tiles(first,cs,f); + + if(type==0) + { + tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel); + } + else + { + tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip); + } + + go_tiles(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + bool bdown=false; + + do + { + //int tile_col(int tile) + //int tile_row(int tile) + //int tile_page(int tile) + //int tile_page_row(int tile) + rest(4); + int top=tile_row(zc_min(tile, tile2)); + int left=zc_min(tile_col(tile), tile_col(tile2)); + int rows=tile_row(zc_max(tile, tile2))-top+1; + int columns=zc_max(tile_col(tile), tile_col(tile2))-left+1; + bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel; + bool redraw=false; + + if(mouse_z!=0) + { + sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE)); + position_mouse_z(0); + redraw=true; + } + + if(keypressed()) + { + //tile_page=(tile/TILES_PER_PAGE); + //tile_row=(tile/TILES_PER_ROW); + //tile_col=(tile%TILES_PER_ROW); + //tile_page_row=(tile_row/TILE_ROWS_PER_PAGE); + switch(readkey()>>8) + { + case KEY_ENTER_PAD: + case KEY_ENTER: + done=2; + break; + + case KEY_ESC: + done=1; + break; + + case KEY_F1: + onHelp(); + break; + + case KEY_EQUALS: + case KEY_PLUS_PAD: + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL] || + key[KEY_ALT] || key[KEY_ALTGR]) + { + if(is_rect) + { + for(int col=0; col0) ? cs-1:11; + + redraw=true; + break; + } + + case KEY_UP: + { + switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?1:0)) + { + case 3: //ALT and CTRL + case 2: //ALT + if(is_rect) + { + saved=false; + go_slide_tiles(columns, rows, top, left); + int bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format; + bool same = true; + + for(int d=0; d=NEWMAXTILES) + srctile-=rows*TILES_PER_ROW; + src_pixelrow=(qword*)(newtilebuf[srctile].data); + } + + *dest_pixelrow=*src_pixelrow; + dest_pixelrow++; + src_pixelrow++; + } + } + + qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck)); + + for(int b=0; b=0; r--) + { + int temptile=((top+r)*TILES_PER_ROW)+left+c; + qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1))); + qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1))); + + for(int pixelrow=(8<=0; pixelrow--) + { + if(pixelrow>4; + *dest_pixelrow|=(*(dest_pixelrow+1)<<4); + + if(p==6) *(dest_pixelrow+1)=*(dest_pixelrow+1)>>4; + } + else + { + *dest_pixelrow=*(dest_pixelrow+1); + } + + dest_pixelrow++; + } + +#else + + for(int p=0; p<(8*bitcheck)-1; p++) + { + if(bitcheck==tf4Bit) + { + *dest_pixelrow=*dest_pixelrow<<4; + *dest_pixelrow|=(*(dest_pixelrow+1)>>4); + + if(p==6) *(dest_pixelrow+1)=*(dest_pixelrow+1)<<4; + } + else + { + *dest_pixelrow=*(dest_pixelrow+1); + } + + dest_pixelrow++; + } + +#endif + + if(c==columns-1) + { + if(!(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])) + { + byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck)); +#ifdef ALLEGRO_LITTLE_ENDIAN + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc<<4; + else *dest_pixelrow=*tempsrc; + +#else + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc>>4; + else *dest_pixelrow=*tempsrc; + +#endif + } + } + else + + { + byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck)); +#ifdef ALLEGRO_LITTLE_ENDIAN + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc<<4; + else *dest_pixelrow=*tempsrc; + +#else + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc>>4; + else *dest_pixelrow=*tempsrc; + +#endif + } + + dest_pixelrow++; + } + } + } + + register_blank_tiles(); + redraw=true; + } + + break; + + case 1: //CTRL + case 0: //None + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?-(tile%TILES_PER_ROW):-1); + redraw=true; + + default: //Others + break; + } + } + break; + + case KEY_RIGHT: + { + switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?1:0)) + { + case 3: //ALT and CTRL + case 2: //ALT + if(is_rect) + { + saved=false; + go_slide_tiles(columns, rows, top, left); + int bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format; + bool same = true; + + for(int c=0; c=0; c--) + { + int temptile=((top+r)*TILES_PER_ROW)+left+c; + byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1; + + for(int pixelrow=15; pixelrow>=0; pixelrow--) + { +#ifdef ALLEGRO_LITTLE_ENDIAN + + //*dest_pixelrow=(*dest_pixelrow)<<4; + for(int p=0; p<(8*bitcheck)-1; p++) + { + if(bitcheck==tf4Bit) + { + *dest_pixelrow=*dest_pixelrow<<4; + *dest_pixelrow|=(*(dest_pixelrow-1)>>4); + + if(p==6) *(dest_pixelrow-1)=*(dest_pixelrow-1)<<4; + } + else + { + *dest_pixelrow=*(dest_pixelrow-1); + } + + dest_pixelrow--; + } + +#else + + for(int p=0; p<(8*bitcheck)-1; p++) + { + if(bitcheck==tf4Bit) + { + *dest_pixelrow=*dest_pixelrow>>4; + *dest_pixelrow|=(*(dest_pixelrow-1)<<4); + + if(p==6) *(dest_pixelrow-1)=*(dest_pixelrow-1)>>4; + } + else + { + *dest_pixelrow=*(dest_pixelrow-1); + } + + dest_pixelrow--; + } + +#endif + + if(c==0) + { + if(!(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])) + { + byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1); +#ifdef ALLEGRO_LITTLE_ENDIAN + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc>>4; + else *dest_pixelrow=*tempsrc; + +#else + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc<<4; + else *dest_pixelrow=*tempsrc; + +#endif + } + } + else + { + byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1); +#ifdef ALLEGRO_LITTLE_ENDIAN + + // (*dest_pixelrow)|=((*(dest_pixelrow-16))&0xF000000000000000ULL)>>60; + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc>>4; + else *dest_pixelrow=*tempsrc; + +#else + + if(bitcheck==tf4Bit) *dest_pixelrow|=*tempsrc<<4; + else *dest_pixelrow=*tempsrc; + +#endif + } + + dest_pixelrow--; + } + } + } + + register_blank_tiles(); + redraw=true; + } + + break; + + case 1: //CTRL + case 0: //None + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1); + redraw=true; + + default: //Others + break; + } + } + break; + + case KEY_PGUP: + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?-1*(tile_row(tile)*TILES_PER_ROW):-TILES_PER_PAGE); + redraw=true; + break; + + case KEY_PGDN: + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?((TILE_PAGES*TILE_ROWS_PER_PAGE)-tile_row(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE); + redraw=true; + break; + + case KEY_HOME: + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?-(tile):-(tile%TILES_PER_PAGE)); + redraw=true; + break; + + case KEY_END: + sel_tile(tile,tile2,first,type,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1); + redraw=true; + break; + + case KEY_P: + { + int whatPage = gettilepagenumber("Goto Page", 0); + + if(whatPage >= 0) + sel_tile(tile,tile2,first,type,((whatPage-tile_page(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW); + + break; + } + + case KEY_O: + if(type==0 && copy>=0) + { + go_tiles(); + + if(key[KEY_LSHIFT] ||key[KEY_RSHIFT]) + { + mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]), rect_sel); + } + else + { + overlay_tile(newtilebuf,tile,copy,cs,(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])); + } + + saved=false; + redraw=true; + } + + break; + + case KEY_E: + if(type==0) + { + edit_tile(tile,flip,cs); + draw_tile_list_window(); + redraw=true; + } + + break; + + case KEY_G: + if(type==0) + { + grab_tile(tile,cs); + draw_tile_list_window(); + redraw=true; + } + + break; + + case KEY_C: + copy=zc_min(tile,tile2); + copycnt=abs(tile-tile2)+1; + redraw=true; + break; + + case KEY_X: + if(type==2) + { + ex=(ex+1)%3; + } + + break; + + //usetiles=true; + case KEY_R: + if(type==2) + break; + + go_tiles(); + + if(is_rect) + { + for(int col=0; colNEWMAXTILES) + { + jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,lfont); + break; + } + + for(int i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i) + { + reset_tile(newtilebuf, tile+i, bitcheck); + } + + if(create_relational_tiles_dlg[3].flags&D_SELECTED) + { + for(int i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i) + { + for(int j=0; j0; --i) + { + for(int j=0; j=0 && y<208*mul) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t = (y>>(4+is_large))*TILES_PER_ROW + (x>>(4+is_large)) + first; + + if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT])) + { + tile2=t; + } + else + { + tile=tile2=t; + } + + if(tile_clicked!=t) + { + dclick_status=DCLICK_NOT; + } + else if(dclick_status == DCLICK_AGAIN) + { + while(gui_mouse_b()) + { + /* do nothing */ + } + + if(((y>>(4+is_large))*TILES_PER_ROW + (x>>(4+is_large)) + first)!=t) + { + dclick_status=DCLICK_NOT; + } + else + { + if(type==0) + { + edit_tile(tile,flip,cs); + draw_tile_list_window(); + redraw=true; + } + else + { + done=2; + } + } + } + + tile_clicked=t; + } + else if(x>300*mul && !bdown) + { + if(y<224*mul && first>0) + { + first-=TILES_PER_PAGE; + redraw=true; + } + + if(y>=224*mul && first=0 && y<208*mul) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t = ((y)>>(4+is_large))*TILES_PER_ROW + ((x)>>(4+is_large)) + first; + + if(tzc_max(tile,tile2)) + tile=tile2=t; + } + + bdown = r_click = true; + f=8; + } + + if(gui_mouse_b()==0) + bdown=false; + + position_mouse_z(0); + +REDRAW: + + if((f%16)==0 || InvalidStatic) + redraw=true; + + if(redraw) + draw_tiles(first,cs,f); + + if(f&8) + { + if(rect_sel) + { + for(int i=zc_min(tile_row(tile),tile_row(tile2))*TILES_PER_ROW+ + zc_min(tile_col(tile),tile_col(tile2)); + i<=zc_max(tile_row(tile),tile_row(tile2))*TILES_PER_ROW+ + zc_max(tile_col(tile),tile_col(tile2)); i++) + { + if(i>=first && i=zc_min(tile_col(tile),tile_col(tile2)) && + tile_col(i)<=zc_max(tile_col(tile),tile_col(tile2))) + { + int x=(i%TILES_PER_ROW)<<(4+is_large); + int y=((i-first)/TILES_PER_ROW)<<(4+is_large); + rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(15)); + } + } + } + else + { + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++) + { + if(i>=first && icolor); + rebuild_trans_table(); + select_tile(t,f,0,c,true); + refresh(rALL); + return D_O_K; +} + +void draw_combo(BITMAP *dest, int x,int y,int c,int cs) +{ + if(c=0) + { + put_combo(buf,0,0,copy,cs,0,0); + stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul); + + if(copycnt>1) + { + textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy); + textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1); + } + else + { + textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy); + } + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<16*mul; dy++) + { + for(int dx=0; dx<16*mul; dx++) + { + screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+15, (216*mul)+yofs+15, vc(0)); + rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+15, (216*mul)+yofs+15, vc(15)); + line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+15, (216*mul)+yofs+15, vc(15)); + line(screen2, (31*mul), (216*mul)+yofs+15, (31*mul)+15, (216*mul)+yofs, vc(15)); + } + } + + jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + put_combo(buf,0,0,tile,cs,0,0); + stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul); + + if(tile>tile2) + { + zc_swap(tile,tile2); + } + + char cbuf[8]; + cbuf[0]=0; + + if(tile2!=tile) + { + sprintf(cbuf,"-%d",tile2); + } + + textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo:"); + textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf); + + if(tile2==tile) + { + int nextcombo=combobuf[tile].nextcombo; + int nextcset=combobuf[tile].nextcset; + jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP); + + if(nextcombo>0) + { + put_combo(buf,0,0,nextcombo,nextcset,0,0); + stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul); + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<16*mul; dy++) + { + for(int dx=0; dx<16*mul; dx++) + { + screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+15, (216*mul)+yofs+15, vc(0)); + rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+15, (216*mul)+yofs+15, vc(15)); + line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+15, (216*mul)+yofs+15, vc(15)); + line(screen2, (136*mul), (216*mul)+yofs+15, (136*mul)+15, (216*mul)+yofs, vc(15)); + } + } + + textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:"); + textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo); + } + + + FONT *tf = font; + font = tfont; + + if(buttons&2) + { + draw_text_button(screen2,((202)*mul),(213*mul)+yofs,(44*mul),(21*mul),"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + } + + if(buttons&4) + { + draw_text_button(screen2,((247)*mul),(213*mul)+yofs,(44*mul),(21*mul),"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true); + } + + font = tf; + + textprintf_ex(screen2,font,(305*mul),(212*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x88"); + textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:"); + textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page); + textprintf_ex(screen2,font,(305*mul),(228*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"\x89"); + + int window_xofs=0; + int window_yofs=0; + int screen_xofs=0; + int screen_yofs=0; + int w = 320*mul; + int h = 240*mul; + + if(is_large) + { + window_xofs=(zq_screen_w-w-12)>>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + } + + custom_vsync(); + scare_mouse(); + blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h); + unscare_mouse(); + SCRFIX(); + //destroy_bitmap(buf); +} + +void sel_combo(int &tile, int &tile2, int s, bool cols) +{ + int page = tile&0xFF00; + tile &= 0xFF; + + if(!cols) + tile += s; + else + { + if(s==-COMBOS_PER_ROW) + tile-=4; + + if(s==COMBOS_PER_ROW) + tile+=4; + + if(s==-1) + tile-=1; + + if(s==1) + tile+=1; + } + + /* + if(s==1) + { + if((tile&3)==3) + tile+=48; + else + ++tile; + } + if(s==-1) + { + if((tile&3)==0) + tile-=48; + else + --tile; + } + } + */ + bound(tile,0,255); + tile += page; + + if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT])) + tile2 = tile; +} + +word ctable[MAXCOMBOS]; + +void draw_combo_list_window() +{ + int window_xofs=0; + int window_yofs=0; + int w = 320; + int h = 240; + + if(is_large) + { + w *= 2; + h *= 2; + } + + window_xofs=(zq_screen_w-w-12)>>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + scare_mouse(); + jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN); + jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP); + FONT *oldfont = font; + font = lfont; + jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true); + font=oldfont; + unscare_mouse(); +} + + + +int select_combo_2(int &tile,int &cs) +{ + reset_combo_animations(); + reset_combo_animations2(); + // static int tile=0; + int page=tile>>8; + int tile2=tile; + int done=0; + int tile_clicked=-1; + int t2; + // int cs = CSet; + int copy=-1; + int copycnt=0; + + position_mouse_z(0); + + for(int i=0; i>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + panel_yofs=3; + tfont = lfont_l; + } + + draw_combo_list_window(); + draw_combos(page,cs,combo_cols); + combo_info(tile,tile2,cs,copy,copycnt,page,4); + unscare_mouse(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + bool bdown=false; + int f=0; + + do + { + rest(4); + bool redraw=false; + + if(mouse_z<0) + { + if(page0) + { + if(page>0) + { + --page; + tile=tile2=(page<<8)+(tile&0xFF); + } + + position_mouse_z(0); + redraw=true; + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_DEL: + tile=0; + done=2; + break; + + case KEY_ENTER_PAD: + case KEY_ENTER: + done=2; + break; + + case KEY_ESC: + done=1; + break; + + case KEY_F1: + onHelp(); + break; + + case KEY_SPACE: + combo_cols=!combo_cols; + redraw=true; + break; + + case KEY_EQUALS: + case KEY_PLUS_PAD: + cs = (cs<11) ? cs+1:0; + redraw=true; + break; + + case KEY_MINUS: + case KEY_MINUS_PAD: + cs = (cs>0) ? cs-1:11; + redraw=true; + break; + + case KEY_UP: + sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols); + redraw=true; + break; + + case KEY_DOWN: + sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols); + redraw=true; + break; + + case KEY_LEFT: + sel_combo(tile,tile2,-1,combo_cols); + redraw=true; + break; + + case KEY_RIGHT: + sel_combo(tile,tile2,1,combo_cols); + redraw=true; + break; + + case KEY_PGUP: + if(page>0) + { + --page; + tile=tile2=(page<<8)+(tile&0xFF); + } + + redraw=true; + break; + + case KEY_PGDN: + if(page=0 && y<208*mul) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t; + + if(!combo_cols) + { + t = (y>>(4+is_large))*COMBOS_PER_ROW + (x>>(4+is_large)); + } + else + { + t = ((x>>(6+is_large))*52) + ((x>>(4+is_large))&3) + ((y>>(4+is_large))<<2); + } + + bound(t,0,255); + t+=page<<8; + tile=tile2=t; + + if(tile_clicked!=t) + { + dclick_status=DCLICK_NOT; + } + else if(dclick_status == DCLICK_AGAIN) + { + while(gui_mouse_b()) + { + /* do nothing */ + } + + if(!combo_cols) + { + t2 = (y>>(4+is_large))*COMBOS_PER_ROW + (x>>(4+is_large)); + } + else + { + t2 = ((x>>(6+is_large))*52) + ((x>>(4+is_large))&3) + ((y>>(4+is_large))<<2); + } + + if(t2!=t) + { + dclick_status=DCLICK_NOT; + } + else + { + done=2; + } + } + + tile_clicked=t; + } + else if(y>=(208*mul) && x>(300*mul) && !bdown) + { + if(y<(224*mul)+panel_yofs && page>0) + { + --page; + redraw=true; + } + + if(y>=(224*mul)+panel_yofs && page=0 && y<208*mul) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t; + + if(!combo_cols) + t = (y>>(4+is_large))*COMBOS_PER_ROW + (x>>(4+is_large)); + else + t = ((x>>(6+is_large))*52) + ((x>>(4+is_large))&3) + ((y>>(4+is_large))<<2); + + bound(t,0,255); + t+=page<<8; + + if(tzc_max(tile,tile2)) + tile=tile2=t; + } + + bdown = r_click = true; + f=8; + } + + if(gui_mouse_b()==0) + bdown=false; + + if(redraw) + draw_combos(page,cs,combo_cols); + + combo_info(tile,tile2,cs,copy,copycnt,page,4); + + if(f&8) + { + int x,y; + scare_mouse(); + + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++) + { + if((i>>8)==page) + { + int t=i&255; + + if(!combo_cols) + { + x=(t%COMBOS_PER_ROW)<<(4+is_large); + y=(t/COMBOS_PER_ROW)<<(4+is_large); + } + else + { + x=((t&3) + ((t/52)<<2)) << (4+is_large); + y=((t%52)>>2) << (4+is_large); + } + + rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(15)); + } + } + + unscare_mouse(); + SCRFIX(); + } + + ++f; + + } + while(!done); + + for(int p=0; p-1) + page = pg; + + if(tl>-1) + tile = tl; + + int tile2=tile; + int done=0; + int cs = CSet; + int copy=-1; + int copycnt=0; + + int tile_clicked=-1; + int t2; + + bool masscopy; + + for(int i=0; i>1; + window_yofs=(zq_screen_h-h-25-6)>>1; + screen_xofs=window_xofs+6; + screen_yofs=window_yofs+25; + panel_yofs=3; + tfont = lfont_l; + } + + draw_combo_list_window(); + draw_combos(page,cs,combo_cols); + combo_info(tile,tile2,cs,copy,copycnt,page,6); + unscare_mouse(); + go_combos(); + position_mouse_z(0); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + bool bdown=false; + int f=0; + + do + { + rest(4); + bool redraw=false; + + if(mouse_z<0) + { + if(page0) + { + if(page>0) + { + --page; + tile=tile2=(page<<8)+(tile&0xFF); + } + + position_mouse_z(0); + redraw=true; + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_ENTER_PAD: + case KEY_ENTER: + done=2; + break; + + case KEY_ESC: + done=1; + break; + + case KEY_F1: + onHelp(); + break; + + case KEY_SPACE: + combo_cols=!combo_cols; + redraw=true; + break; + + case KEY_EQUALS: + case KEY_PLUS_PAD: + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i) + { + combobuf[i].tile = wrap(combobuf[i].tile + ((key[KEY_LSHIFT] || key[KEY_RSHIFT]) ? 20 : 1), + 0, NEWMAXTILES-1); + } + + setup_combo_animations(); + redraw=true; + } + else + { + cs = (cs<11) ? cs+1:0; + redraw=true; + } + + break; + + case KEY_MINUS: + case KEY_MINUS_PAD: + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i) + { + combobuf[i].tile = wrap(combobuf[i].tile - ((key[KEY_LSHIFT] || key[KEY_RSHIFT]) ? 20 : 1), + 0, NEWMAXTILES-1); + } + + setup_combo_animations(); + redraw=true; + } + else + { + cs = (cs>0) ? cs-1:11; + redraw=true; + } + + break; + + case KEY_UP: + sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols); + redraw=true; + break; + + case KEY_DOWN: + sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols); + redraw=true; + break; + + case KEY_LEFT: + sel_combo(tile,tile2,-1,combo_cols); + redraw=true; + break; + + case KEY_RIGHT: + sel_combo(tile,tile2,1,combo_cols); + redraw=true; + break; + + case KEY_PGUP: + if(page>0) + { + --page; + tile=tile2=(page<<8)+(tile&0xFF); + } + + redraw=true; + break; + + case KEY_PGDN: + if(page>2 | (w2&3)<<2; + w2=combobuf[i].csets; + combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F); + } + + redraw=true; + saved=false; + break; + + case KEY_M: + if((copy!=-1)&&(copy!=zc_min(tile,tile2))) + { + move_combos(tile,tile2,copy,copycnt); + saved=false; + } + + redraw=true; + break; + + case KEY_S: + tile=tile2=zc_min(tile,tile2); + + if(copy>=0 && tile!=copy) + { + go_combos(); + + for(int i=0; i>1; + w2=combobuf[i].csets; + combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F); + } + + saved=false; + } + else + { + go_combos(); + copy_combos(tile,tile2,copy,copycnt,masscopy); + setup_combo_animations(); + setup_combo_animations2(); + saved=false; + } + + redraw=true; + break; + + case KEY_I: + { + // rev.1509; Can now insert/remove all selected combos + int z=tile; + int numSelected = abs(tile-tile2) + 1; + tile=zc_min(tile,tile2); + tile2=MAXCOMBOS; + copy = tile + numSelected; // copy=tile+1; + copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile; + + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + char buf[64]; + + if(numSelected>1) + sprintf(buf,"Remove combos %d - %d?",tile, copy-1); + else + sprintf(buf,"Remove combo %d?",tile); + + if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',lfont)==1) + { + move_combos(tile,tile2,copy, copycnt); + //don't allow the user to undo; quest combo references are incorrect -DD + go_combos(); + redraw=true; + saved=false; + } + } + else + { + char buf[64]; + + if(numSelected>1) + sprintf(buf,"Insert %d blank combos?",numSelected); + else + sprintf(buf,"Insert a blank combo?"); + + if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',lfont)==1) + { + move_combos(copy,tile2,tile, copycnt); + go_combos(); + redraw=true; + saved=false; + } + } + + copy=-1; + tile2=tile=z; + + //thse next 2 lines are handled by the move_combos function now + //setup_combo_animations(); + //setup_combo_animations2(); + } + break; + + case KEY_DEL: + { + char buf[40]; + + if(tile==tile2) + { + sprintf(buf,"Delete combo %d?",tile); + } + else + { + sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2)); + } + + if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + go_combos(); + + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++) + { + clear_combo(i); + } + + tile=tile2=zc_min(tile,tile2); + redraw=true; + saved=false; + setup_combo_animations(); + setup_combo_animations2(); + } + } + break; + } + + clear_keybuf(); + } + + if(gui_mouse_b()&1) + { + if(is_large) + { + if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13)) + { + if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs)) + { + done=1; + } + } + } + + int x=gui_mouse_x()-screen_xofs; + int y=gui_mouse_y()-screen_yofs; + + if(y>=0 && y<(208*mul)) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t; + + if(!combo_cols) + { + t = (y>>(4+is_large))*COMBOS_PER_ROW + (x>>(4+is_large)); + } + else + { + t = ((x>>(6+is_large))*52) + ((x>>(4+is_large))&3) + ((y>>(4+is_large))<<2); + } + + bound(t,0,255); + t+=page<<8; + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + tile2=t; + } + else + { + tile=tile2=t; + } + + if(tile_clicked!=t) + { + dclick_status=DCLICK_NOT; + } + else if(dclick_status == DCLICK_AGAIN) + { + while(gui_mouse_b()) + { + /* do nothing */ + } + + if(!combo_cols) + { + t2 = (y>>4)*COMBOS_PER_ROW + (x>>4); + } + else + { + t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2); + } + + bound(t2,0,255); + t2+=page<<8; + + if(t2!=t) + { + dclick_status=DCLICK_NOT; + } + else + { + go_combos(); + edit_combo(tile,false,cs); + redraw=true; + setup_combo_animations(); + setup_combo_animations2(); + } + } + + tile_clicked=t; + } + else if(x>(300*mul) && !bdown) + { + if(y<(224*mul)+panel_yofs && page>0) + { + --page; + redraw=true; + } + + if(y>=(224*mul)+panel_yofs && page=0 && y<(208*mul)) + { + x=zc_min(zc_max(x,0),(320*mul)-1); + int t; + + if(!combo_cols) + { + t = (y>>(4+is_large))*COMBOS_PER_ROW + (x>>(4+is_large)); + } + else + { + t = ((x>>(6+is_large))*52) + ((x>>(4+is_large))&3) + ((y>>(4+is_large))<<2); + } + + bound(t,0,255); + t+=page<<8; + + if(tzc_max(tile,tile2)) + { + tile=tile2=t; + } + } + + bdown = r_click = true; + f=8; + } + +REDRAW: + + if(gui_mouse_b()==0) + { + bdown=false; + } + + if(redraw) + { + draw_combos(page,cs,combo_cols); + } + + combo_info(tile,tile2,cs,copy,copycnt,page,6); + + if(f&8) + { + int x,y; + scare_mouse(); + + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++) + { + if((i>>8)==page) + { + int t=i&255; + + if(!combo_cols) + { + x=(t%COMBOS_PER_ROW)<<(4+is_large); + y=(t/COMBOS_PER_ROW)<<(4+is_large); + } + else + { + x=((t&3) + ((t/52)<<2)) << (4+is_large); + y=((t%52)>>2) << (4+is_large); + } + + rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(15)); + } + } + + unscare_mouse(); + SCRFIX(); + } + + ++f; + + //Seriously? There is duplicate code for the r-click menu? -Gleeok + if(r_click) + { + int m = popup_menu(select_combo_rc_menu,gui_mouse_x(),gui_mouse_y()); + redraw=true; + + switch(m) + { + case 0: + go_combos(); + copy=zc_min(tile,tile2); + copycnt=abs(tile-tile2)+1; + break; + + case 1: + if((key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) && copy != -1) + { + if(advpaste(tile, tile2, copy)==1) + { + saved=false; + redraw=true; + copy=-1; + } + + break; + } + + masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0; + + if(copy==-1) + { + go_combos(); + + for(int i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++) + { + combobuf[i].flip^=2; + byte w2=combobuf[i].walk; + combobuf[i].walk=(w2&5)<<1 | (w2& ~5)>>1; + w2=combobuf[i].csets; + combobuf[i].csets=(w2&0x30)<<2 | (w2& ~0x30)>>2; + } + + saved=false; + } + else + { + go_combos(); + copy_combos(tile,tile2,copy,copycnt,masscopy); + setup_combo_animations(); + setup_combo_animations2(); + saved=false; + } + + redraw=true; + break; + + case 2: + { + tile=tile2=zc_min(tile,tile2); + + if(copy>=0 && tile!=copy) + { + go_combos(); + + for(int i=0; ishowDialog(ts); + if(!ts.userCanceled()) + { + curr_combo.tile=ts.getTile(); + curr_combo.flip=ts.getOrientation(); + return D_REDRAW; + } + /* + if(select_tile(t,f,1,edit_combo_cset,true,0,true)) + { + curr_combo.tile=t; + curr_combo.flip=f; + return D_REDRAW; + } + */ + } + + return D_O_K; +} + +int d_combo_loader(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg==MSG_DRAW) + { + FONT *f = is_large ? lfont_l : font; + textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:"); + textprintf_ex(screen,f,d->x+(!is_large ? 50 : 75),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.tile); + textprintf_ex(screen,f,d->x,d->y+(!is_large ? 8 : 14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:"); + textprintf_ex(screen,f,d->x+(!is_large ? 50 : 75),d->y+(!is_large ? 8 : 14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip); + textprintf_ex(screen,f,d->x,d->y+(!is_large ? 24 : 36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:"); + } + + return D_O_K; +} + +combotype_struct bict[cMAX]; +int bict_cnt=-1; + +void build_bict_list() +{ + bict[0].s = (char *)"(None)"; + bict[0].i = 0; + bict_cnt=1; + + for(int i=1; i0) + zc_swap(bict[i],bict[j]); + +} + +const char *combotypelist(int index, int *list_size) +{ + if(index<0) + { + *list_size = bict_cnt; + return NULL; + } + + return bict[index].s; +} + +int onCmb_dlg_h(); +int onCmb_dlg_v(); +int onCmb_dlg_r(); + +int click_d_ctile_proc() +{ + d_ctile_proc(MSG_CLICK,NULL,0); + return D_REDRAW; +} + +int click_d_combo_proc(); + +static ListData flag_list(flaglist, &font); + +static DIALOG combo_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 54, 21, 241, 184, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 105, 180, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 185, 180, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'h', 0, 0, 0, (void *) onCmb_dlg_h, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'v', 0, 0, 0, (void *) onCmb_dlg_v, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'r', 0, 0, 0, (void *) onCmb_dlg_r, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 't', 0, 0, 0, (void *) click_d_ctile_proc, NULL, NULL }, + // 8 + { d_combo_loader, 60, 48, 0, 0, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + { d_comboframe_proc, 158, 46, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 160, 48, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ctile_proc, 160, 48, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_numedit_proc, 102+5, 68, 21, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // 13 + { d_comboframe_proc, 190, 46, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_wflag_proc, 192, 48, 8, 8, vc(12), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 192, 56, 8, 8, vc(12), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 200, 48, 8, 8, vc(12), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 200, 56, 8, 8, vc(12), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + // 18 + { d_comboframe_proc, 222, 46, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_wflag_proc, 224, 48, 8, 8, vc(11), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 232, 48, 8, 8, vc(11), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 224, 56, 8, 8, vc(11), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + { d_wflag_proc, 232, 56, 8, 8, vc(11), vc(7), 0, 0, 0, 1, NULL, NULL, NULL }, + // 23 + { jwin_text_proc, 60, 126, 48, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_droplist_proc, 89, 122, 180, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 60, 90, 72, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, (void *) "A.Frames:", NULL, NULL }, + { jwin_text_proc, 60, 108, 64, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, (void *) "A.Speed:", NULL, NULL }, + { jwin_numedit_proc, 102+5, 86, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_numedit_proc, 102+5, 104, 26, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 192, 71, 40, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) "Cycle:", NULL, NULL }, + // 30 + { d_comboframe_proc, 190, 79, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 192, 81, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 60, 144, 48, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) "Flag:", NULL, NULL }, + { jwin_droplist_proc, 89, 140, 180, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &flag_list, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'n', 0, 0, 0, (void *) click_d_combo_proc, NULL, NULL }, + { jwin_text_proc, 140, 108, 40, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, (void *) "A.SkipX:", NULL, NULL }, + { jwin_numedit_proc, 180, 104, 26, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 210, 108, 40, 8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, (void *) "A.SkipY:", NULL, NULL }, + { jwin_numedit_proc, 250, 104, 26, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 60, 160, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Refresh Animation on Room Entry", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_check_proc, 60, 169, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Restart Animation when Cycled To", NULL, NULL }, + // 42 + { jwin_button_proc, 271, 125, 12, 12, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "?", NULL, NULL }, + { jwin_button_proc, 271, 143, 12, 12, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "?", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int click_d_combo_proc() +{ + if(key[KEY_LCONTROL]||key[KEY_RCONTROL]) + { + nextcombo_fake_click=2; + } + else + { + nextcombo_fake_click=1; + } + + d_combo_proc(MSG_CLICK,combo_dlg+31,0); + nextcombo_fake_click=0; + return D_REDRAW; +} + +int onCmb_dlg_h() +{ + curr_combo.flip^=1; + + zc_swap(combo_dlg[14].flags, combo_dlg[16].flags); + zc_swap(combo_dlg[15].flags, combo_dlg[17].flags); + zc_swap(combo_dlg[19].flags, combo_dlg[20].flags); + zc_swap(combo_dlg[21].flags, combo_dlg[22].flags); + + for(int i=0; i<4; i++) + if(combo_dlg[i+14].flags & D_SELECTED) + curr_combo.walk |= 1<8, then it's a negative. + { + csets |= 0xF0; + } + + sprintf(combonumstr,"Combo %d", c); + sprintf(cset_str,"%d",csets); + sprintf(frm,"%d",vbound(curr_combo.frames,0,NEWMAXTILES-curr_combo.tile)); + sprintf(spd,"%d",curr_combo.speed); + sprintf(skip,"%d",curr_combo.skipanim); + sprintf(skipy,"%d",curr_combo.skipanimy); + combo_dlg[12].dp = cset_str; + + for(int i=0; i<4; i++) + { + combo_dlg[i+14].flags = curr_combo.walk&(1<d2; + int f = 0; + + if(select_tile(d->d1,f,1,cs,true)) + { + int ok=1; + + if(newtilebuf[d->d1].format==tf8Bit) + jwin_alert("Warning", + "You have selected an 8-bit tile.", + "It will not be drawn correctly", + "on the file select screen.", + "&OK",NULL,'o',0,lfont); + + return D_REDRAW; + } + } + break; + + case MSG_DRAW: + if(is_large) + { + d->w = 32+4; + d->h = 32+4; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + overtile16(buf,d->d1,0,0,d->fg,0); + stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4); + destroy_bitmap(buf); + jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP); + blit(bigbmp,screen,0,0,d->x-is_large,d->y-is_large,d->w,d->h); + destroy_bitmap(bigbmp); + } + + break; + } + + return D_O_K; +} + +static DIALOG icon_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL }, + { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL }, + { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL }, + { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL }, + { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL }, + { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL }, + { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL }, + { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL }, + { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onIcons() +{ + PALETTE pal; + // pal = RAMpal; + memcpy(pal,RAMpal,sizeof(RAMpal)); + icon_dlg[0].dp2=lfont; + + for(int i=0; i<4; i++) + { + icon_dlg[i+2].d1 = misc.icons[i]; + icon_dlg[i+2].fg = i+6; + load_cset(pal, i+6, pSprite(i+spICON1)); + } + + set_palette(pal); + + if(is_large) + large_dialog(icon_dlg); + + int ret = zc_popup_dialog(icon_dlg,7); + + if(ret==6) + { + for(int i=0; i<4; i++) + { + if(misc.icons[i] != icon_dlg[i+2].d1) + { + misc.icons[i] = icon_dlg[i+2].d1; + saved=false; + } + } + } + + set_palette(RAMpal); + return D_O_K; +} + +void center_zq_tiles_dialogs() +{ + jwin_center_dialog(combo_dlg); + jwin_center_dialog(create_relational_tiles_dlg); + jwin_center_dialog(icon_dlg); + jwin_center_dialog(leech_dlg); + jwin_center_dialog(tile_move_list_dlg); +} + + +// Identical to jwin_frame_proc, but is treated differently by large_dialog() +int d_comboframe_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg == MSG_DRAW) + { + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1); + } + + return D_O_K; +} + +int d_combo_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + { + if(d->flags&D_NOCLICK) + { + break; + } + + int combo2; + int cs; + + if(key[KEY_LSHIFT]) + { + if(gui_mouse_b()&1) + { + d->d1++; + + if(d->d1>=MAXCOMBOS) d->d1=0; + } + else if(gui_mouse_b()&2) + { + d->d1--; + + if(d->d1<0) d->d1=MAXCOMBOS-1; + } + + return D_REDRAW; + } + else if(key[KEY_RSHIFT]) + { + if(gui_mouse_b()&1) + { + d->fg++; + + if(d->fg>11) d->fg=0; + } + else if(gui_mouse_b()&2) + { + d->fg--; + + if(d->fg<0) d->fg=11; + } + + return D_REDRAW; + } + else if(key[KEY_ALT]) + { + if(gui_mouse_b()&1) + { + d->d1 = Combo; + d->fg = CSet; + } + + return D_REDRAW; + } + else if(gui_mouse_b()&2||nextcombo_fake_click==2) //right mouse button + { + if(d->d1==0&&d->fg==0&&!(gui_mouse_b()&1)) + { + return D_O_K; + } + + d->d1=0; + d->fg=0; + return D_REDRAW; + } + else if(gui_mouse_b()&1||nextcombo_fake_click==1) //left mouse button + { + combo2=d->d1; + cs=d->fg; + + if(select_combo_2(combo2, cs)) + { + d->d1=combo2; + d->fg=cs; + } + + return D_REDRAW; + } + else + { + return D_REDRAWME; + } + } + + break; + + case MSG_DRAW: + if(is_large) + { + d->w = 32; + d->h = 32; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(d->d1==-1) // Display curr_combo instead of combobuf + { + newcombo *hold = combobuf; + combobuf = &curr_combo; + putcombo(buf,0,0,0,d->fg); + combobuf = hold; + } + else if(d->d1) + { + putcombo(buf,0,0,d->d1,d->fg); + } + + stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h); + destroy_bitmap(buf); + blit(bigbmp,screen,0,0,d->x-is_large,d->y-is_large,d->w,d->h); + destroy_bitmap(bigbmp); + } + } + + return D_O_K; +} + +void center_zq_tiles_dialog() +{ + jwin_center_dialog(advpaste_dlg); +} + + + diff --git a/src/zq_tiles.h b/src/zq_tiles.h new file mode 100644 index 0000000000..efec774498 --- /dev/null +++ b/src/zq_tiles.h @@ -0,0 +1,145 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zq_tiles.cc +// +// Tile editor stuff, etc., for ZQuest. +// +//-------------------------------------------------------- + +#ifndef _ZQ_TILES_H_ +#define _ZQ_TILES_H_ + +#include "zdefs.h" + +#include "zc_alleg.h" + +/*********************************/ +/***** Tiles & Combos ******/ +/*********************************/ +extern tiledata *newundotilebuf; +extern newcombo *undocombobuf; +extern byte cset_reduce_table[PAL_SIZE]; +void calc_cset_reduce_table(PALETTE pal, int cs); + +void register_used_tiles(); +int d_comboframe_proc(int msg, DIALOG *d, int c); +int d_combo_proc(int msg,DIALOG *d,int c); +void go_tiles(); +void go_slide_tiles(int columns, int rows, int top, int left); +void comeback_tiles(); +void go_combos(); +void comeback_combos(); +void little_x(BITMAP *dest, int x, int y, int c, int s); +void zoomtile16(BITMAP *dest,int tile,int x,int y,int cset,int flip,int m); +void draw_text_button(BITMAP *dest,int x,int y,int w,int h,const char *text,int bg,int fg,int flags,bool jwin); +bool do_text_button(int x,int y,int w,int h,const char *text,int bg,int fg,bool jwin); +bool do_text_button_reset(int x,int y,int w,int h,const char *text,int bg,int fg,bool jwin); +void draw_graphics_button(BITMAP *dest,int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,int flags,bool jwin,bool overlay); +bool do_graphics_button(int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,bool jwin,bool overlay); +bool do_graphics_button_reset(int x,int y,int w,int h,BITMAP *bmp,BITMAP *bmp2,int bg,int fg,bool jwin,bool overlay); +void draw_layerradio(BITMAP *dest,int x,int y,int bg,int fg, int value); +void do_layerradio(BITMAP *dest,int x,int y,int bg,int fg,int &value); +void draw_checkbox(BITMAP *dest,int x,int y,int bg,int fg, bool value); +bool do_checkbox(BITMAP *dest,int x,int y,int bg,int fg,int &value); + +//*************** tile flood fill stuff ************** + +//extern byte tf_c; +//extern byte tf_u; + +void tile_floodfill_rec(int x,int y); +void tile_floodfill(int tile,int x,int y,byte c); + +//***************** tile editor stuff ***************** + +//extern int c1; +//extern int c2; +//extern int bgc; +enum { t_pen, t_fill, t_recolor, t_eyedropper, t_move, t_select, t_wand, t_max }; +//extern int tool; +//extern int tool_cur; +//extern int drawing; + +void update_tool_cursor(); +void draw_edit_scr(int tile,int flip,int cs,byte *oldtile, bool create_tbar); +void normalize(int tile,int tile2, bool rect_sel, int flip); +void rotate_tile(int tile, bool backward); +void wrap_tile(int tile, int offset); +void shift_tile_colors(int tile, int amount, bool ignore_transparent); +void edit_tile(int tile,int flip,int &cs); + +/* Grab Tile Code */ + +//extern void *imagebuf; +//extern long imagesize; +//extern int imagetype; +//extern int imagex,imagey,selx,sely; +//extern int bp,grabmode,romofs,romtilemode, romtilecols; +//extern int grabmask; +//extern PALETTE imagepal; + +void puttileROM(BITMAP *dest,int x,int y,byte *src,int cs); +void draw_grab_scr(int tile,int cs,byte *newtile,int black,int white,int width, int height, byte *newformat); +void load_imagebuf(); +bool leech_tiles(tiledata *dest,int start,int cs); +void grab(byte(*dest)[256],byte *def, int width, int height, int oformat, byte *newformat); +void grab_tile(int tile,int &cs); +void draw_tiles(int first,int cs, int f); +int tile_col(int tile); +int tile_row(int tile); +int tile_page(int tile); +int tile_page_row(int tile); +void tile_info_0(int tile,int tile2,int cs,int copy,int copycnt,int page,bool rect_sel); +void tile_info_1(int oldtile,int oldflip,int oldcs,int tile,int flip,int cs,int copy,int page, bool always_use_flip=false); +//void reset_tile(tiledata *buf, int t, int format); +bool copy_tiles(int &tile,int &tile2,int ©,int ©cnt, bool rect_sel, bool move); +bool copy_tiles_united(int &tile,int &tile2,int ©,int ©cnt, bool rect_sel, bool move); +void copy_combos(int &tile,int &tile2,int ©,int ©cnt, bool masscopy); +void move_combos(int &tile,int &tile2,int ©,int ©cnt); +void delete_tiles(int &tile,int &tile2,bool rect_sel); +void overlay_tile2(int dest,int src,int cs,bool backwards); +void sel_tile(int &tile, int &tile2, int &first, int type, int s); +int select_tile(int &tile,int &flip,int type,int &cs,bool edit_cs, int exnow=0, bool always_use_flip=false); +int onTiles(); +void draw_combo(BITMAP *dest, int x,int y,int c,int cs); +void draw_combos(int page,int cs,bool cols); +void combo_info(int tile,int tile2,int cs,int copy,int copycnt,int page,int buttons); +void sel_combo(int &tile, int &tile2, int s, bool cols); + +//extern word ctable[MAXCOMBOS]; + +int select_combo_2(int &tile,int &cs); +int combo_screen(int pg, int tl); +int onCombos(); + +//extern int edit_combo_cset; + +int d_ctile_proc(int msg,DIALOG *d,int c); +int d_combo_loader(int msg,DIALOG *d,int c); + +typedef struct combotype_struct +{ + char *s; + int i; +} combotype_struct; + +//extern combotype_struct bict[cMAX]; +//extern int bict_cnt; + +void build_bict_list(); +const char *combotypelist(int index, int *list_size); + +int click_d_ctile_proc(); +int onCmb_dlg_h(); +int onCmb_dlg_v(); +int onCmb_dlg_r(); +bool edit_combo(int c,bool freshen,int cs); +int d_itile_proc(int msg,DIALOG *d,int c); +int onIcons(); +void center_zq_tiles_dialogs(); +int d_combo_proc(int msg,DIALOG *d,int c); +void center_zq_tiles_dialog(); +#endif + diff --git a/src/zqscale.cpp b/src/zqscale.cpp new file mode 100644 index 0000000000..ccc8bb1ae2 --- /dev/null +++ b/src/zqscale.cpp @@ -0,0 +1,746 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + +// ROUTINES TO SCALE WINDOWED ZQUEST BY AN INTEGER FACTOR +// SHOULD WORK FOR ALL WINDOWED DRIVERS ON ANY SYSTEM +// +// + +#include "precompiled.h" //always first + +#include "allegro.h" +#include "zqscale.h" + +extern int zq_screen_w, zq_screen_h; +extern void Z_message(char *format,...); +extern int mouse_in_rect(int x,int y,int w,int h); + +BITMAP *orig_screen = NULL; +BITMAP *proxy_screen = NULL; +GFX_VTABLE *orig_vtable = NULL; +GFX_VTABLE *proxy_vtable = NULL; +int zqwin_scale = 1; + +void clip_and_stretch_blit(BITMAP *src, BITMAP *dest, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, bool masked=false) +{ + //clip source and destination aarrgh + + //compute the scale factors. These must be preserved. + double scalew = ((double)sw)/((double)dw); + double scaleh = ((double)sh)/((double)dw); + + //clip the source + if(sx < 0) + { + sw+=sx; + dw+=(int)(sx*scalew); + sx=0; + } + + if(sy<0) + { + sh+=sy; + dh+=(int)(sy*scaleh); + sy=0; + } + + if(sx + sw > src->w) + { + int neww = src->w-sx; + int difw = neww-sw; + sw = neww; + dw += (int)(difw*scalew); + } + + if(sy+sh > src->h) + { + int newh = src->h-sy; + int difh = newh-sh; + sh = newh; + dh += (int)(difh*scaleh); + } + + //clip the destination + if(dx < 0) + { + dw+=dx; + sw+=(int)(dx/scalew); + dx=0; + } + + if(dy < 0) + { + dh+=dy; + sh+=(int)(dy/scaleh); + dy=0; + } + + if(dx+dw > dest->w) + { + int neww = dest->w-dx; + int difw = neww-dw; + dw = neww; + sw += (int)(difw/scalew); + } + + if(dy+dh > dest->h) + { + int newh = dest->h-dy; + int difh = newh-dh; + dh = newh; + sh += (int)(difh/scaleh); + } + + if(sw<0 || sh < 0 || dw < 0 || dh < 0) + return; + + if(masked) + masked_stretch_blit(src, dest, sx, sy, sw, sh, dx, dy, dw, dh); + else + stretch_blit(src, dest, sx, sy, sw, sh, dx, dy, dw, dh); +} + +void clip_and_stretch_sprite(BITMAP *dest, BITMAP *src, int x, int y, int w, int h) +{ + clip_and_stretch_blit(src, dest, 0, 0, src->w, src->h, x, y, w, h,true); +} + +void clip_and_rectfill(BITMAP *dest, int x1, int y1, int x2, int y2, int color) +{ + if(x1 >= dest->w || x2 < 0 || y1 >= dest->h || y2 < 0) + return; + + if(x1<0) + { + x1=0; + } + + if(y1<0) + { + y1=0; + } + + if(x2>dest->w) + { + x2 = dest->w; + } + + if(y2>dest->h) + { + y2 = dest->h; + } + + rectfill(dest,x1,y1,x2,y2,color); +} + + + +void zq_set_mouse_range(int x1, int y1, int x2, int y2) +{ + int tempscale=zqwin_scale; + + if(!is_windowed_mode()) + { + tempscale=1; + } + + set_mouse_range(x1*tempscale, y1*tempscale, (x2+1)*tempscale-1, (y2+1)*tempscale-1); +} + + +INLINE int offset_x(BITMAP *bmp) +{ + int ret = 0; + + if(is_sub_bitmap(bmp)) + { + ret = bmp->x_ofs; + } + + return ret; +} + +INLINE int offset_y(BITMAP *bmp) +{ + int ret = 0; + + if(is_sub_bitmap(bmp)) + { + ret = bmp->y_ofs; + } + + return ret; +} + +void zqwin_acquire(struct BITMAP *bmp) +{ + if(orig_vtable->acquire) + { + orig_vtable->acquire(bmp); + } + + acquire_bitmap(orig_screen); + return; +} + +void zqwin_release(struct BITMAP *bmp) +{ + if(orig_vtable->release) + { + orig_vtable->release(bmp); + } + + release_bitmap(orig_screen); + return; +} + +void zqwin_putpixel(struct BITMAP *bmp, int x, int y, int color) +{ + orig_vtable->putpixel(bmp, x, y, color); + x += offset_x(bmp); + y += offset_y(bmp); + /* + for(int i = 0; i < zqwin_scale; i++) + { + for(int j = 0; j < zqwin_scale; j++) + { + putpixel(orig_screen, x*zqwin_scale+i, y*zqwin_scale+j, color); + } + } + */ + clip_and_rectfill(orig_screen, x*zqwin_scale, y*zqwin_scale, (((x+1)*zqwin_scale)-1), (((y+1)*zqwin_scale)-1), color); + return; +} + +void zqwin_vline(struct BITMAP *bmp, int x, int y1, int y2, int color) +{ + orig_vtable->vline(bmp, x, y1, y2, color); + x += offset_x(bmp); + int dy = offset_y(bmp); + y1 += dy; + y2 += dy; + /* + for(int i = 0; i < zqwin_scale; i++) + { + _allegro_vline(orig_screen, x*zqwin_scale+i, y1*zqwin_scale, (y2+1)*zqwin_scale-1, color); + } + */ + clip_and_rectfill(orig_screen, x*zqwin_scale, y1*zqwin_scale, (((x+1)*zqwin_scale)-1), (((y2+1)*zqwin_scale)-1), color); + return; +} + +void zqwin_hline(struct BITMAP *bmp, int x1, int y, int x2, int color) +{ + orig_vtable->hline(bmp, x1, y, x2, color); + int dx = offset_x(bmp); + x1 += dx; + x2 += dx; + y += offset_y(bmp); + /* + for(int i = 0; i < zqwin_scale; i++) + { + _allegro_hline(orig_screen, x1*zqwin_scale, y*zqwin_scale+i, (x2+1)*zqwin_scale-1, color); + } + */ + clip_and_rectfill(orig_screen, x1*zqwin_scale, y*zqwin_scale, (((x2+1)*zqwin_scale)-1), (((y+1)*zqwin_scale)-1), color); + return; +} + +void zqwin_hfill(struct BITMAP *bmp, int x1, int y, int x2, int color) +{ + orig_vtable->hfill(bmp, x1, y, x2, color); + int dx = offset_x(bmp); + x1 += dx; + x2 += dx; + y += offset_y(bmp); + + for(int i = 0; i < zqwin_scale; i++) + { + orig_screen->vtable->hfill(orig_screen, x1*zqwin_scale, y*zqwin_scale+i, (x2+1)*zqwin_scale-1, color); + } + + return; +} + +void line_helper(BITMAP *bmp, int x, int y, int d) +{ + clip_and_rectfill(bmp, x*zqwin_scale, y*zqwin_scale, (((x+1)*zqwin_scale)-1), (((y+1)*zqwin_scale)-1), d); +} + +void zqwin_line(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + orig_vtable->line(bmp, x1, y1, x2, y2, color); + //not sure what this stuff does here... + /* + int dx = offset_x(bmp); + x1 += dx; + x2 += dx; + int dy = offset_y(bmp); + y1 += dy; + y2 += dy; + do_line(orig_screen, x1*zqwin_scale, y1*zqwin_scale, (((x2+1)*zqwin_scale)-1), (((y2+1)*zqwin_scale)-1), color, line_helper); + */ + + return; +} + +void zqwin_rectfill(struct BITMAP *bmp, int x1, int y1, int x2, int y2, int color) +{ + orig_vtable->rectfill(bmp, x1, y1, x2, y2, color); + int dx = offset_x(bmp); + x1 += dx; + x2 += dx; + int dy = offset_y(bmp); + y1 += dy; + y2 += dy; + clip_and_rectfill(orig_screen, x1*zqwin_scale, y1*zqwin_scale, (x2+1)*zqwin_scale-1, (y2+1)*zqwin_scale-1, color); + return; +} + +void zqwin_draw_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) +{ + orig_vtable->draw_sprite(bmp, sprite, x, y); + x += offset_x(bmp); + y += offset_y(bmp); + //this method crashes on OS X if we try to blit outside the destination sprite. + //do some manual clipping + clip_and_stretch_sprite(orig_screen, sprite, x*zqwin_scale, y*zqwin_scale, sprite->w*zqwin_scale, sprite->h*zqwin_scale); + return; +} + +void zqwin_draw_256_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y) +{ + orig_vtable->draw_256_sprite(bmp, sprite, x, y); + x += offset_x(bmp); + y += offset_y(bmp); + clip_and_stretch_sprite(orig_screen, sprite, x*zqwin_scale, y*zqwin_scale, sprite->w*zqwin_scale, sprite->h*zqwin_scale); + return; +} + +void zqwin_draw_character(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color, int bg) +{ + orig_vtable->draw_character(bmp,sprite,x,y,color,bg); + clip_and_stretch_blit(bmp, orig_screen, x, y, sprite->w, sprite->h, (x+offset_x(bmp))*zqwin_scale, (y+offset_y(bmp))*zqwin_scale, sprite->w*zqwin_scale, sprite->h*zqwin_scale); + return; +} + +void zqwin_draw_glyph(struct BITMAP *bmp, AL_CONST struct FONT_GLYPH *glyph, int x, int y, int color, int bg) +{ + orig_vtable->draw_glyph(bmp,glyph,x,y,color,bg); + clip_and_stretch_blit(bmp, orig_screen, x, y, glyph->w, glyph->h, (x+offset_x(bmp))*zqwin_scale, (y+offset_y(bmp))*zqwin_scale, glyph->w*zqwin_scale, glyph->h*zqwin_scale); + return; +} + +void zqwin_blit_from_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_from_memory(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_to_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_to_memory(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_from_system(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_from_system(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_to_system(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_to_system(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_to_self(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_to_self(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + int mx = gui_mouse_x() - mouse_x_focus; + int my = gui_mouse_y() - mouse_y_focus; + int x1 = dest_x + offset_x(dest); + int y1 = dest_y + offset_y(dest); + + if(mouse_sprite) + { + int mw = mouse_sprite->w; + int mh = mouse_sprite->h; + + if((mx < x1 + width) && (my < y1 + height) && (mx + mw >= x1) && (my + mh >= y1)) + { + static BITMAP* tmp = NULL; + mx = (mx > 0) ? mx : 0; + my = (my > 0) ? my : 0; + mw = MIN((proxy_screen->w-mx),mw); + mh = MIN((proxy_screen->h-my),mh); + int l_x = (mx < x1) ? mx : x1; + int l_y = (my < y1) ? my : y1; + int __mx2 = mx + mw; + int __my2 = my + mh; + int x2 = x1 + width; + int y2 = y1 + height; + x2 = (x2 > __mx2) ? x2 : __mx2; + y2 = (y2 > __my2) ? y2 : __my2; + int l_w = x2 - l_x; + int l_h = y2 - l_y; + + if(!tmp) + { + tmp = create_bitmap_ex(8, mw, mh); + } + else if(mw > tmp->w || mh > tmp->h) + { + destroy_bitmap(tmp); + tmp = create_bitmap_ex(8, mw, mh); + } + + orig_vtable->blit_to_self(proxy_screen, tmp, mx, my, 0, 0, mw, mh); + //orig_vtable->draw_256_sprite(proxy_screen, mouse_sprite, mx, my); + clip_and_stretch_blit(proxy_screen, orig_screen, l_x, l_y, l_w, l_h, l_x*zqwin_scale, l_y*zqwin_scale, l_w*zqwin_scale, l_h*zqwin_scale); + orig_vtable->blit_to_self(tmp, proxy_screen, 0, 0, mx, my, mw, mh); + } + else + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, x1*zqwin_scale, y1*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + } + else + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, x1*zqwin_scale, y1*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + } + + return; +} + +void zqwin_blit_to_self_forward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_to_self_forward(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_to_self_backward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_to_self_backward(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_blit_between_formats(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->blit_between_formats(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_masked_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height) +{ + orig_vtable->masked_blit(source,dest,source_x,source_y,dest_x,dest_y,width,height); + + if(is_same_bitmap(dest, proxy_screen)) + { + clip_and_stretch_blit(dest, orig_screen, dest_x, dest_y, width, height, (dest_x+offset_x(dest))*zqwin_scale, (dest_y+offset_y(dest))*zqwin_scale, width*zqwin_scale, height*zqwin_scale); + } + + return; +} + +void zqwin_clear_to_color(struct BITMAP *bitmap, int color) +{ +// orig_vtable->clear_to_color(bitmap, color); + orig_vtable->rectfill(bitmap,0,0,bitmap->w-1,bitmap->h-1,color); + + if(is_same_bitmap(bitmap, proxy_screen)) + { +// clear_to_color(orig_screen, color); + rectfill(orig_screen,0,0,orig_screen->w-1,orig_screen->h-1,color); + } + + return; +} + +#include +void zqwin_set_clip(struct BITMAP *bitmap) +{ + if(is_same_bitmap(bitmap, proxy_screen)) + { + int dx = offset_x(bitmap); + int dy = offset_y(bitmap); + orig_screen->cl = (bitmap->cl+dx)*zqwin_scale; + orig_screen->cr = (bitmap->cr+dx+1)*zqwin_scale-1; + orig_screen->ct = (bitmap->ct+dy)*zqwin_scale; + orig_screen->cb = (bitmap->cb+dy+1)*zqwin_scale-1; + } + + return; +} + + +bool is_windowed_mode(int mode) +{ + switch(mode) + { +#ifdef ALLEGRO_WINDOWS + + case GFX_AUTODETECT_WINDOWED: + case GFX_DIRECTX_WIN: + case GFX_DIRECTX_OVL: + case GFX_GDI: + return true; +#elif defined ALLEGRO_LINUX + + case GFX_AUTODETECT_WINDOWED: + case GFX_XWINDOWS: + case GFX_XDGA: + case GFX_XDGA2: + case GFX_XDGA2_SOFT: + return true; +#elif defined ALLEGRO_MACOSX + + case GFX_AUTODETECT_WINDOWED: + case GFX_QUARTZ_WINDOW: + return true; +#endif + + default: + ; + } + + return false; +} + + +int zqwin_set_gfx_mode(int card, int w, int h, int v_w, int v_h) +{ + //these are here to bypass compiler warnings about unused arguments + v_w=v_w; + v_h=v_h; + + int failed = 0; + + bool wasProxied = (screen == proxy_screen) && (proxy_screen != NULL); + + if(wasProxied) + { + screen = orig_screen; + } + + bool becomesWindowed = true; + + if(is_windowed_mode(card)) + { + failed = set_gfx_mode(card,w*zqwin_scale,h*zqwin_scale,0,0); + } + else + { + // zqwin_set_scale(2, true); + failed = set_gfx_mode(card,w*zqwin_scale,h*zqwin_scale,0,0); + } + + if(failed) + { + if(wasProxied) + { + screen = proxy_screen; + } + } + else + { + orig_screen = screen; + + if(becomesWindowed && (zqwin_scale > 1)) + { + clear_bitmap(proxy_screen); + screen = proxy_screen; + //set_mouse_speed(zqwin_scale<<1, zqwin_scale<<1); + zq_set_mouse_range(0,0,w-1,h-1); + } + + /* + else + { + set_mouse_speed(2,2); + } + */ + } + + set_mouse_speed(2,2); +// if(is_windowed_mode()) + //{ + //if(zcgui_screen) destroy_bitmap(zcgui_screen); + //zcgui_screen = create_bitmap_ex(get_color_depth(), screen->w, screen->h); + //zcgui_scrref = zcgui_screen; + //} + //else + //{ + //zcgui_scrref = screen; + //} + + + return failed; +} + +int zqscale_mouse_x() +{ + double my_x=(double)mouse_x/(double)(gfx_driver->windowed?zqwin_scale:1); + return (int)my_x; +} + +int zqscale_mouse_y() +{ + double my_y=(double)mouse_y/(double)(gfx_driver->windowed?zqwin_scale:1); + return (int)my_y; +} + + +bool zqwin_set_scale(int scale, bool defer) +{ + // These are here to make compiler happy + defer=defer; + + int old_scale; + old_scale = zqwin_scale; + +#ifndef ROMVIEW_SCALE + zqwin_scale = (scale > 1) ? scale : 1; +#ifndef COMPILE_FOR_LINUX + gui_mouse_x=zqscale_mouse_x; + gui_mouse_y=zqscale_mouse_y; +#endif + return true; +#else + + if((!proxy_screen) && (scale > 1)) + { + proxy_screen = create_bitmap_ex(8, zq_screen_w, zq_screen_h); + proxy_vtable = (GFX_VTABLE*)zc_malloc(sizeof(GFX_VTABLE)); + + if(!proxy_screen || !proxy_vtable) + { + zqwin_scale = 1; + return false; + } + + orig_vtable = proxy_screen->vtable; + *proxy_vtable = *orig_vtable; + //FILL IT IN + proxy_vtable->acquire = zqwin_acquire; + proxy_vtable->release = zqwin_release; + proxy_vtable->set_clip = zqwin_set_clip; + + if(proxy_vtable->putpixel) proxy_vtable->putpixel = zqwin_putpixel; + + if(proxy_vtable->vline) proxy_vtable->vline = zqwin_vline; + + if(proxy_vtable->hline) proxy_vtable->hline = zqwin_hline; + + if(proxy_vtable->hfill) proxy_vtable->hfill = zqwin_hfill; + + if(proxy_vtable->line) proxy_vtable->line = zqwin_line; + + if(proxy_vtable->rectfill) proxy_vtable->rectfill = zqwin_rectfill; + + if(proxy_vtable->draw_sprite) proxy_vtable->draw_sprite = zqwin_draw_sprite; + + if(proxy_vtable->draw_256_sprite) proxy_vtable->draw_256_sprite = zqwin_draw_256_sprite; + + if(proxy_vtable->draw_character) proxy_vtable->draw_character = zqwin_draw_character; + + if(proxy_vtable->draw_glyph) proxy_vtable->draw_glyph = zqwin_draw_glyph; + + if(proxy_vtable->blit_from_memory) proxy_vtable->blit_from_memory = zqwin_blit_from_memory; + + if(proxy_vtable->blit_to_memory) proxy_vtable->blit_to_memory = zqwin_blit_to_memory; + + if(proxy_vtable->blit_from_system) proxy_vtable->blit_from_system = zqwin_blit_from_system; + + if(proxy_vtable->blit_to_system) proxy_vtable->blit_to_system = zqwin_blit_to_system; + + if(proxy_vtable->blit_to_self) proxy_vtable->blit_to_self = zqwin_blit_to_self; + + if(proxy_vtable->blit_to_self_forward) proxy_vtable->blit_to_self_forward = zqwin_blit_to_self_forward; + + if(proxy_vtable->blit_to_self_backward) proxy_vtable->blit_to_self_backward = zqwin_blit_to_self_backward; + + if(proxy_vtable->blit_between_formats) proxy_vtable->blit_between_formats = zqwin_blit_between_formats; + + if(proxy_vtable->masked_blit) proxy_vtable->masked_blit = zqwin_masked_blit; + + if(proxy_vtable->clear_to_color) proxy_vtable->clear_to_color = zqwin_clear_to_color; + + //THEN INTERJECT IT + proxy_screen->vtable = proxy_vtable; + } + + zqwin_scale = (scale > 1) ? scale : 1; + + if((!defer) && (zqwin_scale != old_scale)) + //if (zqwin_scale != old_scale) + { + if(gfx_driver && gfx_driver->windowed) + { + if(zqwin_set_gfx_mode(gfx_driver->id,zq_screen_w,zq_screen_h,0,0)) + { + zqwin_scale = old_scale; + return false; + } + } + } + + + // Mouse Scale Issue Fix Just commented these out and presto it works :-D +#ifndef COMPILE_FOR_LINUX + gui_mouse_x=zqscale_mouse_x; + gui_mouse_y=zqscale_mouse_y; +#endif + + return true; +#endif +} + + diff --git a/src/zqscale.h b/src/zqscale.h new file mode 100644 index 0000000000..845bf805b9 --- /dev/null +++ b/src/zqscale.h @@ -0,0 +1,12 @@ +#ifndef _ZQSCALE_H_ +#define _ZQSCALE_H_ + +bool zqwin_set_scale(int scale, bool defer = false); +int zqwin_set_gfx_mode(int card, int w, int h, int v_w, int v_h); +void zq_set_mouse_range(int x1, int y1, int x2, int y2); + +#ifdef ROMVIEW_SCALE +#define set_gfx_mode zqwin_set_gfx_mode +#endif +#endif + diff --git a/src/zquest.cpp b/src/zquest.cpp new file mode 100644 index 0000000000..8ac62eb736 --- /dev/null +++ b/src/zquest.cpp @@ -0,0 +1,23529 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zquest.cc +// +// Main code for the quest editor. +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +/* + #define INTERNAL_VERSION 0xA721 + */ + +#include "precompiled.h" //always first + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parser/Compiler.h" +#include "zc_alleg.h" +#include "mem_debug.h" +void setZScriptVersion(int) { } //bleh... + +#include +#include + +#include +#include + +#include "ffc.h" +#include "gui.h" +#include "load_gif.h" +#include "save_gif.h" +#include "editbox.h" +#include "zq_misc.h" +#include "zq_tiles.h" // tile and combo code + +#include "zquest.h" +#include "zquestdat.h" +#include "ffasm.h" + +// the following are used by both zelda.cc and zquest.cc +#include "zdefs.h" +#include "tiles.h" +#include "colors.h" +#include "qst.h" +#include "zsys.h" +#include "zcmusic.h" + +#include "midi.h" +#include "sprite.h" +#include "items.h" +#include "fontsdat.h" +#include "jwinfsel.h" +#include "zq_class.h" +#include "subscr.h" +#include "zq_subscr.h" +#include "ffscript.h" +#include "EditboxNew.h" +#include "sfx.h" + +#include "zq_custom.h" // custom items and guys +#include "zq_strings.h" + +#include "zqscale.h" + +#include "questReport.h" + +//SDL_Surface *sdl_screen; + +#ifdef ALLEGRO_DOS +static const char *data_path_name = "dos_data_path"; +static const char *midi_path_name = "dos_midi_path"; +static const char *image_path_name = "dos_image_path"; +static const char *tmusic_path_name = "dos_tmusic_path"; +static const char *last_quest_name = "dos_last_quest"; +static const char *qtname_name = "dos_qtname%d"; +static const char *qtpath_name = "dos_qtpath%d"; +#elif defined(ALLEGRO_WINDOWS) +static const char *data_path_name = "win_data_path"; +static const char *midi_path_name = "win_midi_path"; +static const char *image_path_name = "win_image_path"; +static const char *tmusic_path_name = "win_tmusic_path"; +static const char *last_quest_name = "win_last_quest"; +static const char *qtname_name = "win_qtname%d"; +static const char *qtpath_name = "win_qtpath%d"; +#elif defined(ALLEGRO_LINUX) +static const char *data_path_name = "linux_data_path"; +static const char *midi_path_name = "linux_midi_path"; +static const char *image_path_name = "linux_image_path"; +static const char *tmusic_path_name = "linux_tmusic_path"; +static const char *last_quest_name = "linux_last_quest"; +static const char *qtname_name = "linux_qtname%d"; +static const char *qtpath_name = "linux_qtpath%d"; +#elif defined(ALLEGRO_MACOSX) +static const char *data_path_name = "macosx_data_path"; +static const char *midi_path_name = "macosx_midi_path"; +static const char *image_path_name = "macosx_image_path"; +static const char *tmusic_path_name = "macosx_tmusic_path"; +static const char *last_quest_name = "macosx_last_quest"; +static const char *qtname_name = "macosx_qtname%d"; +static const char *qtpath_name = "macosx_qtpath%d"; +#endif + +#include "win32.h" //win32 fixes + +#include "zq_init.h" +#include "zq_doors.h" +#include "zq_cset.h" + +#ifdef _MSC_VER +#include +#define stricmp _stricmp +#define unlink _unlink +#define snprintf _snprintf +#endif + +#include "messageList.h" +#include "dialog/zquest/cheatEditor.h" +#include "dialog/zquest/infoShopEditor.h" +#include "dialog/zquest/paletteViewer.h" +#include "dialog/zquest/questRules.h" +#include "dialog/zquest/shopEditor.h" +#include "dialog/zquest/simpleListSelector.h" +#include "dialog/zquest/zscriptMain.h" +//#include "gui/gtk/manager.h" +#include "gui/allegro/manager.h" +#include + +GUI::GUIManager* gui; +MessageList msgList; // Trivial for now + + +#define zc_max(a,b) ((a)>(b)?(a):(b)) +#define zc_min(a,b) ((a)<(b)?(a):(b)) + +void do_previewtext(); + +int startdmapxy[6] = {-1000, -1000, -1000, -1000, -1000, -1000}; +bool cancelgetnum=false; + +int tooltip_timer=0, tooltip_maxtimer=30, tooltip_current_combo=0, tooltip_current_ffc=0; +int mousecomboposition; + +int original_playing_field_offset=0; +int playing_field_offset=original_playing_field_offset; +int passive_subscreen_height=56; +int passive_subscreen_offset=0; + +bool disable_saving=false, OverwriteProtection; +int scale_arg; +int zq_scale; +bool halt=false; +bool show_sprites=true; +bool show_hitboxes = false; + +// Used to find FFC script names +extern std::map > ffcmap; +std::vector asffcscripts; +extern std::map > globalmap; +std::vector asglobalscripts; +extern std::map > itemmap; +std::vector asitemscripts; + +int CSET_SIZE = 16; +int CSET_SHFT = 4; +//editbox_data temp_eb_data; +/* + #define CSET(x) ((x)<>3]; +int sfxdat=1; + +extern void deallocate_biic_list(); + +zinitdata zinit; + +int onImport_ComboAlias(); +int onExport_ComboAlias(); + + +typedef struct map_and_screen +{ + int map; + int screen; +} map_and_screen; + +typedef int (*intF)(); +typedef struct command_pair +{ + char name[80]; + int flags; + intF command; +} command_pair; + +extern command_pair commands[cmdMAX]; + +map_and_screen map_page[9]= {{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}}; +int alignment_arrow_timer=0; +int Flip=0,Combo=0,CSet=2,First[3]= {0,0,0},current_combolist=0,current_comboalist=0,current_mappage=0; +int Flags=0,Flag=1,menutype=(m_block); +int MouseScroll, SavePaths, CycleOn, ShowGrid, GridColor, TileProtection, InvalidStatic, UseSmall, RulesetDialog, EnableTooltips, ShowFFScripts, ShowSquares, ShowInfo; +int FlashWarpSquare = -1, FlashWarpClk = 0; // flash the destination warp return when ShowSquares is active +bool Vsync, ShowFPS; +int ComboBrush; //show the brush instead of the normal mouse +int ComboBrushPause; //temporarily disable the combo brush +int BrushPosition; //top left, middle, bottom right, etc. +int FloatBrush; //makes the combo brush float a few pixels up and left +//complete with shadow +int OpenLastQuest; //makes the program reopen the quest that was +//open at the time you quit +int ShowMisalignments; //makes the program display arrows over combos that are +//not aligned with the next screen. +int AnimationOn; //animate the combos in zquest? +int AutoBackupRetention; //use auto-backup feature? if so, how many backups (1-10) to keep +int AutoSaveInterval; //how often a timed autosave is made (not overwriting the current file) +int UncompressedAutoSaves; //should timed saves be uncompressed/encrypted? +int KeyboardRepeatDelay; //the time in milliseconds after holding down a key that the key starts to repeat +int KeyboardRepeatRate; //the time in milliseconds between each repetition of a repeated key + +time_t auto_save_time_start, auto_save_time_current; +double auto_save_time_diff; +int AutoSaveRetention; //how many autosaves of a quest to keep +int ImportMapBias; //tells what has precedence on map importing +int BrushWidth=1, BrushHeight=1; +bool quit=false,saved=true; +bool __debug=false; +//bool usetiles=true; +byte LayerMask[2]; //determines which layers are on or off. 0-15 +int LayerMaskInt[7]; +int CurrentLayer=0; +int DuplicateAction[4]; +int OnlyCheckNewTilesForDuplicates; +/* + , HorizontalDuplicateAction; + int VerticalDuplicateAction, BothDuplicateAction; + */ +word msg_count, qt_count; +int LeechUpdate; +int LeechUpdateTiles; +int SnapshotFormat; + +int memrequested; +byte Color; +int jwin_pal[jcMAX]; +int gui_colorset=0; + +combo_alias combo_aliases[MAXCOMBOALIASES]; +static int combo_apos=0; //currently selected combo +static int combo_alistpos[3]= {0,0,0}; //first displayed combo alias +int alias_origin=0; +int alias_cset_mod=0; + +bool trip=false; + +int fill_type=1; + +bool first_save=false; +char *filepath,*temppath,*midipath,*datapath,*imagepath,*tmusicpath,*last_timed_save; +char *helpbuf; +std::string helpstr; + +ZCMUSIC *zcmusic = NULL; +int midi_volume = 255; +extern int prv_mode; +int prv_warp = 0; +int prv_twon = 0; +int ff_combo = 0; + +int Frameskip = 0, RequestedFPS = 60, zqUseWin32Proc = 1, ForceExit = 0; +int zqColorDepth = 8; +byte disable_direct_updating = 0; +int joystick_index=0; + +char *getBetaControlString(); + + +void loadlvlpal(int level); +bool get_debug() +{ + return __debug; + //return true; +} + +void set_debug(bool d) +{ + __debug=d; + return; +} + +// **** Timers **** + +volatile int lastfps=0; +volatile int framecnt=0; +volatile int myvsync = 0; + +void myvsync_callback() +{ + ++myvsync; +} + +END_OF_FUNCTION(myvsync_callback) + + + +// quest data +zquestheader header; +byte quest_rules[QUESTRULES_SIZE]; +byte midi_flags[MIDIFLAGS_SIZE]; +byte music_flags[MUSICFLAGS_SIZE]; +word map_count; +miscQdata misc; +std::vector TheMaps; +zcmap *ZCMaps; +byte *quest_file; +dmap *DMaps; +MsgStr *MsgStrings; +int msg_strings_size; +//DoorComboSet *DoorComboSets; +zctune *customtunes; +//emusic *enhancedMusic; +ZCHEATS zcheats; +byte use_cheats; +byte use_tiles; +extern zinitdata zinit; +char palnames[MAXLEVELS][17]; +quest_template QuestTemplates[MAXQTS]; +char fontsdat_sig[52]; +char zquestdat_sig[52]; +char qstdat_sig[52]; +char sfxdat_sig[52]; + +int gme_track=0; + +int dlevel; // just here until gamedata is properly done + +bool gotoless_not_equal; // Used by BuildVisitors.cpp + +bool bad_version(int ver) +{ + if(ver < 0x170) + return true; + + return false; +} + +fix LinkModifiedX() +{ + if(resize_mouse_pos) + { + return (fix)((gui_mouse_x()/mapscreensize)-((8*mapscreensize)-1)+(showedges?8:0)); + } + else + { + return (fix)(gui_mouse_x()-7); + } +} + +fix LinkModifiedY() +{ + if(resize_mouse_pos) + { + return (fix)((gui_mouse_y()/mapscreensize)-((8*mapscreensize)-1)-16+(showedges?16:0)); + } + else + { + return (fix)(gui_mouse_y()-7); + } +} + +static MENU import_menu[] = +{ + { (char *)"&Map", onImport_Map, NULL, 0, NULL }, + { (char *)"&DMaps", onImport_DMaps, NULL, 0, NULL }, + { (char *)"&Tiles", onImport_Tiles, NULL, 0, NULL }, + { (char *)"&Enemies", onImport_Guys, NULL, 0, NULL }, + { (char *)"Su&bscreen", onImport_Subscreen, NULL, 0, NULL }, + { (char *)"&Palettes", onImport_Pals, NULL, 0, NULL }, + { (char *)"&String Table", onImport_Msgs, NULL, 0, NULL }, + { (char *)"&Combo Table", onImport_Combos, NULL, 0, NULL }, + { (char *)"&Combo Alias", onImport_ComboAlias, NULL, 0, NULL }, + { (char *)"&Graphics Pack", onImport_ZGP, NULL, 0, NULL }, + { (char *)"&Quest Template", onImport_ZQT, NULL, 0, NULL }, + { (char *)"&Unencoded Quest", onImport_UnencodedQuest, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU export_menu[] = +{ + { (char *)"&Map", onExport_Map, NULL, 0, NULL }, + { (char *)"&DMaps", onExport_DMaps, NULL, 0, NULL }, + { (char *)"&Tiles", onExport_Tiles, NULL, 0, NULL }, + { (char *)"&Enemies", onExport_Guys, NULL, 0, NULL }, + { (char *)"Su&bscreen", onExport_Subscreen, NULL, 0, NULL }, + { (char *)"&Palettes", onExport_Pals, NULL, 0, NULL }, + { (char *)"&String Table", onExport_Msgs, NULL, 0, NULL }, + { (char *)"Text Dump", onExport_MsgsText, NULL, 0, NULL }, + { (char *)"&Combo Table", onExport_Combos, NULL, 0, NULL }, + { (char *)"&Combo Alias", onExport_ComboAlias, NULL, 0, NULL }, + { (char *)"&Graphics Pack", onExport_ZGP, NULL, 0, NULL }, + { (char *)"&Quest Template", onExport_ZQT, NULL, 0, NULL }, + { (char *)"&Unencoded Quest", onExport_UnencodedQuest, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU file_menu[] = +{ + { (char *)"&New", onNew, NULL, 0, NULL }, + { (char *)"&Open\tF3", onOpen, NULL, 0, NULL }, + { (char *)"&Save\tF2", onSave, NULL, 0, NULL }, + { (char *)"Save &as...", onSaveAs, NULL, 0, NULL }, + { (char *)"&Revert", onRevert, NULL, 0, NULL }, + { (char *)"Quest &Templates...", onQuestTemplates, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Import\t ", NULL, import_menu, 0, NULL }, + { (char *)"&Export\t ", NULL, export_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"E&xit\tESC", onExit, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU maps_menu[] = +{ + { (char *)"&Goto Map...", onGotoMap, NULL, 0, NULL }, + { (char *)"Next Map\t.", onIncMap, NULL, 0, NULL }, + { (char *)"Previous Map\t,", onDecMap, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"D&elete Map", onDeleteMap, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU misc_menu[] = +{ + { (char *)"S&ubscreens", onEditSubscreens, NULL, 0, NULL }, + { (char *)"&Master Subscreen Type", onSubscreen, NULL, 0, NULL }, + { (char *)"&Shop Types", onShopTypes, NULL, 0, NULL }, + { (char *)"&Info Types", onInfoTypes, NULL, 0, NULL }, + { (char *)"&Warp Rings", onWarpRings, NULL, 0, NULL }, + { (char *)"&Triforce Pieces", onTriPieces, NULL, 0, NULL }, + { (char *)"&End String", onEndString, NULL, 0, NULL }, + { (char *)"Item &Drop Sets", onItemDropSets, NULL, 0, NULL }, +//{ (char *)"Screen &Opening/Closing", onScreenOpeningClosing, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU spr_menu[] = +{ + { (char *)"&Weapons/Misc", onCustomWpns, NULL, 0, NULL }, + { (char *)"&Link", onCustomLink, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +MENU colors_menu[] = +{ + { (char *)"&Main ", onColors_Main, NULL, 0, NULL }, + { (char *)"&Levels ", onColors_Levels, NULL, 0, NULL }, + { (char *)"&Sprites ", onColors_Sprites, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU defs_menu[] = +{ + { (char *)"&Palettes", onDefault_Pals, NULL, 0, NULL }, + { (char *)"&Tiles", onDefault_Tiles, NULL, 0, NULL }, + { (char *)"&Combos", onDefault_Combos, NULL, 0, NULL }, + { (char *)"&Items", onDefault_Items, NULL, 0, NULL }, + { (char *)"&Enemies", onDefault_Guys, NULL, 0, NULL }, + { (char *)"&Weapon Sprites", onDefault_Weapons, NULL, 0, NULL }, + { (char *)"&Map Styles", onDefault_MapStyles, NULL, 0, NULL }, + { (char *)"SF&X Data", onDefault_SFX, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +int onEditComboAlias(); + +static MENU graphics_menu[] = +{ + { (char *)"&Palettes\t ", NULL, colors_menu, 0, NULL }, + { (char *)"&Sprites\t ", NULL, spr_menu, 0, NULL }, + { (char *)"&Combos", onCombos, NULL, 0, NULL }, + { (char *)"&Tiles", onTiles, NULL, 0, NULL }, + { (char *)"&Game icons", onIcons, NULL, 0, NULL }, + { (char *)"Misc co&lors", onMiscColors, NULL, 0, NULL }, + { (char *)"&Map styles", onMapStyles, NULL, 0, NULL }, + { (char *)"&Door Combo Sets", onDoorCombos, NULL, 0, NULL }, + { (char *)"Combo &Aliases", onEditComboAlias, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU audio_menu[] = +{ + { (char *)"SF&X Data", onSelectSFX, NULL, 0, NULL }, + { (char *)"&MIDIs", onMidis, NULL, 0, NULL }, +//{ (char *)"&Enhanced Music", onEnhancedMusic, NULL, D_DISABLED, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU script_menu[] = +{ + { (char *)"Import ASM &FFC Script", onImportFFScript, NULL, 0, NULL }, + { (char *)"Import ASM &Item Script", onImportItemScript, NULL, 0, NULL }, + { (char *)"Import ASM &Global Script", onImportGScript, NULL, 0, NULL }, + { (char *)"Compile &ZScript...", onCompileScript, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU quest_menu[] = +{ + { (char *)"&Header", onHeader, NULL, 0, NULL }, + { (char *)"&Rules", onQuestRules, NULL, 0, NULL }, + { (char *)"Ma&p Count", onMapCount, NULL, 0, NULL }, + { (char *)"Ch&eats", onCheats, NULL, 0, NULL }, + { (char *)"&Items", onCustomItems, NULL, 0, NULL }, + { (char *)"Ene&mies", onCustomEnemies, NULL, 0, NULL }, + { (char *)"&Strings", onStrings, NULL, 0, NULL }, + { (char *)"&DMaps", onDmaps, NULL, 0, NULL }, + { (char *)"I&nit Data", onInit, NULL, 0, NULL }, + { (char *)"Misc D&ata\t ", NULL, misc_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Graphics\t ", NULL, graphics_menu, 0, NULL }, + { (char *)"A&udio\t ", NULL, audio_menu, 0, NULL }, + { (char *)"S&cripts\t ", NULL, script_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Template", onTemplates, NULL, 0, NULL }, + { (char *)"De&faults\t ", NULL, defs_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU paste_menu[] = +{ + { (char *)"Paste &To All", onPasteToAll, NULL, 0, NULL }, + { (char *)"Paste &All To All", onPasteAllToAll, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU paste_item_menu[] = +{ + { (char *)"&Undercombo", onPasteUnderCombo, NULL, 0, NULL }, + { (char *)"&Secret Combos", onPasteSecretCombos, NULL, 0, NULL }, + { (char *)"&Freeform Combos", onPasteFFCombos, NULL, 0, NULL }, + { (char *)"Screen &Data", onPasteScreenData, NULL, 0, NULL }, + { (char *)"&Warps", onPasteWarps, NULL, 0, NULL }, + { (char *)"Warp &Return", onPasteWarpLocations, NULL, 0, NULL }, + { (char *)"&Enemies", onPasteEnemies, NULL, 0, NULL }, + { (char *)"Room &Type Data", onPasteRoom, NULL, 0, NULL }, + { (char *)"&Guy/String", onPasteGuy, NULL, 0, NULL }, + { (char *)"Doo&rs", onPasteDoors, NULL, 0, NULL }, + { (char *)"&Layers", onPasteLayers, NULL, 0, NULL }, + { (char *)"&Palette", onPastePalette, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU edit_menu[] = +{ + { (char *)"&Undo\tU", onUndo, NULL, 0, NULL }, + { (char *)"&Copy\tC", onCopy, NULL, 0, NULL }, + { (char *)"&Paste\tV", onPaste, NULL, 0, NULL }, + { (char *)"Paste A&ll", onPasteAll, NULL, 0, NULL }, + { (char *)"&Adv. Paste\t ", NULL, paste_menu, 0, NULL }, + { (char *)"Paste &Spec.\t ", NULL, paste_item_menu, 0, NULL }, + { (char *)"&Delete\tDel", onDelete, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Maps\t ", NULL, maps_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU drawing_mode_menu[] = +{ + { (char *)"&Normal", onDrawingModeNormal, NULL, 0, NULL }, + { (char *)"&Relational", onDrawingModeRelational, NULL, 0, NULL }, + { (char *)"&Dungeon Carving", onDrawingModeDungeon, NULL, 0, NULL }, + { (char *)"&Combo Alias", onDrawingModeAlias, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU integrity_check_menu[] = +{ + { (char *)"&All ", onIntegrityCheckAll, NULL, 0, NULL }, + { (char *)"&Warps ", onIntegrityCheckWarps, NULL, 0, NULL }, + { (char *)"&Screens ", onIntegrityCheckRooms, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU quest_reports_menu[] = +{ + { (char *)"&Combo Locations", onComboLocationReport, NULL, 0, NULL }, + { (char *)"&Combo Type Locations", onComboTypeLocationReport, NULL, 0, NULL }, + { (char *)"&Enemy Locations", onEnemyLocationReport, NULL, 0, NULL }, + { (char *)"&Item Locations", onItemLocationReport, NULL, 0, NULL }, + { (char *)"&Script Locations", onScriptLocationReport, NULL, 0, NULL }, + { (char *)"&What Links Here", onWhatWarpsReport, NULL, 0, NULL }, + { (char *)"In&tegrity Check\t ", NULL, integrity_check_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU tool_menu[] = +{ + { (char *)"Combo &Flags\tF8", onFlags, NULL, 0, NULL }, + { (char *)"&Color Set Fix", onCSetFix, NULL, 0, NULL }, + { (char *)"&NES Dungeon Template", onTemplate, NULL, 0, NULL }, + { (char *)"&Apply Template to All", onReTemplate, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Preview Mode\tX", onPreviewMode, NULL, 0, NULL }, + { (char *)"Drawing &Mode\t ", NULL, drawing_mode_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&List Combos Used\t'", onUsedCombos, NULL, 0, NULL }, + { (char *)"&Quest Reports\t ", NULL, quest_reports_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU view_menu[] = +{ + { (char *)"View &Map...", onViewMap, NULL, 0, NULL }, + { (char *)"View &Palette", onShowPal, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Show &Walkability\tW", onShowWalkability, NULL, 0, NULL }, + { (char *)"Show &Flags\tF", onShowFlags, NULL, 0, NULL }, + { (char *)"Show &CSets", onShowCSet, NULL, 0, NULL }, + { (char *)"Show &Types", onShowCType, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Show Screen &Info\tN", onToggleShowInfo, NULL, 0, NULL }, + { (char *)"Show &Squares", onToggleShowSquares, NULL, 0, NULL }, + { (char *)"Show Script &Names", onToggleShowScripts, NULL, 0, NULL }, + { (char *)"Show &Grid\t~", onToggleGrid, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +int onSelectFFCombo(); + +static MENU data_menu[] = +{ + { (char *)"&Screen Data\tF9", onScrData, NULL, 0, NULL }, + { (char *)"&Freeform Combos\tF7", onSelectFFCombo, NULL, 0, NULL }, + { (char *)"La&yers\tF12", onLayers, NULL, 0, NULL }, + { (char *)"&Tile Warp\tF10", onTileWarp, NULL, 0, NULL }, + { (char *)"Side &Warp\tF11", onSideWarp, NULL, 0, NULL }, + { (char *)"Secret &Combos\tF5", onSecretCombo, NULL, 0, NULL }, + { (char *)"&Under Combo", onUnderCombo, NULL, 0, NULL }, + { (char *)"&Doors\tF6", onDoors, NULL, 0, NULL }, + { (char *)"Ma&ze Path", onPath, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Guy\tG", onGuy, NULL, 0, NULL }, + { (char *)"&Message String\tS", onString, NULL, 0, NULL }, + { (char *)"&Room Type\tR", onRType, NULL, 0, NULL }, + { (char *)"Catch &All\tA", onCatchall, NULL, D_DISABLED, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Item\tI", onItem, NULL, 0, NULL }, + { (char *)"&Enemies\tE", onEnemies, NULL, 0, NULL }, + { (char *)"&Palette\tF4", onScreenPalette, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU tunes_menu[] = +{ + { (char *)"Wind Fish", playTune1, NULL, 0, NULL }, + { (char *)"Overworld", playTune2, NULL, 0, NULL }, + { (char *)"Hyrule Castle", playTune3, NULL, 0, NULL }, + { (char *)"Lost Woods", playTune4, NULL, 0, NULL }, + { (char *)"Great Sea", playTune5, NULL, 0, NULL }, + { (char *)"East Hyrule", playTune6, NULL, 0, NULL }, + { (char *)"Dancing Dragon", playTune7, NULL, 0, NULL }, + { (char *)"Stone Tower", playTune8, NULL, 0, NULL }, + { (char *)"Villages", playTune9, NULL, 0, NULL }, + { (char *)"Swamp + Desert", playTune10, NULL, 0, NULL }, + { (char *)"Outset Island", playTune11, NULL, 0, NULL }, + { (char *)"Kakariko Village", playTune12, NULL, 0, NULL }, + { (char *)"Clock Town", playTune13, NULL, 0, NULL }, + { (char *)"Temple", playTune14, NULL, 0, NULL }, + { (char *)"Dark World", playTune15, NULL, 0, NULL }, + { (char *)"Dragon Roost", playTune16, NULL, 0, NULL }, + { (char *)"Horse Race", playTune17, NULL, 0, NULL }, + { (char *)"Credits", playTune18, NULL, 0, NULL }, + { (char *)"Zelda's Lullaby", playTune19, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU etc_menu[] = +{ + { (char *)"&Help", onHelp, NULL, 0, NULL }, + { (char *)"&About", onAbout, NULL, 0, NULL }, + { (char *)"Video &Mode", onZQVidMode, NULL, 0, NULL }, + { (char *)"&Options...", onOptions, NULL, 0, NULL }, + { (char *)"&Fullscreen", onFullScreen, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&View Pic...", onViewPic, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"The Travels of Link", NULL, tunes_menu, 0, NULL }, + { (char *)"&Play music", playMusic, NULL, 0, NULL }, + { (char *)"&Change track", changeTrack, NULL, 0, NULL }, + { (char *)"&Stop tunes", stopMusic, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"&Take Snapshot\tZ", onSnapshot, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU the_menu[] = +{ + { (char *)"&File", NULL, (MENU *) file_menu, 0, NULL }, + { (char *)"&Quest", NULL, (MENU *) quest_menu, 0, NULL }, + { (char *)"&Edit", NULL, (MENU *) edit_menu, 0, NULL }, + { (char *)"&View", NULL, (MENU *) view_menu, 0, NULL }, + { (char *)"&Tools", NULL, (MENU *) tool_menu, 0, NULL }, + { (char *)"&Screen", NULL, (MENU *) data_menu, 0, NULL }, + { (char *)"Et&c", NULL, (MENU *) etc_menu, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +void rebuild_trans_table(); +int launchPicViewer(BITMAP **pictoview, PALETTE pal, + int *px2, int *py2, double *scale, bool isviewingmap); + +int onResetTransparency() +{ + restore_mouse(); + rebuild_trans_table(); + gui->alert("Notice", "Translucency table rebuilt"); + + refresh(rALL); + return D_O_K; +} + +extern int zqwin_scale; + +int onFullScreen() +{ + int old_scale = zqwin_scale; +#ifdef ALLEGRO_DOS + return D_O_K; +#endif + get_palette(RAMpal); + show_mouse(NULL); + scrtmp = screen; + screen = hw_screen; + hw_screen = scrtmp; + bool windowed=is_windowed_mode()!=0; + + if(windowed) + { + zqwin_set_scale(1); + } + else + { + zqwin_set_scale(scale_arg); + } + + int ret=set_gfx_mode(windowed?GFX_AUTODETECT_FULLSCREEN:GFX_AUTODETECT_WINDOWED,zq_screen_w*zqwin_scale,zq_screen_h*zqwin_scale,0,0); + + if(ret!=0) + { + if(zqwin_scale==1&&windowed) + { + zqwin_set_scale(2); + ret=set_gfx_mode(windowed?GFX_AUTODETECT_FULLSCREEN:GFX_AUTODETECT_WINDOWED,zq_screen_w*zqwin_scale,zq_screen_h*zqwin_scale,0,0); + + if(ret!=0) + { + zqwin_set_scale(scale_arg); + ret=set_gfx_mode(GFX_AUTODETECT_WINDOWED,zq_screen_w*zqwin_scale,zq_screen_h*zqwin_scale,0,0); + + if(ret!=0) + { + Z_message("Can't set video mode (%d).\n", ret); + Z_message(allegro_error); + //quit_game(); + exit(1); + } + } + } + else + { + zqwin_set_scale(old_scale); + ret=set_gfx_mode(GFX_AUTODETECT_FULLSCREEN,zq_screen_w*zqwin_scale,zq_screen_h*zqwin_scale,0,0); + + if(ret!=0) + { + Z_message("Can't set video mode (%d).\n", ret); + Z_message(allegro_error); + // quit_game(); + exit(1); + } + } + } + + scrtmp = hw_screen; + hw_screen = screen; + screen = scrtmp; + set_palette(RAMpal); + gui_mouse_focus=0; + gui_bg_color=jwin_pal[jcBOX]; + gui_fg_color=jwin_pal[jcBOXFG]; + gui_mg_color=jwin_pal[jcMEDDARK]; + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + //zqwin_set_scale(zq_scale); + set_palette(RAMpal); + position_mouse(zq_screen_w/2,zq_screen_h/2); + show_mouse(screen); + set_display_switch_mode(SWITCH_BACKGROUND); + set_display_switch_callback(SWITCH_OUT, switch_out); + set_display_switch_callback(SWITCH_IN, switch_in); + return D_REDRAW; +} + +int onEnter() +{ +#ifdef ALLEGRO_DOS +#else + + if(key[KEY_ALT]||key[KEY_ALTGR]) + { + return onFullScreen(); + } + +#endif + return D_O_K; +} + +//PROC, x, y, w, h, fg, bg, key, flags, d1, d2, *dp, *dp2, *dp3 + +//*text, (*proc), *child, flags, *dp + +int d_nbmenu_proc(int msg,DIALOG *d,int c); + + +/*int onY() +{ + return D_O_K; +}*/ + +int onToggleGrid() +{ + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + GridColor=(GridColor+8)%16; + } + else + { + ShowGrid=!ShowGrid; + } + + return D_O_K; +} + +int onToggleShowScripts() +{ + ShowFFScripts=!ShowFFScripts; + return D_O_K; +} + +int onToggleShowSquares() +{ + ShowSquares=!ShowSquares; + return D_O_K; +} + +int onToggleShowInfo() +{ + ShowInfo=!ShowInfo; + return D_O_K; +} + +static DIALOG dialogs[] = +{ + // still unused: jm + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { d_nbmenu_proc, 0, 0, 0, 13, 0, 0, 0, D_USER, 0, 0, (void *) the_menu, NULL, NULL }, + + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '=', 0, 0, 0, (void *) onIncreaseCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '-', 0, 0, 0, (void *) onDecreaseCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '*', 0, 0, 0, (void *) onIncreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_CLOSEBRACE, 0, (void *) onIncreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '/', 0, 0, 0, (void *) onDecreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_OPENBRACE, 0, (void *) onDecreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_UP, 0, (void *) onUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DOWN, 0, (void *) onDown, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_LEFT, 0, (void *) onLeft, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT, 0, (void *) onRight, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGUP, 0, (void *) onPgUp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PGDN, 0, (void *) onPgDn, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PLUS_PAD, 0, (void *) onIncreaseCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_MINUS_PAD, 0, (void *) onDecreaseCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ASTERISK, 0, (void *) onIncreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_SLASH_PAD, 0, (void *) onDecreaseFlag, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F2, 0, (void *) onSave, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F3, 0, (void *) onOpen, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F4, 0, (void *) onScreenPalette, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F5, 0, (void *) onSecretCombo, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F6, 0, (void *) onDoors, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F7, 0, (void *) onSelectFFCombo, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F8, 0, (void *) onFlags, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F9, 0, (void *) onScrData, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F10, 0, (void *) onTileWarp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F11, 0, (void *) onSideWarp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, 0, (void *) onLayers, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, 0, (void *) onExit, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_A, 0, (void *) onCatchall, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_B, 0, (void *) onResetTransparency, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_C, 0, (void *) onCopy, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_D, 0, (void *) onToggleDarkness, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_E, 0, (void *) onEnemies, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F, 0, (void *) onShowFlags, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_G, 0, (void *) onGuy, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_H, 0, (void *) onH, NULL, NULL }, //Flip + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_I, 0, (void *) onItem, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_J, 0, (void *) onJ, NULL, NULL }, //This does nothing + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_K, 0, (void *) onCombos, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_L, 0, (void *) onShowDarkness, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_M, 0, (void *) onM, NULL, NULL }, // This does nothing + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_N, 0, (void *) onToggleShowInfo, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_O, 0, (void *) onDrawingMode, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_P, 0, (void *) onGotoPage, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_Q, 0, (void *) onShowComboInfoCSet, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_R, 0, (void *) onRType, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_S, 0, (void *) onString, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_T, 0, (void *) onTiles, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_U, 0, (void *) onUndo, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_V, 0, (void *) onPaste, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_W, 0, (void *) onShowWalkability, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_X, 0, (void *) onPreviewMode, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_Y, 0, (void *) onCompileScript, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_Z, 0, (void *) onSnapshot, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '0', 0, 0, 0, (void *) on0, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '1', 0, 0, 0, (void *) on1, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '2', 0, 0, 0, (void *) on2, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '3', 0, 0, 0, (void *) on3, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '4', 0, 0, 0, (void *) on4, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '5', 0, 0, 0, (void *) on5, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '6', 0, 0, 0, (void *) on6, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '7', 0, 0, 0, (void *) on7, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '8', 0, 0, 0, (void *) on8, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '9', 0, 0, 0, (void *) on9, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, ')', 0, 0, 0, (void *) on10, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '!', 0, 0, 0, (void *) on11, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '@', 0, 0, 0, (void *) on12, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '#', 0, 0, 0, (void *) on13, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '$', 0, 0, 0, (void *) on14, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, ',', 0, 0, 0, (void *) onDecMap, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '.', 0, 0, 0, (void *) onIncMap, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '<', 0, 0, 0, (void *) onDecScrPal, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, '>', 0, 0, 0, (void *) onIncScrPal, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_TILDE, 0, (void *) onToggleGrid, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, (void *) onUsedCombos, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_SPACE, 0, (void *) onSpacebar, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, 0, (void *) onDelete, NULL, NULL }, // + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ENTER, 0, (void *) onEnter, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG getnum_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 80, 80, 160, 72, vc(0), vc(11), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_rtext_proc, 114, 104+4, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Value:", NULL, NULL }, + { jwin_edit_proc, 168, 104, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 126, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 126, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int getnumber(const char *prompt,int initialval) +{ + cancelgetnum=true; + char buf[20]; + sprintf(buf,"%d",initialval); + getnum_dlg[0].dp=(void *)prompt; + getnum_dlg[0].dp2=lfont; + getnum_dlg[2].dp=(void *)buf; + + if(is_large) + large_dialog(getnum_dlg); + + int ret=zc_popup_dialog(getnum_dlg,2); + + if(ret!=0&&ret!=4) + { + cancelgetnum=false; + } + + if(ret==3) + return atoi(buf); + + return initialval; +} + +int gettilepagenumber(const char *prompt, int initialval) +{ + char buf[20]; + sprintf(buf,"%d",initialval); + getnum_dlg[0].dp=(void *)prompt; + getnum_dlg[0].dp2=lfont; + getnum_dlg[2].dp=buf; + + if(is_large) + large_dialog(getnum_dlg); + + int ret = zc_popup_dialog(getnum_dlg,2); + + if(ret==3) + return atoi(buf); + + return -1; +} + +int gethexnumber(const char *prompt,int initialval) +{ + cancelgetnum=true; + char buf[20]; + sprintf(buf,"%X",initialval); + getnum_dlg[0].dp=(void *)prompt; + getnum_dlg[0].dp2=lfont; + getnum_dlg[2].dp=(void *)buf; + + if(is_large) + large_dialog(getnum_dlg); + + int ret=zc_popup_dialog(getnum_dlg,2); + + if(ret!=0&&ret!=4) + { + cancelgetnum=false; + } + + if(ret==3) + return xtoi(buf); + + return initialval; +} + +void update_combo_cycling() +{ + Map.update_combo_cycling(); +} + +void update_freeform_combos() +{ + Map.update_freeform_combos(); +} + +bool layers_valid(mapscr *tempscr) +{ + for(int i=0; i<6; i++) + { + if(tempscr->layermap[i]>map_count) + { + return false; + } + } + + return true; +} + +void fix_layers(mapscr *tempscr, bool showwarning) +{ + char buf[256]= + "One or more layers on this screen used " + "maps that do not exist. The settings of these" + "layers have been changed: "; + + for(int i=0; i<6; i++) + { + if(tempscr->layermap[i]>map_count) + { + strcat(buf, "%d "); + sprintf(buf, buf, i+1); + tempscr->layermap[i]=0; + } + } + + if(showwarning) + gui->alert("Invalid layers detected", buf); +} + +/***********************/ +/*** dialog handlers ***/ +/***********************/ + +extern const char *colorlist(int index, int *list_size); + +static char autobackup_str_buf[32]; +const char *autobackuplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,10); + + if(index==0) + { + sprintf(autobackup_str_buf,"Disabled"); + } + else + { + sprintf(autobackup_str_buf,"%2d",index); + } + + return autobackup_str_buf; + } + + *list_size=11; + return NULL; +} + +static char autosave_str_buf[32]; +const char *autosavelist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,10); + + if(index==0) + { + sprintf(autosave_str_buf,"Disabled"); + } + else + { + sprintf(autosave_str_buf,"%2d Minute%c",index,index>1?'s':0); + } + + return autosave_str_buf; + } + + *list_size=11; + return NULL; +} + +const char *autosavelist2(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,9); + sprintf(autosave_str_buf,"%2d",index+1); + return autosave_str_buf; + } + + *list_size=10; + return NULL; +} + + +static int options_1_list[] = +{ + // dialog control number + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -1 +}; + +static int options_2_list[] = +{ + // dialog control number + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -1 +}; + +static TABPANEL options_tabs[] = +{ + // (text) + { (char *)" 1 ", D_SELECTED, options_1_list, 0, NULL }, + { (char *)" 2 ", 0, options_2_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static ListData autobackup_list(autobackuplist, &font); +static ListData autosave_list(autosavelist, &font); +static ListData autosave_list2(autosavelist2, &font); +static ListData color_list(colorlist, &font); +static ListData snapshotformat_list(snapshotformatlist, &font); + +static DIALOG options_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 260, 238, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "ZQuest Options", NULL, NULL }, + { jwin_tab_proc, 4, 23, 252, 182, vc(0), vc(15), 0, 0, 0, 0, (void *) options_tabs, NULL, (void *)options_dlg }, + { jwin_button_proc, 60, 212, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 140, 212, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 4 + { jwin_check_proc, 12, 44, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Mouse scroll", NULL, NULL }, + { jwin_check_proc, 12, 54, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Save paths", NULL, NULL }, + { jwin_check_proc, 12, 64, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Palette cycle", NULL, NULL }, + { jwin_check_proc, 12, 74, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Vsync", NULL, NULL }, + { jwin_check_proc, 12, 84, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show Frames Per Second", NULL, NULL }, + { jwin_check_proc, 12, 94, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combo Brush", NULL, NULL }, + { jwin_check_proc, 12, 104, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Floating Brush", NULL, NULL }, + { jwin_check_proc, 12, 114, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Reload Last Quest", NULL, NULL }, + { jwin_check_proc, 12, 124, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show Misaligns", NULL, NULL }, + { jwin_check_proc, 12, 134, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Animate Combos", NULL, NULL }, + { jwin_check_proc, 12, 144, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Overwrite Protection", NULL, NULL }, + { jwin_check_proc, 12, 154, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Tile Protection", NULL, NULL }, + { jwin_check_proc, 12, 164, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Use Static for Invalid Data", NULL, NULL }, + { jwin_check_proc, 12, 174, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Use Small Mode", NULL, NULL }, + { jwin_check_proc, 12, 184, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Show Ruleset Dialog When Creating New Quests", NULL, NULL }, + { jwin_check_proc, 12, 194, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enable Tooltips", NULL, NULL }, + + // 20 + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + + // 31 + { jwin_text_proc, 12, 48, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Auto-backup Retention:", NULL, NULL }, + { jwin_droplist_proc, 120, 44, 73, 16, 0, 0, 0, 0, 0, 0, (void *) &autobackup_list, NULL, NULL }, + { jwin_text_proc, 12, 66, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Auto-save Interval:", NULL, NULL }, + { jwin_droplist_proc, 105, 62, 86, 16, 0, 0, 0, 0, 0, 0, (void *) &autosave_list, NULL, NULL }, + { jwin_text_proc, 12, 84, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Auto-save Retention:", NULL, NULL }, + { jwin_droplist_proc, 111, 80, 49, 16, 0, 0, 0, 0, 0, 0, (void *) &autosave_list2, NULL, NULL }, + { jwin_check_proc, 12, 98, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Uncompressed Auto-saves", NULL, NULL }, + { jwin_text_proc, 12, 112, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Grid Color:", NULL, NULL }, + { jwin_droplist_proc, 64, 108, 100, 16, 0, 0, 0, 0, 0, 0, (void *) &color_list, NULL, NULL }, + { jwin_text_proc, 12, 130, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Snapshot Format:", NULL, NULL }, + { jwin_droplist_proc, 93, 126, 55, 16, 0, 0, 0, 0, 0, 0, (void *) &snapshotformat_list, NULL, NULL }, + + // 42 + { jwin_text_proc, 12, 148, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Keyboard Repeat Delay:", NULL, NULL }, + { jwin_edit_proc, 121, 144, 36, 16, 0, 0, 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 12, 166, 129, 9, 0, 0, 0, 0, 0, 0, (void *) "Keyboard Repeat Rate:", NULL, NULL }, + { jwin_edit_proc, 121, 162, 36, 16, 0, 0, 0, 0, 5, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onOptions() +{ + int OldAutoSaveInterval=AutoSaveInterval; + char kbdelay[80], kbrate[80]; + sprintf(kbdelay, "%d", KeyboardRepeatDelay); + sprintf(kbrate, "%d", KeyboardRepeatRate); + options_dlg[0].dp2=lfont; + reset_combo_animations(); + reset_combo_animations2(); + go(); + options_dlg[4].flags = MouseScroll ? D_SELECTED : 0; + options_dlg[5].flags = SavePaths ? D_SELECTED : 0; + options_dlg[6].flags = CycleOn ? D_SELECTED : 0; + options_dlg[7].flags = Vsync ? D_SELECTED : 0; + options_dlg[8].flags = ShowFPS ? D_SELECTED : 0; + options_dlg[9].flags = ComboBrush ? D_SELECTED : 0; + options_dlg[10].flags = FloatBrush ? D_SELECTED : 0; + options_dlg[11].flags = OpenLastQuest ? D_SELECTED : 0; + options_dlg[12].flags = ShowMisalignments ? D_SELECTED : 0; + options_dlg[13].flags = AnimationOn ? D_SELECTED : 0; + options_dlg[14].flags = OverwriteProtection ? D_SELECTED : 0; + options_dlg[15].flags = TileProtection ? D_SELECTED : 0; + options_dlg[16].flags = InvalidStatic ? D_SELECTED : 0; + options_dlg[17].flags = UseSmall ? D_SELECTED : 0; + options_dlg[18].flags = RulesetDialog ? D_SELECTED : 0; + options_dlg[19].flags = EnableTooltips ? D_SELECTED : 0; + options_dlg[32].d1 = AutoBackupRetention; + options_dlg[34].d1 = AutoSaveInterval; + options_dlg[36].d1 = AutoSaveRetention; + options_dlg[37].flags = UncompressedAutoSaves ? D_SELECTED : 0; + options_dlg[39].d1 = GridColor; + options_dlg[41].d1 = SnapshotFormat; + options_dlg[43].dp = kbdelay; + options_dlg[45].dp = kbrate; + + if(is_large) + large_dialog(options_dlg); + + if(zc_popup_dialog(options_dlg,-1) == 2) + { + MouseScroll = options_dlg[4].flags & D_SELECTED ? 1 : 0; + SavePaths = options_dlg[5].flags & D_SELECTED ? 1 : 0; + CycleOn = options_dlg[6].flags & D_SELECTED ? 1 : 0; + Vsync = options_dlg[7].flags & D_SELECTED ? 1 : 0; + ShowFPS = options_dlg[8].flags & D_SELECTED ? 1 : 0; + ComboBrush = options_dlg[9].flags & D_SELECTED ? 1 : 0; + FloatBrush = options_dlg[10].flags & D_SELECTED ? 1 : 0; + OpenLastQuest = options_dlg[11].flags & D_SELECTED ? 1 : 0; + ShowMisalignments = options_dlg[12].flags & D_SELECTED ? 1 : 0; + AnimationOn = options_dlg[13].flags & D_SELECTED ? 1 : 0; + OverwriteProtection = options_dlg[14].flags & D_SELECTED ? 1 : 0; + TileProtection = options_dlg[15].flags & D_SELECTED ? 1 : 0; + InvalidStatic = options_dlg[16].flags & D_SELECTED ? 1 : 0; + UseSmall = options_dlg[17].flags & D_SELECTED ? 1 : 0; + RulesetDialog = options_dlg[18].flags & D_SELECTED ? 1 : 0; + EnableTooltips = options_dlg[19].flags & D_SELECTED ? 1 : 0; + AutoBackupRetention = options_dlg[32].d1; + AutoSaveInterval = options_dlg[34].d1; + AutoSaveRetention = options_dlg[36].d1; + UncompressedAutoSaves = options_dlg[37].flags & D_SELECTED ? 1 : 0; + GridColor = options_dlg[39].d1; + SnapshotFormat = options_dlg[41].d1; + KeyboardRepeatDelay = atoi(kbdelay); + KeyboardRepeatRate = atoi(kbrate); + + set_keyboard_rate(KeyboardRepeatDelay,KeyboardRepeatRate); + } + + if(AutoSaveInterval!=OldAutoSaveInterval) + { + time(&auto_save_time_start); + } + + save_config_file(); + setup_combo_animations(); + setup_combo_animations2(); + refresh(rALL); + comeback(); + return D_O_K; +} + +enum {dm_normal, dm_relational, dm_dungeon, dm_alias, dm_max}; +const char *dm_names[dm_max]= +{ + "Normal", + "Relational", + "Dungeon", + "Alias" +}; + +byte relational_tile_grid[11+(rtgyo*2)][16+(rtgxo*2)]; + +void fix_drawing_mode_menu() +{ + for(int i=0; ialert("Confirm overwrite", + "Apply NES dungeon template to all screens on this map?", + "&Yes", "&No", 2); + if(ret==1) + { + Map.TemplateAll(); + refresh(rALL); + } + + return D_O_K; +} + +int onUndo() +{ + Map.Uhuilai(); + refresh(rALL); + return D_O_K; +} + +int onCopy() +{ + if(prv_mode) + { + Map.set_prvcmb(Map.get_prvcmb()==0?1:0); + return D_O_K; + } + + Map.Copy(); + return D_O_K; +} + +int onH() +{ + return D_O_K; +} + +int onPaste() +{ + { + Map.Paste(); + refresh(rALL); + } + return D_O_K; +} + +int onPasteAll() +{ + Map.PasteAll(); + refresh(rALL); + return D_O_K; +} + +int onPasteToAll() +{ + Map.PasteToAll(); + refresh(rALL); + return D_O_K; +} + +int onPasteAllToAll() +{ + Map.PasteAllToAll(); + refresh(rALL); + return D_O_K; +} + +int onPasteUnderCombo() +{ + Map.PasteUnderCombo(); + refresh(rALL); + return D_O_K; +} + +int onPasteSecretCombos() +{ + Map.PasteSecretCombos(); + refresh(rALL); + return D_O_K; +} + +int onPasteFFCombos() +{ + Map.PasteFFCombos(); + refresh(rALL); + return D_O_K; +} + +int onPasteWarps() +{ + Map.PasteWarps(); + refresh(rALL); + return D_O_K; +} + +int onPasteScreenData() +{ + Map.PasteScreenData(); + refresh(rALL); + return D_O_K; +} + +int onPasteWarpLocations() +{ + Map.PasteWarpLocations(); + refresh(rALL); + return D_O_K; +} + +int onPasteDoors() +{ + Map.PasteDoors(); + refresh(rALL); + return D_O_K; +} + +int onPasteLayers() +{ + Map.PasteLayers(); + refresh(rALL); + return D_O_K; +} + +int onPastePalette() +{ + Map.PastePalette(); + refresh(rALL); + return D_O_K; +} + +int onPasteRoom() +{ + Map.PasteRoom(); + refresh(rALL); + return D_O_K; +} + +int onPasteGuy() +{ + Map.PasteGuy(); + refresh(rALL); + return D_O_K; +} + +int onPasteEnemies() +{ + Map.PasteEnemies(); + refresh(rALL); + return D_O_K; +} + +int onDelete() +{ + restore_mouse(); + + if(Map.CurrScr()->valid&mVALID) + { + int ret=gui->alert("Confirm Delete", + "Delete this screen?", + "&Yes", "&No", 2); + if(ret==1) + { + Map.Ugo(); + Map.clearscr(Map.getCurrScr()); + refresh(rALL); + } + } + + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + saved=false; + return D_O_K; + +} + +int onDeleteMap() +{ + int ret=gui->alert("Confirm delete", + "Clear this entire map?", + "&Yes", "&No", 2); + if(ret==1) + { + Map.clearmap(false); + refresh(rALL); + saved=false; + } + + return D_O_K; +} + +int onToggleDarkness() +{ + Map.CurrScr()->flags^=4; + refresh(rMAP+rMENU); + saved=false; + return D_O_K; +} + +int onIncMap() +{ + int m=Map.getCurrMap(); + int oldcolor=Map.getcolor(); + Map.setCurrMap(m+1>=map_count?0:m+1); + + if(m!=Map.getCurrMap()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + int newcolor=Map.getcolor(); + + if(newcolor!=oldcolor) + { + rebuild_trans_table(); + } + + refresh(rALL); + return D_O_K; +} + +int onDecMap() +{ + int m=Map.getCurrMap(); + int oldcolor=Map.getcolor(); + Map.setCurrMap((m-1<0)?map_count-1:zc_min(m-1,map_count-1)); + + if(m!=Map.getCurrMap()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + int newcolor=Map.getcolor(); + + if(newcolor!=oldcolor) + { + rebuild_trans_table(); + } + + refresh(rALL); + return D_O_K; +} + + +int onDefault_Pals() +{ + int ret=gui->alert("Confirm reset", + "Reset all palette data?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + + if(!init_colordata(true, &header, &misc)) + gui->alert("Error", "Palette reset failed."); + + refresh_pal(); + } + + return D_O_K; +} + +int onDefault_Combos() +{ + int ret=gui->alert("Confirm reset", + "Reset combo data?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + + if(!init_combos(true, &header)) + gui->alert("Error", "Combo reset failed."); + + refresh(rALL); + } + + return D_O_K; +} + +int onDefault_Items() +{ + int ret=gui->alert("Confirm reset", + "Reset all items?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + reset_items(true, &header); + } + + return D_O_K; +} + +int onDefault_Weapons() +{ + int ret=gui->alert("Confirm reset", + "Reset weapon/misc. sprite data?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + reset_wpns(true, &header); + } + + return D_O_K; +} + +int onDefault_Guys() +{ + int ret=gui->alert("Confirm reset", + "Reset all enemy/NPC data?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + reset_guys(); + } + + return D_O_K; +} + + +int onDefault_Tiles() +{ + int ret=gui->alert("Confirm reset", + "Reset all tiles?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + + if(!init_tiles(true, &header)) + gui->alert("Error", "Tile reset failed."); + + refresh(rALL); + } + + return D_O_K; +} + +void change_sfx(SAMPLE *sfx1, SAMPLE *sfx2); + +int onDefault_SFX() +{ + int ret=gui->alert("Confirm reset", + "Reset all sound effects?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + SAMPLE *temp_sample; + + for(int i=1; i>3); + } + } + + return D_O_K; +} + + +int onDefault_MapStyles() +{ + int ret=gui->alert("Confirm reset", + "Reset all map styles?", + "&Yes", "&No", 2); + if(ret==1) + { + saved=false; + reset_mapstyles(true, &misc); + } + + return D_O_K; +} + + +int on0() +{ + saved=false; + Map.setcolor(0); + refresh(rSCRMAP); + return D_O_K; +} +int on1() +{ + saved=false; + Map.setcolor(1); + refresh(rSCRMAP); + return D_O_K; +} +int on2() +{ + saved=false; + Map.setcolor(2); + refresh(rSCRMAP); + return D_O_K; +} +int on3() +{ + saved=false; + Map.setcolor(3); + refresh(rSCRMAP); + return D_O_K; +} +int on4() +{ + saved=false; + Map.setcolor(4); + refresh(rSCRMAP); + return D_O_K; +} +int on5() +{ + saved=false; + Map.setcolor(5); + refresh(rSCRMAP); + return D_O_K; +} + +int on6() +{ + saved=false; + Map.setcolor(6); + refresh(rSCRMAP); + return D_O_K; +} +int on7() +{ + saved=false; + Map.setcolor(7); + refresh(rSCRMAP); + return D_O_K; +} +int on8() +{ + saved=false; + Map.setcolor(8); + refresh(rSCRMAP); + return D_O_K; +} +int on9() +{ + saved=false; + Map.setcolor(9); + refresh(rSCRMAP); + return D_O_K; +} +int on10() +{ + saved=false; + Map.setcolor(10); + refresh(rSCRMAP); + return D_O_K; +} +int on11() +{ + saved=false; + Map.setcolor(11); + refresh(rSCRMAP); + return D_O_K; +} +int on12() +{ + saved=false; + Map.setcolor(12); + refresh(rSCRMAP); + return D_O_K; +} +int on13() +{ + saved=false; + Map.setcolor(13); + refresh(rSCRMAP); + return D_O_K; +} +int on14() +{ + saved=false; + Map.setcolor(14); + refresh(rSCRMAP); + return D_O_K; +} + +int onLeft() +{ + int tempcurrscr=Map.getCurrScr(); + + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT]) + { + Map.scroll(2); + + if(tempcurrscr!=Map.getCurrScr()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + refresh(rALL); + } + else if((First[current_combolist]>0)&&(draw_mode!=dm_alias)) + { + First[current_combolist]-=1; + clear_tooltip(); + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]>0)&&(draw_mode==dm_alias)) + { + combo_alistpos[current_comboalist]-=1; + clear_tooltip(); + refresh(rCOMBOS); + } + + clear_keybuf(); + return D_O_K; +} + +int onRight() +{ + int tempcurrscr=Map.getCurrScr(); + + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT]) + { + Map.scroll(3); + + if(tempcurrscr!=Map.getCurrScr()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + refresh(rALL); + } + else if((First[current_combolist]<(MAXCOMBOS-(combolist[0].w*combolist[0].h)))&&(draw_mode!=dm_alias)) + { + First[current_combolist]+=1; + clear_tooltip(); + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]<(MAXCOMBOALIASES-(combolist[0].w*combolist[0].h)))&&(draw_mode==dm_alias)) + { + combo_alistpos[current_comboalist]+=1; + clear_tooltip(); + refresh(rCOMBOS); + } + + clear_keybuf(); + return D_O_K; +} + +int onUp() +{ + int tempcurrscr=Map.getCurrScr(); + + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT]) + { + Map.scroll(0); + + if(tempcurrscr!=Map.getCurrScr()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + refresh(rALL); + } + else if((First[current_combolist]>0)&&(draw_mode!=dm_alias)) + { + First[current_combolist]-=zc_min(First[current_combolist],combolist[0].w); + clear_tooltip(); + + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]>0)&&(draw_mode==dm_alias)) + { + combo_alistpos[current_comboalist]-=zc_min(combo_alistpos[current_comboalist],combolist[0].w); + clear_tooltip(); + refresh(rCOMBOS); + } + + clear_keybuf(); + return D_O_K; +} + +int onDown() +{ + int tempcurrscr=Map.getCurrScr(); + + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT]) + { + Map.scroll(1); + + if(tempcurrscr!=Map.getCurrScr()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + + refresh(rALL); + } + else if((First[current_combolist]<(MAXCOMBOS-(combolist[0].w*combolist[0].h)))&&(draw_mode!=dm_alias)) + { + First[current_combolist]+=zc_min((MAXCOMBOS-combolist[0].w)-First[current_combolist],combolist[0].w); + clear_tooltip(); + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]<(MAXCOMBOALIASES-(comboaliaslist[0].w*comboaliaslist[0].h)))&&(draw_mode==dm_alias)) + { + combo_alistpos[current_comboalist]+=zc_min((MAXCOMBOALIASES-combolist[0].w)-combo_alistpos[current_comboalist],combolist[0].w); + clear_tooltip(); + refresh(rCOMBOS); + } + + clear_keybuf(); + return D_O_K; +} + +int onPgUp() +{ + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT] && + !key[KEY_ZC_LCONTROL] && !key[KEY_ZC_RCONTROL] && !is_large) + { + menutype=wrap(menutype-1,0,m_menucount-1); + refresh(rMENU); + } + else if((First[current_combolist]>0)&&(draw_mode!=dm_alias)) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + First[current_combolist]-=zc_min(First[current_combolist],256); + clear_tooltip(); + } + else + { + First[current_combolist]-=zc_min(First[current_combolist],(combolist[0].w*combolist[0].h)); + clear_tooltip(); + } + + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]>0)&&(draw_mode==dm_alias)) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + combo_alistpos[current_comboalist]=0; + clear_tooltip(); + } + else + { + combo_alistpos[current_comboalist]-=zc_min(combo_alistpos[current_comboalist],(comboaliaslist[0].w*comboaliaslist[0].h)); + clear_tooltip(); + } + + refresh(rCOMBOS); + } + + return D_O_K; +} + +int onPgDn() +{ + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT] && + !key[KEY_ZC_LCONTROL] && !key[KEY_ZC_RCONTROL] && !is_large) + { + menutype=wrap(menutype+1,0,m_menucount-1); + refresh(rMENU); + } + else if((First[current_combolist]<(MAXCOMBOS-(combolist[0].w*combolist[0].h)))&&(draw_mode!=dm_alias)) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + First[current_combolist]=zc_min((MAXCOMBOS-combolist[0].w*combolist[0].h),First[current_combolist]+256); + clear_tooltip(); + } + else + { + First[current_combolist]=zc_min((MAXCOMBOS-(combolist[0].w*combolist[0].h)),First[current_combolist]+(combolist[0].w*combolist[0].h)); + clear_tooltip(); + } + + refresh(rCOMBOS); + } + else if((combo_alistpos[current_comboalist]<(MAXCOMBOALIASES-(comboaliaslist[0].w*comboaliaslist[0].h)))&&(draw_mode==dm_alias)) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + combo_alistpos[current_comboalist]=MAXCOMBOALIASES-(comboaliaslist[0].w*comboaliaslist[0].h); + clear_tooltip(); + } + else + { + combo_alistpos[current_comboalist]=zc_min((MAXCOMBOALIASES-(comboaliaslist[0].w*comboaliaslist[0].h)),combo_alistpos[current_comboalist]+(comboaliaslist[0].w*comboaliaslist[0].h)); + clear_tooltip(); + } + + refresh(rCOMBOS); + } + + return D_O_K; +} + +int onIncreaseCSet() +{ + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT] && + !key[KEY_ZC_LCONTROL] && !key[KEY_ZC_RCONTROL] && + !key[KEY_ALT] && !key[KEY_ALTGR]) + { + if(draw_mode!=dm_alias) + { + CSet=wrap(CSet+1,0,11); + refresh(rCOMBOS+rMENU+rCOMBO); + } + else + { + alias_cset_mod=wrap(alias_cset_mod+1,0,11); + } + } + else if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return D_O_K; + } + } + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + return D_O_K; + } + + saved=false; + Map.Ugo(); + int changeby=1; + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + changeby*=16; + } + + if(key[KEY_ALT] || key[KEY_ALTGR]) + { + changeby*=256; + } + + for(int i=0; i<176; i++) + { + int temp=Map.AbsoluteScr(drawmap, drawscr)->data[i]; + + temp+=changeby; + + if(temp>=MAXCOMBOS) + { + temp=temp-MAXCOMBOS; + } + + Map.AbsoluteScr(drawmap, drawscr)->data[i]=temp; + } + + refresh(rMAP+rSCRMAP); + } + + return D_O_K; +} + +int onDecreaseCSet() +{ + if(!key[KEY_LSHIFT] && !key[KEY_RSHIFT] && + !key[KEY_ZC_LCONTROL] && !key[KEY_ZC_RCONTROL] && + !key[KEY_ALT] && !key[KEY_ALTGR]) + { + if(draw_mode!=dm_alias) + { + CSet=wrap(CSet-1,0,11); + refresh(rCOMBOS+rMENU+rCOMBO); + } + else + { + alias_cset_mod=wrap(alias_cset_mod-1,0,11); + } + } + else if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return D_O_K; + } + } + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + return D_O_K; + } + + saved=false; + Map.Ugo(); + int changeby=1; + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + changeby*=16; + } + + if(key[KEY_ALT] || key[KEY_ALTGR]) + { + changeby*=256; + } + + for(int i=0; i<176; i++) + { + int temp=Map.AbsoluteScr(drawmap, drawscr)->data[i]; + temp-=changeby; + + if(temp<0) + { + temp=MAXCOMBOS+temp; + } + + Map.AbsoluteScr(drawmap, drawscr)->data[i]=temp; + } + + refresh(rMAP+rSCRMAP); + } + + return D_O_K; +} + +int onGotoPage() +{ + int choosepage=getnumber("Scroll to Combo Page", 0); + + if(!cancelgetnum) + { + int page=(zc_min(choosepage,COMBO_PAGES-1)); + First[current_combolist]=page<<8; + } + + return D_O_K; +} + +bool getname(const char *prompt,const char *ext,EXT_LIST *list,const char *def,bool usefilename) +{ + go(); + int ret=0; + ret = getname_nogo(prompt,ext,list,def,usefilename); + comeback(); + return ret != 0; +} + + +bool getname_nogo(const char *prompt,const char *ext,EXT_LIST *list,const char *def,bool usefilename) +{ + if(def!=temppath) + strcpy(temppath,def); + + if(!usefilename) + { + int i=(int)strlen(temppath); + + while(i>=0 && temppath[i]!='\\' && temppath[i]!='/') + temppath[i--]=0; + } + + // int ret = file_select_ex(prompt,temppath,ext,255,-1,-1); + int ret=0; + int sel=0; + + if(list==NULL) + { + ret = jwin_file_select_ex(prompt,temppath,ext,2048,-1,-1,lfont); + } + else + { + ret = jwin_file_browse_ex(prompt, temppath, list, &sel, 2048, -1, -1, lfont); + } + + return ret!=0; +} + + +static char track_number_str_buf[32]; +const char *tracknumlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,255); + sprintf(track_number_str_buf,"%02d",index+1); + return track_number_str_buf; + } + + *list_size=zcmusic_get_tracks(zcmusic); + return NULL; +} + +static ListData tracknum_list(tracknumlist, &font); + +static DIALOG change_track_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200-16, 72, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Track", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_droplist_proc, 72-12, 60+4, 161, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &tracknum_list, NULL, NULL }, + { jwin_button_proc, 70, 87, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 150, 87, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; +// return list_dlg[2].d1; + +int changeTrack() +{ + restore_mouse(); + change_track_dlg[0].dp2=lfont; + change_track_dlg[2].d1=gme_track; + + if(is_large) large_dialog(change_track_dlg); + + if(zc_popup_dialog(change_track_dlg,2)==3) + { + gme_track=change_track_dlg[2].d1; + zcmusic_change_track(zcmusic, gme_track); + } + + return D_O_K; +} + + +int playMusic() +{ + char *ext; + bool ismidi=false; + char allmusic_types[256]; + sprintf(allmusic_types, "%s;mid", zcmusic_types); + + if(getname("Load Music",(char*)allmusic_types,NULL,midipath,false)) + { + strcpy(midipath,temppath); + + ext=get_extension(midipath); + + if( + (stricmp(ext,"ogg")==0)|| + (stricmp(ext,"mp3")==0)|| + (stricmp(ext,"it")==0)|| + (stricmp(ext,"xm")==0)|| + (stricmp(ext,"s3m")==0)|| + (stricmp(ext,"mod")==0)|| + (stricmp(ext,"spc")==0)|| + (stricmp(ext,"gym")==0)|| + (stricmp(ext,"nsf")==0)|| + (stricmp(ext,"gbs")==0)|| + (stricmp(ext,"vgm")==0) + ) + { + ismidi=false; + } + else if((stricmp(ext,"mid")==0)) + { + ismidi=true; + } + else + { + return D_O_K; + } + + stop_midi(); + + if(zcmusic != NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + zcmusic = NULL; + } + + if(ismidi) + { + if((song=load_midi(midipath))!=NULL) + { + if(play_midi(song,true)==0) + { + etc_menu[8].flags = + commands[cmdPlayTune].flags = 0; + + etc_menu[9].flags = D_SELECTED; + commands[cmdPlayMusic].flags = 0; + + etc_menu[10].flags = + commands[cmdChangeTrack].flags = D_DISABLED; + } + } + } + else + { + gme_track=0; + zcmusic = (ZCMUSIC*)zcmusic_load_file(midipath); + + if(zcmusic!=NULL) + { + etc_menu[8].flags = + commands[cmdPlayTune].flags = 0; + + etc_menu[9].flags=D_SELECTED; + commands[cmdPlayMusic].flags = 0; + + etc_menu[10].flags = + commands[cmdChangeTrack].flags = (zcmusic_get_tracks(zcmusic)<2)?D_DISABLED:0; + + zcmusic_play(zcmusic, midi_volume); + } + } + } + + return D_O_K; +} + +// It took awhile to get these values right, so no meddlin'! +int playTune1() +{ + return playTune(0); +} +int playTune2() +{ + return playTune(81); +} +int playTune3() +{ + return playTune(233); +} +int playTune4() +{ + return playTune(553); +} +int playTune5() +{ + return playTune(814); +} +int playTune6() +{ + return playTune(985); +} +int playTune7() +{ + return playTune(1153); +} +int playTune8() +{ + return playTune(1333); +} +int playTune9() +{ + return playTune(1556); +} +int playTune10() +{ + return playTune(1801); +} +int playTune11() +{ + return playTune(2069); +} +int playTune12() +{ + return playTune(2189); +} +int playTune13() +{ + return playTune(2569); +} +int playTune14() +{ + return playTune(2753); +} +int playTune15() +{ + return playTune(2856); +} +int playTune16() +{ + return playTune(3042); +} +int playTune17() +{ + return playTune(3125); +} +int playTune18() +{ + return playTune(3217); +} +int playTune19() +{ + return playTune(3296); +} + +int playTune(int pos) +{ + stop_midi(); + + if(zcmusic != NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + zcmusic = NULL; + } + + if(play_midi((MIDI*)zcdata[THETRAVELSOFLINK_MID].dat,true)==0) + { + midi_seek(pos); + + etc_menu[8].flags = D_SELECTED; + commands[cmdPlayTune].flags = 0; + + etc_menu[9].flags = + commands[cmdPlayMusic].flags = 0; + + etc_menu[10].flags = + commands[cmdChangeTrack].flags = D_DISABLED; + } + + return D_O_K; +} + +int stopMusic() +{ + stop_midi(); + + if(zcmusic != NULL) + { + zcmusic_stop(zcmusic); + zcmusic_unload_file(zcmusic); + zcmusic = NULL; + } + + etc_menu[8].flags = + etc_menu[9].flags = + commands[cmdPlayTune].flags = + commands[cmdPlayMusic].flags = 0; + + etc_menu[10].flags = + commands[cmdChangeTrack].flags = D_DISABLED; + return D_O_K; +} + +#include "zq_files.h" + +int onTemplates() +{ + edit_qt(); + return D_O_K; +} + +// +----------+ +// | | +// | View Pic | +// | | +// | | +// | | +// +----------+ + +BITMAP *pic=NULL; +BITMAP *bmap=NULL; +PALETTE picpal; +PALETTE mappal; +int picx=0,picy=0,mapx=0,mapy=0,pblack,pwhite; + +double picscale=1.0,mapscale=1.0; +bool vp_showpal=true, vp_showsize=true, vp_center=true; + +//INLINE int pal_sum(RGB p) { return p.r + p.g + p.b; } + +void get_bw(RGB *pal,int &black,int &white) +{ + black=white=1; + + for(int i=1; i<256; i++) + { + if(pal_sum(pal[i])pal_sum(pal[white])) + white=i; + } +} + +void draw_bw_mouse(int white, int old_mouse, int new_mouse) +{ + blit(mouse_bmp[old_mouse][0],mouse_bmp[new_mouse][0],0,0,0,0,16,16); + + for(int y=0; y<16; y++) + { + for(int x=0; x<16; x++) + { + if(getpixel(mouse_bmp[new_mouse][0],x,y)!=0) + { + putpixel(mouse_bmp[new_mouse][0],x,y,white); + } + } + } +} + +int load_the_pic(BITMAP **dst, PALETTE dstpal) +{ + PALETTE temppal; + + for(int i=0; i<256; i++) + { + temppal[i]=dstpal[i]; + dstpal[i]=RAMpal[i]; + } + + // set up the new palette + for(int i=0; i<64; i++) + { + dstpal[i].r = i; + dstpal[i].g = i; + dstpal[i].b = i; + } + + set_palette(dstpal); + + BITMAP *graypic = create_bitmap_ex(8,SCREEN_W,SCREEN_H); + int _w = screen->w-1; + int _h = screen->h-1; + + // gray scale the current frame + for(int y=0; y<_h; y++) + { + for(int x=0; x<_w; x++) + { + int c = screen->line[y][x]; + int gray = zc_min((temppal[c].r*42 + temppal[c].g*75 + temppal[c].b*14) >> 7, 63); + graypic->line[y][x] = gray; + } + } + + blit(graypic,screen,0,0,0,0,SCREEN_W,SCREEN_H); + destroy_bitmap(graypic); + char extbuf[2][80]; + memset(extbuf[0],0,80); + memset(extbuf[1],0,80); + sprintf(extbuf[0], "View Image (%s", snapshotformat_str[0][1]); + strcpy(extbuf[1], snapshotformat_str[0][1]); + + for(int i=1; iw-zq_screen_w; + picy=(*dst)->h-zq_screen_h; + } + + return 0; +} + +int mapMaker(BITMAP * _map, PALETTE _mappal) +{ + char buf[50]; + int num=0; + + do + { +#ifdef ALLEGRO_MACOSX + snprintf(buf, 50, "../../../zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#else + snprintf(buf, 50, "zelda%03d.%s", ++num, snapshotformat_str[SnapshotFormat][1]); +#endif + buf[49]='\0'; + } + while(num<999 && exists(buf)); + + save_bitmap(buf,_map,_mappal); + + return D_O_K; +} + +int onViewPic() +{ + return launchPicViewer(&pic,picpal,&picx,&picy,&picscale,false); +} + +int launchPicViewer(BITMAP **pictoview, PALETTE pal, int *px2, int *py2, double *scale2, bool isviewingmap) +{ + restore_mouse(); + BITMAP *buf; + bool done=false, redraw=true; + + go(); + scare_mouse(); + clear_bitmap(screen); + + // Always call load_the_map() when viewing the map. + if((!*pictoview || isviewingmap) && (isviewingmap ? load_the_map() : load_the_pic(pictoview,pal))) + { + set_palette(RAMpal); + unscare_mouse(); + comeback(); + return D_O_K; + } + + get_bw(pal,pblack,pwhite); + + int oldfgcolor = gui_fg_color; + int oldbgcolor = gui_bg_color; + + buf = create_bitmap_ex(8,zq_screen_w,zq_screen_h); + + if(!buf) + { + jwin_alert("Error","Error creating temp bitmap",NULL,NULL,"OK",NULL,13,27,lfont); + return D_O_K; + } + + // go(); + // scare_mouse(); + // clear_bitmap(screen); + set_palette(pal); + + do + { + if(redraw) + { + clear_to_color(buf,pblack); + stretch_blit(*pictoview,buf,0,0,(*pictoview)->w,(*pictoview)->h, + int(zq_screen_w+(*px2-(*pictoview)->w)* *scale2)/2,int(zq_screen_h+(*py2-(*pictoview)->h)* *scale2)/2, + int((*pictoview)->w* *scale2),int((*pictoview)->h* *scale2)); + + if(vp_showpal) + for(int i=0; i<256; i++) + rectfill(buf,((i&15)<<2)+zq_screen_w-64,((i>>4)<<2)+zq_screen_h-64,((i&15)<<2)+zq_screen_w-64+3,((i>>4)<<2)+zq_screen_h-64+3,i); + + if(vp_showsize) + { + // text_mode(pblack); + textprintf_ex(buf,font,0,zq_screen_h-8,pwhite,pblack,"%dx%d %.2f%%",(*pictoview)->w,(*pictoview)->h,*scale2*100.0); + } + + blit(buf,screen,0,0,0,0,zq_screen_w,zq_screen_h); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + redraw=false; + } + + custom_vsync(); + + int step = 4; + + if(*scale2 < 1.0) + step = int(4.0/ *scale2); + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + step <<= 2; + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + step = 1; + + if(key[KEY_UP]) + { + *py2+=step; + redraw=true; + } + + if(key[KEY_DOWN]) + { + *py2-=step; + redraw=true; + } + + if(key[KEY_LEFT]) + { + *px2+=step; + redraw=true; + } + + if(key[KEY_RIGHT]) + { + *px2-=step; + redraw=true; + } + + if(keypressed() && !redraw) + switch(readkey()>>8) + { + case KEY_PGUP: + *scale2*=0.95; + + if(*scale2<0.1) *scale2=0.1; + + redraw=true; + break; + + case KEY_PGDN: + *scale2/=0.95; + + if(*scale2>5.0) *scale2=5.0; + + redraw=true; + break; + + case KEY_HOME: + *scale2/=2.0; + + if(*scale2<0.1) *scale2=0.1; + + redraw=true; + break; + + case KEY_END: + *scale2*=2.0; + + if(*scale2>5.0) *scale2=5.0; + + redraw=true; + break; + + case KEY_TILDE: + *scale2=0.5; + redraw=true; + break; + + case KEY_Z: + *px2=(*pictoview)->w-zq_screen_w; + *py2=(*pictoview)->h-zq_screen_h; + vp_center=false; + redraw=true; + break; + + case KEY_1: + *scale2=1.0; + redraw=true; + break; + + case KEY_2: + *scale2=2.0; + redraw=true; + break; + + case KEY_3: + *scale2=3.0; + redraw=true; + break; + + case KEY_4: + *scale2=4.0; + redraw=true; + break; + + case KEY_5: + *scale2=5.0; + redraw=true; + break; + + case KEY_C: + *px2=*py2=0; + redraw=vp_center=true; + break; + + case KEY_S: + vp_showsize = !vp_showsize; + redraw=true; + break; + + case KEY_D: + vp_showpal = !vp_showpal; + redraw=true; + break; + + case KEY_P: + if(isviewingmap) break; + + case KEY_ESC: + done=true; + break; + + case KEY_SPACE: + if(isviewingmap ? load_the_map() : load_the_pic(pictoview,pal)==2) + { + done=true; + } + else + { + redraw=true; + gui_bg_color = pblack; + gui_fg_color = pwhite; + *scale2=1.0; + set_palette(pal); + } + + get_bw(pal,pblack,pwhite); + break; + } + } + while(!done); + + destroy_bitmap(buf); + set_palette(RAMpal); + unscare_mouse(); + gui_fg_color = oldfgcolor; + gui_bg_color = oldbgcolor; + + comeback(); + position_mouse_z(0); + return D_O_K; +} + +static DIALOG loadmap_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 225, 113, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "View Map", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 32, 26, 96, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Resolution", NULL, NULL }, + // 3 + { jwin_radio_proc, 16, 36, 97, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "1/4 - 1024x352", NULL, NULL }, + { jwin_radio_proc, 16, 46, 97, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "1/2 - 2048x704", NULL, NULL }, + { jwin_radio_proc, 16, 56, 97, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Full - 4096x1408", NULL, NULL }, + { jwin_text_proc, 144, 26, 97, 9, vc(11), vc(1), 0, 0, 0, 0, (void *) "Options", NULL, NULL }, + // 7 + { jwin_check_proc, 144, 36, 97, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Walk", NULL, NULL }, + { jwin_check_proc, 144, 46, 97, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Flags", NULL, NULL }, + { jwin_check_proc, 144, 56, 97, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Dark", NULL, NULL }, + { jwin_check_proc, 144, 66, 97, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Items", NULL, NULL }, + // 11 + { jwin_button_proc, 42, 80, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 122, 80, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_check_proc, 16, 68, 97, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Save to File (Mapmaker)", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int load_the_map() +{ + static int res = 1; + static int flags = cDEBUG; + + loadmap_dlg[0].dp2 = lfont; + loadmap_dlg[3].flags = (res==2) ? D_SELECTED : 0; + loadmap_dlg[4].flags = (res==1) ? D_SELECTED : 0; + loadmap_dlg[5].flags = (res==0) ? D_SELECTED : 0; + loadmap_dlg[7].flags = (flags&cWALK) ? D_SELECTED : 0; + loadmap_dlg[8].flags = (flags&cFLAGS) ? D_SELECTED : 0; + loadmap_dlg[9].flags = (flags&cNODARK) ? 0 : D_SELECTED; + loadmap_dlg[10].flags = (flags&cNOITEM) ? 0 : D_SELECTED; + loadmap_dlg[13].flags = 0; + + if(is_large) + large_dialog(loadmap_dlg); + + if(zc_popup_dialog(loadmap_dlg,11) != 11) + { + return 1; + } + + flags = cDEBUG; + + if(loadmap_dlg[3].flags&D_SELECTED) res=2; + + if(loadmap_dlg[4].flags&D_SELECTED) res=1; + + if(loadmap_dlg[5].flags&D_SELECTED) res=0; + + if(loadmap_dlg[7].flags&D_SELECTED) flags|=cWALK; + + if(loadmap_dlg[8].flags&D_SELECTED) flags|=cFLAGS; + + if(!(loadmap_dlg[9].flags&D_SELECTED)) flags|=cNODARK; + + if(!(loadmap_dlg[10].flags&D_SELECTED)) flags|=cNOITEM; + + if(bmap) + { + destroy_bitmap(bmap); + } + + + bmap = create_bitmap_ex(8,(256*16)>>res,(176*8)>>res); + + if(!bmap) + { + jwin_alert("Error","Error creating bitmap.",NULL,NULL,"OK",NULL,13,27,lfont); + return 2; + } + + for(int y=0; y<8; y++) + { + for(int x=0; x<16; x++) + { + Map.draw(screen2, 0, 0, flags, -1, y*16+x); + stretch_blit(screen2, bmap, 0, 0, 256, 176, x<<(8-res), (y*176)>>res, 256>>res,176>>res); + } + } + + memcpy(mappal,RAMpal,sizeof(RAMpal)); + vp_showpal = false; + get_bw(picpal,pblack,pwhite); + mapx = mapy = 0; + mapscale = 1; + imagepath[0] = 0; + + if(loadmap_dlg[13].flags & D_SELECTED) mapMaker(bmap, mappal); + + return 0; +} + +int onViewMap() +{ + int temp_aligns=ShowMisalignments; + ShowMisalignments=0; + /*if(load_the_map()==0) + {*/ + launchPicViewer(&bmap,mappal,&mapx, &mapy, &mapscale,true); + //} + ShowMisalignments=temp_aligns; + return D_O_K; +} + +static const char *dirstr[4] = {"North","South","West","East"}; +char _pathstr[40]="North,North,North,North"; + +char *pathstr(byte path[]) +{ + sprintf(_pathstr,"%s,%s,%s,%s",dirstr[path[0]],dirstr[path[1]], + dirstr[path[2]],dirstr[path[3]]); + return _pathstr; +} + +char _ticksstr[32]="99.99 seconds"; + +char *ticksstr(int tics) +{ + int mins=tics/(60*60); + tics=tics-(mins*60*60); + int secs=tics/60; + tics=tics-(secs*60); + tics=tics*100/60; + + if(mins>0) + { + sprintf(_ticksstr,"%d:%02d.%02d",mins, secs, tics); + } + else + { + sprintf(_ticksstr,"%d.%02d seconds",secs, tics); + } + + return _ticksstr; +} +void textprintf_disabled(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color_hl, int color_sh, AL_CONST char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + + textout_ex(bmp, f, buf, x+1, y+1, color_hl, -1); + + textout_ex(bmp, f, buf, x, y, color_sh, -1); +} + +void textprintf_centre_disabled(BITMAP *bmp, AL_CONST FONT *f, int x, int y, int color_hl, int color_sh, AL_CONST char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_centre_ex(bmp, f, buf, x+1, y+1, color_hl, -1); + textout_centre_ex(bmp, f, buf, x, y, color_sh, -1); +} + +void drawpanel(int pnl) +{ + mapscr *scr=Map.CurrScr(); + int NextCombo=combobuf[Combo].nextcombo; + int NextCSet=combobuf[Combo].nextcset; + + if(prv_mode) + { + jwin_draw_frame(menu1,0,panel[8].y,panel[8].x+panel[0].w, panel[0].h, FR_WIN); + rectfill(menu1,panel[8].x,panel[8].y+2,panel[8].x+panel[0].w-3,panel[8].y+panel[0].h-3,jwin_pal[jcBOX]); + } + else + { + jwin_draw_frame(menu1,0,panel[0].y,panel[0].x+panel[0].w,panel[0].h, FR_WIN); + rectfill(menu1,panel[0].x,panel[0].y+2,panel[0].x+panel[0].w-3,panel[0].y+panel[0].h-3,jwin_pal[jcBOX]); + + if(!is_large) + { + jwin_draw_frame(menu1,combolistscrollers[0].x,combolistscrollers[0].y,combolistscrollers[0].w,combolistscrollers[0].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[0].x+5-i,combolistscrollers[0].y+4+i, combolistscrollers[0].x+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[0].x,combolistscrollers[0].y+combolistscrollers[0].h-2,combolistscrollers[0].w,combolistscrollers[0].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[0].x+5-i,combolistscrollers[0].y+combolistscrollers[0].h+4-i, combolistscrollers[0].x+5+i, vc(0)); + } + } + + textprintf_disabled(menu1,spfont,panel[0].x+panel[0].w-7,panel[0].y+3,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"%d",menutype+1); + + switch(pnl) + { + // New Large Mode single panel + case -1: + { + // Coords1 + set_clip_rect(menu1,panel[8].x,panel[8].y,panel[8].x+panel[8].w-5,panel[8].y+panel[8].h); + + for(int i=0; i<4; i++) + { + jwin_draw_frame(menu1,panel[8].x+14+(32*i),panel[8].y+12,20,20,FR_DEEP); + + if(i==0 && scr->hasitem && scr->item > 0) + { + rectfill(menu1,panel[8].x+16+(32*i),panel[8].y+14,panel[8].x+31+(32*i),panel[8].y+29,0); + overtile16(menu1, itemsbuf[scr->item].tile,panel[8].x+16+(32*i),panel[8].y+14,itemsbuf[scr->item].csets&15,0); + } + else + blit(icon_bmp[i][coord_frame], menu1, 0, 0, panel[8].x+16+(32*i),panel[8].y+14, 16, 16); + } + + textprintf_centre_ex(menu1,font,panel[8].x+24+0*32,panel[8].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->itemx); + textprintf_centre_ex(menu1,font,panel[8].x+24+1*32,panel[8].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->stairx); + textprintf_centre_ex(menu1,font,panel[8].x+24+2*32,panel[8].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warparrivalx); + textprintf_centre_ex(menu1,font,panel[8].x+24+3*32,panel[8].y+34,jwin_pal[jcBOXFG],-1,"%d",Flag); + + textprintf_centre_ex(menu1,font,panel[8].x+24+0*32,panel[8].y+42,jwin_pal[jcBOXFG],-1,"%d",scr->itemy); + textprintf_centre_ex(menu1,font,panel[8].x+24+1*32,panel[8].y+42,jwin_pal[jcBOXFG],-1,"%d",scr->stairy); + textprintf_centre_ex(menu1,font,panel[8].x+24+2*32,panel[8].y+42,jwin_pal[jcBOXFG],-1,"%d",scr->warparrivaly); + + // Coords2 + for(int i=0; i<4; i++) + { + jwin_draw_frame(menu1,panel[8].x+14+(32*i),panel[8].y+54,20,20,FR_DEEP); + blit(icon_bmp[ICON_BMP_RETURN_A+i][coord_frame], menu1, 0, 0, panel[8].x+16+(32*i),panel[8].y+56, 16, 16); + } + + textprintf_centre_ex(menu1,font,panel[8].x+24+0*32,panel[8].y+76,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[0]); + textprintf_centre_ex(menu1,font,panel[8].x+24+1*32,panel[8].y+76,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[1]); + textprintf_centre_ex(menu1,font,panel[8].x+24+2*32,panel[8].y+76,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[2]); + textprintf_centre_ex(menu1,font,panel[8].x+24+3*32,panel[8].y+76,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[3]); + + textprintf_centre_ex(menu1,font,panel[8].x+24+0*32,panel[8].y+84,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[0]); + textprintf_centre_ex(menu1,font,panel[8].x+24+1*32,panel[8].y+84,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[1]); + textprintf_centre_ex(menu1,font,panel[8].x+24+2*32,panel[8].y+84,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[2]); + textprintf_centre_ex(menu1,font,panel[8].x+24+3*32,panel[8].y+84,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[3]); + + // Enemies + int epx = 2+panel[8].x+14+4*32; + int epy = 2+panel[8].y+12; + jwin_draw_frame(menu1, epx-2,epy-2, 16*4+4,16*3+4,FR_DEEP); + rectfill(menu1, epx, epy, -1+epx+16*4,-1+epy+16*3,vc(0)); + + for(int i=0; i< 10 && Map.CurrScr()->enemy[i]!=0; i++) + { + int id = Map.CurrScr()->enemy[i]; + int tile = get_bit(quest_rules, qr_NEWENEMYTILES) ? guysbuf[id].e_tile : guysbuf[id].tile; + int cset = guysbuf[id].cset; + + if(tile) + overtile16(menu1, tile+efrontfacingtile(id),epx+(i%4)*16,epy+((i/4)*16),cset,0); + } + } + break; + + case m_block: + { + char name[256], shortname[256]; + strncpy(name,get_filename(filepath),255); + + if(name[0]==0) + { + sprintf(name, "[Untitled]"); + } + + strip_extra_spaces(name); + shorten_string(shortname, name, pfont, 255, (panel[0].x+panel[0].w-86)-(panel[0].x+1)-4); + set_clip_rect(menu1,panel[0].x,panel[0].y,panel[0].x+panel[0].w-5,panel[0].y+46); + extract_name(filepath,name,FILENAME8__); + textprintf_disabled(menu1,pfont,panel[0].x+1,panel[0].y+3,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"File:"); + textprintf_ex(menu1,pfont,panel[0].x+1,panel[0].y+13,vc(0),-1,"%s",shortname); + textprintf_disabled(menu1,pfont,panel[0].x+1,panel[0].y+24,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Combo:"); + textprintf_ex(menu1,pfont,panel[0].x+1+text_length(pfont, "Combo: "),panel[0].y+24,vc(0),-1,"%d",Combo); + textprintf_disabled(menu1,pfont,panel[0].x+1,panel[0].y+34,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Type:"); +// textprintf_ex(menu1,pfont,panel[0].x+1+text_length(pfont, "Type: "),panel[0].y+34,vc(0),-1,"%s",combotype_string[combobuf[Combo].type]); + textprintf_ex(menu1,pfont,panel[0].x+1+text_length(pfont, "Type: "),panel[0].y+34,vc(0),-1,"%s",combo_class_buf[combobuf[Combo].type].name); + textprintf_centre_disabled(menu1,spfont,panel[0].x+panel[0].w-76,panel[0].y+3,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Combo"); + jwin_draw_frame(menu1,panel[0].x+panel[0].w-86,panel[0].y+9,20, 20, FR_DEEP); + put_combo(menu1,panel[0].x+panel[0].w-84,panel[0].y+11,Combo,CSet,0,0); + + textprintf_centre_disabled(menu1,spfont,panel[0].x+panel[0].w-52,panel[0].y+3,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Walk"); + jwin_draw_frame(menu1,panel[0].x+panel[0].w-62,panel[0].y+9,20, 20, FR_DEEP); + put_combo(menu1,panel[0].x+panel[0].w-60,panel[0].y+11,Combo,CSet,0,0); + put_walkflags(menu1,panel[0].x+panel[0].w-60,panel[0].y+11,Combo,0); + + textprintf_centre_disabled(menu1,spfont,panel[0].x+panel[0].w-28,panel[0].y+3,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Cycle"); + jwin_draw_frame(menu1,panel[0].x+panel[0].w-38,panel[0].y+9,20, 20, FR_DEEP); + + if(NextCombo>0) + { + put_combo(menu1,panel[0].x+panel[0].w-36,panel[0].y+11,NextCombo,NextCSet,0,0); + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<16; dy++) + { + for(int dx=0; dx<16; dx++) + { + menu1->line[dy+panel[0].y+11][dx+panel[0].x+panel[0].w-36]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(menu1, panel[0].x+panel[0].w-36,panel[0].y+11, panel[0].x+panel[0].w-36+15,panel[0].y+11+15,vc(0)); + rect(menu1, panel[0].x+panel[0].w-36,panel[0].y+11, panel[0].x+panel[0].w-36+15,panel[0].y+11+15,vc(15)); + line(menu1, panel[0].x+panel[0].w-36,panel[0].y+11, panel[0].x+panel[0].w-36+15,panel[0].y+11+15,vc(15)); + line(menu1, panel[0].x+panel[0].w-36,panel[0].y+11+15, panel[0].x+panel[0].w-36+15,panel[0].y+11,vc(15)); + } + } + + textprintf_disabled(menu1,spfont,panel[0].x+panel[0].w-28,panel[0].y+32,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"CSet"); + textprintf_ex(menu1,spfont,panel[0].x+panel[0].w-10,panel[0].y+32,jwin_pal[jcBOXFG],-1,"%d", CSet); + + textprintf_disabled(menu1,spfont,panel[0].x+panel[0].w-32,panel[0].y+39,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Layer"); + textprintf_ex(menu1,spfont,panel[0].x+panel[0].w-10,panel[0].y+39,jwin_pal[jcBOXFG],-1,"%d", CurrentLayer); + } + break; + + case m_coords: + set_clip_rect(menu1,panel[1].x,panel[1].y,panel[1].x+panel[1].w-5,panel[1].y+46); + + for(int i=0; i<4; i++) + { + jwin_draw_frame(menu1,panel[1].x+14+(32*i),panel[1].y+4,20,20,FR_DEEP); + + if(i==0 && scr->hasitem && scr->item > 0) + { + rectfill(menu1,panel[8].x+16+(32*i),panel[1].y+6,panel[1].x+31+(32*i),panel[1].y+21,0); + overtile16(menu1, itemsbuf[scr->item].tile,panel[1].x+16+(32*i),panel[1].y+6,itemsbuf[scr->item].csets&15,0); + } + else + blit(icon_bmp[i][coord_frame], menu1, 0, 0, panel[1].x+16+(32*i),panel[1].y+6, 16, 16); + } + + textprintf_centre_ex(menu1,font,panel[1].x+24+0*32,panel[1].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->itemx); + textprintf_centre_ex(menu1,font,panel[1].x+24+1*32,panel[1].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->stairx); + //textprintf_centre_ex(menu1,font,panel[1].x+24+2*32,panel[1].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx); + textprintf_centre_ex(menu1,font,panel[1].x+24+2*32,panel[1].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warparrivalx); + textprintf_centre_ex(menu1,font,panel[1].x+24+3*32,panel[1].y+26,jwin_pal[jcBOXFG],-1,"%d",Flag); + + textprintf_centre_ex(menu1,font,panel[1].x+24+0*32,panel[1].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->itemy); + textprintf_centre_ex(menu1,font,panel[1].x+24+1*32,panel[1].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->stairy); + //textprintf_centre_ex(menu1,font,panel[1].x+24+2*32,panel[1].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny); + textprintf_centre_ex(menu1,font,panel[1].x+24+2*32,panel[1].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warparrivaly); + + break; + + case m_coords2: + set_clip_rect(menu1,panel[7].x,panel[7].y,panel[7].x+panel[7].w-5,panel[7].y+46); + + for(int i=0; i<4; i++) + { + jwin_draw_frame(menu1,panel[7].x+14+(32*i),panel[7].y+4,20,20,FR_DEEP); + blit(icon_bmp[ICON_BMP_RETURN_A+i][coord_frame], menu1, 0, 0, panel[7].x+16+(32*i),panel[7].y+6, 16, 16); + } + + textprintf_centre_ex(menu1,font,panel[7].x+24+0*32,panel[7].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[0]); + textprintf_centre_ex(menu1,font,panel[7].x+24+1*32,panel[7].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[1]); + textprintf_centre_ex(menu1,font,panel[7].x+24+2*32,panel[7].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[2]); + textprintf_centre_ex(menu1,font,panel[7].x+24+3*32,panel[7].y+26,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturnx[3]); + //textprintf_centre_ex(menu1,font,panel[7].x+24+4*32,panel[7].y+26,jwin_pal[jcBOXFG],-1,"%d",Flag); + + textprintf_centre_ex(menu1,font,panel[7].x+24+0*32,panel[7].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[0]); + textprintf_centre_ex(menu1,font,panel[7].x+24+1*32,panel[7].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[1]); + textprintf_centre_ex(menu1,font,panel[7].x+24+2*32,panel[7].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[2]); + textprintf_centre_ex(menu1,font,panel[7].x+24+3*32,panel[7].y+34,jwin_pal[jcBOXFG],-1,"%d",scr->warpreturny[3]); + + break; + + case m_flags: + { + set_clip_rect(menu1,panel[2].x,panel[2].y,panel[2].x+panel[2].w-5,panel[2].y+46); + + byte f=scr->flags; + byte wf=scr->flags2; + byte f3=scr->flags3; + char *flagheader=(char *)"E_WSLE_HET_S_MLW_DIB"; + char flagdata[30]; + + for(byte i=0; ienemyflags; + char *enemyflagheader=(char *)"BILFR24Z"; + char enemyflagdata[30]; + + for(byte i=0; ipattern)]); + } + break; + + case m_guy: + { + set_clip_rect(menu1,panel[3].x,panel[3].y,panel[3].x+panel[3].w-5,panel[3].y+46); + char buf[MSGSIZE+1], shortbuf[MSGSIZE+1]; + strncpy(buf,MsgString(scr->str, true, false),72); + buf[MSGSIZE] = '\0'; + + if((scr->str)==0) + { + sprintf(buf, "(None)"); + } + + strip_extra_spaces(buf); + shorten_string(shortbuf, buf, pfont, 72, 140); + textprintf_disabled(menu1,pfont,panel[3].x+6,panel[0].y+8,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Guy:"); + textprintf_disabled(menu1,pfont,panel[3].x+6,panel[0].y+16,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"String:"); + textprintf_disabled(menu1,pfont,panel[3].x+6,panel[0].y+24,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Room:"); + textprintf_ex(menu1,pfont,panel[3].x+40-16,panel[3].y+8,jwin_pal[jcBOXFG],-1,"%s",guy_string[scr->guy]); + textprintf_ex(menu1,pfont,panel[3].x+40-6,panel[3].y+16,jwin_pal[jcBOXFG],-1,"%s",shortbuf); + textprintf_ex(menu1,pfont,panel[3].x+40-10,panel[3].y+24,jwin_pal[jcBOXFG],-1,"%s",roomtype_string[scr->room]); + int rtype=scr->room; + + if(strcmp(catchall_string[rtype]," ")) + { + textprintf_disabled(menu1,pfont,panel[3].x+6,panel[0].y+32,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"%s:",catchall_string[rtype]); + int xofs=text_length(pfont,catchall_string[rtype])+5; + + switch(rtype) + { + case rSP_ITEM: + textprintf_ex(menu1,pfont,panel[3].x+7+xofs,panel[3].y+32,jwin_pal[jcBOXFG],-1,"%s",item_string[scr->catchall]); + break; + + case rINFO: + textprintf_ex(menu1,pfont,panel[3].x+7+xofs,panel[3].y+32,jwin_pal[jcBOXFG],-1,"(%d) %s",scr->catchall,misc.info[scr->catchall].name); + break; + + case rP_SHOP: + case rSHOP: + textprintf_ex(menu1,pfont,panel[3].x+7+xofs,panel[3].y+32,jwin_pal[jcBOXFG],-1,"(%d) %s",scr->catchall,misc.shop[scr->catchall].name); + break; + + default: + textprintf_ex(menu1,pfont,panel[3].x+7+xofs,panel[3].y+32,jwin_pal[jcBOXFG],-1,"%d",scr->catchall); + break; + } + } + } + break; + + case m_warp: + set_clip_rect(menu1,panel[4].x,panel[4].y,panel[4].x+panel[4].w-5,panel[4].y+46); + + textprintf_disabled(menu1,font,panel[4].x+7,panel[4].y+6,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Tile Warp:"); + textprintf_disabled(menu1,font,panel[4].x+7,panel[4].y+14,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Type:"); + textprintf_disabled(menu1,font,panel[4].x+7,panel[4].y+26,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Side Warp:"); + textprintf_disabled(menu1,font,panel[4].x+7,panel[4].y+34,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Type:"); + textprintf_ex(menu1,font,panel[4].x+59,panel[4].y+6,jwin_pal[jcBOXFG],-1,"%d:%02X",Map.CurrScr()->tilewarpdmap[0],scr->tilewarpscr[0]); + textprintf_ex(menu1,font,panel[4].x+59,panel[4].y+14,jwin_pal[jcBOXFG],-1,"%s",warptype_string[scr->tilewarptype[0]]); + + textprintf_ex(menu1,font,panel[4].x+59,panel[4].y+26,jwin_pal[jcBOXFG],-1,"%d:%02X",Map.CurrScr()->sidewarpdmap[0],scr->sidewarpscr[0]); + textprintf_ex(menu1,font,panel[4].x+59,panel[4].y+34,jwin_pal[jcBOXFG],-1,"%s",warptype_string[scr->sidewarptype[0]]); + break; + + case m_misc: + { + set_clip_rect(menu1,panel[5].x,panel[5].y,panel[5].x+panel[5].w-5,panel[5].y+46); + + textprintf_disabled(menu1,font,panel[5].x+7,panel[5].y+14,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Triggers:"); + byte wf=scr->flags2; + char *triggerheader=(char *)"TBLR"; + char triggerdata[30]; + + for(byte i=0; iflags&64?pathstr(scr->path):"(None)"); + textprintf_ex(menu1,font,panel[5].x+54,panel[5].y+34,jwin_pal[jcBOXFG],-1,"%s",scr->flags&64?dirstr[scr->exitdir]:"(None)"); + } + break; + + case m_layers: + if(!is_large) + { + set_clip_rect(menu1,panel[6].x,panel[6].y,panel[6].x+panel[6].w-5,panel[6].y+46); + + textprintf_centre_disabled(menu1,font,panel[6].x+88,panel[6].y+2,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Layers"); + textprintf_centre_disabled(menu1,font,panel[6].x+13,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"0"); + draw_checkbox(menu1,panel[6].x+9,panel[6].y+20,vc(1),vc(14), LayerMaskInt[0]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+38,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"1"); + draw_checkbox(menu1,panel[6].x+34,panel[6].y+20,vc(1),vc(14), LayerMaskInt[1]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+63,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"2"); + draw_checkbox(menu1,panel[6].x+59,panel[6].y+20,vc(1),vc(14), LayerMaskInt[2]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+88,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"3"); + draw_checkbox(menu1,panel[6].x+84,panel[6].y+20,vc(1),vc(14), LayerMaskInt[3]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+113,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"4"); + draw_checkbox(menu1,panel[6].x+109,panel[6].y+20,vc(1),vc(14), LayerMaskInt[4]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+138,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"5"); + draw_checkbox(menu1,panel[6].x+134,panel[6].y+20,vc(1),vc(14), LayerMaskInt[5]!=0); + textprintf_centre_disabled(menu1,font,panel[6].x+163,panel[6].y+11,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"6"); + draw_checkbox(menu1,panel[6].x+159,panel[6].y+20,vc(1),vc(14), LayerMaskInt[6]!=0); + draw_layerradio(menu1,panel[6].x+9,panel[6].y+30,vc(1),vc(14), CurrentLayer); + + textprintf_disabled(menu1,spfont,panel[6].x+panel[6].w-28,panel[6].y+36,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"CSet"); + textprintf_ex(menu1,spfont,panel[6].x+panel[6].w-10,panel[6].y+36,jwin_pal[jcBOXFG],-1,"%d", CSet); + } + + break; + } //switch(menutype) + } +} + +void show_screen_error(const char *str, int i, int c) +{ + rectfill(menu1, 575-text_length(lfont_l,str),388-(i*16),575,388-((i-1)*16)-4,vc(0)); + textout_shadowed_ex(menu1,lfont_l, str,575-text_length(lfont_l,str),388-(i*16),c,vc(0),-1); +} + +void tile_warp_notification(int which, char *buf) +{ + char letter = 'A'+which; + + switch(Map.CurrScr()->tilewarptype[which]) + { + case wtCAVE: + sprintf(buf,"Tile Warp %c: Cave/Item Cellar",letter); + break; + + default: + { + char buf2[25]; + + if(strlen(DMaps[Map.CurrScr()->tilewarpdmap[which]].name)==0) + { + sprintf(buf2,"%d",Map.CurrScr()->tilewarpdmap[which]); + } + else + sprintf(buf2,"%d-%s",Map.CurrScr()->tilewarpdmap[which],DMaps[Map.CurrScr()->tilewarpdmap[which]].name); + + sprintf(buf,"Tile Warp %c: %s, %02X", letter, buf2, Map.CurrScr()->tilewarpscr[which]); + break; + } + + case wtNOWARP: + sprintf(buf,"Tile Warp %c: Cancel Warp", letter); + break; + } +} + +void side_warp_notification(int which, int dir, char *buf) +{ + char letter = 'A'+which; + char buf3[16]; + + if(dir==0 && Map.CurrScr()->timedwarptics) + sprintf(buf3,"%s, Timed",dirstr[dir]); + else if(dir==4) + sprintf(buf3,"Timed"); + else + strcpy(buf3, dirstr[dir]); + + switch(Map.CurrScr()->sidewarptype[which]) + { + case wtCAVE: + sprintf(buf,"Side Warp %c (%s): Cave/Item Cellar",letter, buf3); + break; + + default: + { + // Destination DMap name + if(strlen(DMaps[Map.CurrScr()->sidewarpdmap[which]].name)==0) + { + sprintf(buf,"Side Warp %c (%s): %d, %02X", letter, buf3, Map.CurrScr()->sidewarpdmap[which], Map.CurrScr()->sidewarpscr[which]); + } + else + sprintf(buf,"Side Warp %c (%s): %d-%s, %02X", letter, buf3, Map.CurrScr()->sidewarpdmap[which],DMaps[Map.CurrScr()->sidewarpdmap[which]].name, Map.CurrScr()->sidewarpscr[which]); + + break; + } + + case wtNOWARP: + sprintf(buf,"Side Warp %c (%s): Cancel Warp", letter, buf3); + break; + } +} + +static bool arrowcursor = true; // Used by combo aliases and Combo Brush cursors. -L + +void refresh(int flags) +{ + // CPage = Map.CurrScr()->cpage; + int curscr; + + if(flags&rCLEAR) + clear_to_color(menu1,vc(0)); + + if(flags&rMAP) + { + if(!layers_valid(Map.CurrScr())) + fix_layers(Map.CurrScr(), true); + + curscr=Map.getCurrScr(); + Map.setCurrScr(curscr); // to update palette + clear_to_color(mapscreenbmp,vc(0)); + Map.draw(mapscreenbmp, showedges?16:0, showedges?16:0, Flags, -1, -1); + + if(showedges) + { + if(Map.getCurrScr()<128) + { + //not the first row of screens + if(Map.getCurrScr()>15) + { + Map.drawrow(mapscreenbmp, 16, 0, Flags, 160, -1, Map.getCurrScr()-16); + } + else + { + Map.drawstaticrow(mapscreenbmp, 16, 0); + } + + //not the last row of screens + if(Map.getCurrScr()<112) + { + Map.drawrow(mapscreenbmp, 16, 192, Flags, 0, -1, Map.getCurrScr()+16); + } + else + { + Map.drawstaticrow(mapscreenbmp, 16, 192); + } + + //not the first column of screens + if(Map.getCurrScr()&0x0F) + { + Map.drawcolumn(mapscreenbmp, 0, 16, Flags, 15, -1, Map.getCurrScr()-1); + } + else + { + Map.drawstaticcolumn(mapscreenbmp, 0, 16); + } + + //not the last column of screens + if((Map.getCurrScr()&0x0F)<15) + { + Map.drawcolumn(mapscreenbmp, 272, 16, Flags, 0, -1, Map.getCurrScr()+1); + } + else + { + Map.drawstaticcolumn(mapscreenbmp, 272, 16); + } + + //not the first row or first column of screens + if((Map.getCurrScr()>15)&&(Map.getCurrScr()&0x0F)) + { + Map.drawblock(mapscreenbmp, 0, 0, Flags, 175, -1, Map.getCurrScr()-17); + } + else + { + Map.drawstaticblock(mapscreenbmp, 0, 0); + } + + //not the first row or last column of screens + if((Map.getCurrScr()>15)&&((Map.getCurrScr()&0x0F)<15)) + { + Map.drawblock(mapscreenbmp, 272, 0, Flags, 160, -1, Map.getCurrScr()-15); + } + else + { + Map.drawstaticblock(mapscreenbmp, 272, 0); + } + + //not the last row or first column of screens + if((Map.getCurrScr()<112)&&(Map.getCurrScr()&0x0F)) + { + Map.drawblock(mapscreenbmp, 0, 192, Flags, 15, -1, Map.getCurrScr()+15); + } + else + { + Map.drawstaticblock(mapscreenbmp, 0, 192); + } + + //not the last row or last column of screens + if((Map.getCurrScr()<112)&&((Map.getCurrScr()&0x0F)<15)) + { + Map.drawblock(mapscreenbmp, 272, 192, Flags, 0, -1, Map.getCurrScr()+17); + } + else + { + Map.drawstaticblock(mapscreenbmp, 272, 192); + } + } + } + + if(showxypos_icon) + { + if(showxypos_color==vc(15)) + safe_rect(mapscreenbmp,showxypos_x+(showedges?16:0),showxypos_y+(showedges?16:0),showxypos_x+(showedges?16:0)+showxypos_w-1,showxypos_y+(showedges?16:0)+showxypos_h-1,showxypos_color); + else + rectfill(mapscreenbmp,showxypos_x+(showedges?16:0),showxypos_y+(showedges?16:0),showxypos_x+(showedges?16:0)+showxypos_w-1,showxypos_y+(showedges?16:0)+showxypos_h-1,showxypos_color); + } + + if(showxypos_cursor_icon) + { + safe_rect(mapscreenbmp,showxypos_cursor_x+(showedges?16:0),showxypos_cursor_y+(showedges?16:0),showxypos_cursor_x+(showedges?16:0)+showxypos_w-1,showxypos_cursor_y+(showedges?16:0)+showxypos_h-1,vc(15)); + } + + if(ShowSquares) + { + if(Map.CurrScr()->stairx || Map.CurrScr()->stairy) + { + int x1 = Map.CurrScr()->stairx+(showedges?16:0); + int y1 = Map.CurrScr()->stairy+(showedges?16:0); + safe_rect(mapscreenbmp,x1,y1,x1+15,y1+15,vc(14)); + } + + if(Map.CurrScr()->warparrivalx || Map.CurrScr()->warparrivaly) + { + int x1 = Map.CurrScr()->warparrivalx +(showedges?16:0); + int y1 = Map.CurrScr()->warparrivaly +(showedges?16:0); + safe_rect(mapscreenbmp,x1,y1,x1+15,y1+15,vc(10)); + } + + for(int i=0; i<4; i++) if(Map.CurrScr()->warpreturnx[i] || Map.CurrScr()->warpreturny[i]) + { + int x1 = Map.CurrScr()->warpreturnx[i]+(showedges?16:0); + int y1 = Map.CurrScr()->warpreturny[i]+(showedges?16:0); + int clr = vc(9); + + if(FlashWarpSquare==i) + { + if(!FlashWarpClk) + FlashWarpSquare=-1; + else if(!(--FlashWarpClk%3)) + clr = vc(15); + } + + safe_rect(mapscreenbmp,x1,y1,x1+15,y1+15,clr); + } + + /* + for (int i=0; i<4; i++) for (int j=0; j<9; i++) + { + int x1 = stx[i][j]+(showedges?16:0); + int y1 = sty[i][j]+(showedges?16:0); + rect(mapscreenbmp,x1,y1,x1+15,y1+15,vc(15)); + } + */ + + } + + if(mapscreensize==1) + { + blit(mapscreenbmp,menu1,0,0,mapscreen_x,mapscreen_y,mapscreenbmp->w,mapscreenbmp->h); + } + else + { + stretch_blit(mapscreenbmp,menu1,0,0,mapscreenbmp->w,mapscreenbmp->h,mapscreen_x,mapscreen_y,int(mapscreensize*mapscreenbmp->w),int(mapscreensize*mapscreenbmp->h)); + } + + if(showedges) + { + //top preview + for(int j=0; jwidth*mgridscale)?((combo->width)*16)-mx/mapscreensize:0, 0, BrushWidth*16, BrushHeight*16, zc_max((mx-(combo->width)*mgridscale),0)+(showedges?mgridscale:0), my+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + + case 2: + stretch_blit(brushbmp, brushscreen, 0, (myheight*mgridscale)?((combo->height)*16)-my/mapscreensize:0, BrushWidth*16, BrushHeight*16, mx+(showedges?mgridscale:0), zc_max((my-(combo->height)*mgridscale),0)+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + + case 3: + stretch_blit(brushbmp, brushscreen, (mxwidth*mgridscale)?((combo->width)*16)-mx/mapscreensize:0, (myheight*mgridscale)?((combo->height)*16)-my/mapscreensize:0, BrushWidth*16, BrushHeight*16, zc_max((mx-(combo->width)*mgridscale),0)+(showedges?mgridscale:0), zc_max((my-(combo->height)*mgridscale),0)+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + } + } + else + { + switch(alias_origin) + { + case 0: + blit(brushbmp, brushscreen, 0, 0, mx+(showedges?mgridscale:0), my+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + + case 1: + blit(brushbmp, brushscreen, (mxwidth*16)?((combo->width)*16)-mx:0, 0, zc_max((mx-(combo->width)*16),0)+(showedges?mgridscale:0), my+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + + case 2: + blit(brushbmp, brushscreen, 0, (myheight*16)?((combo->height)*16)-my:0, mx+(showedges?mgridscale:0), zc_max((my-(combo->height)*16),0)+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + + case 3: + blit(brushbmp, brushscreen, (mxwidth*16)?((combo->width)*16)-mx:0, (myheight*16)?((combo->height)*16)-my:0, zc_max((mx-(combo->width)*16),0)+(showedges?mgridscale:0), zc_max((my-(combo->height)*16),0)+(showedges?mgridscale:0), BrushWidth*mgridscale, BrushHeight*mgridscale); + break; + } + } + } + } + + masked_blit(brushscreen, menu1, 0, 0, 0, 16, (16+(showedges?2:0))*mgridscale, (11+(showedges?2:0))*mgridscale); + BrushWidth=tempbw; + BrushHeight=tempbh; + } + else + { + if(!arrowcursor) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + arrowcursor = true; + } + } + + if(ShowGrid) + { + int w=16; + int h=11; + + if(showedges) + { + w=18; + h=13; + } + + for(int x=16; xvalid&mVALID) + { + //vc(0) + rectfill(menu1,(i&15)*3*BMM+minimap.x+3,(i/16)*3*BMM+minimap.y+12, + (i&15)*3*BMM+(is_large?8:2)+minimap.x+3,(i/16)*3*BMM+minimap.y+12+(is_large?8:2), lc1((Map.Scr(i)->color)&15)); + + if(((Map.Scr(i)->color)&15)>0) + { + if(!is_large) + putpixel(menu1,(i&15)*3*BMM+1+minimap.x+3,(i/16)*3*BMM+minimap.y+12+1,lc2((Map.Scr(i)->color)&15)); + else + rectfill(menu1,(i&15)*3*BMM+2+minimap.x+4,(i/16)*3*BMM+minimap.y+11+4,(i&15)*3*BMM+2+minimap.x+6,(i/16)*3* BMM+minimap.y+11+6, lc2((Map.Scr(i)->color)&15)); + } + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<3*BMM; dy++) + { + for(int dx=0; dx<3*BMM; dx++) + { + menu1->line[dy+(i/16)*3*BMM+minimap.y+12][dx+(i&15)*3*BMM+minimap.x+3]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(menu1, (i&15)*3*BMM+minimap.x+3, (i/16)*3*BMM+minimap.y+12, + (i&15)*3*BMM+minimap.x+3+(1+BMM*BMM), (i/16)*3*BMM+minimap.y+12+(1+BMM*BMM), vc(0)); + } + } + } + + int s=Map.getCurrScr(); + // The white marker rect + safe_rect(menu1,(s&15)*3*BMM+minimap.x+3,(s/16)*3*BMM+minimap.y+12,(s&15)*3*BMM+(is_large?8:2)+minimap.x+3,(s/16)*3*BMM+minimap.y+12+(is_large?8:2),vc(15)); + + textprintf_disabled(menu1,font,minimap.x,minimap.y,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"M"); + textprintf_ex(menu1,font,minimap.x+8,minimap.y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-3d",Map.getCurrMap()+1); + + textprintf_disabled(menu1,font,minimap.x+36,minimap.y,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"S"); + textprintf_ex(menu1,font,minimap.x+36+8,minimap.y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%02X",s); + } + } + + if(flags&rCOMBOS) + { + if(is_large) + { + jwin_draw_frame(menu1,combolist_window.x,combolist_window.y,combolist_window.w,combolist_window.h, FR_WIN); + rectfill(menu1,combolist_window.x+2,combolist_window.y+2,combolist_window.x+combolist_window.w-3,combolist_window.y+combolist_window.h-3,jwin_pal[jcBOX]); + jwin_draw_frame(menu1,combolistscrollers[0].x,combolistscrollers[0].y,combolistscrollers[0].w,combolistscrollers[0].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[0].x+5-i,combolistscrollers[0].y+4+i, combolistscrollers[0].x+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[0].x+combolistscrollers[0].w,combolistscrollers[0].y,combolistscrollers[0].w,combolistscrollers[0].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[0].x+combolistscrollers[0].w+5-i,combolistscrollers[0].y+6-i, combolistscrollers[0].x+combolistscrollers[0].w+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[1].x,combolistscrollers[1].y,combolistscrollers[1].w,combolistscrollers[1].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[1].x+5-i,combolistscrollers[1].y+4+i, combolistscrollers[1].x+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[1].x+combolistscrollers[1].w,combolistscrollers[1].y,combolistscrollers[1].w,combolistscrollers[1].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[1].x+combolistscrollers[1].w+5-i,combolistscrollers[1].y+6-i, combolistscrollers[1].x+combolistscrollers[1].w+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[2].x,combolistscrollers[2].y,combolistscrollers[2].w,combolistscrollers[2].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[2].x+5-i,combolistscrollers[2].y+4+i, combolistscrollers[2].x+5+i, vc(0)); + } + + jwin_draw_frame(menu1,combolistscrollers[2].x+combolistscrollers[2].w,combolistscrollers[2].y,combolistscrollers[2].w,combolistscrollers[2].h,FR_ETCHED); + + for(int i=0; i<3; i++) + { + _allegro_hline(menu1,combolistscrollers[2].x+combolistscrollers[2].w+5-i,combolistscrollers[2].y+6-i, combolistscrollers[2].x+combolistscrollers[2].w+5+i, vc(0)); + } + } + + if(draw_mode!=dm_alias) + { + if(is_large) + { + jwin_draw_frame(menu1,combolist[0].x-2,combolist[0].y-2,(combolist[0].w<<4)+4,(combolist[0].h<<4)+4,FR_DEEP); + jwin_draw_frame(menu1,combolist[1].x-2,combolist[1].y-2,(combolist[1].w<<4)+4,(combolist[1].h<<4)+4,FR_DEEP); + jwin_draw_frame(menu1,combolist[2].x-2,combolist[2].y-2,(combolist[2].w<<4)+4,(combolist[2].h<<4)+4,FR_DEEP); + + if(MouseScroll) + { + jwin_draw_frame(menu1,combolist[0].x-2,combolist[0].y-10,(combolist[0].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,combolist[1].x-2,combolist[1].y-10,(combolist[1].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,combolist[2].x-2,combolist[2].y-10,(combolist[2].w<<4)+4,6,FR_DEEP); + + rectfill(menu1,combolist[0].x,combolist[0].y-8,combolist[0].x+(combolist[0].w<<4)-1,combolist[0].y-7,jwin_pal[jcBOXFG]); + rectfill(menu1,combolist[1].x,combolist[1].y-8,combolist[1].x+(combolist[1].w<<4)-1,combolist[1].y-7,jwin_pal[jcBOXFG]); + rectfill(menu1,combolist[2].x,combolist[2].y-8,combolist[2].x+(combolist[2].w<<4)-1,combolist[2].y-7,jwin_pal[jcBOXFG]); + + jwin_draw_frame(menu1,combolist[0].x-2,combolist[0].y+(combolist[0].h<<4)+4,(combolist[0].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,combolist[1].x-2,combolist[1].y+(combolist[1].h<<4)+4,(combolist[1].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,combolist[2].x-2,combolist[2].y+(combolist[2].h<<4)+4,(combolist[2].w<<4)+4,6,FR_DEEP); + + rectfill(menu1,combolist[0].x,combolist[0].y+(combolist[0].h<<4)+6,combolist[0].x+(combolist[0].w<<4)-1,combolist[0].y+(combolist[0].h<<4)+7,jwin_pal[jcBOXFG]); + rectfill(menu1,combolist[1].x,combolist[1].y+(combolist[1].h<<4)+6,combolist[1].x+(combolist[1].w<<4)-1,combolist[1].y+(combolist[1].h<<4)+7,jwin_pal[jcBOXFG]); + rectfill(menu1,combolist[2].x,combolist[2].y+(combolist[2].h<<4)+6,combolist[2].x+(combolist[2].w<<4)-1,combolist[2].y+(combolist[2].h<<4)+7,jwin_pal[jcBOXFG]); + } + } + + int drawmap, drawscr; + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + for(int i=0; i<(combolist[j].w*combolist[j].h); i++) + { + put_combo(menu1,(i%combolist[j].w)*16+combolist[j].x,(i/combolist[j].w)*16+combolist[j].y,i+First[j],CSet,Flags&(cFLAGS|cWALK),0); + } + } + } + + int rect_pos=Combo-First[current_combolist]; + + if((rect_pos>=0)&&(rect_pos<(First[current_combolist]+(combolist[current_combolist].w*combolist[current_combolist].h)))) + safe_rect(menu1, (rect_pos&(combolist[current_combolist].w-1))*16+combolist[current_combolist].x, (rect_pos/combolist[current_combolist].w)*16+combolist[current_combolist].y, ((rect_pos&(combolist[current_combolist].w-1))*16+combolist[current_combolist].x)+15, ((rect_pos/combolist[current_combolist].w)*16+combolist[current_combolist].y)+15, 255); + } + else + { + if(is_large) + { + jwin_draw_frame(menu1,comboaliaslist[0].x-2,comboaliaslist[0].y-2,(comboaliaslist[0].w<<4)+4,(comboaliaslist[0].h<<4)+4,FR_DEEP); + jwin_draw_frame(menu1,comboaliaslist[1].x-2,comboaliaslist[1].y-2,(comboaliaslist[1].w<<4)+4,(comboaliaslist[1].h<<4)+4,FR_DEEP); + jwin_draw_frame(menu1,comboaliaslist[2].x-2,comboaliaslist[2].y-2,(comboaliaslist[2].w<<4)+4,(comboaliaslist[2].h<<4)+4,FR_DEEP); + + jwin_draw_frame(menu1,comboalias_preview[0].x-2,comboalias_preview[0].y-2,comboalias_preview[0].w+4,comboalias_preview[0].h+4,FR_DEEP); + jwin_draw_frame(menu1,comboalias_preview[1].x-2,comboalias_preview[1].y-2,comboalias_preview[1].w+4,comboalias_preview[1].h+4,FR_DEEP); + jwin_draw_frame(menu1,comboalias_preview[2].x-2,comboalias_preview[2].y-2,comboalias_preview[2].w+4,comboalias_preview[2].h+4,FR_DEEP); + + if(MouseScroll) + { + jwin_draw_frame(menu1,comboaliaslist[0].x-2,comboaliaslist[0].y-10,(comboaliaslist[0].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,comboaliaslist[1].x-2,comboaliaslist[1].y-10,(comboaliaslist[1].w<<4)+4,6,FR_DEEP); + jwin_draw_frame(menu1,comboaliaslist[2].x-2,comboaliaslist[2].y-10,(comboaliaslist[2].w<<4)+4,6,FR_DEEP); + + rectfill(menu1,comboaliaslist[0].x,comboaliaslist[0].y-8,comboaliaslist[0].x+(comboaliaslist[0].w<<4)-1,comboaliaslist[0].y-7,jwin_pal[jcBOXFG]); + rectfill(menu1,comboaliaslist[1].x,comboaliaslist[1].y-8,comboaliaslist[1].x+(comboaliaslist[1].w<<4)-1,comboaliaslist[1].y-7,jwin_pal[jcBOXFG]); + rectfill(menu1,comboaliaslist[2].x,comboaliaslist[2].y-8,comboaliaslist[2].x+(comboaliaslist[2].w<<4)-1,comboaliaslist[2].y-7,jwin_pal[jcBOXFG]); + + jwin_draw_frame(menu1,comboalias_preview[0].x-2,comboalias_preview[0].y+comboalias_preview[0].h+4,comboalias_preview[0].w+4,6,FR_DEEP); + jwin_draw_frame(menu1,comboalias_preview[1].x-2,comboalias_preview[1].y+comboalias_preview[1].h+4,comboalias_preview[1].w+4,6,FR_DEEP); + jwin_draw_frame(menu1,comboalias_preview[2].x-2,comboalias_preview[2].y+comboalias_preview[2].h+4,comboalias_preview[2].w+4,6,FR_DEEP); + + rectfill(menu1,comboalias_preview[0].x,comboalias_preview[0].y+comboalias_preview[0].h+6,comboalias_preview[0].x+comboalias_preview[0].w-1,comboalias_preview[0].y+comboalias_preview[0].h+7,jwin_pal[jcBOXFG]); + rectfill(menu1,comboalias_preview[1].x,comboalias_preview[1].y+comboalias_preview[1].h+6,comboalias_preview[1].x+comboalias_preview[1].w-1,comboalias_preview[1].y+comboalias_preview[1].h+7,jwin_pal[jcBOXFG]); + rectfill(menu1,comboalias_preview[2].x,comboalias_preview[2].y+comboalias_preview[2].h+6,comboalias_preview[2].x+comboalias_preview[2].w-1,comboalias_preview[2].y+comboalias_preview[2].h+7,jwin_pal[jcBOXFG]); + } + } + + BITMAP *prv = create_bitmap_ex(8,64,64); + clear_bitmap(prv); + int scalefactor = 1; + + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + for(int i=0; i<(comboaliaslist[j].w*comboaliaslist[j].h); i++) + { + draw_combo_alias_thumbnail(menu1, &combo_aliases[combo_alistpos[j]+i], (i%comboaliaslist[j].w)*16+comboaliaslist[j].x,(i/comboaliaslist[j].w)*16+comboaliaslist[j].y,1); + } + + if((combo_aliases[combo_apos].width>7)||(combo_aliases[combo_apos].height>7)) + { + scalefactor=4; + } + else if((combo_aliases[combo_apos].width>3)||(combo_aliases[combo_apos].height>3)) + { + scalefactor=2; + } + + stretch_blit(brushbmp, prv, 0,0,scalefactor*64,zc_min(scalefactor*64,176),0,0,64,scalefactor==4?44:64); + blit(prv,menu1,0,0,comboalias_preview[j].x,comboalias_preview[j].y,comboalias_preview[j].w,comboalias_preview[j].h); + } + + int rect_pos=combo_apos-combo_alistpos[current_comboalist]; + + if((rect_pos>=0)&&(rect_pos<(combo_alistpos[current_comboalist]+(comboaliaslist[current_comboalist].w*comboaliaslist[current_comboalist].h)))) + safe_rect(menu1,(rect_pos&(combolist[current_comboalist].w-1))*16+combolist[current_comboalist].x,(rect_pos/combolist[current_comboalist].w)*16+combolist[current_comboalist].y,((rect_pos&(combolist[current_comboalist].w-1))*16+combolist[current_comboalist].x)+15,((rect_pos/combolist[current_comboalist].w)*16+combolist[current_comboalist].y)+15,255); + } + + destroy_bitmap(prv); + } + } + + if(flags&rCOMBO) + { + int drawmap, drawscr; + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + // Combo preview + if(is_large) + { + static BITMAP *combo_preview_bmp=create_bitmap_ex(8,32,32); + static BITMAP *cycle_preview_bmp=create_bitmap_ex(8,32,32); + // Combo + put_combo(combo_preview_bmp,0,0,(draw_mode==dm_alias)?combo_aliases[combo_apos].combos[0]:Combo,(draw_mode==dm_alias)?wrap(combo_aliases[combo_apos].csets[0]+alias_cset_mod, 0, 11):CSet,Flags&(cFLAGS|cWALK),0); + jwin_draw_frame(menu1,combo_preview.x-2,combo_preview.y-2,combo_preview.w+4,combo_preview.h+4, FR_DEEP); + stretch_blit(combo_preview_bmp, menu1, 0, 0, 16, 16, combo_preview.x, combo_preview.y, combo_preview.w, combo_preview.h); + + if(draw_mode!=dm_alias) + { + char buf[17]; + sprintf(buf,"Combo: %d",Combo); + textprintf_ex(menu1,pfont,combo_preview.x-text_length(pfont,buf)-8,combo_preview.y+2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",buf); + sprintf(buf,"CSet: %d",CSet); + int offs = 8; + textprintf_ex(menu1,pfont,combo_preview.x-text_length(pfont,buf)-8,combo_preview.y+11,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",buf); + strncpy(buf,combo_class_buf[combobuf[Combo].type].name,16); + + if(strlen(combo_class_buf[combobuf[Combo].type].name) > 16) + { + buf[15]='.'; + buf[14]='.'; + offs = 5; + } + + buf[16]='\0'; + //if (combobuf[Combo].type != 0) + textprintf_ex(menu1,pfont,combo_preview.x-text_length(pfont,buf)-offs,combo_preview.y+20,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",buf); + } + + // Cycle + int NextCombo=combobuf[Combo].nextcombo; + int NextCSet=combobuf[Combo].nextcset; + jwin_draw_frame(menu1,combo_preview.x+int(combo_preview.w*1.5)-2,combo_preview.y-2,combo_preview.w+4,combo_preview.h+4, FR_DEEP); + + if(NextCombo>0 && draw_mode != dm_alias) + { + put_combo(cycle_preview_bmp,0,0,NextCombo,NextCSet,Flags&(cFLAGS|cWALK),0); + + if(Flags&cWALK) put_walkflags(cycle_preview_bmp,0,0,NextCombo,0); + + if(Flags&cFLAGS) put_flags(cycle_preview_bmp,0,0,NextCombo,0,cFLAGS,0); + + stretch_blit(cycle_preview_bmp, menu1, 0, 0, 16, 16, combo_preview.x+int(combo_preview.w*1.5), combo_preview.y, combo_preview.w, combo_preview.h); + } + else + { + if(InvalidStatic) + { + for(int dy=0; dy<32; dy++) + { + for(int dx=0; dx<32; dx++) + { + menu1->line[dy+combo_preview.y][dx+combo_preview.x+int(combo_preview.w*1.5)]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(menu1, combo_preview.x+int(combo_preview.w*1.5),combo_preview.y, combo_preview.x+int(combo_preview.w*2.5),combo_preview.y+combo_preview.h,vc(0)); + safe_rect(menu1, combo_preview.x+int(combo_preview.w*1.5),combo_preview.y, combo_preview.x+int(combo_preview.w*2.5),combo_preview.y+combo_preview.h,vc(15)); + line(menu1, combo_preview.x+int(combo_preview.w*1.5),combo_preview.y, combo_preview.x+int(combo_preview.w*2.5),combo_preview.y+combo_preview.h,vc(15)); + line(menu1, combo_preview.x+int(combo_preview.w*1.5),combo_preview.y+combo_preview.h, combo_preview.x+int(combo_preview.w*2.5),combo_preview.y,vc(15)); + } + } + + if(draw_mode!=dm_alias) + { + + textprintf_ex(menu1,pfont,combo_preview.x+int(combo_preview.w*2.5)+6,combo_preview.y+2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle: %d",NextCombo); + textprintf_ex(menu1,pfont,combo_preview.x+int(combo_preview.w*2.5)+6,combo_preview.y+11,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet: %d",NextCSet); + char buf[17]; + int offs = 8; + strncpy(buf,combo_class_buf[combobuf[NextCombo].type].name,16); + + if(strlen(combo_class_buf[combobuf[NextCombo].type].name) > 15) + { + buf[15]='.'; + buf[14]='.'; + offs = 5; + } + + buf[16]='\0'; + textprintf_ex(menu1,pfont,combo_preview.x+int(combo_preview.w*2.5)+6,combo_preview.y+20,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",buf); + } + + } + else + { + put_combo(menu1,combo_preview.x,combo_preview.y,(draw_mode==dm_alias)?combo_aliases[combo_apos].combos[0]:Combo,(draw_mode==dm_alias)?wrap(combo_aliases[combo_apos].csets[0]+alias_cset_mod, 0, 11):CSet,Flags&(cFLAGS|cWALK),0); + } + } + + if(flags&rMENU) + { + drawpanel(is_large?-1:menutype); + set_clip_rect(menu1,0,0,zq_screen_w-1,zq_screen_h-1); + } + + if(flags&rFAVORITES) + { + if(is_large) + { + jwin_draw_frame(menu1,favorites_window.x,favorites_window.y,favorites_window.w,favorites_window.h, FR_WIN); + rectfill(menu1,favorites_window.x+2,favorites_window.y+2,favorites_window.x+favorites_window.w-3,favorites_window.y+favorites_window.h-3,jwin_pal[jcBOX]); + jwin_draw_frame(menu1,favorites_list.x-2,favorites_list.y-2,(favorites_list.w<<4)+4,(favorites_list.h<<4)+4, FR_DEEP); + rectfill(menu1,favorites_list.x,favorites_list.y,favorites_list.x+(favorites_list.w<<4)-1,favorites_list.y+(favorites_list.h<<4)-1,jwin_pal[jcBOXFG]); + textprintf_ex(menu1,font,favorites_list.x-2,favorites_list.y-11,jwin_pal[jcBOXFG],-1,"Favorite Combos"); + + if(draw_mode!=dm_alias) + { + for(int i=0; i<(favorites_list.w*favorites_list.h); i++) + { + if(favorite_combos[i]==-1) + { + if(InvalidStatic) + { + for(int dy=0; dy<16; dy++) + { + for(int dx=0; dx<16; dx++) + { + menu1->line[(i/favorites_list.w)*16+favorites_list.y+dy][(i%favorites_list.w)*16+favorites_list.x+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(0)); + safe_rect(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(15)); + line(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(15)); + line(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y+15, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y, vc(15)); + } + } + else + { + put_combo(menu1,(i%favorites_list.w)*16+favorites_list.x,(i/favorites_list.w)*16+favorites_list.y,favorite_combos[i],CSet,Flags&(cFLAGS|cWALK),0); + } + } + } + else + { + for(int i=0; i<(favorites_list.w*favorites_list.h); i++) + { + if(favorite_comboaliases[i]==-1) + { + if(InvalidStatic) + { + for(int dy=0; dy<16; dy++) + { + for(int dx=0; dx<16; dx++) + { + menu1->line[(i/favorites_list.w)*16+favorites_list.y+dy][(i%favorites_list.w)*16+favorites_list.x+dx]=vc((((rand()%100)/50)?0:8)+(((rand()%100)/50)?0:7)); + } + } + } + else + { + rectfill(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(0)); + safe_rect(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(15)); + line(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y+15, vc(15)); + line(menu1, (i%favorites_list.w)*16+favorites_list.x, (i/favorites_list.w)*16+favorites_list.y+15, (i%favorites_list.w)*16+favorites_list.x+15, (i/favorites_list.w)*16+favorites_list.y, vc(15)); + } + } + else + { + draw_combo_alias_thumbnail(menu1, &combo_aliases[favorite_comboaliases[i]], (i%favorites_list.w)*16+favorites_list.x,(i/favorites_list.w)*16+favorites_list.y,1); + } + } + } + } + } + + if(flags&rCOMMANDS) + { + if(is_large) + { + jwin_draw_frame(menu1,commands_window.x,commands_window.y,commands_window.w,commands_window.h, FR_WIN); + rectfill(menu1,commands_window.x+2,commands_window.y+2,commands_window.x+commands_window.w-3,commands_window.y+commands_window.h-3,jwin_pal[jcBOX]); + jwin_draw_frame(menu1,commands_list.x-2,commands_list.y-2,(commands_list.w*command_buttonwidth)+4,(commands_list.h*command_buttonheight)+4, FR_DEEP); + rectfill(menu1,commands_list.x,commands_list.y,commands_list.x+(commands_list.w*command_buttonwidth)-1,commands_list.y+(commands_list.h*command_buttonheight)-1,jwin_pal[jcBOXFG]); + textprintf_ex(menu1,font,commands_list.x-2,commands_list.y-14,jwin_pal[jcBOXFG],-1,"Favorite Commands"); + FONT *tfont=font; + font=pfont; + + for(int cmd=0; cmd<(commands_list.w*commands_list.h); ++cmd) + { + draw_text_button(menu1, + (cmd%commands_list.w)*command_buttonwidth+commands_list.x, + (cmd/commands_list.w)*command_buttonheight+commands_list.y, + command_buttonwidth, + command_buttonheight, + (favorite_commands[cmd]==cmdCatchall&&strcmp(catchall_string[Map.CurrScr()->room]," "))?catchall_string[Map.CurrScr()->room]:commands[favorite_commands[cmd]].name, + vc(1), + vc(14), + commands[favorite_commands[cmd]].flags, + true); + } + + font=tfont; + } + } + + if(is_large) // Layer panels + { + jwin_draw_frame(menu1,layer_panel.x-2,layer_panel.y,layer_panel.w+2,layer_panel.h,FR_DEEP); + rectfill(menu1,layer_panel.x+2,layer_panel.y+2,layer_panel.x+layer_panel.w-3,layer_panel.y+layer_panel.h-3,jwin_pal[jcBOX]); + + bool groundlayers = false; + bool overheadlayers = false; + bool flyinglayers = false; + + for(int i=0; i<=6; ++i) + { + char tbuf[15]; + + if(i>0 && Map.CurrScr()->layermap[i-1]) + { + if(i<3) groundlayers = true; + else if(i<5) overheadlayers = true; + else if(i<7) flyinglayers = true; + + sprintf(tbuf, "%s%d (%d:%02X)", (i==2 && Map.CurrScr()->flags7&fLAYER2BG) || (i==3 && Map.CurrScr()->flags7&fLAYER3BG) ? "-":"", i, Map.CurrScr()->layermap[i-1], Map.CurrScr()->layerscreen[i-1]); + } + else + { + sprintf(tbuf, "%s%d", (i==2 && Map.CurrScr()->flags7&fLAYER2BG) || (i==3 && Map.CurrScr()->flags7&fLAYER3BG) ? "-":"", i); + } + + int rx = (i * (layerpanel_buttonwidth+23)) + layer_panel.x+6; + int ry = layer_panel.y+16; + draw_text_button(menu1, rx,ry, layerpanel_buttonwidth, layerpanel_buttonheight, tbuf,vc(1),vc(14), CurrentLayer==i? D_SELECTED : (!Map.CurrScr()->layermap[i-1] && i>0) ? D_DISABLED : 0,true); + draw_checkbox(menu1,rx+layerpanel_buttonwidth+4,ry+2,vc(1),vc(14), LayerMaskInt[i]!=0); + + // Draw the group divider + if(i==3 || i==5) + { + _allegro_vline(menu1, rx-4, layer_panel.y+3, layer_panel.y+36, jwin_pal[jcLIGHT]); + _allegro_vline(menu1, rx-5, layer_panel.y+3, layer_panel.y+36, jwin_pal[jcMEDDARK]); + } + } + + if(groundlayers) + textprintf_ex(menu1,font,layer_panel.x+60,layer_panel.y+4,jwin_pal[jcBOXFG],-1,"Ground (Walkable) Layers"); + else + textprintf_disabled(menu1,font,layer_panel.x+60,layer_panel.y+4,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Ground (Walkable) Layers"); + + if(overheadlayers) + textprintf_ex(menu1,font,layer_panel.x+268,layer_panel.y+4,jwin_pal[jcBOXFG],-1,"Overhead Layers (Ground)"); + else + textprintf_disabled(menu1,font,layer_panel.x+268,layer_panel.y+4,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Overhead Layers (Ground)"); + + if(flyinglayers) + textprintf_ex(menu1,font,layer_panel.x+434,layer_panel.y+4,jwin_pal[jcBOXFG],-1,"Overhead Layers (Flying)"); + else + textprintf_disabled(menu1,font,layer_panel.x+434,layer_panel.y+4,jwin_pal[jcLIGHT],jwin_pal[jcMEDDARK],"Overhead Layers (Flying)"); + + //font=tfont; + } + + //} //if(true) + if(zq_showpal) + { + for(int i=0; i<256; i++) + { + rectfill(menu1,((i&15)<<2)+256,((i>>4)<<2)+176,((i&15)<<2)+259,((i>>4)<<2)+179,i); + } + } + + if(ShowFPS) + { + textprintf_shadowed_ex(menu1,is_large?lfont:sfont,0,prv_mode?32:16,vc(15),vc(0),-1,"FPS:%-3d",lastfps); + } + + if(prv_mode) + { + textout_shadowed_ex(menu1,sfont,"Preview Mode",0,16,vc(15),vc(0),-1); + + if(prv_twon) + { + textprintf_shadowed_ex(menu1,sfont,0,24,vc(15),vc(0),-1,"T Warp=%d tics", Map.get_prvtime()); + } + + do_previewtext(); + + } + + if(ShowFFScripts && !prv_mode) + { + int ypos = ShowFPS ? 28 : 18; + + for(int i=0; i< MAXFFCS; i++) + if(Map.CurrScr()->ffcs[i].script && Map.CurrScr()->ffcs[i].data) + { + textout_shadowed_ex(menu1,is_large ? lfont_l : font, ffcmap[Map.CurrScr()->ffcs[i].script-1].second.c_str(),2,ypos,vc(showxypos_ffc==i ? 14 : 15),vc(0),-1); + ypos+=16; + } + } + + // Show Errors & Details + //This includes the presence of: Screen State Carryover, Timed Warp, Maze Path, the 'Sideview Gravity', 'Invisible Link', + //'Save Screen', 'Continue Here' and 'Treat As..' Screen Flags, + // the String, every Room Type and Catch All, and all four Tile and Side Warps. + if(is_large && !prv_mode && ShowInfo) + { + int i=0; + char buf[2048]; + + // Start with general information + if(Map.CurrScr()->flags3&fINVISLINK) + { + sprintf(buf,"Invisible Link"); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.getLayerTargetMap() > 0) + { + int m = Map.getLayerTargetMultiple(); + sprintf(buf,"Used as a layer by screen %d:%02X",Map.getLayerTargetMap(),Map.getLayerTargetScr()); + char buf2[16]; + + if(m>0) + { + sprintf(buf2," and %d other%s",m,m>1?"s":""); + strcat(buf,buf2); + } + + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->nextmap) + { + sprintf(buf,"Screen State carries over to %d:%02X",Map.CurrScr()->nextmap,Map.CurrScr()->nextscr); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->timedwarptics) + { + sprintf(buf,"%s%sTimed Warp: %s",(Map.CurrScr()->flags4&fTIMEDDIRECT)?"Direct ":"",(Map.CurrScr()->flags5&fRANDOMTIMEDWARP)?"Random ":"",ticksstr(Map.CurrScr()->timedwarptics)); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->flags&fMAZE) + { + sprintf(buf,"Maze Path: %s (Exit %s)",pathstr(Map.CurrScr()->path),dirstr[Map.CurrScr()->exitdir]); + show_screen_error(buf,i++,vc(15)); + } + + bool continuescreen = false, savecombo = false; + + if(Map.CurrScr()->flags4&fAUTOSAVE) + { + sprintf(buf,"Automatic Save%s Screen", (Map.CurrScr()->flags6&fCONTINUEHERE) ? "-Continue":""); + show_screen_error(buf,i++,vc(15)); + continuescreen = ((Map.CurrScr()->flags6&fCONTINUEHERE)!=0); + savecombo = true; + } + else if(Map.CurrScr()->flags6&fCONTINUEHERE) + { + sprintf(buf,"Continue Screen"); + show_screen_error(buf,i++,vc(15)); + continuescreen = true; + } + + if(Map.CurrScr()->flags7&fSIDEVIEW) + { + sprintf(buf,"Sideview Gravity"); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->flags6 & (fCAVEROOM|fDUNGEONROOM)) + { + sprintf(buf,"Treat As %s%s Screen", (Map.CurrScr()->flags6&fCAVEROOM) ? "Interior":"NES Dungeon", + (Map.CurrScr()->flags6 & (fCAVEROOM|fDUNGEONROOM)) == (fCAVEROOM|fDUNGEONROOM) ? " or NES Dungeon":""); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->oceansfx != 0) + { + sprintf(buf,"Ambient Sound: %s",sfx_string[Map.CurrScr()->oceansfx]); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->bosssfx != 0) + { + sprintf(buf,"Boss Roar Sound: %s",sfx_string[Map.CurrScr()->bosssfx]); + show_screen_error(buf,i++,vc(15)); + } + + if(Map.CurrScr()->str) + { + strncpy(buf,MsgString(Map.CurrScr()->str, true, false),72); + buf[72] = '\0'; + char shortbuf[72]; + strip_extra_spaces(buf); + shorten_string(shortbuf, buf, lfont_l, 72, 280); + sprintf(buf,"String %s",shortbuf); + show_screen_error(buf,i++,vc(15)); + } + + if((Map.CurrScr()->flags&fWHISTLE) || (Map.CurrScr()->flags7&fWHISTLEWATER)) + { + sprintf(buf,"Whistle ->%s%s%s",(Map.CurrScr()->flags&fWHISTLE)?" Stairs":"", + (Map.CurrScr()->flags&fWHISTLE && Map.CurrScr()->flags7&fWHISTLEWATER)?", ":"", + (Map.CurrScr()->flags7&fWHISTLEWATER)?"Dry Lake":""); + show_screen_error(buf,i++,vc(15)); + } + + switch(Map.CurrScr()->room) + { + case rSP_ITEM: + sprintf(buf,"Special Item is %s",item_string[Map.CurrScr()->catchall]); + show_screen_error(buf,i++, vc(15)); + break; + + case rINFO: + { + int shop = Map.CurrScr()->catchall; + sprintf(buf,"Pay For Info: -%d, -%d, -%d", + misc.info[shop].price[0],misc.info[shop].price[1],misc.info[shop].price[2]); + show_screen_error(buf,i++, vc(15)); + } + break; + + case rMONEY: + sprintf(buf,"Secret Money: %d Rupees",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + + case rGAMBLE: + show_screen_error("Gamble Room",i++, vc(15)); + break; + + case rREPAIR: + sprintf(buf,"Door Repair: -%d Rupees",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + + case rRP_HC: + sprintf(buf,"Take %s or %s", item_string[iRPotion], item_string[iHeartC]); + show_screen_error(buf,i++, vc(15)); + break; + + case rGRUMBLE: + show_screen_error("Feed the Goriya",i++, vc(15)); + break; + + case rTRIFORCE: + show_screen_error("Level 9 Entrance",i++, vc(15)); + break; + + case rP_SHOP: + case rSHOP: + { + int shop = Map.CurrScr()->catchall; + sprintf(buf,"%sShop: ", + Map.CurrScr()->room==rP_SHOP ? "Potion ":""); + + for(int j=0; j<3; j++) if(misc.shop[shop].item[j]>0) // Print the 3 items and prices + { + strcat(buf,item_string[misc.shop[shop].item[j]]); + strcat(buf,":"); + char pricebuf[4]; + sprintf(pricebuf,"%d",misc.shop[shop].price[j]); + strcat(buf,pricebuf); + + if(j<2 && misc.shop[shop].item[j+1]>0) strcat(buf,", "); + } + + show_screen_error(buf,i++, vc(15)); + } + break; + + case rTAKEONE: + { + int shop = Map.CurrScr()->catchall; + sprintf(buf,"Take Only One: %s%s%s%s%s", + misc.shop[shop].item[0]<1?"":item_string[misc.shop[shop].item[0]],misc.shop[shop].item[0]>0?", ":"", + misc.shop[shop].item[1]<1?"":item_string[misc.shop[shop].item[1]],(misc.shop[shop].item[1]>0&&misc.shop[shop].item[2]>0)?", ":"", + misc.shop[shop].item[2]<1?"":item_string[misc.shop[shop].item[2]]); + show_screen_error(buf,i++, vc(15)); + } + break; + + case rBOMBS: + sprintf(buf,"More Bombs: -%d Rupees",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + + case rARROWS: + sprintf(buf,"More Arrows: -%d Rupees",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + + case rSWINDLE: + sprintf(buf,"Leave Life or %d Rupees",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + + case r10RUPIES: + show_screen_error("10 Rupees",i++, vc(15)); + break; + + case rGANON: + show_screen_error("Ganon Room",i++, vc(15)); + break; + + case rZELDA: + show_screen_error("Zelda Room",i++, vc(15)); + break; + + case rMUPGRADE: + show_screen_error("1/2 Magic Upgrade",i++, vc(15)); + break; + + case rLEARNSLASH: + show_screen_error("Learn Slash",i++, vc(15)); + break; + + case rWARP: + sprintf(buf,"3-Stair Warp: Warp Ring %d",Map.CurrScr()->catchall); + show_screen_error(buf,i++, vc(15)); + break; + } + + bool undercombo = false, warpa = false, warpb = false, warpc = false, warpd = false, warpr = false; + + for(int c=0; c<176+128+1+MAXFFCS; ++c) + { + // Checks both combos, secret combos, undercombos and FFCs +//Fixme: + int ctype = + combobuf[vbound( + (c>=305 ? Map.CurrScr()->ffcs[c-305].data : + c>=304 ? Map.CurrScr()->undercombo : + c>=176 ? Map.CurrScr()->secretcombo[c-176] : + Map.CurrScr()->data.empty() ? 0 : // Sanity check: does room combo data exist? + Map.CurrScr()->data[c] + ), 0, MAXCOMBOS-1)].type; + + if(!undercombo && integrityBoolUnderCombo(Map.CurrScr(),ctype)) + { + undercombo = true; + show_screen_error("Under Combo is combo 0",i++, vc(7)); + } + + // Tile Warp types + switch(ctype) + { + case cSAVE: + case cSAVE2: + if(!savecombo) + { + savecombo = true; + + if(integrityBoolSaveCombo(Map.CurrScr(),ctype)) + show_screen_error("Save Screen",i++, vc(15)); + else + show_screen_error("Save-Continue Screen",i++, vc(15)); + } + + break; + + case cSTAIRR: + case cPITR: + case cSWARPR: + if(!warpr && (Map.CurrScr()->tilewarptype[0]==wtCAVE || Map.CurrScr()->tilewarptype[1]==wtCAVE || + Map.CurrScr()->tilewarptype[2]==wtCAVE || Map.CurrScr()->tilewarptype[3]==wtCAVE)) + { + warpr = true; + show_screen_error("Random Tile Warp contains Cave/Item Cellar",i++, vc(7)); + } + + break; + + case cCAVED: + case cPITD: + case cSTAIRD: + case cCAVE2D: + case cSWIMWARPD: + case cDIVEWARPD: + case cSWARPD: + if(!warpd) + { + warpd = true; + tile_warp_notification(3,buf); + show_screen_error(buf,i++, vc(15)); + } + + break; + + case cCAVEC: + case cPITC: + case cSTAIRC: + case cCAVE2C: + case cSWIMWARPC: + case cDIVEWARPC: + case cSWARPC: + if(!warpc) + { + warpc = true; + tile_warp_notification(2,buf); + show_screen_error(buf,i++, vc(15)); + } + + break; + + case cCAVEB: + case cPITB: + case cSTAIRB: + case cCAVE2B: + case cSWIMWARPB: + case cDIVEWARPB: + case cSWARPB: + if(!warpb) + { + warpb = true; + tile_warp_notification(1,buf); + show_screen_error(buf,i++, vc(15)); + } + + break; + + case cCAVE: + case cPIT: + case cSTAIR: + case cCAVE2: + case cSWIMWARP: + case cDIVEWARP: + case cSWARPA: + if(!warpa) + { + warpa = true; + tile_warp_notification(0,buf); + show_screen_error(buf,i++, vc(15)); + } + + break; + } + } + + int sidewarpnotify = 0; + + if(Map.CurrScr()->flags2&wfUP) + { + side_warp_notification(Map.CurrScr()->sidewarpindex&3,0,buf); + show_screen_error(buf,i++, vc(15)); + sidewarpnotify|=(1<<(Map.CurrScr()->sidewarpindex&3)); + } + + if(Map.CurrScr()->flags2&wfDOWN) + { + side_warp_notification((Map.CurrScr()->sidewarpindex>>2)&3,1,buf); + show_screen_error(buf,i++, vc(15)); + sidewarpnotify|=(1<<((Map.CurrScr()->sidewarpindex>>2)&3)); + } + + if(Map.CurrScr()->flags2&wfLEFT) + { + side_warp_notification((Map.CurrScr()->sidewarpindex>>4)&3,2,buf); + show_screen_error(buf,i++, vc(15)); + sidewarpnotify|=(1<<((Map.CurrScr()->sidewarpindex>>4)&3)); + } + + if(Map.CurrScr()->flags2&wfRIGHT) + { + side_warp_notification((Map.CurrScr()->sidewarpindex>>6)&3,3,buf); + show_screen_error(buf,i++, vc(15)); + sidewarpnotify|=(1<<((Map.CurrScr()->sidewarpindex>>6)&3)); + } + + if(!(sidewarpnotify&1) && Map.CurrScr()->timedwarptics) + { + side_warp_notification(0,4,buf); // Timed Warp + show_screen_error(buf,i++, vc(15)); + } + + // Now for errors + if((Map.CurrScr()->flags4&fSAVEROOM) && !savecombo) show_screen_error("Save Point->Continue Here, but no Save Point combo?",i++, vc(14)); + + if(integrityBoolEnemiesItem(Map.CurrScr())) show_screen_error("Enemies->Item, but no enemies",i++, vc(7)); + + if(integrityBoolEnemiesSecret(Map.CurrScr())) show_screen_error("Enemies->Secret, but no enemies",i++, vc(7)); + + if(integrityBoolStringNoGuy(Map.CurrScr())) show_screen_error("String, but Guy is (none)",i++, vc(14)); + + if(integrityBoolGuyNoString(Map.CurrScr())) show_screen_error("Non-Fairy Guy, but String is (none)",i++, vc(14)); + + if(integrityBoolRoomNoGuy(Map.CurrScr())) show_screen_error("Guy is (none)",i++, vc(14)); + + if(integrityBoolRoomNoString(Map.CurrScr())) show_screen_error("String is (none)",i++, vc(14)); + + if(integrityBoolRoomNoGuyNoString(Map.CurrScr())) show_screen_error("Guy and String are (none)",i++, vc(14)); + } + + if(!is_large) + { + if(draw_mode!=dm_normal) + { + textout_shadowed_right_ex(menu1,sfont,dm_names[draw_mode],mapscreen_x+((16+(showedges?1:0))*16*mapscreensize)-1,mapscreen_y+((showedges?1:0)*16*mapscreensize),vc(15),vc(0),-1); + } + } + + if((tooltip_timer>=tooltip_maxtimer)&&(tooltip_box.x>=0&&tooltip_box.y>=0)) + { + masked_blit(tooltipbmp, menu1, 0, 0, tooltip_box.x, tooltip_box.y, tooltip_box.w, tooltip_box.h); + } + +// textprintf_ex(menu1,font,16, 200,vc(15),-1,"%d %d %d %d %d",tooltip_timer,tooltip_box.x,tooltip_box.y,tooltip_box.w,tooltip_box.h); + + scare_mouse(); + + if(flags&rCLEAR) + { + blit(menu1,screen,0,0,0,0,zq_screen_w,zq_screen_h); + } + else + { + blit(menu1,screen,0,16,0,16,zq_screen_w,zq_screen_h-16); + blit(menu1,screen,combolist_window.x-64,0,combolist_window.x-64,0,combolist_window.w+64,16); + + if(flags&rCOMBO) + { + blit(menu1,screen,combo_preview.x,combo_preview.y,combo_preview.x,combo_preview.y,combo_preview.w,combo_preview.h); + } + } + + ComboBrushPause=0; + + unscare_mouse(); + SCRFIX(); +} + +void select_scr() +{ + if(Map.getCurrMap()>=Map.getMapCount()) + return; + + int tempcb=ComboBrush; + ComboBrush=0; + + //scooby + while(gui_mouse_b()) + { + /* + int x=gui_mouse_x(); + if(x>minimap.x+(minimap.w-6)*BMM) x=minimap.x+3+(minimap.w-6)*BMM; + if(xminimap.y+9+3+(minimap.h-6)*BMM) y=minimap.y+9+3+(minimap.h-6)*BMM; + if(y=MAPSCRS) + s-=16; + + if(s!=Map.getCurrScr()) + { + Map.setCurrScr(s); + // vsync(); + // refresh(rALL); + } + + do_animations(); + refresh(rALL); + } + + ComboBrush=tempcb; +} + +bool select_favorite() +{ + int tempcb=ComboBrush; + ComboBrush=0; + bool valid=false; + + while(gui_mouse_b()) + { + valid=false; + int x=gui_mouse_x(); + + if(xfavorites_list.x+(favorites_list.w*16)-1) x=favorites_list.x+(favorites_list.w*16)-1; + + int y=gui_mouse_y(); + + if(yfavorites_list.y+(favorites_list.h*16)-1) y=favorites_list.y+(favorites_list.h*16)-1; + + int tempc=(((y-favorites_list.y)>>4)*favorites_list.w)+((x-favorites_list.x)>>4); + + if(draw_mode!=dm_alias) + { + if(favorite_combos[tempc]!=-1) + { + Combo=favorite_combos[tempc]; + valid=true; + } + } + else + { + if(favorite_comboaliases[tempc]!=-1) + { + combo_apos=favorite_comboaliases[tempc]; + valid=true; + } + } + + do_animations(); + refresh(rALL); + } + + ComboBrush=tempcb; + return valid; +} + +void select_combo(int clist) +{ + current_combolist=clist; + int tempcb=ComboBrush; + ComboBrush=0; + + while(gui_mouse_b()) + { + int x=gui_mouse_x(); + + if(xcombolist[current_combolist].x+(combolist[current_combolist].w*16)-1) x=combolist[current_combolist].x+(combolist[current_combolist].w*16)-1; + + int y=gui_mouse_y(); + + if(ycombolist[current_combolist].y+(combolist[current_combolist].h*16)-1) y=combolist[current_combolist].y+(combolist[current_combolist].h*16)-1; + + Combo=(((y-combolist[current_combolist].y)>>4)*combolist[current_combolist].w)+((x-combolist[current_combolist].x)>>4)+First[current_combolist]; + do_animations(); + refresh(rALL); + } + + ComboBrush=tempcb; +} + +void select_comboa(int clist) +{ + current_comboalist=clist; + int tempcb=ComboBrush; + ComboBrush=0; + alias_cset_mod=0; + + while(gui_mouse_b()) + { + int x=gui_mouse_x(); + + if(xcomboaliaslist[current_comboalist].x+(comboaliaslist[current_comboalist].w*16)-1) x=comboaliaslist[current_comboalist].x+(comboaliaslist[current_comboalist].w*16)-1; + + int y=gui_mouse_y(); + + if(ycomboaliaslist[current_comboalist].y+(comboaliaslist[current_comboalist].h*16)-1) y=comboaliaslist[current_comboalist].y+(comboaliaslist[current_comboalist].h*16)-1; + + combo_apos=(((y-comboaliaslist[current_comboalist].y)>>4)*comboaliaslist[current_comboalist].w)+((x-comboaliaslist[current_comboalist].x)>>4)+combo_alistpos[current_comboalist]; + do_animations(); + refresh(rALL); + } + + ComboBrush=tempcb; +} + +void update_combobrush() +{ + clear_bitmap(brushbmp); + + if(draw_mode==dm_alias) + { + //int count=(combo_aliases[combo_apos].width+1)*(combo_aliases[combo_apos].height+1)*(comboa_lmasktotal(combo_aliases[combo_apos].layermask)); + for(int z=0; z<=comboa_lmasktotal(combo_aliases[combo_apos].layermask); z++) + { + for(int y=0; y<=combo_aliases[combo_apos].height; y++) + { + for(int x=0; x<=combo_aliases[combo_apos].width; x++) + { + int position = ((y*(combo_aliases[combo_apos].width+1))+x)+((combo_aliases[combo_apos].width+1)*(combo_aliases[combo_apos].height+1)*z); + + if(combo_aliases[combo_apos].combos[position]) + { + if(z==0) + { + putcombo(brushbmp,x<<4,y<<4,combo_aliases[combo_apos].combos[position],wrap(combo_aliases[combo_apos].csets[position]+alias_cset_mod, 0, 11)); + } + else + { + overcombo(brushbmp,x<<4,y<<4,combo_aliases[combo_apos].combos[position],wrap(combo_aliases[combo_apos].csets[position]+alias_cset_mod, 0, 11)); + } + } + } + } + } + + switch(alias_origin) + { + case 0: + //if(!(combo_aliases[combo_apos].combos[0])) + textprintf_shadowed_ex(brushbmp, sfont, 6, 6, vc(15), vc(0), -1, "x"); + break; + + case 1: + //if(!(combo_aliases[combo_apos].combos[combo_aliases[combo_apos].width])) + textprintf_shadowed_ex(brushbmp, sfont, 6+(combo_aliases[combo_apos].width*16), 6, vc(15), vc(0), -1, "x"); + break; + + case 2: + //if(!(combo_aliases[combo_apos].combos[(combo_aliases[combo_apos].width+1)*combo_aliases[combo_apos].height])) + textprintf_shadowed_ex(brushbmp, sfont, 6, 6+(combo_aliases[combo_apos].height*16), vc(15), vc(0), -1, "x"); + break; + + case 3: + //if(!(combo_aliases[combo_apos].combos[(combo_aliases[combo_apos].width+1)*(combo_aliases[combo_apos].height)-1])) + textprintf_shadowed_ex(brushbmp, sfont, 6+(combo_aliases[combo_apos].width*16), 6+(combo_aliases[combo_apos].height*16), vc(15), vc(0), -1, "x"); + break; + } + } + else + { + if(combo_cols==false) + { + for(int i=0; i<256; i++) + { + if(((i%COMBOS_PER_ROW)layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + refresh(rMAP+rSCRMAP); + + while(gui_mouse_b()) + { + int x=gui_mouse_x(); + int y=gui_mouse_y(); + double startx=mapscreen_x+(showedges?(16*mapscreensize):0); + double starty=mapscreen_y+(showedges?(16*mapscreensize):0); + int startxint=mapscreen_x+(showedges?int(16*mapscreensize):0); + int startyint=mapscreen_y+(showedges?int(16*mapscreensize):0); + + if(isinRect(x,y,startxint,startyint,int(startx+(256*mapscreensize)-1),int(starty+(176*mapscreensize)-1))) + { + int cxstart=(x-startxint)/int(16*mapscreensize); + int cystart=(y-startyint)/int(16*mapscreensize); + int cstart=(cystart*16)+cxstart; + combo_alias *combo = &combo_aliases[combo_apos]; + + switch(draw_mode) + { + case dm_normal: + { + int cc=Combo; + + if(!combo_cols) + { + for(int cy=0; cy+cystart<11&&cydata[c]=cc+cx; + } + + Map.AbsoluteScr(drawmap, drawscr)->cset[c]=CSet; + } + + cc+=20; + } + } + else + { + int p=Combo/256; + int pc=Combo%256; + + for(int cy=0; cy+cystart<11&&cy=0&&cc<256) + { + cc+=(p*256); + + if(!justcset) Map.AbsoluteScr(drawmap, drawscr)->data[c]=cc; + + Map.AbsoluteScr(drawmap, drawscr)->cset[c]=CSet; + } + } + } + } + + update_combobrush(); + } + break; + + case dm_relational: + { + int c2,c3; + int cx, cy, cx2, cy2; + cy=cstart>>4; + cx=cstart&15; + + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + relational_tile_grid[(cy+rtgyo)][cx+rtgxo]=1; + Map.AbsoluteScr(drawmap, drawscr)->data[cstart]=Combo+47; + Map.AbsoluteScr(drawmap, drawscr)->cset[cstart]=CSet; + } + else + { + relational_tile_grid[(cy+rtgyo)][cx+rtgxo]=0; + } + + for(int y2=-1; y2<2; ++y2) + { + cy2=cy+y2; + + if((cy2>11)||(cy2<0)) + { + continue; + } + + for(int x2=-1; x2<2; ++x2) + { + cx2=cx+x2; + + if((cx2>15)||(cx2<0)) + { + continue; + } + + c2=cstart+(y2*16)+x2; + c3=((relational_tile_grid[((cy2-1)+rtgyo)][(cx2+1)+rtgxo]?1:0)<<0)+ + ((relational_tile_grid[((cy2-1)+rtgyo)][(cx2-1)+rtgxo]?1:0)<<1)+ + ((relational_tile_grid[((cy2+1)+rtgyo)][(cx2-1)+rtgxo]?1:0)<<2)+ + ((relational_tile_grid[((cy2+1)+rtgyo)][(cx2+1)+rtgxo]?1:0)<<3)+ + ((relational_tile_grid[((cy2)+rtgyo)][(cx2+1)+rtgxo]?1:0)<<4)+ + ((relational_tile_grid[((cy2-1)+rtgyo)][(cx2)+rtgxo]?1:0)<<5)+ + ((relational_tile_grid[((cy2)+rtgyo)][(cx2-1)+rtgxo]?1:0)<<6)+ + ((relational_tile_grid[((cy2+1)+rtgyo)][(cx2)+rtgxo]?1:0)<<7); + + if(relational_tile_grid[((c2>>4)+rtgyo)][(c2&15)+rtgxo]==0) + { + Map.AbsoluteScr(drawmap, drawscr)->data[c2]=Combo+relational_source_grid[c3]; + Map.AbsoluteScr(drawmap, drawscr)->cset[c2]=CSet; + } + } + } + } + break; + + case dm_dungeon: + { + int c2,c3,c4; + int cx, cy, cx2, cy2; + cy=cstart>>4; + cx=cstart&15; + + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + relational_tile_grid[(cy+rtgyo)][cx+rtgxo]=0; + + for(int y2=-1; y2<2; ++y2) + { + cy2=cy+y2; + + if((cy2>11)||(cy2<0)) + { + continue; + } + + for(int x2=-1; x2<2; ++x2) + { + cx2=cx+x2; + + if((cx2>15)||(cx2<0)) + { + continue; + } + + if(relational_tile_grid[(cy2+rtgyo)][cx2+rtgxo]!=0) + { + relational_tile_grid[(cy2+rtgyo)][cx2+rtgxo]=1; + }; + } + } + + Map.AbsoluteScr(drawmap, drawscr)->data[cstart]=Combo; + Map.AbsoluteScr(drawmap, drawscr)->cset[cstart]=CSet; + } + else + { + relational_tile_grid[(cy+rtgyo)][cx+rtgxo]=2; + + for(int y2=-1; y2<2; ++y2) + { + cy2=cy+y2; + + if((cy2>11)||(cy2<0)) + { + continue; + } + + for(int x2=-1; x2<2; ++x2) + { + cx2=cx+x2; + + if((cx2>15)||(cx2<0)) + { + continue; + } + + if(relational_tile_grid[(cy2+rtgyo)][cx2+rtgxo]==0) + { + relational_tile_grid[(cy2+rtgyo)][cx2+rtgxo]=1; + }; + } + } + + Map.AbsoluteScr(drawmap, drawscr)->data[cstart]=Combo+48+47; + Map.AbsoluteScr(drawmap, drawscr)->cset[cstart]=CSet; + } + + for(int y2=0; y2<11; ++y2) + { + for(int x2=0; x2<16; ++x2) + { + c2=(y2*16)+x2; + c4=relational_tile_grid[((y2)+rtgyo)][(x2)+rtgxo]; + c3=(((relational_tile_grid[((y2-1)+rtgyo)][(x2+1)+rtgxo]>c4)?1:0)<<0)+ + (((relational_tile_grid[((y2-1)+rtgyo)][(x2-1)+rtgxo]>c4)?1:0)<<1)+ + (((relational_tile_grid[((y2+1)+rtgyo)][(x2-1)+rtgxo]>c4)?1:0)<<2)+ + (((relational_tile_grid[((y2+1)+rtgyo)][(x2+1)+rtgxo]>c4)?1:0)<<3)+ + (((relational_tile_grid[((y2)+rtgyo)][(x2+1)+rtgxo]>c4)?1:0)<<4)+ + (((relational_tile_grid[((y2-1)+rtgyo)][(x2)+rtgxo]>c4)?1:0)<<5)+ + (((relational_tile_grid[((y2)+rtgyo)][(x2-1)+rtgxo]>c4)?1:0)<<6)+ + (((relational_tile_grid[((y2+1)+rtgyo)][(x2)+rtgxo]>c4)?1:0)<<7); + + if(relational_tile_grid[(y2+rtgyo)][x2+rtgxo]<2) + { + Map.AbsoluteScr(drawmap, drawscr)->data[c2]=Combo+relational_source_grid[c3]+(48*c4); + Map.AbsoluteScr(drawmap, drawscr)->cset[c2]=CSet; + } + } + } + } + break; + + case dm_alias: + if(!combo->layermask) + { + int ox=0, oy=0; + + switch(alias_origin) + { + case 0: + ox=0; + oy=0; + break; + + case 1: + ox=(combo->width); + oy=0; + break; + + case 2: + ox=0; + oy=(combo->height); + break; + + case 3: + ox=(combo->width); + oy=(combo->height); + break; + } + + for(int cy=0; cy-oy+cystart<11&&cy<=combo->height; cy++) + { + for(int cx=0; cx-ox+cxstart<16&&cx<=combo->width; cx++) + { + if((cx+cxstart-ox>=0)&&(cy+cystart-oy>=0)) + { + int c=cstart+((cy-oy)*16)+cx-ox; + int p=(cy*(combo->width+1))+cx; + + if(combo->combos[p]) + { + Map.AbsoluteScr(drawmap, drawscr)->data[c]=combo->combos[p]; + Map.AbsoluteScr(drawmap, drawscr)->cset[c]=wrap(combo->csets[p]+alias_cset_mod, 0, 11); + } + } + } + } + } + else + { + int amap=0, ascr=0; + int lcheck = 1; + int laypos = 0; + int ox=0, oy=0; + + switch(alias_origin) + { + case 0: + ox=0; + oy=0; + break; + + case 1: + ox=(combo->width); + oy=0; + break; + + case 2: + ox=0; + oy=(combo->height); + break; + + case 3: + ox=(combo->width); + oy=(combo->height); + break; + } + + for(int cz=0; cz<7; cz++, lcheck<<=1) + { + if(!cz) + { + amap = Map.getCurrMap(); + ascr = Map.getCurrScr(); + } + else + { + if(cz==1) lcheck>>=1; + + if(combo->layermask&lcheck) + { + amap = Map.CurrScr()->layermap[cz-1]-1; + ascr = Map.CurrScr()->layerscreen[cz-1]; + laypos++; + } + } + + for(int cy=0; cy-oy+cystart<11&&cy<=combo->height; cy++) + { + for(int cx=0; cx-ox+cxstart<16&&cx<=combo->width; cx++) + { + if((!cz)||/*(Map.CurrScr()->layermap[cz>0?cz-1:0])*/amap>=0) + { + if((cz==0)||(combo->layermask&lcheck)) + { + if((cx+cxstart-ox>=0)&&(cy+cystart-oy>=0)) + { + int c=cstart+((cy-oy)*16)+cx-ox; + int p=((cy*(combo->width+1))+cx)+((combo->width+1)*(combo->height+1)*laypos); + + if((combo->combos[p])&&(amap>=0)) + { + Map.AbsoluteScr(amap, ascr)->data[c]=combo->combos[p]; + Map.AbsoluteScr(amap, ascr)->cset[c]=wrap(combo->csets[p]+alias_cset_mod, 0, 11); + } + } + } + } + } + } + } + } + + break; + } + } + + do_animations(); + refresh(rALL); + } +} + + + + +void replace(int c) +{ + saved=false; + Map.Ugo(); + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + int targetcombo = Map.AbsoluteScr(drawmap, drawscr)->data[c]; + int targetcset = Map.AbsoluteScr(drawmap, drawscr)->cset[c]; + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT]) + { + for(int i=0; i<176; i++) + { + if((Map.AbsoluteScr(drawmap, drawscr)->cset[i])==targetcset) + { + Map.AbsoluteScr(drawmap, drawscr)->cset[i]=CSet; + } + } + } + else + { + for(int i=0; i<176; i++) + { + if(((Map.AbsoluteScr(drawmap, drawscr)->data[i])==targetcombo) && + ((Map.AbsoluteScr(drawmap, drawscr)->cset[i])==targetcset)) + { + Map.AbsoluteScr(drawmap, drawscr)->data[i]=Combo; + Map.AbsoluteScr(drawmap, drawscr)->cset[i]=CSet; + } + } + } + + refresh(rMAP); +} + +void draw_block(int start,int w,int h) +{ + saved=false; + Map.Ugo(); + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + for(int y=0; ydata[start+(y<<4)+x]=Combo+(y*4)+x; + Map.AbsoluteScr(drawmap, drawscr)->cset[start+(y<<4)+x]=CSet; + + } + + refresh(rMAP+rSCRMAP); +} + +void fill(mapscr* fillscr, int targetcombo, int targetcset, int sx, int sy, int dir, int diagonal, bool only_cset) +{ + if(!only_cset) + { + if((fillscr->data[((sy<<4)+sx)])!=targetcombo) + return; + } + + if((fillscr->cset[((sy<<4)+sx)])!=targetcset) + return; + + if(!only_cset) + { + fillscr->data[((sy<<4)+sx)]=Combo; + } + + fillscr->cset[((sy<<4)+sx)]=CSet; + + if((sy>0) && (dir!=down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx, sy-1, up, diagonal, only_cset); + + if((sy<10) && (dir!=up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx, sy+1, down, diagonal, only_cset); + + if((sx>0) && (dir!=right)) // && ((Map.CurrScr()->data[((sy<<4)+sx-1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx-1, sy, left, diagonal, only_cset); + + if((sx<15) && (dir!=left)) // && ((Map.CurrScr()->data[((sy<<4)+sx+1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx+1, sy, right, diagonal, only_cset); + + if(diagonal==1) + { + if((sy>0) && (sx>0) && (dir!=r_down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx-1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx-1, sy-1, l_up, diagonal, only_cset); + + if((sy<10) && (sx<15) && (dir!=l_up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx+1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx+1, sy+1, r_down, diagonal, only_cset); + + if((sx>0) && (sy<10) && (dir!=r_up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx-1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx-1, sy+1, l_down, diagonal, only_cset); + + if((sx<15) && (sy>0) && (dir!=l_down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx+1)]&0x7FF)==target)) + fill(fillscr, targetcombo, targetcset, sx+1, sy-1, r_up, diagonal, only_cset); + } + +} + + +void fill2(mapscr* fillscr, int targetcombo, int targetcset, int sx, int sy, int dir, int diagonal, bool only_cset) +{ + if(!only_cset) + { + if((fillscr->data[((sy<<4)+sx)])==targetcombo) + return; + } + + if((fillscr->cset[((sy<<4)+sx)])==targetcset) + return; + + if(!only_cset) + { + fillscr->data[((sy<<4)+sx)]=Combo; + } + + fillscr->cset[((sy<<4)+sx)]=CSet; + + if((sy>0) && (dir!=down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx, sy-1, up, diagonal, only_cset); + + if((sy<10) && (dir!=up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx, sy+1, down, diagonal, only_cset); + + if((sx>0) && (dir!=right)) // && ((Map.CurrScr()->data[((sy<<4)+sx-1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx-1, sy, left, diagonal, only_cset); + + if((sx<15) && (dir!=left)) // && ((Map.CurrScr()->data[((sy<<4)+sx+1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx+1, sy, right, diagonal, only_cset); + + if(diagonal==1) + { + if((sy>0) && (sx>0) && (dir!=r_down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx-1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx-1, sy-1, l_up, diagonal, only_cset); + + if((sy<10) && (sx<15) && (dir!=l_up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx+1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx+1, sy+1, r_down, diagonal, only_cset); + + if((sx>0) && (sy<10) && (dir!=r_up)) // && ((Map.CurrScr()->data[(((sy+1)<<4)+sx-1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx-1, sy+1, l_down, diagonal, only_cset); + + if((sx<15) && (sy>0) && (dir!=l_down)) // && ((Map.CurrScr()->data[(((sy-1)<<4)+sx+1)]&0x7FF)!=target)) + fill2(fillscr, targetcombo, targetcset, sx+1, sy-1, r_up, diagonal, only_cset); + } +} + + +/**************************/ +/***** Mouse *****/ +/**************************/ + +void doxypos(byte &px2,byte &py2,int color,int mask) +{ + doxypos(px2,py2,color,mask,false,0,0,16,16); +} + +void doxypos(byte &px2,byte &py2,int color,int mask, bool immediately, int cursoroffx, int cursoroffy, int iconw, int iconh) +{ + int tempcb=ComboBrush; + ComboBrush=0; + scare_mouse(); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_POINT_BOX][0]); + unscare_mouse(); + + int oldpx=px2, oldpy=py2; + double startx=mapscreen_x+(showedges?(16*mapscreensize):0); + double starty=mapscreen_y+(showedges?(16*mapscreensize):0); + int startxint=mapscreen_x+(showedges?int(16*mapscreensize):0); + int startyint=mapscreen_y+(showedges?int(16*mapscreensize):0); + showxypos_x=px2; + showxypos_y=py2; + showxypos_w=iconw; + showxypos_h=iconh; + showxypos_color=vc(color); + showxypos_icon=true; + bool canedit=false; + bool done=false; + + while(!done && (!(gui_mouse_b()&2) || immediately)) + { + int x=gui_mouse_x(); + int y=gui_mouse_y(); + + if(!gui_mouse_b() || immediately) + { + canedit=true; + } + + if(canedit && gui_mouse_b()==1 && isinRect(x,y,startxint,startyint,int(startx+(256*mapscreensize)-1),int(starty+(176*mapscreensize)-1))) + { + scare_mouse(); + zq_set_mouse_range(startxint,startyint,int(startxint+(256*mapscreensize)-1),int(startyint+(176*mapscreensize)-1)); + + while(gui_mouse_b()==1) + { + x=int((gui_mouse_x()-(showedges?int(16*mapscreensize):0))/mapscreensize)-cursoroffx; + y=int((gui_mouse_y()-16-(showedges?int(16*mapscreensize):0))/mapscreensize)-cursoroffy; + showxypos_cursor_icon=true; + showxypos_cursor_x=x&mask; + showxypos_cursor_y=y&mask; + do_animations(); + refresh(rALL | rNOCURSOR); + int xpos, ypos; + + if(is_large) + { + xpos = 450; + ypos = 405; + } + else + { + xpos = 700; + ypos = 500; + } + + textprintf_ex(screen,font,xpos,ypos,vc(15),vc(0),"%d %d %d %d",startxint,startyint,int(startxint+(256*mapscreensize)-1),int(startyint+(176*mapscreensize)-1)); + textprintf_ex(screen,font,xpos,ypos+10,vc(15),vc(0),"%d %d %d %d %d %d",x,y,gui_mouse_x(),gui_mouse_y(),showxypos_cursor_x,showxypos_cursor_y); + } + + if(gui_mouse_b()==0) + { + px2=byte(x&mask); + py2=byte(y&mask); + } + + zq_set_mouse_range(0,0,zq_screen_w-1,zq_screen_h-1); + unscare_mouse(); + done=true; + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_ESC: + case KEY_ENTER: + goto finished; + } + } + + do_animations(); + refresh(rALL | rNOCURSOR); + } + +finished: + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + refresh(rMAP+rMENU); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + showxypos_x=-1000; + showxypos_y=-1000; + showxypos_color=-1000; + showxypos_ffc=-1000; + showxypos_icon=false; + showxypos_cursor_x=-1000; + showxypos_cursor_y=-1000; + showxypos_cursor_icon=false; + + if(px2!=oldpx||py2!=oldpy) + { + saved=false; + } + + ComboBrush=tempcb; +} + +void doflags() +{ + set_mouse_sprite(mouse_bmp[MOUSE_BMP_FLAG][0]); + int of=Flags; + Flags=cFLAGS; + refresh(rMAP | rNOCURSOR); + + bool canedit=false; + + while(!(gui_mouse_b()&2)) + { + int x=gui_mouse_x(); + int y=gui_mouse_y(); + double startx=mapscreen_x+(showedges?(16*mapscreensize):0); + double starty=mapscreen_y+(showedges?(16*mapscreensize):0); + int startxint=mapscreen_x+(showedges?int(16*mapscreensize):0); + int startyint=mapscreen_y+(showedges?int(16*mapscreensize):0); + int cx=(x-startxint)/int(16*mapscreensize); + int cy=(y-startyint)/int(16*mapscreensize); + int c=(cy*16)+cx; + + if(!gui_mouse_b()) + canedit=true; + + if(canedit && gui_mouse_b()==1 && isinRect(x,y,startxint,startyint,int(startx+(256*mapscreensize)-1),int(starty+(176*mapscreensize)-1))) + { + saved=false; + + if(CurrentLayer==0) + { + Map.CurrScr()->sflag[c]=Flag; + } + else + { + // Notify if they are using a flag that doesn't work on this layer. + if((Flag >= mfTRAP_H && Flag <= mfNOBLOCKS) || (Flag == mfFAIRY) || (Flag == mfMAGICFAIRY) + || (Flag == mfALLFAIRY) || (Flag == mfRAFT) || (Flag == mfRAFT_BRANCH) + || (Flag == mfDIVE_ITEM) || (Flag == mfARMOS_SECRET) || (Flag == mfNOENEMY) + || (Flag == mfBLOCKHOLE) || (Flag == mfZELDA)) + { + char buf[38]; + sprintf(buf, "You are currently working on layer %d.", CurrentLayer); + jwin_alert("Notice",buf,"This combo flag only functions when placed on layer 0.",NULL,"O&K",NULL,'k',0,lfont); + } + + TheMaps[(Map.CurrScr()->layermap[CurrentLayer-1]-1)*MAPSCRS+(Map.CurrScr()->layerscreen[CurrentLayer-1])].sflag[c]=Flag; + // Map.CurrScr()->sflag[c]=Flag; + } + + refresh(rMAP | rNOCURSOR); + } + + if(mouse_z) + { + for(int i=0; i0) + { + onIncreaseFlag(); + } + else + { + onDecreaseFlag(); + } + } + + position_mouse_z(0); + } + + if(keypressed()) + { + switch(readkey()>>8) + { + case KEY_ESC: + case KEY_ENTER: + goto finished; + + case KEY_ASTERISK: + case KEY_CLOSEBRACE: + onIncreaseFlag(); + break; + + case KEY_SLASH_PAD: + case KEY_OPENBRACE: + onDecreaseFlag(); + break; + + case KEY_UP: + onUp(); + break; + + case KEY_DOWN: + onDown(); + break; + + case KEY_LEFT: + onLeft(); + break; + + case KEY_RIGHT: + onRight(); + break; + + case KEY_PGUP: + onPgUp(); + break; + + case KEY_PGDN: + onPgDn(); + break; + + case KEY_COMMA: + onDecMap(); + break; + + case KEY_STOP: + onIncMap(); + break; + } + + // The cursor could've been overwritten by the Combo Brush? + set_mouse_sprite(mouse_bmp[MOUSE_BMP_FLAG][0]); + } + + do_animations(); + refresh(rALL | rNOCURSOR); + } + +finished: + Flags=of; + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + refresh(rMAP+rMENU); + + while(gui_mouse_b()) + { + /* do nothing */ + } +} + +// Drag FFCs around +void moveffc(int i, int cx, int cy) +{ + int ffx = int(Map.CurrScr()->ffcs[i].x/10000.0); + int ffy = int(Map.CurrScr()->ffcs[i].y/10000.0); + showxypos_ffc = i; + doxypos((byte&)ffx,(byte&)ffy,15,0xFF,true,cx-ffx,cy-ffy,((Map.CurrScr()->ffcs[i].getTileWidth())*16),((Map.CurrScr()->ffcs[i].getTileHeight())*16)); + + if((ffx != int(Map.CurrScr()->ffcs[i].x/10000.0)) || (ffy != int(Map.CurrScr()->ffcs[i].y/10000.0))) + { + Map.CurrScr()->ffcs[i].x = ffx*10000; + Map.CurrScr()->ffcs[i].y = ffy*10000; + saved = false; + } +} + +void set_brush_width(int width); +void set_brush_height(int height); + +int set_brush_width_1() +{ + set_brush_width(1); + return D_O_K; +} +int set_brush_width_2() +{ + set_brush_width(2); + return D_O_K; +} +int set_brush_width_3() +{ + set_brush_width(3); + return D_O_K; +} +int set_brush_width_4() +{ + set_brush_width(4); + return D_O_K; +} +int set_brush_width_5() +{ + set_brush_width(5); + return D_O_K; +} +int set_brush_width_6() +{ + set_brush_width(6); + return D_O_K; +} +int set_brush_width_7() +{ + set_brush_width(7); + return D_O_K; +} +int set_brush_width_8() +{ + set_brush_width(8); + return D_O_K; +} +int set_brush_width_9() +{ + set_brush_width(9); + return D_O_K; +} +int set_brush_width_10() +{ + set_brush_width(10); + return D_O_K; +} +int set_brush_width_11() +{ + set_brush_width(11); + return D_O_K; +} +int set_brush_width_12() +{ + set_brush_width(12); + return D_O_K; +} +int set_brush_width_13() +{ + set_brush_width(13); + return D_O_K; +} +int set_brush_width_14() +{ + set_brush_width(14); + return D_O_K; +} +int set_brush_width_15() +{ + set_brush_width(15); + return D_O_K; +} +int set_brush_width_16() +{ + set_brush_width(16); + return D_O_K; +} + +int set_brush_height_1() +{ + set_brush_height(1); + return D_O_K; +} +int set_brush_height_2() +{ + set_brush_height(2); + return D_O_K; +} +int set_brush_height_3() +{ + set_brush_height(3); + return D_O_K; +} +int set_brush_height_4() +{ + set_brush_height(4); + return D_O_K; +} +int set_brush_height_5() +{ + set_brush_height(5); + return D_O_K; +} +int set_brush_height_6() +{ + set_brush_height(6); + return D_O_K; +} +int set_brush_height_7() +{ + set_brush_height(7); + return D_O_K; +} +int set_brush_height_8() +{ + set_brush_height(8); + return D_O_K; +} +int set_brush_height_9() +{ + set_brush_height(9); + return D_O_K; +} +int set_brush_height_10() +{ + set_brush_height(10); + return D_O_K; +} +int set_brush_height_11() +{ + set_brush_height(11); + return D_O_K; +} + +static MENU brush_width_menu[] = +{ + { (char *)"1", set_brush_width_1, NULL, 0, NULL }, + { (char *)"2", set_brush_width_2, NULL, 0, NULL }, + { (char *)"3", set_brush_width_3, NULL, 0, NULL }, + { (char *)"4", set_brush_width_4, NULL, 0, NULL }, + { (char *)"5", set_brush_width_5, NULL, 0, NULL }, + { (char *)"6", set_brush_width_6, NULL, 0, NULL }, + { (char *)"7", set_brush_width_7, NULL, 0, NULL }, + { (char *)"8", set_brush_width_8, NULL, 0, NULL }, + { (char *)"9", set_brush_width_9, NULL, 0, NULL }, + { (char *)"10", set_brush_width_10, NULL, 0, NULL }, + { (char *)"11", set_brush_width_11, NULL, 0, NULL }, + { (char *)"12", set_brush_width_12, NULL, 0, NULL }, + { (char *)"13", set_brush_width_13, NULL, 0, NULL }, + { (char *)"14", set_brush_width_14, NULL, 0, NULL }, + { (char *)"15", set_brush_width_15, NULL, 0, NULL }, + { (char *)"16", set_brush_width_16, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU brush_height_menu[] = +{ + + { (char *)"1", set_brush_height_1, NULL, 0, NULL }, + { (char *)"2", set_brush_height_2, NULL, 0, NULL }, + { (char *)"3", set_brush_height_3, NULL, 0, NULL }, + { (char *)"4", set_brush_height_4, NULL, 0, NULL }, + { (char *)"5", set_brush_height_5, NULL, 0, NULL }, + { (char *)"6", set_brush_height_6, NULL, 0, NULL }, + { (char *)"7", set_brush_height_7, NULL, 0, NULL }, + { (char *)"8", set_brush_height_8, NULL, 0, NULL }, + { (char *)"9", set_brush_height_9, NULL, 0, NULL }, + { (char *)"10", set_brush_height_10, NULL, 0, NULL }, + { (char *)"11", set_brush_height_11, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +int set_flood(); +int set_fill_4(); +int set_fill_8(); +int set_fill2_4(); +int set_fill2_8(); + +void flood() +{ + // int start=0, w=0, h=0; + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + /* for(int y=0; ydata[i]=Combo; + } + } + + for(int i=0; i<176; i++) + { + Map.AbsoluteScr(drawmap, drawscr)->cset[i]=CSet; + } + + refresh(rMAP+rSCRMAP); +} + +void fill_4() +{ + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + int x=gui_mouse_x()-mapscreen_x-(showedges?(16*mapscreensize):0); + int y=gui_mouse_y()-mapscreen_y-(showedges?(16*mapscreensize):0); + int by= (y>>4)/(mapscreensize); + int bx= (x>>4)/(mapscreensize); + + if(Map.AbsoluteScr(drawmap,drawscr)->cset[(by<<4)+bx]!=CSet || + (Map.AbsoluteScr(drawmap,drawscr)->data[(by<<4)+bx]!=Combo && + !(key[KEY_LSHIFT]||key[KEY_RSHIFT]))) + { + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + fill(Map.AbsoluteScr(drawmap, drawscr), + (Map.AbsoluteScr(drawmap, drawscr)->data[(by<<4)+bx]), + (Map.AbsoluteScr(drawmap, drawscr)->cset[(by<<4)+bx]), bx, by, 255, 0, (key[KEY_LSHIFT]||key[KEY_RSHIFT])); + refresh(rMAP+rSCRMAP); + } +} + +void fill_8() +{ + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + int x=gui_mouse_x()-mapscreen_x-(showedges?(16*mapscreensize):0); + int y=gui_mouse_y()-mapscreen_y-(showedges?(16*mapscreensize):0); + int by= (y>>4)/(mapscreensize); + int bx= (x>>4)/(mapscreensize); + + if(Map.AbsoluteScr(drawmap,drawscr)->cset[(by<<4)+bx]!=CSet || + (Map.AbsoluteScr(drawmap,drawscr)->data[(by<<4)+bx]!=Combo && + !(key[KEY_LSHIFT]||key[KEY_RSHIFT]))) + { + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + fill(Map.AbsoluteScr(drawmap, drawscr), + (Map.AbsoluteScr(drawmap, drawscr)->data[(by<<4)+bx]), + (Map.AbsoluteScr(drawmap, drawscr)->cset[(by<<4)+bx]), bx, by, 255, 1, (key[KEY_LSHIFT]||key[KEY_RSHIFT])); + refresh(rMAP+rSCRMAP); + } +} + +void fill2_4() +{ + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + int x=gui_mouse_x()-mapscreen_x-(showedges?(16*mapscreensize):0); + int y=gui_mouse_y()-mapscreen_y-(showedges?(16*mapscreensize):0);; + int by= (((y&0xF0))>>4)/(mapscreensize); + int bx= (x>>4)/(mapscreensize); + + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + fill2(Map.AbsoluteScr(drawmap, drawscr), Combo, CSet, bx, by, 255, 0, (key[KEY_LSHIFT]||key[KEY_RSHIFT])); + refresh(rMAP+rSCRMAP); +} + +void fill2_8() +{ + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + int x=gui_mouse_x()-mapscreen_x-(showedges?(16*mapscreensize):0); + int y=gui_mouse_y()-mapscreen_y-(showedges?(16*mapscreensize):0);; + int by= (((y&0xF0))>>4)/(mapscreensize); + int bx= (x>>4)/(mapscreensize); + + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + + fill2(Map.AbsoluteScr(drawmap, drawscr), Combo, CSet, bx, by, 255, 1, (key[KEY_LSHIFT]||key[KEY_RSHIFT])); + refresh(rMAP+rSCRMAP); +} + +static MENU fill_menu[] = +{ + { (char *)"Flood", set_flood, NULL, 0, NULL }, + { (char *)"Fill (4-way)", set_fill_4, NULL, 0, NULL }, + { (char *)"Fill (8-way)", set_fill_8, NULL, 0, NULL }, + { (char *)"Fill2 (4-way)", set_fill2_4, NULL, 0, NULL }, + { (char *)"Fill2 (8-way)", set_fill2_8, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +int set_flood() +{ + for(int x=0; x<5; x++) + { + fill_menu[x].flags=0; + } + + fill_menu[0].flags=D_SELECTED; + fill_type=0; + return D_O_K; +} + +int set_fill_4() +{ + for(int x=0; x<5; x++) + { + fill_menu[x].flags=0; + } + + fill_menu[1].flags=D_SELECTED; + fill_type=1; + return D_O_K; +} + +int set_fill_8() +{ + for(int x=0; x<5; x++) + { + fill_menu[x].flags=0; + } + + fill_menu[2].flags=D_SELECTED; + fill_type=2; + return D_O_K; +} + +int set_fill2_4() +{ + for(int x=0; x<5; x++) + { + fill_menu[x].flags=0; + } + + fill_menu[3].flags=D_SELECTED; + fill_type=3; + return D_O_K; +} + +int set_fill2_8() +{ + for(int x=0; x<5; x++) + { + fill_menu[x].flags=0; + } + + fill_menu[4].flags=D_SELECTED; + fill_type=4; + return D_O_K; +} + +int draw_block_1_2() +{ + draw_block(mousecomboposition,1,2); + return D_O_K; +} + +int draw_block_2_1() +{ + draw_block(mousecomboposition,2,1); + return D_O_K; +} + +int draw_block_2_2() +{ + draw_block(mousecomboposition,2,2); + return D_O_K; +} + +int draw_block_2_3() +{ + draw_block(mousecomboposition,2,3); + return D_O_K; +} + +int draw_block_3_2() +{ + draw_block(mousecomboposition,3,2); + return D_O_K; +} + +int draw_block_4_2() +{ + draw_block(mousecomboposition,4,2); + return D_O_K; +} + +int draw_block_4_4() +{ + draw_block(mousecomboposition,4,4); + return D_O_K; +} + +static MENU draw_block_menu[] = +{ + { (char *)"1x2", draw_block_1_2, NULL, 0, NULL }, + { (char *)"2x1", draw_block_2_1, NULL, 0, NULL }, + { (char *)"2x2", draw_block_2_2, NULL, 0, NULL }, + { (char *)"2x3", draw_block_2_3, NULL, 0, NULL }, + { (char *)"3x2", draw_block_3_2, NULL, 0, NULL }, + { (char *)"4x2", draw_block_4_2, NULL, 0, NULL }, + { (char *)"4x4", draw_block_4_4, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU draw_rc_menu[] = +{ + { (char *)"Select Combo", NULL, NULL, 0, NULL }, + { (char *)"Scroll to Combo", NULL, NULL, 0, NULL }, + { (char *)"Edit Combo", NULL, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Replace All", NULL, NULL, 0, NULL }, + { (char *)"Draw Block", NULL, draw_block_menu, 0, NULL }, + { (char *)"Set Brush Width\t ", NULL, brush_width_menu, 0, NULL }, + { (char *)"Set Brush Height\t ", NULL, brush_height_menu, 0, NULL }, + { (char *)"Set Fill Type\t ", NULL, fill_menu, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Follow Tile Warp", NULL, NULL, 0, NULL }, + { (char *)"Edit Tile Warp", NULL, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Place + Edit FFC 1", NULL, NULL, 0, NULL }, + { (char *)"Paste FFC as FFC 1", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU draw_ffc_rc_menu[] = +{ + { (char *)"Copy FFC", NULL, NULL, 0, NULL }, + { (char *)"Paste FFC data", NULL, NULL, 0, NULL }, + { (char *)"Edit FFC", NULL, NULL, 0, NULL }, + { (char *)"Clear FFC", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU combosel_rc_menu[] = +{ + { (char *)"Edit Combo", NULL, NULL, 0, NULL }, + { (char *)"Open Combo Page", NULL, NULL, 0, NULL }, + { (char *)"Open Tile Page", NULL, NULL, 0, NULL }, + { (char *)"Combo Locations", NULL, NULL, 0, NULL }, + { (char *)"", NULL, NULL, 0, NULL }, + { (char *)"Scroll to Page...", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +static MENU fav_rc_menu[] = +{ + { (char *)"Scroll to Combo ", NULL, NULL, 0, NULL }, + { (char *)"Edit Combo ", NULL, NULL, 0, NULL }, + { (char *)"Remove Combo ", NULL, NULL, 0, NULL }, + { NULL, NULL, NULL, 0, NULL } +}; + +void set_brush_width(int width) +{ + for(int x=0; x<16; x++) + { + brush_width_menu[x].flags=0; + } + + BrushWidth=width; + brush_width_menu[width-1].flags=D_SELECTED; + refresh(rALL); +} + +void set_brush_height(int height) +{ + for(int x=0; x<11; x++) + { + brush_height_menu[x].flags=0; + } + + BrushHeight=height; + brush_height_menu[height-1].flags=D_SELECTED; + refresh(rALL); +} + +void restore_mouse() +{ + ComboBrushPause=1; + scare_mouse(); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + unscare_mouse(); +} + +static int comboa_cnt=0; +static int layer_cnt=0; + +static DIALOG clist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_abclist_proc, 72-12-4, 60+4, 176+24+8, 92+3, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 163, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +command_struct bic[cmdMAX]; +int bic_cnt=-1; + +void build_bic_list() +{ + int start=bic_cnt=0; + + for(int i=start; i0 && strcmp(bic[j].s,"")) + { + zc_swap(bic[i],bic[j]); + } + } + } +} + +const char *commandlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = bic_cnt; + return NULL; + } + + return bic[index].s; +} + +int select_command(const char *prompt,int cmd) +{ + if(bic_cnt==-1) + build_bic_list(); + + int index=0; + + for(int j=0; j=0) + { + saved=false; + } + else if(ret == -1) + { + return cmd; + } + + return ret; +} + +int onEditFFCombo(int); + +static char paste_ffc_menu_text[21]; +static char paste_ffc_menu_text2[21]; +static char follow_warp_menu_text[21]; +static char follow_warp_menu_text2[21]; + +void domouse() +{ + static bool mouse_down = false; + static int scrolldelay = 0; + int x=gui_mouse_x(); + int y=gui_mouse_y(); + double startx=mapscreen_x+(showedges?(16*mapscreensize):0); + double starty=mapscreen_y+(showedges?(16*mapscreensize):0); + int startxint=mapscreen_x+(showedges?int(16*mapscreensize):0); + int startyint=mapscreen_y+(showedges?int(16*mapscreensize):0); + int cx=(x-startxint)/int(16*mapscreensize); + int cy=(y-startyint)/int(16*mapscreensize); + int c=(cy*16)+cx; + mousecomboposition=c; + + int redraw=0; + + update_combobrush(); + // put_combo(brushbmp,0,0,Combo,CSet,0,0); + + if(!isinRect(x,y,tooltip_trigger.x,tooltip_trigger.y,tooltip_trigger.x+tooltip_trigger.w-1,tooltip_trigger.y+tooltip_trigger.h-1)) + { + clear_tooltip(); + } + + // For some reason, this causes an invisible cursor in a windowed ZQuest... + /*if(!isinRect(x,y,startxint,startyint,int(startx+(256*mapscreensize)-1),int(starty+(176*mapscreensize)-1))) + { + restore_mouse(); + }*/ + + ++scrolldelay; + + if(MouseScroll && + ( + ((x>=combolist[0].x) && (x=combolist[1].x) && (x=combolist[2].x) && (x=combolist[test_list].x) && (x=combolist[test_list].y-mouse_scroll_h && y<=combolist[test_list].y && First[test_list]) + { + if((key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL])&&(key[KEY_ALT] || key[KEY_ALTGR])) + { + First[test_list]=0; + } + else if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + First[test_list]-=zc_min(First[test_list],256); + } + else if(key[KEY_ALT] || key[KEY_ALTGR]) + { + First[test_list]-=zc_min(First[test_list],(combolist[test_list].w*combolist[test_list].h)); + } + else + { + First[test_list]-=zc_min(First[test_list],combolist[test_list].w); + } + + redraw|=rCOMBOS; + } + + if(y>=combolist[test_list].y+(combolist[test_list].h*16)-1 && y=0; i--) + if(Map.CurrScr()->ffcs[i].data!=0 && (CurrentLayer<2 || (Map.CurrScr()->ffcs[i].flags&ffOVERLAY))) + { + int ffx = int(Map.CurrScr()->ffcs[i].x/10000.0); + int ffy = int(Map.CurrScr()->ffcs[i].y/10000.0); + int cx2 = (x-startxint)/mapscreensize; + int cy2 = (y-startyint)/mapscreensize; + + if(cx2 >= ffx && cx2 < ffx+((Map.CurrScr()->ffcs[i].getTileWidth())*16) && cy2 >= ffy && cy2 < ffy+((Map.CurrScr()->ffcs[i].getTileHeight())*16)) + { + // FFC tooltip + if(tooltip_current_ffc != i) + { + clear_tooltip(); + } + + tooltip_current_ffc = i; + char msg[288]; + sprintf(msg,"FFC: %d Combo: %d\nCSet: %d Type: %s\nScript: %s", + i+1, Map.CurrScr()->ffcs[i].data,Map.CurrScr()->ffcs[i].cset, + combo_class_buf[combobuf[Map.CurrScr()->ffcs[i].data].type].name, + Map.CurrScr()->ffcs[i].script<=0 ? "(None)" : ffcmap[Map.CurrScr()->ffcs[i].script-1].second.c_str()); + update_tooltip(x, y, startxint, startyint, int(256*mapscreensize),int(176*mapscreensize), msg); + break; + } + } + + int drawmap; + int drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + } + } + + if(tooltip_current_combo != c) + { + clear_tooltip(); + } + + tooltip_current_combo = c; + char msg[288]; + memset(msg, 0, 256); + sprintf(msg,"Pos: %d Combo: %d\nCSet: %d Flags: %d, %d\nCombo type: %s", + c, Map.AbsoluteScr(drawmap, drawscr)->data[c], + Map.AbsoluteScr(drawmap, drawscr)->cset[c], Map.CurrScr()->sflag[c],combobuf[Map.CurrScr()->data[c]].flag, + combo_class_buf[combobuf[(Map.AbsoluteScr(drawmap, drawscr)->data[c])].type].name); + update_tooltip(x, y, startxint, startyint, int(256*mapscreensize),int(176*mapscreensize), msg); + } + + if(is_large) + { + for(int j=0; j<4; j++) + { + int xx = panel[8].x+14+(32*j); + int yy = panel[8].y+12; + + if(isinRect(x,y,xx,yy,xx+20,yy+20)) + { + char msg[160]; + sprintf(msg, + j==0 ? "Item Location" : + j==1 ? "Stairs Secret\nTriggered when a Trigger Push Block is pushed." : + j==2 ? "Arrival Square\nLink's location when he begins/resumes the game." : + "Combo Flags"); + update_tooltip(x,y,xx,yy,20,20,msg); + } + } + + // Warp Returns + for(int j=0; j<4; j++) + { + int xx = panel[8].x+14+(32*j); + int yy = panel[8].y+54; + + if(isinRect(x,y,xx,yy,xx+20,yy+20)) + { + char msg[160]; + sprintf(msg,"Warp Return Square %c\nLink's destination after warping to this screen.",(char)('A'+j)); + update_tooltip(x,y,xx,yy,20,20,msg); + } + } + + // Enemies + int epx = 2+panel[8].x+14+4*32; + int epy = 2+panel[8].y+12; + + if(isinRect(x,y,epx,epy,epx+16*4+4,epy+16*3+4)) + { + char msg[160]; + sprintf(msg,"Enemies that appear on this screen."); + update_tooltip(x,y,epx,epy,16*4+4,16*3+4,msg); + } + } + + if(draw_mode!=dm_alias) + { + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + if(isinRect(x,y,combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + int cc=((x-combolist[j].x)>>4); + int cr=((y-combolist[j].y)>>4); + int c2=(cr*combolist[j].w)+cc+First[j]; + char msg[160]; + + if(combobuf[c2].flag != 0) + sprintf(msg, "Combo %d: %s\nInherent flag:%s", c2, combo_class_buf[combobuf[c2].type].name, flag_string[combobuf[c2].flag]); + else + sprintf(msg, "Combo %d: %s", c2, combo_class_buf[combobuf[c2].type].name); + + update_tooltip(x,y,combolist[j].x+(cc<<4),combolist[j].y+(cr<<4),16,16, msg); + } + } + } + } + else + { + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + if(isinRect(x,y,comboaliaslist[j].x,comboaliaslist[j].y,comboaliaslist[j].x+(comboaliaslist[j].w*16)-1,comboaliaslist[j].y+(comboaliaslist[j].h*16)-1)) + { + int cc=((x-comboaliaslist[j].x)>>4); + int cr=((y-comboaliaslist[j].y)>>4); + int c2=(cr*comboaliaslist[j].w)+cc+combo_alistpos[j]; + char msg[80]; + sprintf(msg, "Combo alias %d", c2); + update_tooltip(x,y,comboaliaslist[j].x+(cc<<4),comboaliaslist[j].y+(cr<<4),16,16, msg); + } + } + } + } + + // Mouse clicking stuff + if(gui_mouse_b()==0) + { + mouse_down = false; + canfill=true; + } + else if(gui_mouse_b()&1) + { + //on the map screen + if(isinRect(x,y,startxint,startyint,int(startx+(256*mapscreensize)-1),int(starty+(176*mapscreensize)-1))) + { + int cx2 = (x-startxint)/mapscreensize; + int cy2 = (y-startyint)/mapscreensize; + + // Move items + if(Map.CurrScr()->hasitem) + { + int ix = Map.CurrScr()->itemx; + int iy = Map.CurrScr()->itemy; + + if(cx2 >= ix && cx2 < ix+16 && cy2 >= iy && cy2 < iy+16) + doxypos(Map.CurrScr()->itemx,Map.CurrScr()->itemy,11,0xF8,true,0,0,16,16); + } + + // Move FFCs + for(int i=MAXFFCS-1; i>=0; i--) + if(Map.CurrScr()->ffcs[i].data!=0 && (CurrentLayer<2 || (Map.CurrScr()->ffcs[i].flags&ffOVERLAY))) + { + int ffx = int(Map.CurrScr()->ffcs[i].x/10000.0); + int ffy = int(Map.CurrScr()->ffcs[i].y/10000.0); + + if(cx2 >= ffx && cx2 < ffx+((Map.CurrScr()->ffcs[i].getTileWidth())*16) && cy2 >= ffy && cy2 < ffy+((Map.CurrScr()->ffcs[i].getTileHeight())*16)) + { + moveffc(i,cx2,cy2); + break; + } + } + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + if(canfill) + { + switch(fill_type) + { + case 0: + flood(); + break; + + case 1: + fill_4(); + break; + + case 2: + fill_8(); + break; + + case 3: + fill2_4(); + break; + + case 4: + fill2_8(); + break; + } + + canfill=false; + } + } + else draw(key[KEY_LSHIFT] || key[KEY_RSHIFT]); + } + + //on the map tabs + if(is_large) + { + for(int btn=0; btn<(showedges?9:8); ++btn) + { + char tbuf[10]; + sprintf(tbuf, "%d:%02X", map_page[btn].map+1, map_page[btn].screen); + + if(isinRect(x,y,mapscreen_x+(btn*16*2*mapscreensize),mapscreen_y+((showedges?13:11)*16*mapscreensize),mapscreen_x+(btn*16*2*mapscreensize)+map_page_bar[btn].w,mapscreen_y+((showedges?13:11)*16*mapscreensize)+map_page_bar[btn].h)) + { + if(do_text_button(map_page_bar[btn].x,map_page_bar[btn].y,map_page_bar[btn].w,map_page_bar[btn].h,tbuf,vc(1),vc(14),true)) + { + map_page[current_mappage].map=Map.getCurrMap(); + map_page[current_mappage].screen=Map.getCurrScr(); + current_mappage=btn; + Map.setCurrMap(map_page[current_mappage].map); + Map.setCurrScr(map_page[current_mappage].screen); + } + } + } + } + + //on the drawing mode button + if(is_large) + { + if(isinRect(x,y,combolist_window.x-64,0,combolist_window.x-1,15)) + { + if(do_text_button(combolist_window.x-64,0,64,16,dm_names[draw_mode],vc(1),vc(14),true)) + { + draw_mode=(draw_mode+1)%dm_max; + fix_drawing_mode_menu(); + } + } + } + + //on the minimap + if(isinRect(x,y,minimap.x+3,minimap.y+12,minimap.x+minimap.w-5,minimap.y+minimap.h-4)) + { + select_scr(); + } + + if(is_large) + { + if(isinRect(x,y,panel[8].x+16,panel[8].y+14,panel[8].x+16+15,panel[0].y+14+15)) + { + onItem(); + + if(Map.CurrScr()->hasitem) + doxypos(Map.CurrScr()->itemx,Map.CurrScr()->itemy,11,0xF8); + } + + if(isinRect(x,y,panel[8].x+16+32,panel[8].y+14,panel[8].x+16+32+15,panel[0].y+14+15)) + { + doxypos(Map.CurrScr()->stairx,Map.CurrScr()->stairy,14,0xF0); + } + + if(isinRect(x,y,panel[8].x+16+(32*2),panel[8].y+14,panel[8].x+16+(32*2)+15,panel[8].y+14+15)) + { + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + { + gui->alert("Obsolete square", + "The arrival square is ignored if the quest rule " + "\"Use Warp Return Points Only\" is enabled. It is included " + "only for backwards-compatibility purposes."); + } + + doxypos(Map.CurrScr()->warparrivalx,Map.CurrScr()->warparrivaly,10,0xF8); + } + + if(isinRect(x,y,panel[8].x+16+(32*3),panel[8].y+14,panel[8].x+16+(32*3)+15,panel[8].y+14+15)) + { + onFlags(); + } + + if(isinRect(x,y,panel[8].x+16,panel[8].y+56,panel[8].x+16+15,panel[8].y+56+15)) + { + doxypos(Map.CurrScr()->warpreturnx[0],Map.CurrScr()->warpreturny[0],9,0xF8); + } + + if(isinRect(x,y,panel[8].x+16+32,panel[8].y+56,panel[8].x+16+32+15,panel[8].y+56+15)) + { + doxypos(Map.CurrScr()->warpreturnx[1],Map.CurrScr()->warpreturny[1],9,0xF8); + } + + if(isinRect(x,y,panel[8].x+16+(32*2),panel[8].y+56,panel[8].x+16+(32*2)+15,panel[8].y+56+15)) + { + doxypos(Map.CurrScr()->warpreturnx[2],Map.CurrScr()->warpreturny[2],9,0xF8); + } + + if(isinRect(x,y,panel[8].x+16+(32*3),panel[8].y+56,panel[8].x+16+(32*3)+15,panel[8].y+56+15)) + { + doxypos(Map.CurrScr()->warpreturnx[3],Map.CurrScr()->warpreturny[3],9,0xF8); + } + + int epx = 2+panel[8].x+14+4*32; + int epy = 2+panel[8].y+12; + + if(isinRect(x,y,epx,epy,epx+16*4,epy+16*3)) + { + onEnemies(); + } + } + else + { + if(menutype==m_coords) + { + if(isinRect(x,y,panel[0].x+16,panel[0].y+6,panel[0].x+16+15,panel[0].y+6+15)) + { + onItem(); + + if(Map.CurrScr()->hasitem) + doxypos(Map.CurrScr()->itemx,Map.CurrScr()->itemy,11,0xF8); + } + + if(isinRect(x,y,panel[0].x+48,panel[0].y+6,panel[0].x+48+15,panel[0].y+6+15)) + { + doxypos(Map.CurrScr()->stairx,Map.CurrScr()->stairy,14,0xF0); + } + + if(isinRect(x,y,panel[0].x+80,panel[0].y+6,panel[0].x+80+15,panel[0].y+6+15)) + { + if(get_bit(quest_rules,qr_NOARRIVALPOINT)) + jwin_alert("Obsolete Square","The arrival square is obsolete if you use the", + "'Use Warp Return Points Only' quest rule. It is included", + "only for backwards-compatibility purposes.","O&K",NULL,'k',0,lfont); + + doxypos(Map.CurrScr()->warparrivalx,Map.CurrScr()->warparrivaly,10,0xF8); + } + + if(isinRect(x,y,panel[0].x+112,panel[0].y+6,panel[0].x+112+15,panel[0].y+6+15)) + { + onFlags(); + } + } + + if(menutype==m_coords2) + { + if(isinRect(x,y,panel[7].x+16,panel[7].y+6,panel[7].x+16+15,panel[7].y+6+15)) + { + doxypos(Map.CurrScr()->warpreturnx[0],Map.CurrScr()->warpreturny[0],9,0xF8); + } + + if(isinRect(x,y,panel[7].x+48,panel[7].y+6,panel[7].x+48+15,panel[7].y+6+15)) + { + doxypos(Map.CurrScr()->warpreturnx[1],Map.CurrScr()->warpreturny[1],9,0xF8); + } + + if(isinRect(x,y,panel[7].x+80,panel[7].y+6,panel[7].x+80+15,panel[7].y+6+15)) + { + doxypos(Map.CurrScr()->warpreturnx[2],Map.CurrScr()->warpreturny[2],9,0xF8); + } + + if(isinRect(x,y,panel[7].x+112,panel[7].y+6,panel[7].x+112+15,panel[7].y+6+15)) + { + doxypos(Map.CurrScr()->warpreturnx[3],Map.CurrScr()->warpreturny[3],9,0xF8); + } + } + else if(menutype==m_layers) + { + if(isinRect(x, y, panel[6].x+9,panel[6].y+20,panel[6].x+9+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+9,panel[6].y+20,vc(1),vc(14), LayerMaskInt[0]); + } + + if(isinRect(x, y, panel[6].x+34,panel[6].y+20,panel[6].x+34+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+34,panel[6].y+20,vc(1),vc(14), LayerMaskInt[1]); + } + + if(isinRect(x, y, panel[6].x+59,panel[6].y+20,panel[6].x+59+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+59,panel[6].y+20,vc(1),vc(14), LayerMaskInt[2]); + } + + if(isinRect(x, y, panel[6].x+84,panel[6].y+20,panel[6].x+84+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+84,panel[6].y+20,vc(1),vc(14), LayerMaskInt[3]); + } + + if(isinRect(x, y, panel[6].x+109,panel[6].y+20,panel[6].x+109+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+109,panel[6].y+20,vc(1),vc(14), LayerMaskInt[4]); + } + + if(isinRect(x, y, panel[6].x+134,panel[6].y+20,panel[6].x+134+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+134,panel[6].y+20,vc(1),vc(14), LayerMaskInt[5]); + } + + if(isinRect(x, y, panel[6].x+159,panel[6].y+20,panel[6].x+159+8,panel[6].y+20+8)) + { + do_checkbox(menu1,panel[6].x+159,panel[6].y+20,vc(1),vc(14), LayerMaskInt[6]); + } + + if(isinRect(x, y, panel[6].x+9,panel[6].y+30, panel[6].x+9+(6*25)+8,panel[6].y+30+8)) + { + do_layerradio(menu1,panel[6].x+9,panel[6].y+30,vc(1),vc(14), CurrentLayer); + } + + redraw|=rMENU; + } + } + + if(draw_mode!=dm_alias) + { + for(int temp_counter=0; temp_counter<3; ++temp_counter) + { + int temp_x1=combolistscrollers[temp_counter].x; + int temp_y1=combolistscrollers[temp_counter].y; + int temp_x2=combolistscrollers[temp_counter].x+combolistscrollers[temp_counter].w-1; + int temp_y2=combolistscrollers[temp_counter].y+combolistscrollers[temp_counter].h-2; + + int temp_x3=combolistscrollers[temp_counter].x; + int temp_y3=combolistscrollers[temp_counter].y+combolistscrollers[temp_counter].h-1; + int temp_x4=combolistscrollers[temp_counter].x+combolistscrollers[temp_counter].w-1; + int temp_y4=combolistscrollers[temp_counter].y+combolistscrollers[temp_counter].h*2-3; + + if(is_large) + { + temp_x1=combolistscrollers[temp_counter].x; + temp_y1=combolistscrollers[temp_counter].y; + temp_x2=combolistscrollers[temp_counter].x+combolistscrollers[temp_counter].w-1; + temp_y2=combolistscrollers[temp_counter].y+combolistscrollers[temp_counter].h-1; + + temp_x3=combolistscrollers[temp_counter].x+combolistscrollers[temp_counter].w; + temp_y3=combolistscrollers[temp_counter].y; + temp_x4=combolistscrollers[temp_counter].x+combolistscrollers[temp_counter].w*2-1; + temp_y4=combolistscrollers[temp_counter].y+combolistscrollers[temp_counter].h-1; + } + + if(isinRect(x,y,temp_x1,temp_y1,temp_x2,temp_y2) && First[temp_counter]>0 && !mouse_down) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + First[temp_counter]-=zc_min(First[temp_counter],256); + } + else + { + First[temp_counter]-=zc_min(First[temp_counter],(combolist[0].w*combolist[0].h)); + } + + redraw|=rCOMBOS; + } + else if(isinRect(x,y,temp_x3,temp_y3,temp_x4,temp_y4) && First[temp_counter]<(MAXCOMBOS-(combolist[0].w*combolist[0].h)) && !mouse_down) + { + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + First[temp_counter]+=zc_min((MAXCOMBOS-256)-First[temp_counter],256); + } + else + { + First[temp_counter]+=zc_min((MAXCOMBOS-(combolist[0].w*combolist[0].h))-First[temp_counter],(combolist[0].w*combolist[0].h)); + } + + redraw|=rCOMBOS; + } + } + + if((isinRect(x,y,panel[0].x+panel[0].w-28,panel[0].y+32,panel[0].x+panel[0].w-28+24,panel[0].y+32+5) && menutype==m_block && !mouse_down) || + (isinRect(x,y,panel[6].x+panel[6].w-28,panel[6].y+36,panel[6].x+panel[6].w-28+24,panel[6].y+36+5) && menutype==m_layers && !mouse_down)) + { + CSet=wrap(CSet+1,0,11); + refresh(rCOMBOS+rMENU+rCOMBO); + } + + if(isinRect(x,y,panel[0].x+panel[0].w-32,panel[0].y+39,panel[0].x+panel[0].w-32+28,panel[0].y+39+5) && menutype==m_block && !mouse_down) + { + bool validlayer=false; + + while(!validlayer) + { + CurrentLayer=wrap(CurrentLayer+1,0,6); + + if((CurrentLayer==0)||(Map.CurrScr()->layermap[CurrentLayer-1])) + { + validlayer=true; + } + } + + refresh(rMENU); + } + + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + if(isinRect(x,y,combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + select_combo(j); + } + } + } + } + else + { + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + if(isinRect(x,y,comboaliaslist[j].x,comboaliaslist[j].y,comboaliaslist[j].x+(comboaliaslist[j].w*16)-1,comboaliaslist[j].y+(comboaliaslist[j].h*16)-1)) + { + select_comboa(j); + } + } + } + } + + //on the favorites list + if(isinRect(x,y,favorites_list.x,favorites_list.y,favorites_list.x+(favorites_list.w*16)-1,favorites_list.y+(favorites_list.h*16)-1)) + { + int row=vbound(((y-favorites_list.y)>>4),0,favorites_list.h-1); + int col=vbound(((x-favorites_list.x)>>4),0,favorites_list.w-1); + int f=(row*favorites_list.w)+col; + + if(key[KEY_LSHIFT] || key[KEY_RSHIFT] || + (draw_mode==dm_alias?favorite_comboaliases:favorite_combos)[f]==-1) + { + int tempcb=ComboBrush; + ComboBrush=0; + + while(gui_mouse_b()) + { + x=gui_mouse_x(); + y=gui_mouse_y(); + + if(draw_mode != dm_alias) + { + if(favorite_combos[f]!=Combo) + { + favorite_combos[f]=Combo; + saved=false; + } + } + else + { + if(favorite_comboaliases[f]!=combo_apos) + { + favorite_comboaliases[f]=combo_apos; + saved=false; + } + } + + do_animations(); + refresh(rALL | rFAVORITES); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + + ComboBrush=tempcb; + } + else if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + int tempcb=ComboBrush; + ComboBrush=0; + + while(gui_mouse_b()) + { + x=gui_mouse_x(); + y=gui_mouse_y(); + + if(draw_mode != dm_alias) + { + if(favorite_combos[f]!=-1) + { + favorite_combos[f]=-1; + saved=false; + } + } + else + { + if(favorite_comboaliases[f]!=-1) + { + favorite_comboaliases[f]=-1; + saved=false; + } + } + + do_animations(); + refresh(rALL | rFAVORITES); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + + ComboBrush=tempcb; + } + else + { + select_favorite(); + } + } + + //on the commands buttons + if(is_large /*&& rALL&rCOMMANDS*/) //do we really need to check that? + { + for(int cmd=0; cmd<(commands_list.w*commands_list.h); ++cmd) + { + int check_x=(cmd%commands_list.w)*command_buttonwidth+commands_list.x; + int check_y=(cmd/commands_list.w)*command_buttonheight+commands_list.y; + bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]); + bool ctrl=(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]); + + if(isinRect(x,y,check_x,check_y,check_x+command_buttonwidth,check_y+command_buttonheight)&&(commands[favorite_commands[cmd]].flags!=D_DISABLED||(shift||ctrl))) + { + FONT *tfont=font; + font=pfont; + + if(do_text_button_reset(check_x,check_y,command_buttonwidth, command_buttonheight, favorite_commands[cmd]==cmdCatchall&&strcmp(catchall_string[Map.CurrScr()->room]," ")?catchall_string[Map.CurrScr()->room]:commands[favorite_commands[cmd]].name,vc(1),vc(14),true)) + { + if(ctrl) + { + favorite_commands[cmd]=0; + } + else if(shift || favorite_commands[cmd]==0) + { + favorite_commands[cmd]=onCommand(favorite_commands[cmd]); + } + else + { + font=tfont; + int (*pfun)(); + pfun=commands[favorite_commands[cmd]].command; + pfun(); + } + } + + font=tfont; + } + } + } + + // On the layer panel + if(is_large) + { + for(int i=0; i<=6; ++i) + { + int rx = (i * (layerpanel_buttonwidth+23)) + layer_panel.x+6; + int ry = layer_panel.y+16; + + if((i==0 || Map.CurrScr()->layermap[i-1]) && isinRect(x,y,rx,ry,rx+layerpanel_buttonwidth-1,ry+layerpanel_buttonheight-1)) + { + char tbuf[15]; + + if(i!=0 && Map.CurrScr()->layermap[i-1]) + { + sprintf(tbuf, "%s%d (%d:%02X)", + (i==2 && Map.CurrScr()->flags7&fLAYER2BG) || (i==3 && Map.CurrScr()->flags7&fLAYER3BG) ? "-":"", + i, Map.CurrScr()->layermap[i-1], Map.CurrScr()->layerscreen[i-1]); + } + else + { + sprintf(tbuf, "%d", i); + } + + if(do_text_button(rx, ry, layerpanel_buttonwidth, layerpanel_buttonheight, tbuf,vc(1),vc(14),true)) + { + CurrentLayer = i; + } + } + + if(isinRect(x,y,rx+layerpanel_buttonwidth+4,ry+2,rx+layerpanel_buttonwidth+12,ry+10)) + do_checkbox(menu1,rx+layerpanel_buttonwidth+4,ry+2,vc(1),vc(14), LayerMaskInt[i]); + } + } + + mouse_down = true; + } + else if(gui_mouse_b()&2) + { + if(isinRect(x,y,startxint,startyint, int(startx+(256*mapscreensize)-1), int(starty+(176*mapscreensize)-1))) + { + ComboBrushPause=1; + refresh(rMAP); + restore_mouse(); + ComboBrushPause=0; + + bool clickedffc = false; + int earliestfreeffc = MAXFFCS; + + // FFC right-click menu + // This loop also serves to find the free ffc with the smallest slot number. + for(int i=MAXFFCS-1; i>=0; i--) + { + if(Map.CurrScr()->ffcs[i].data==0 && i < earliestfreeffc) + earliestfreeffc = i; + + if(clickedffc || !(Map.CurrScr()->valid&mVALID)) + continue; + + if(Map.CurrScr()->ffcs[i].data!=0 && (CurrentLayer<2 || (Map.CurrScr()->ffcs[i].flags&ffOVERLAY))) + { + int ffx = int(Map.CurrScr()->ffcs[i].x/10000.0); + int ffy = int(Map.CurrScr()->ffcs[i].y/10000.0); + int cx2 = (x-startxint)/mapscreensize; + int cy2 = (y-startyint)/mapscreensize; + + if(cx2 >= ffx && cx2 < ffx+((Map.CurrScr()->ffcs[i].getTileWidth())*16) && cy2 >= ffy && cy2 < ffy+((Map.CurrScr()->ffcs[i].getTileHeight())*16)) + { + draw_ffc_rc_menu[1].flags = (Map.getCopyFFC()>-1) ? 0 : D_DISABLED; + + int m = popup_menu(draw_ffc_rc_menu,x,y); + + switch(m) + { + case 0: + Map.CopyFFC(i); + break; + + case 1: // Paste Copied FFC + { + if(jwin_alert("Confirm Paste","Really replace the FFC with","the data of the copied FFC?",NULL,"&Yes","&No",'y','n',lfont)==1) + { + Map.PasteOneFFC(i); + saved=false; + } + } + break; + + case 2: + onEditFFCombo(i); + break; + + case 3: + if(jwin_alert("Confirm Clear","Really clear this Freeform Combo?",NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + Map.CurrScr()->ffcs[i].clear(); + + for(int j=0; j<8; j++) + Map.CurrScr()->ffcs[i].initd[j] = 0; + + for(int j=0; j<2; j++) + Map.CurrScr()->ffcs[i].inita[j] = 10000; + + saved = false; + } + + break; + } + + clickedffc = true; + break; + } + } + + } + + // Combo right-click menu + if(!clickedffc) + { + // FFC-specific options + if(earliestfreeffc < MAXFFCS) + { + sprintf(paste_ffc_menu_text, "Place + Edit FFC %d",earliestfreeffc+1); + sprintf(paste_ffc_menu_text2,"Paste FFC as FFC %d",earliestfreeffc+1); + draw_rc_menu[13].text = paste_ffc_menu_text; + draw_rc_menu[13].flags = 0; + + if(Map.getCopyFFC()>-1) + { + draw_rc_menu[14].text = paste_ffc_menu_text2; + draw_rc_menu[14].flags = 0; + } + else draw_rc_menu[14].flags = D_DISABLED; + } + else + { + draw_rc_menu[13].text = (char*)"Place + Edit FFC"; + draw_rc_menu[14].text = (char*)"Paste FFC"; + draw_rc_menu[14].flags = draw_rc_menu[13].flags = D_DISABLED; + } + + int warpindex = Map.warpindex(Map.AbsoluteScr(Map.getCurrMap(), Map.getCurrScr())->data[c]); + + if(warpindex > -1) + { + sprintf(follow_warp_menu_text, "Follow Tile Warp %c",warpindex==4 ? 'R' : 'A'+warpindex); + sprintf(follow_warp_menu_text2,"Edit Tile Warp %c",warpindex==4 ? 'R' : 'A'+warpindex); + draw_rc_menu[10].text = follow_warp_menu_text; + draw_rc_menu[11].text = follow_warp_menu_text2; + draw_rc_menu[10].flags = draw_rc_menu[11].flags = 0; + } + else + { + draw_rc_menu[10].text = (char*)"Follow Tile Warp"; + draw_rc_menu[11].text = (char*)"Edit Tile Warp"; + draw_rc_menu[11].flags = draw_rc_menu[10].flags = D_DISABLED; + } + + int m = popup_menu(draw_rc_menu,x,y); + + switch(m) + { + case 0: + case 1: + { + int drawmap, drawscr; + + if(CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + if(m==0) + { + Combo=Map.AbsoluteScr(drawmap, drawscr)->data[c]; + } + + if(m==1||(key[KEY_LSHIFT]||key[KEY_RSHIFT])) + { + First[current_combolist]=vbound((Map.AbsoluteScr(drawmap, drawscr)->data[c]/combolist[0].w*combolist[0].w)-(combolist[0].w*combolist[0].h/2),0,MAXCOMBOS-(combolist[0].w*combolist[0].h)); + } + } + break; + + case 2: + { + int drawmap, drawscr; + + if(CurrentLayer==0) + { + + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + + if(drawmap<0) + { + return; + } + } + + edit_combo(Map.AbsoluteScr(drawmap, drawscr)->data[c],true,Map.AbsoluteScr(drawmap, drawscr)->cset[c]); + } + break; + + case 4: + replace(c); + break; + + case 10: // Follow Tile Warp + { + if(warpindex>=4) + { + jwin_alert("Random Tile Warp","This is a random tile warp combo, so it chooses","randomly between the screen's four Tile Warps.",NULL,"O&K",NULL,'k',0,lfont); + warpindex=rand()&3; + } + + int tm = Map.getCurrMap(); + int ts = Map.getCurrScr(); + int wt = Map.CurrScr()->tilewarptype[warpindex]; + + if(wt==wtCAVE || wt==wtNOWARP) + { + char buf[56]; + sprintf(buf,"This screen's Tile Warp %c is set to %s,",'A'+warpindex,warptype_string[wt]); + jwin_alert(warptype_string[wt],buf,"so it doesn't lead to another screen.",NULL,"O&K",NULL,'k',0,lfont); + break; + break; + } + + Map.dowarp(0,warpindex); + + if(ts!=Map.getCurrScr() || tm!=Map.getCurrMap()) + { + FlashWarpSquare = (TheMaps[tm*MAPSCRS+ts].warpreturnc>>(warpindex*2))&3; + FlashWarpClk = 32; + } + + break; + } + + case 11: // Edit Tile Warp + { + if(warpindex>=4) + { + jwin_alert("Random Tile Warp","This is a random tile warp combo, so it chooses","randomly between the screen's four Tile Warps.",NULL,"O&K",NULL,'k',0,lfont); + warpindex=0; + } + + if(warpindex > -1 && warpindex < 4) + onTileWarpIndex(warpindex); + + break; + } + + case 13: + { + Map.CurrScr()->ffcs[earliestfreeffc].x = (((x-startxint)&(~0x000F))/mapscreensize)*10000; + Map.CurrScr()->ffcs[earliestfreeffc].y = (((y-startyint)&(~0x000F))/mapscreensize)*10000; + Map.CurrScr()->ffcs[earliestfreeffc].data = Combo; + Map.CurrScr()->ffcs[earliestfreeffc].cset = CSet; + onEditFFCombo(earliestfreeffc); + } + break; + + case 14: + { + Map.CurrScr()->ffcs[earliestfreeffc].x = (((x-startxint)&(~0x000F))/mapscreensize)*10000; + Map.CurrScr()->ffcs[earliestfreeffc].y = (((y-startyint)&(~0x000F))/mapscreensize)*10000; + Map.PasteOneFFC(earliestfreeffc); + } + break; + + default: + break; + } + } + } + + for(int j=0; j<3; ++j) + { + if(j==0||is_large) + { + if(draw_mode != dm_alias) + { + if(isinRect(x,y,combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + select_combo(j); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + int m = popup_menu(combosel_rc_menu,x,y); + + switch(m) + { + case 0: + reset_combo_animations(); + reset_combo_animations2(); + edit_combo(Combo,true,CSet); + setup_combo_animations(); + setup_combo_animations2(); + redraw|=rALL; + break; + + case 1: + combo_screen(Combo>>8,Combo); + redraw|=rALL; + break; + + case 2: + { + int t = combobuf[Combo].tile; + int f = 0; + select_tile(t,f,0,CSet,true); + redraw|=rALL; + break; + } + + case 3: + onComboLocationReport(); + break; + + case 5: + { + onGotoPage(); + redraw|=rALL; + break; + } + break; + } + } + } + } + else + { + if(isinRect(x,y,comboaliaslist[j].x,comboaliaslist[j].y,comboaliaslist[j].x+(comboaliaslist[j].w*16)-1,comboaliaslist[j].y+(comboaliaslist[j].h*16)-1)) + { + select_comboa(j); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + comboa_cnt = combo_apos; + onEditComboAlias(); + redraw|=rALL; + } + } + } + } + } + + // Right click main panel + if(is_large) + { + if(isinRect(x,y,panel[8].x+16,panel[8].y+14,panel[8].x+16+15,panel[0].y+14+15)) + { + onItem(); + } + } + else + { + if(menutype==m_coords) + { + if(isinRect(x,y,panel[0].x+16,panel[0].y+6,panel[0].x+16+15,panel[0].y+6+15)) + { + onItem(); + } + } + } + + if((isinRect(x,y,panel[0].x+panel[0].w-28,panel[0].y+32,panel[0].x+panel[0].w-28+24,panel[0].y+32+5) && menutype==m_block && !mouse_down) || + (isinRect(x,y,panel[6].x+panel[6].w-28,panel[6].y+36,panel[6].x+panel[6].w-28+24,panel[6].y+36+5) && menutype==m_layers && !mouse_down)) + { + CSet=wrap(CSet-1,0,11); + refresh(rCOMBOS+rMENU+rCOMBO); + } + + if(isinRect(x,y,panel[0].x+panel[0].w-32,panel[0].y+39,panel[0].x+panel[0].w-32+28,panel[0].y+39+5) && menutype==m_block && !mouse_down) + { + bool validlayer=false; + + while(!validlayer) + { + CurrentLayer=wrap(CurrentLayer-1,0,6); + + if((CurrentLayer==0)||(Map.CurrScr()->layermap[CurrentLayer-1])) + { + validlayer=true; + } + } + + refresh(rMENU); + } + + if(is_large) + { + for(int cmd=0; cmd<(commands_list.w*commands_list.h); ++cmd) + { + int check_x=(cmd%commands_list.w)*command_buttonwidth+commands_list.x; + int check_y=(cmd/commands_list.w)*command_buttonheight+commands_list.y; + + if(isinRect(x,y,check_x,check_y,check_x+command_buttonwidth,check_y+command_buttonheight)) + { + FONT *tfont=font; + font=pfont; + + if(do_text_button_reset(check_x,check_y,command_buttonwidth, command_buttonheight, favorite_commands[cmd]==cmdCatchall&&strcmp(catchall_string[Map.CurrScr()->room]," ")?catchall_string[Map.CurrScr()->room]:commands[favorite_commands[cmd]].name,vc(1),vc(14),true)) + { + favorite_commands[cmd]=onCommand(favorite_commands[cmd]); + } + + font=tfont; + } + } + } + + if(isinRect(x,y,favorites_list.x,favorites_list.y,favorites_list.x+(favorites_list.w*16)-1,favorites_list.y+(favorites_list.h*16)-1)) + { + bool valid=select_favorite(); + + if(valid) + { + if(isinRect(gui_mouse_x(),gui_mouse_y(),favorites_list.x,favorites_list.y,favorites_list.x+(favorites_list.w*16)-1,favorites_list.y+(favorites_list.h*16)-1)) + { + int m = popup_menu(fav_rc_menu,x,y); + int row=vbound(((y-favorites_list.y)>>4),0,favorites_list.h-1); + int col=vbound(((x-favorites_list.x)>>4),0,favorites_list.w-1); + int f=(row*favorites_list.w)+col; + + switch(m) + { + case 0: + First[current_combolist]=vbound((Combo/combolist[0].w*combolist[0].w)-(combolist[0].w*combolist[0].h/2),0,MAXCOMBOS-(combolist[0].w*combolist[0].h)); + break; + + case 1: + if(draw_mode != dm_alias) + { + reset_combo_animations(); + reset_combo_animations2(); + edit_combo(Combo,true,CSet); + setup_combo_animations(); + setup_combo_animations2(); + } + else + { + comboa_cnt = combo_apos; + onEditComboAlias(); + } + + redraw|=rALL; + break; + + case 2: + if(draw_mode != dm_alias) + { + favorite_combos[f]=-1; + } + else + { + favorite_comboaliases[f]=-1; + } + + break; + } + } + } + } + + mouse_down = true; + } + else if(gui_mouse_b()&4) //not sure what to do here yet + { + } + + if(mouse_z!=0) + { + int z=0; + + for(int j=0; j<3; ++j) + { + z=abs(mouse_z); + + if(key[KEY_ALT]||key[KEY_ALTGR]) + { + z*=combolist[j].h; + } + + if(j==0||is_large) + { + if(draw_mode != dm_alias) + { + if(isinRect(x,y,combolist[j].x,combolist[j].y,combolist[j].x+(combolist[j].w*16)-1,combolist[j].y+(combolist[j].h*16)-1)) + { + if(mouse_z<0) //scroll down + { + First[current_combolist] = zc_min(MAXCOMBOS-combolist[j].w*combolist[j].h, + First[current_combolist] + combolist[j].w*z); + redraw|=rALL; + } + else //scroll up + { + if(First[current_combolist]>0) + { + First[current_combolist]-=zc_min(First[current_combolist],combolist[j].w*z); + // refresh(rCOMBOS); + redraw|=rALL; + } + } + } + } + else + { + if(isinRect(x,y,comboaliaslist[j].x,comboaliaslist[j].y,comboaliaslist[j].x+(comboaliaslist[j].w*16)-1,comboaliaslist[j].y+(comboaliaslist[j].h*16)-1)) + { + if(mouse_z<0) //scroll down + { + combo_alistpos[current_comboalist] = zc_min(MAXCOMBOALIASES - comboaliaslist[j].w*comboaliaslist[j].h, + combo_alistpos[current_comboalist]+comboaliaslist[j].w*z); + redraw|=rALL; + } + else //scroll up + { + if(combo_alistpos[current_comboalist]>0) + { + combo_alistpos[current_comboalist]-=zc_min(combo_alistpos[current_comboalist],comboaliaslist[j].w*z); + // refresh(rCOMBOS); + redraw|=rALL; + } + } + } + } + } + } + + z=abs(mouse_z); + + if((!is_large && isinRect(x,y,minimap.x,minimap.y+8,minimap.x+63,minimap.y+8+35)) || + (is_large && isinRect(x,y,minimap.x,minimap.y+8,minimap.x+145,minimap.y+8+85))) + { + for(int i=0; i0) onIncMap(); + else onDecMap(); + } + } + + if(isinRect(x,y,panel[0].x,panel[0].y,panel[0].x+191,panel[0].y+47) && !is_large) + { + for(int i=0; i0) + { + onPgUp(); + } + else + { + onPgDn(); + } + } + } + + position_mouse_z(0); + } +} + +int onShowPal() +{ + PaletteViewer pv; + gui->showDialog(pv); + return D_O_K; +} + +static DIALOG csetfix_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 80, 176+1, 96+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "CSet Fix", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_radio_proc, 104+22, 108, 80+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Full Screen", NULL, NULL }, + { jwin_radio_proc, 104+22, 118+2, 80+1, 8+1, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Dungeon Floor", NULL, NULL }, + { d_dummy_proc, 120, 128, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 104+22, 128+4, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "All Layers", NULL, NULL }, + { jwin_button_proc, 90, 152, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 152, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onCSetFix() +{ + restore_mouse(); + csetfix_dlg[0].dp2=lfont; + int s=2,x2=14,y2=9; + + if(is_large) + large_dialog(csetfix_dlg); + + if(zc_popup_dialog(csetfix_dlg,-1)==6) + { + Map.Ugo(); + + if(csetfix_dlg[2].flags&D_SELECTED) + { + s=0; + x2=16; + y2=11; + } + + if(csetfix_dlg[5].flags&D_SELECTED) + { + /* + int drawmap, drawscr; + if (CurrentLayer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + drawmap=Map.CurrScr()->layermap[CurrentLayer-1]-1; + drawscr=Map.CurrScr()->layerscreen[CurrentLayer-1]; + if (drawmap<0) + { + return; + } + } + + saved=false; + Map.Ugo(); + + if(!(Map.AbsoluteScr(drawmap, drawscr)->valid&mVALID)) + { + Map.CurrScr()->valid|=mVALID; + Map.AbsoluteScr(drawmap, drawscr)->valid|=mVALID; + Map.setcolor(Color); + } + for(int i=0; i<176; i++) + { + Map.AbsoluteScr(drawmap, drawscr)->data[i]=Combo; + Map.AbsoluteScr(drawmap, drawscr)->cset[i]=CSet; + } + refresh(rMAP+rSCRMAP); + */ + } + + for(int y=s; ycset[(y<<4)+x] = CSet; + } + } + + refresh(rMAP); + saved = false; + } + + return D_O_K; +} + +static DIALOG template_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 80, 176+1, 116+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "NES Dungeon Template", NULL, NULL }, + { d_comboframe_proc, 178, 122+3, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 180, 124+3, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // { d_bitmap_proc, 180, 104, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_radio_proc, 104+33, 128+3, 64+1, 8+1, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Floor:", NULL, NULL }, + { jwin_radio_proc, 104+33, 148+3, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "No Floor", NULL, NULL }, + { jwin_button_proc, 90, 172, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 172, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 104, 102, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "This copies the contents of", NULL, NULL }, + { jwin_text_proc, 104, 112, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "screen 83 of the current map.", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onTemplate() +{ + static bool donethis=false; + + if(!donethis||!(key[KEY_LSHIFT]||key[KEY_RSHIFT])) + { + template_dlg[2].d1=Combo; + template_dlg[2].fg=CSet; + donethis=true; + } + + restore_mouse(); + + if(Map.getCurrScr()==TEMPLATE) + return D_O_K; + + // BITMAP *floor_bmp = create_bitmap_ex(8,16,16); + // if(!floor_bmp) return D_O_K; + template_dlg[0].dp2=lfont; + // put_combo(floor_bmp,0,0,Combo,CSet,0,0); + // template_dlg[2].dp=floor_bmp; + + if(is_large) + large_dialog(template_dlg); + + if(zc_popup_dialog(template_dlg,-1)==5) + { + saved=false; + Map.Ugo(); + Map.Template((template_dlg[3].flags==D_SELECTED) ? template_dlg[2].d1 : -1, template_dlg[2].fg); + refresh(rMAP+rSCRMAP); + } + + // destroy_bitmap(floor_bmp); + return D_O_K; +} + +static DIALOG cpage_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 20, 176+1, 212+1, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ctext_proc, 160, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Combo Page", NULL, NULL }, + { jwin_button_proc, 90, 182, 61, 21, vc(14), vc(1), 's', D_EXIT, 0, 0, (void *) "&Set", NULL, NULL }, + { jwin_button_proc, 170, 182, 61, 21, vc(14), vc(1), 'c', D_EXIT, 0, 0, (void *) "&Cancel", NULL, NULL }, + { jwin_button_proc, 90, 210, 61, 21, vc(14), vc(1), 'a', D_EXIT, 0, 0, (void *) "Set &All", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + // 6 + { jwin_radio_proc, 76, 44, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "0" , NULL, NULL }, + { jwin_radio_proc, 76, 52, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "1" , NULL, NULL }, + { jwin_radio_proc, 76, 60, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "2" , NULL, NULL }, + { jwin_radio_proc, 76, 68, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "3" , NULL, NULL }, + { jwin_radio_proc, 76, 76, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "4" , NULL, NULL }, + { jwin_radio_proc, 76, 84, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "5" , NULL, NULL }, + { jwin_radio_proc, 76, 92, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "6" , NULL, NULL }, + { jwin_radio_proc, 76, 100, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "7" , NULL, NULL }, + { jwin_radio_proc, 76, 108, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "8" , NULL, NULL }, + { jwin_radio_proc, 76, 116, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "9" , NULL, NULL }, + { jwin_radio_proc, 76, 124, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "10" , NULL, NULL }, + { jwin_radio_proc, 76, 132, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "11" , NULL, NULL }, + { jwin_radio_proc, 76, 140, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "12" , NULL, NULL }, + { jwin_radio_proc, 76, 148, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "13" , NULL, NULL }, + { jwin_radio_proc, 76, 156, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "14" , NULL, NULL }, + { jwin_radio_proc, 76, 164, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "15" , NULL, NULL }, + { jwin_radio_proc, 120, 44, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "16" , NULL, NULL }, + { jwin_radio_proc, 120, 52, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "17" , NULL, NULL }, + { jwin_radio_proc, 120, 60, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "18" , NULL, NULL }, + { jwin_radio_proc, 120, 68, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "19" , NULL, NULL }, + { jwin_radio_proc, 120, 76, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "20" , NULL, NULL }, + { jwin_radio_proc, 120, 84, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "21" , NULL, NULL }, + { jwin_radio_proc, 120, 92, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "22" , NULL, NULL }, + { jwin_radio_proc, 120, 100, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "23" , NULL, NULL }, + { jwin_radio_proc, 120, 108, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "24" , NULL, NULL }, + { jwin_radio_proc, 120, 116, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "25" , NULL, NULL }, + { jwin_radio_proc, 120, 124, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "26" , NULL, NULL }, + { jwin_radio_proc, 120, 132, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "27" , NULL, NULL }, + { jwin_radio_proc, 120, 140, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "28" , NULL, NULL }, + { jwin_radio_proc, 120, 148, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "29" , NULL, NULL }, + { jwin_radio_proc, 120, 156, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "30" , NULL, NULL }, + { jwin_radio_proc, 120, 164, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "31" , NULL, NULL }, + { jwin_radio_proc, 164, 44, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "32" , NULL, NULL }, + { jwin_radio_proc, 164, 52, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "33" , NULL, NULL }, + { jwin_radio_proc, 164, 60, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "34" , NULL, NULL }, + { jwin_radio_proc, 164, 68, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "35" , NULL, NULL }, + { jwin_radio_proc, 164, 76, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "36" , NULL, NULL }, + { jwin_radio_proc, 164, 84, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "37" , NULL, NULL }, + { jwin_radio_proc, 164, 92, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "38" , NULL, NULL }, + { jwin_radio_proc, 164, 100, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "39" , NULL, NULL }, + { jwin_radio_proc, 164, 108, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "40" , NULL, NULL }, + { jwin_radio_proc, 164, 116, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "41" , NULL, NULL }, + { jwin_radio_proc, 164, 124, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "42" , NULL, NULL }, + { jwin_radio_proc, 164, 132, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "43" , NULL, NULL }, + { jwin_radio_proc, 164, 140, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "44" , NULL, NULL }, + { jwin_radio_proc, 164, 148, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "45" , NULL, NULL }, + { jwin_radio_proc, 164, 156, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "46" , NULL, NULL }, + { jwin_radio_proc, 164, 164, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "47" , NULL, NULL }, + { jwin_radio_proc, 208, 44, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "48" , NULL, NULL }, + { jwin_radio_proc, 208, 52, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "49" , NULL, NULL }, + { jwin_radio_proc, 208, 60, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "50" , NULL, NULL }, + { jwin_radio_proc, 208, 68, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "51" , NULL, NULL }, + { jwin_radio_proc, 208, 76, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "52" , NULL, NULL }, + { jwin_radio_proc, 208, 84, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "53" , NULL, NULL }, + { jwin_radio_proc, 208, 92, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "54" , NULL, NULL }, + { jwin_radio_proc, 208, 100, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "55" , NULL, NULL }, + { jwin_radio_proc, 208, 108, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "56" , NULL, NULL }, + { jwin_radio_proc, 208, 116, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "57" , NULL, NULL }, + { jwin_radio_proc, 208, 124, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "58" , NULL, NULL }, + { jwin_radio_proc, 208, 132, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "59" , NULL, NULL }, + { jwin_radio_proc, 208, 140, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "60" , NULL, NULL }, + { jwin_radio_proc, 208, 148, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "61" , NULL, NULL }, + { jwin_radio_proc, 208, 156, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "62" , NULL, NULL }, + { jwin_radio_proc, 208, 164, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "63" , NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onComboPage() +{ + for(int i=0; i<64; i++) + cpage_dlg[i+6].flags = Map.CurrScr()->old_cpage==i?D_SELECTED:0; + + int ret = zc_popup_dialog(cpage_dlg,3); + + int p = 0; + + for(int i=0; i<64; i++) + + if(cpage_dlg[i+6].flags==D_SELECTED) + p=i; + + if(ret==2) + { + saved=false; + Map.CurrScr()->old_cpage = p; + } + + if(ret==4 && jwin_alert("Confirm Overwrite","Set all combo pages","on this map?",NULL,"&Yes","&No",'y','n',lfont)==1) + { + saved=false; + + for(int i=0; i<=TEMPLATE; i++) + Map.Scr(i)->old_cpage = p; + } + + refresh(rALL); + return D_O_K; +} + +int d_sel_scombo_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + while(gui_mouse_b()) + { + int x = zc_min(zc_max(gui_mouse_x() - d->x,0)>>4, 15); + int y = zc_min(zc_max(gui_mouse_y() - d->y,0)&0xF0, 160); + + if(x+y != d->d1) + { + d->d1 = x+y; + custom_vsync(); + scare_mouse(); + d_sel_scombo_proc(MSG_DRAW,d,0); + unscare_mouse(); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + } + + break; + + case MSG_DRAW: + { + blit((BITMAP*)(d->dp),screen,0,0,d->x,d->y,d->w,d->h); + int x = d->x + (((d->d1)&15)<<4); + int y = d->y + ((d->d1)&0xF0); + rect(screen,x,y,x+15,y+15,vc(15)); + } + break; + } + + return D_O_K; +} + +/* +static DIALOG sel_scombo_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 24, 16, 272+1, 216+1, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_sel_scombo_proc, 32, 24, 256, 176, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 208, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 208, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void select_scombo(int &pos) +{ + go(); + Map.draw_template2(screen2,0,0); + sel_scombo_dlg[1].dp = screen2; + sel_scombo_dlg[1].d1 = pos; + + while (gui_mouse_b()) { + //nothing + } + + if(zc_do_dialog(sel_scombo_dlg,3)==2) + pos = sel_scombo_dlg[1].d1; + + comeback(); +} +*/ + +static DIALOG cflag_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_abclist_proc, 72-12-4, 60+4, 176+24+8, 92+3, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 70, 163, 51, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 190, 163, 51, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_button_proc, 130, 163, 51, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Help", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +void ctype_help(int id) +{ + if(id < 0 || id >= cMAX) return; // Sanity check + + if(id==0) + { + jwin_alert("Help","Select a Type, then click","this button to find out what it does.",NULL,"O&K",NULL,'k',0,lfont); + } + else if(id >= cCVUP && id <= cCVRIGHT) + { + char buf1[80]; + sprintf(buf1,"be moved %sward at 1/4 of his normal walking",id==cCVUP ? "up" : id==cCVDOWN ? "down" : id==cCVLEFT ? "left" : "right"); + jwin_alert(combo_class_buf[id].name,"While Link is standing on top of this, he will",buf1,"speed, until he collides with a solid combo.","O&K",NULL,'k',0,lfont); + } + else if((id >= cDAMAGE1 && id <= cDAMAGE4) || (id >= cDAMAGE5 && id <= cDAMAGE7)) + { + char buf1[80]; + int lvl = (id < cDAMAGE5 ? (id - cDAMAGE1 + 1) : (id - cDAMAGE5 + 1)); + sprintf(buf1,"that protect against Damage Combo Level %d,",lvl); + char buf2[80]; + int d = -combo_class_buf[id].modify_hp_amount/8; + + if(d==1) + sprintf(buf2,"he is damaged for 1/2 of a heart."); + else + sprintf(buf2,"he is damaged for %d heart%s.", d/2, d == 2 ? "" : "s"); + + jwin_alert(combo_class_buf[id].name,"If Link touches this combo without Boots",buf1,buf2, "O&K",NULL,'k',0,lfont); + } + else if(id >= cSLASHTOUCHY && id <= cBUSHNEXTTOUCHY) + { + char buf1[80]; + sprintf(buf1,"Identical to %s, but if slashing this combo",combotype_help_string[id*3]); + jwin_alert(combo_class_buf[id].name,buf1,"changes it to another slash-affected combo,","then that combo will also change.","O&K",NULL,'k',0,lfont); + } + else if(id >= cSCRIPT1 && id <= cSCRIPT5) + { + jwin_alert(combo_class_buf[id].name,"This type has no built-in effect, but can be","given special significance with ZASM or ZScript.",NULL,"O&K",NULL,'k',0,lfont); + } + else + jwin_alert(combo_class_buf[id].name,combotype_help_string[id*3],combotype_help_string[1+(id*3)],combotype_help_string[2+(id*3)],"O&K",NULL,'k',0,lfont); +} + +void cflag_help(int id) +{ + if(id < 0 || id >= mfMAX) return; // Sanity check + + if(id==0) + { + jwin_alert("Help","Select a Flag, then click","this button to find out what it does.",NULL,"O&K",NULL,'k',0,lfont); + } + else if(id>=mfSECRETS01 && id <=mfSECRETS16) + { + char buf1[80]; + sprintf(buf1,"with Secret Combo %d. (Also, flagged Destructible Combos",id); + jwin_alert(flag_string[id],"When Screen Secrets are triggered, this is replaced",buf1,"will use that Secret Combo instead of the Under Combo.)","O&K",NULL,'k',0,lfont); + } + else if(id >=37 && id <= 46) + { + char buf1[80]; + sprintf(buf1,"When the %d%s enemy in the Enemy List is spawned, it appears",(id-37)+1,((id-37)+1)==1?"st":((id-37)+1)==2?"nd":((id-37)+1)==3?"rd":"th"); + jwin_alert(flag_string[id],buf1,"on this flag instead of using the Enemy Pattern.","The uppermost, then leftmost, instance of this flag is used.","O&K",NULL,'k',0,lfont); + } + else if(id >= mfPUSHUDNS && id <= mfPUSHRINS) + { + char buf1[80]; + int t = ((id-mfPUSHUDNS) % 7); + sprintf(buf1,"Allows Link to push the combo %s %s,", + (t == 0) ? "up and down" : (t == 1) ? "left and right" : (t == 2) ? "in any direction" : (t == 3) ? "up" : (t == 4) ? "down" : (t == 5) ? "left" : "right", + (id>=mfPUSHUDINS) ? "many times":"once"); + jwin_alert(flag_string[id],buf1,"triggering Block->Shutters but not Screen Secrets.","","O&K",NULL,'k',0,lfont); + } + else if(id >= mfSCRIPT1 && id <= mfSCRIPT5) + jwin_alert(flag_string[id],"These flags have no built-in effect, but can be","given special significance with ZASM or ZScript.",NULL,"O&K",NULL,'k',0,lfont); + else + jwin_alert(flag_string[id],flag_help_string[id*3],flag_help_string[1+(id*3)],flag_help_string[2+(id*3)],"O&K",NULL,'k',0,lfont); +} + +int select_cflag(const char *prompt,int index) +{ + cflag_dlg[0].dp=(void *)prompt; + cflag_dlg[0].dp2=lfont; + cflag_dlg[2].d1=index; + ListData select_cflag_list(flaglist, &font); + cflag_dlg[2].dp=(void *) &select_cflag_list; + + if(is_large) + large_dialog(cflag_dlg); + + int ret; + + do + { + ret=zc_popup_dialog(cflag_dlg,2); + + if(ret==5) + { + int id = cflag_dlg[2].d1; + cflag_help(id); + } + } + while(ret==5); + + if(ret==0||ret==4) + { + position_mouse_z(0); + return -1; + } + + return cflag_dlg[2].d1; +} + +int select_flag(int &f) +{ + int ret=select_cflag("Flag Type",f); + + if(ret>=0) + { + f=ret; + return true; + } + + return false; +} + +int d_scombo_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + { + int c2=d->d1; + int cs=d->fg; + int f=d->d2; + + if(key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + while(gui_mouse_b()) + { + /* do nothing */ + } + + if(select_flag(f)) + { + d->d2=f; + + } + } + else if(key[KEY_LSHIFT]) + { + if(gui_mouse_b()&1) + { + d->d1++; + + if(d->d1>=MAXCOMBOS) d->d1=0; + } + else if(gui_mouse_b()&2) + { + d->d1--; + + if(d->d1<0) d->d1=MAXCOMBOS-1; + } + } + else if(key[KEY_RSHIFT]) + { + if(gui_mouse_b()&1) + { + d->fg++; + + if(d->fg>11) d->fg=0; + } + else if(gui_mouse_b()&2) + { + d->fg--; + + if(d->fg<0) d->fg=11; + } + } + else if(key[KEY_ALT]) + { + if(gui_mouse_b()&1) + { + d->d1 = Combo; + d->fg = CSet; + } + } + else + { + if(select_combo_2(c2, cs)) + { + d->d1=c2; + d->fg=cs; + } + } + + return D_REDRAW; + } + break; + + case MSG_DRAW: + if(is_large) + { + d->w = 32; + d->h = 32; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(d->d1) + { + putcombo(buf,0,0,d->d1,d->fg); + + if(Flags&cFLAGS) + put_flags(buf,0,0,d->d1,d->fg,cFLAGS,d->d2); + } + + stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h); + destroy_bitmap(buf); + blit(bigbmp,screen,0,0,d->x-is_large,d->y-is_large,d->w,d->h); + destroy_bitmap(bigbmp); + } + + + /*BITMAP *buf = create_bitmap_ex(8,16,16); + if(buf) + { + clear_bitmap(buf); + if(d->d1) + putcombo(buf,0,0,d->d1,d->fg); + + blit(buf,screen,0,0,d->x,d->y,d->w,d->h); + destroy_bitmap(buf); + }*/ + break; + } + + return D_O_K; +} + +/*int d_scombo2_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_CLICK: + if (key[KEY_ZC_LCONTROL] || key[KEY_ZC_RCONTROL]) + { + select_scombo(d->d1); + } + else + { + select_scombo(d->d1); + } + scare_mouse(); + d_scombo_proc(MSG_DRAW,d,0); + unscare_mouse(); + break; + + + case MSG_DRAW: + BITMAP *buf = create_bitmap_ex(8,16,16); + if(buf) + { + clear_bitmap(buf); + Map.draw_secret2(buf,d->d1); + blit(buf,screen,0,0,d->x,d->y,16,16); + destroy_bitmap(buf); + } + break; + } + + return D_O_K; +}*/ + +int onSecretF(); + +static int secret_burn_list[] = +{ + // dialog control number + 4, 5, 6, 7, 48, 49, 50, 51, 92, 93, 94, 95, -1 +}; + +static int secret_arrow_list[] = +{ + // dialog control number + 8, 9, 10, 52, 53, 54, 96, 97, 98, -1 +}; + +static int secret_bomb_list[] = +{ + // dialog control number + 11, 12, 55, 56, 99, 100, -1 +}; + +static int secret_boomerang_list[] = +{ + // dialog control number + 13, 14, 15, 57, 58, 59, 101, 102, 103, -1 +}; + +static int secret_magic_list[] = +{ + // dialog control number + 16, 17, 60, 61, 104, 105, -1 +}; + +static int secret_sword_list[] = +{ + // dialog control number + 18, 19, 20, 21, 22, 23, 24, 25, 62, 63, 64, 65, 66, 67, 68, 69, 106, 107, 108, 109, 110, 111, 112, 113, -1 +}; + +static int secret_misc_list[] = +{ + // dialog control number + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, -1 +}; + +static TABPANEL secret_tabs[] = +{ + // (text) + { (char *)"Burn", D_SELECTED, secret_burn_list, 0, NULL }, + { (char *)"Arrow", 0, secret_arrow_list, 0, NULL }, + { (char *)"Bomb", 0, secret_bomb_list, 0, NULL }, + { (char *)"Boomerang", 0, secret_boomerang_list, 0, NULL }, + { (char *)"Magic", 0, secret_magic_list, 0, NULL }, + { (char *)"Sword", 0, secret_sword_list, 0, NULL }, + { (char *)"Misc", 0, secret_misc_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static DIALOG secret_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 301, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_tab_proc, 6, 25, 289, 156, 0, 0, 0, 0, 0, 0, (void *) secret_tabs, NULL, (void *)secret_dlg }, + { jwin_button_proc, 80, 187, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 160, 187, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 4 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Blue Candle", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Red Candle", NULL, NULL }, + { jwin_text_proc, 12, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Wand Fire", NULL, NULL }, + { jwin_text_proc, 12, 119, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Din's Fire", NULL, NULL }, + //8 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Wooden Arrow", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Silver Arrow", NULL, NULL }, + { jwin_text_proc, 12, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Golden Arrow", NULL, NULL }, + //11 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Bomb", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Super Bomb", NULL, NULL }, + //13 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Wooden Boomerang", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Magic Boomerang", NULL, NULL }, + { jwin_text_proc, 12, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Fire Boomerang", NULL, NULL }, + //16 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Wand Magic", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Reflected Magic", NULL, NULL }, + //18 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Sword", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "White Sword", NULL, NULL }, + { jwin_text_proc, 12, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Magic Sword", NULL, NULL }, + { jwin_text_proc, 12, 119, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Master Sword", NULL, NULL }, + { jwin_text_proc, 160, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Sword Beam", NULL, NULL }, + { jwin_text_proc, 160, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "White Sword Beam", NULL, NULL }, + { jwin_text_proc, 160, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Magic Sword Beam", NULL, NULL }, + { jwin_text_proc, 160, 119, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Master Sword Beam", NULL, NULL }, + //26 + { jwin_text_proc, 12, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Stairs", NULL, NULL }, + { jwin_text_proc, 12, 75, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Reflected Fireball", NULL, NULL }, + { jwin_text_proc, 12, 97, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Hookshot", NULL, NULL }, + { jwin_text_proc, 12, 119, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Wand", NULL, NULL }, + { jwin_text_proc, 12, 141, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Hammer", NULL, NULL }, + { jwin_text_proc, 12, 163, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Any Weapon", NULL, NULL }, + //32 + { jwin_ctext_proc, 211, 53, 16, 16, vc(11), vc(1), 0, 0, 0, 0, (void *) "Flags 16-31", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 02", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 03", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 04", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 05", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 06", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 07", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 08", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 09", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 10", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 11", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 12", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 13", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 14", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 15", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, FR_DEEP, 0, (void *) "Secret Combo 16", NULL, NULL }, + //48 (burn) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //52 (arrow) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //55 (bomb) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //57 (boomerang) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //60 (magic) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //62 (sword) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 256, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 256, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 256, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 256, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //70 (misc) + { jwin_frame_proc, 108, 47, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 135, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 108, 157, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //76 + { jwin_frame_proc, 168, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 190, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 212, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 234, 69, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 168, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 190, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 212, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 234, 91, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 168, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 190, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 212, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 234, 113, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 168, 135, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 190, 135, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 212, 135, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 234, 135, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + + //92 (burn) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //96 (arrow) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //99 (bomb) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //101 (boomerang) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //104 (magic) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //106 (sword) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 258, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 258, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 258, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 258, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //114 (misc) + { d_scombo_proc, 110, 49, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 137, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 110, 159, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //120 + { d_scombo_proc, 170, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 192, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 214, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 236, 71, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 170, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 192, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 214, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 236, 93, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 170, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 192, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 214, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 236, 115, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 170, 137, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 192, 137, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 214, 137, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_scombo_proc, 236, 137, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //136 + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 'f', 0, 0, 0, (void *) onSecretF, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onSecretF() +{ + Flags^=cFLAGS; + object_message(secret_dlg+1, MSG_DRAW, 0); + return D_O_K; +} + + +int onSecretCombo() +{ + secret_dlg[0].dp2=lfont; + + + mapscr *s; + + if(CurrentLayer==0) + { + s=Map.CurrScr(); + } + else + { + // s=TheMaps[(Map.CurrScr()->layermap[CurrentLayer-1]-1)*MAPSCRS+(Map.CurrScr()->layerscreen[CurrentLayer-1])]; + s=Map.AbsoluteScr((Map.CurrScr()->layermap[CurrentLayer-1]-1), (Map.CurrScr()->layerscreen[CurrentLayer-1])); + } + + char secretcombonumstr[27]; + sprintf(secretcombonumstr,"Secret Combos for Layer %d", CurrentLayer); + secret_dlg[0].dp = secretcombonumstr; + + secret_dlg[92].d1 = s->secretcombo[sBCANDLE]; + secret_dlg[92].fg = s->secretcset[sBCANDLE]; + secret_dlg[92].d2 = s->secretflag[sBCANDLE]; + + secret_dlg[93].d1 = s->secretcombo[sRCANDLE]; + secret_dlg[93].fg = s->secretcset[sRCANDLE]; + secret_dlg[93].d2 = s->secretflag[sRCANDLE]; + + secret_dlg[94].d1 = s->secretcombo[sWANDFIRE]; + secret_dlg[94].fg = s->secretcset[sWANDFIRE]; + secret_dlg[94].d2 = s->secretflag[sWANDFIRE]; + + secret_dlg[95].d1 = s->secretcombo[sDINSFIRE]; + secret_dlg[95].fg = s->secretcset[sDINSFIRE]; + secret_dlg[95].d2 = s->secretflag[sDINSFIRE]; + + secret_dlg[96].d1 = s->secretcombo[sARROW]; + secret_dlg[96].fg = s->secretcset[sARROW]; + secret_dlg[96].d2 = s->secretflag[sARROW]; + + secret_dlg[97].d1 = s->secretcombo[sSARROW]; + secret_dlg[97].fg = s->secretcset[sSARROW]; + secret_dlg[97].d2 = s->secretflag[sSARROW]; + + secret_dlg[98].d1 = s->secretcombo[sGARROW]; + secret_dlg[98].fg = s->secretcset[sGARROW]; + secret_dlg[98].d2 = s->secretflag[sGARROW]; + + secret_dlg[99].d1 = s->secretcombo[sBOMB]; + secret_dlg[99].fg = s->secretcset[sBOMB]; + secret_dlg[99].d2 = s->secretflag[sBOMB]; + + secret_dlg[100].d1 = s->secretcombo[sSBOMB]; + secret_dlg[100].fg = s->secretcset[sSBOMB]; + secret_dlg[100].d2 = s->secretflag[sSBOMB]; + + for(int i=0; i<3; i++) + { + secret_dlg[101+i].d1 = s->secretcombo[sBRANG+i]; + secret_dlg[101+i].fg = s->secretcset[sBRANG+i]; + secret_dlg[101+i].d2 = s->secretflag[sBRANG+i]; + } + + for(int i=0; i<2; i++) + { + secret_dlg[104+i].d1 = s->secretcombo[sWANDMAGIC+i]; + secret_dlg[104+i].fg = s->secretcset[sWANDMAGIC+i]; + secret_dlg[104+i].d2 = s->secretflag[sWANDMAGIC+i]; + } + + for(int i=0; i<8; i++) + { + secret_dlg[106+i].d1 = s->secretcombo[sSWORD+i]; + secret_dlg[106+i].fg = s->secretcset[sSWORD+i]; + secret_dlg[106+i].d2 = s->secretflag[sSWORD+i]; + } + + secret_dlg[114].d1 = s->secretcombo[sSTAIRS]; + secret_dlg[114].fg = s->secretcset[sSTAIRS]; + secret_dlg[114].d2 = s->secretflag[sSTAIRS]; + + secret_dlg[115].d1 = s->secretcombo[sREFFIREBALL]; + secret_dlg[115].fg = s->secretcset[sREFFIREBALL]; + secret_dlg[115].d2 = s->secretflag[sREFFIREBALL]; + + for(int i=0; i<4; i++) + { + secret_dlg[116+i].d1 = s->secretcombo[sHOOKSHOT+i]; + secret_dlg[116+i].fg = s->secretcset[sHOOKSHOT+i]; + secret_dlg[116+i].d2 = s->secretflag[sHOOKSHOT+i]; + } + + for(int i=0; i<16; i++) + { + secret_dlg[120+i].d1 = s->secretcombo[sSECRET01+i]; + secret_dlg[120+i].fg = s->secretcset[sSECRET01+i]; + secret_dlg[120+i].d2 = s->secretflag[sSECRET01+i]; + } + + if(is_large) + { + large_dialog(secret_dlg,1.75); + + for(int i=48; i<92; i++) + { + secret_dlg[i].w = secret_dlg[i].h = 36; + } + } + + go(); + + if(zc_do_dialog(secret_dlg,3) == 2) + { + saved = false; + s->secretcombo[sBCANDLE] = secret_dlg[92].d1; + s->secretcset[sBCANDLE] = secret_dlg[92].fg; + s->secretflag[sBCANDLE] = secret_dlg[92].d2; + + s->secretcombo[sRCANDLE] = secret_dlg[93].d1; + s->secretcset[sRCANDLE] = secret_dlg[93].fg; + s->secretflag[sRCANDLE] = secret_dlg[93].d2; + + s->secretcombo[sWANDFIRE] = secret_dlg[94].d1; + s->secretcset[sWANDFIRE] = secret_dlg[94].fg; + s->secretflag[sWANDFIRE] = secret_dlg[94].d2; + + s->secretcombo[sDINSFIRE] = secret_dlg[95].d1; + s->secretcset[sDINSFIRE] = secret_dlg[95].fg; + s->secretflag[sDINSFIRE] = secret_dlg[95].d2; + + s->secretcombo[sARROW] = secret_dlg[96].d1; + s->secretcset[sARROW] = secret_dlg[96].fg; + s->secretflag[sARROW] = secret_dlg[96].d2; + + s->secretcombo[sSARROW] = secret_dlg[97].d1; + s->secretcset[sSARROW] = secret_dlg[97].fg; + s->secretflag[sSARROW] = secret_dlg[97].d2; + + s->secretcombo[sGARROW] = secret_dlg[98].d1; + s->secretcset[sGARROW] = secret_dlg[98].fg; + s->secretflag[sGARROW] = secret_dlg[98].d2; + + s->secretcombo[sBOMB] = secret_dlg[99].d1; + s->secretcset[sBOMB] = secret_dlg[99].fg; + s->secretflag[sBOMB] = secret_dlg[99].d2; + + s->secretcombo[sSBOMB] = secret_dlg[100].d1; + s->secretcset[sSBOMB] = secret_dlg[100].fg; + s->secretflag[sSBOMB] = secret_dlg[100].d2; + + for(int i=0; i<3; i++) + { + s->secretcombo[sBRANG+i] = secret_dlg[101+i].d1; + s->secretcset[sBRANG+i] = secret_dlg[101+i].fg; + s->secretflag[sBRANG+i] = secret_dlg[101+i].d2; + } + + for(int i=0; i<2; i++) + { + s->secretcombo[sWANDMAGIC+i] = secret_dlg[104+i].d1; + s->secretcset[sWANDMAGIC+i] = secret_dlg[104+i].fg; + s->secretflag[sWANDMAGIC+i] = secret_dlg[104+i].d2; + } + + for(int i=0; i<8; i++) + { + s->secretcombo[sSWORD+i] = secret_dlg[106+i].d1; + s->secretcset[sSWORD+i] = secret_dlg[106+i].fg; + s->secretflag[sSWORD+i] = secret_dlg[106+i].d2; + } + + s->secretcombo[sSTAIRS] = secret_dlg[114].d1; + s->secretcset[sSTAIRS] = secret_dlg[114].fg; + s->secretflag[sSTAIRS] = secret_dlg[114].d2; + + s->secretcombo[sREFFIREBALL] = secret_dlg[115].d1; + s->secretcset[sREFFIREBALL] = secret_dlg[115].fg; + s->secretflag[sREFFIREBALL] = secret_dlg[115].d2; + + for(int i=0; i<4; i++) + { + s->secretcombo[sHOOKSHOT+i] = secret_dlg[116+i].d1; + s->secretcset[sHOOKSHOT+i] = secret_dlg[116+i].fg; + s->secretflag[sHOOKSHOT+i] = secret_dlg[116+i].d2; + } + + for(int i=0; i<16; i++) + { + s->secretcombo[sSECRET01+i] = secret_dlg[120+i].d1; + s->secretcset[sSECRET01+i] = secret_dlg[120+i].fg; + s->secretflag[sSECRET01+i] = secret_dlg[120+i].d2; + } + + } + + comeback(); + return D_O_K; +} + +static DIALOG under_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 60, 176+1,120+1,vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Under Combo", NULL, NULL }, + { jwin_text_proc, 115, 83, 20, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Current", NULL, NULL }, + { d_comboframe_proc, 122, 92, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 124, 94, 16, 16, 0, 0, 0, D_NOCLICK, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 184, 83, 20, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "New", NULL, NULL }, + { d_comboframe_proc, 182, 92, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 184, 94, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 124, 61, 21, vc(14), vc(1), 's', D_EXIT, 0, 0, (void *) "&Set", NULL, NULL }, + { jwin_button_proc, 170, 124, 61, 21, vc(14), vc(1), 'c', D_EXIT, 0, 0, (void *) "&Cancel", NULL, NULL }, + { jwin_button_proc, 90, 152, 61, 21, vc(14), vc(1), 'a', D_EXIT, 0, 0, (void *) "Set &All", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onUnderCombo() +{ + under_dlg[0].dp2 = lfont; + + under_dlg[3].d1=Map.CurrScr()->undercombo; + under_dlg[3].fg=Map.CurrScr()->undercset; + + under_dlg[6].d1=Combo; + under_dlg[6].fg=CSet; + + if(is_large) + { + large_dialog(under_dlg); + // Doesn't place "New" and "Current" text too well + under_dlg[1].x=342; + under_dlg[4].x=438; + } + + int ret = zc_popup_dialog(under_dlg,-1); + + if(ret==7) + { + saved=false; + Map.CurrScr()->undercombo = under_dlg[6].d1; + Map.CurrScr()->undercset = under_dlg[6].fg; + } + + if(ret==9 && jwin_alert("Confirm Overwrite","Set all Under Combos","on this map?",NULL,"&Yes","&No",'y','n',lfont)==1) + { + saved=false; + + for(int i=0; i<128; i++) + { + Map.Scr(i)->undercombo = under_dlg[6].d1; + Map.Scr(i)->undercset = under_dlg[6].fg; + } + } + + return D_O_K; +} + +static DIALOG list_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_list_proc, 72-12-4, 60+4, 176+24+8, 92+3, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 163, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void ilist_rclick_func(int index, int x, int y); +DIALOG ilist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_ilist_proc, 72-12-4, 60+4, 176+24+8, 92+3, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 163, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { jwin_button_proc, 220, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG wlist_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_wlist_proc, 72-12-4, 60+4, 176+24+8, 92+3, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 163, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + +/* + typedef struct item_struct { + char *s; + int i; + } item_struct; + */ +item_struct bii[iMax+1]; +int bii_cnt=-1; + +void build_bii_list(bool usenone) +{ + int start=bii_cnt=0; + + if(usenone) + { + bii[0].s = (char *)"(None)"; + bii[0].i = -2; + bii_cnt=1; + start=0; + } + + for(int i=start; i0 && strcmp(bii[j].s,"")) + { + zc_swap(bii[i],bii[j]); + } + } + } +} + +const char *itemlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = bii_cnt; + return NULL; + } + + return bii[index].s; +} + +// disable items on dmaps stuff +int DI[iMax]; +int nDI; + +void initDI(int index) +{ + int j=0; + + for(int i=0; i0 && strcmp(biw[j].s,"")) + zc_swap(biw[i],biw[j]); + } +} + +const char *weaponlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = biw_cnt; + return NULL; + } + + return biw[index].s; +} + +int select_weapon(const char *prompt,int weapon) +{ + if(biw_cnt==-1) + build_biw_list(); + + int index=0; + + for(int j=0; j=0) + { + bound(index,0,WAV_COUNT-1); + sprintf(sfx_str_buf,"%d: %s",index, index ? sfx_string[index] : "(None)"); + return sfx_str_buf; + } + + *list_size=WAV_COUNT; + return NULL; +} + +static char lenseffect_str_buf[15]; + +const char *lenseffectlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,12); + + if(index==0) + { + sprintf(lenseffect_str_buf,"Normal"); + } + else if(index<7) + { + sprintf(lenseffect_str_buf,"Hide layer %d", index); + } + else + { + sprintf(lenseffect_str_buf,"Reveal layer %d", index-6); + } + + return lenseffect_str_buf; + } + + *list_size=13; + return NULL; +} + +static ListData nextmap_list(nextmaplist, &font); +static ListData ns_list(nslist,&font); +static ListData screenmidi_list(screenmidilist, &font); +static ListData sfx_list(sfxlist, &font); +static ListData lenseffect_list(lenseffectlist, &font); + +static DIALOG scrdata_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 4, 53-29, 304+1+5+6, 156+1+38+7+10, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Screen Data", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 2 + { jwin_button_proc, 90, 176+37, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 176+37, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { jwin_tab_proc, 7, 46, 295+15, 147+17, vc(14), vc(1), 0, 0, 1, 0, (void *) scrdata_tabs, NULL, (void *)scrdata_dlg }, + // 6 + { jwin_check_proc, 165, 78, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Block->Shutters", NULL, NULL }, + //Moved to E. Flags + { jwin_check_proc, 165, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enemies->Item", NULL, NULL }, + + { jwin_check_proc, 15, 178, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Dark Room", NULL, NULL }, + { d_dummy_proc, 160, 56-24, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //S.Flags 2 + { jwin_check_proc, 165, 78, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Whistle->Stairs", NULL, NULL }, + { jwin_check_proc, 165, 118, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Toggle 'Allow Ladder'", NULL, NULL }, + + { jwin_check_proc, 165, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Use Maze Path", NULL, NULL }, + { d_dummy_proc, 160, 56-24, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //S.Data 2 + { jwin_check_proc, 140, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Play Secret SFX On Screen Entry", NULL, NULL }, + + { jwin_check_proc, 15, 78, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combos Affect Midair Link", NULL, NULL }, + //E.Flags + { jwin_check_proc, 15, 178, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Traps Ignore Walkability", NULL, NULL }, + { jwin_check_proc, 165, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enemies->Secret", NULL, NULL }, + //18 + { jwin_check_proc, 165, 188, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Hold Up Item", NULL, NULL }, + //S.Flags 2 + { jwin_check_proc, 15, 88, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Cycle Combos On Screen Init", NULL, NULL }, + //E. Flags + { jwin_check_proc, 15, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "All Enemies Are Invisible", NULL, NULL }, + + { jwin_check_proc, 15, 118, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Invisible Link", NULL, NULL }, + { jwin_check_proc, 15, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "No Subscreen", NULL, NULL }, + + { jwin_check_proc, 165, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Sprites Carry Over In Warps", NULL, NULL }, + + { jwin_check_proc, 15, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "...But Don't Offset Screen", NULL, NULL }, + //E. Flags + { jwin_check_proc, 165, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enemies Always Return", NULL, NULL }, + + // These five now appear on the Timed Warp tab. + { jwin_check_proc, 15, 118, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Timed Warps are Direct", NULL, NULL }, + { jwin_check_proc, 15, 128, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Secrets Disable Timed Warp", NULL, NULL }, + // 28 + { jwin_text_proc, 15, 88, 128, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Timed Warp Ticks:", NULL, NULL }, + { d_ticsedit_proc, 15, 98, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc,17+2+36+1, 98+4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 15, 68, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Screen State Carry Over:", NULL, NULL }, + { jwin_text_proc, 15, 88, 72, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Next Map:", NULL, NULL }, + { jwin_text_proc, 15, 106, 96, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Next Screen:", NULL, NULL }, + { jwin_droplist_proc, 90, 84, 54, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &nextmap_list, NULL, NULL }, +// { jwin_edit_proc, 90, 84, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_droplist_proc, 90, 102, 54, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &ns_list, NULL, NULL }, +// { jwin_edit_proc, 17, 114, 32-6, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // { d_hexedit_proc, 97, 102, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + + //Moved to E Flags + { jwin_check_proc, 165, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enemies->Secret is Permanent", NULL, NULL }, + + { jwin_check_proc, 165, 128, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Auto-Warps are Direct", NULL, NULL }, + //38 + { jwin_check_proc, 15, 128, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Save Point->Continue Here", NULL, NULL }, + { jwin_check_proc, 15, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Save Game On Entry", NULL, NULL }, + // This now appears on the Timed Warp tab. + { jwin_check_proc, 15, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Timed Warp Is Random (A, B, C or D)", NULL, NULL }, + + { jwin_check_proc, 15, 98, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Damage Combos Ignore Boots", NULL, NULL }, + //S.Flags 1 + { jwin_check_proc, 165, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Sensitive Warps are Direct", NULL, NULL }, + { jwin_check_proc, 165, 88, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Secrets are Temporary", NULL, NULL }, + //44 + { jwin_check_proc, 165, 128, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Toggle 'No Diving'", NULL, NULL }, + //S.Flags 1 + { jwin_check_proc, 15, 78, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Treat as Interior Screen", NULL, NULL }, + { jwin_check_proc, 15, 88, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Treat as NES Dungeon Screen", NULL, NULL }, + { jwin_check_proc, 165, 98, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Hit All Triggers->Perm Secret", NULL, NULL }, + + { jwin_check_proc, 15, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Continue Here", NULL, NULL }, + { jwin_check_proc, 15, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "No Continue Here After Warp", NULL, NULL }, + //50, S.Flags 1 + { jwin_check_proc, 165, 108, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Hit All Triggers->16-31", NULL, NULL }, + + { jwin_check_proc, 15, 108, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Toggle Rings Affect Combos", NULL, NULL }, + { jwin_check_proc, 15, 178, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "FF Combos Wrap Around", NULL, NULL }, + { jwin_check_proc, 15, 188, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "No FFC Carryover", NULL, NULL }, + //S.Flags 1 + { jwin_check_proc, 15, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Layer 3 Is Background", NULL, NULL }, + { jwin_check_proc, 15, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Layer 2 Is Background", NULL, NULL }, + { jwin_check_proc, 165, 198, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Item Falls From Ceiling", NULL, NULL }, + { jwin_check_proc, 15, 98, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Sideview Gravity", NULL, NULL }, + { jwin_check_proc, 15, 128, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "No Link Marker in Minimap", NULL, NULL }, + //S. Flags 2 + { jwin_check_proc, 165, 88, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Whistle->Palette Change", NULL, NULL }, + { jwin_check_proc, 165, 98, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Whistle->Dry Lake", NULL, NULL }, + { d_dummy_proc, 160, 56-24, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //62 + { jwin_ctext_proc, 225, 68, 180, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "No Reset / No Carry Over", NULL, NULL }, + { jwin_ctext_proc, 225, 78, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Secrets", NULL, NULL }, + { jwin_ctext_proc, 225, 88, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Item", NULL, NULL }, + { jwin_ctext_proc, 225, 98, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Special Item", NULL, NULL }, + { jwin_ctext_proc, 225, 108, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Lock Block", NULL, NULL }, + { jwin_ctext_proc, 225, 118, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Boss Lock Block", NULL, NULL }, + { jwin_ctext_proc, 225, 128, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Chest", NULL, NULL }, + { jwin_ctext_proc, 225, 138, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Locked Chest", NULL, NULL }, + { jwin_ctext_proc, 225, 148, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Boss Locked Chest", NULL, NULL }, + { jwin_ctext_proc, 225, 168, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Door Down(D)", NULL, NULL }, + { jwin_ctext_proc, 225, 178, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Door Left(D)", NULL, NULL }, + { jwin_ctext_proc, 225, 188, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Door Right(D)", NULL, NULL }, + //74 + { jwin_check_proc, 160, 78, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 88, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 98, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 108, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 118, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 128, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 138, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 148, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 168, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 178, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 160, 188, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 78, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 88, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 98, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 108, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 118, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 128, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 138, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_check_proc, 280, 148, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + //93 + { jwin_text_proc, 17, 130, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Screen MIDI:", NULL, NULL }, + { jwin_droplist_proc, 17, 138, 133, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &screenmidi_list, NULL, NULL }, + { jwin_text_proc, 17, 68, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Damage Combo Sensitivity:", NULL, NULL }, + { jwin_edit_proc, 140, 66, 40, 16, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + //97 + { jwin_ctext_proc, 225, 158, 140, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Door Up(D)", NULL, NULL }, + { jwin_check_proc, 160, 158, 8+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_text_proc, 17, 88, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ambient Sound:", NULL, NULL }, + { jwin_droplist_proc, 140, 86, 140, 16, 0, 0, 0, 0, 3, 0, (void *) & sfx_list, NULL, NULL }, + + { jwin_text_proc, 17, 108, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Boss Roar Sound:", NULL, NULL }, + { jwin_droplist_proc, 140, 106, 140, 16, 0, 0, 0, 0, 3, 0, (void *) & sfx_list, NULL, NULL }, + + { jwin_text_proc, 17, 148, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Secret Sound:", NULL, NULL }, + { jwin_droplist_proc, 140, 146, 140, 16, 0, 0, 0, 0, 3, 0, (void *) & sfx_list, NULL, NULL }, + { jwin_text_proc, 17, 128, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Hold Up Item Sound:", NULL, NULL }, + { jwin_droplist_proc, 140, 126, 140, 16, 0, 0, 0, 0, 3, 0, (void *) & sfx_list, NULL, NULL }, + //107 + { jwin_check_proc, 15, 78, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, // Zora + { jwin_check_proc, 15, 88, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, // Corner Traps + { jwin_check_proc, 15, 98, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, // Middle Traps + { jwin_check_proc, 15, 108, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, // Falling Rocks + { jwin_check_proc, 15, 118, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, // Statue Fire + { jwin_check_proc, 15, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "First Enemy Is 'Ring Leader'", NULL, NULL }, + { jwin_check_proc, 15, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "First Enemy Carries Item", NULL, NULL }, + // 'Invisible Enemies' goes between these two + { jwin_check_proc, 15, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Dungeon Boss (Don't Return)", NULL, NULL }, + { jwin_text_proc, 15, 68, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Environmental Enemies:", NULL, NULL }, + { jwin_text_proc, 15, 128, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Enemy Flags:", NULL, NULL }, + { jwin_text_proc, 15, 68, 200, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Timed Warp: After a given time, Side Warp A is triggered.", NULL, NULL }, + //118 + { jwin_text_proc, 15, 68, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Room Type", NULL, NULL }, + { jwin_text_proc, 15, 108, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "View", NULL, NULL }, + { jwin_text_proc, 165, 68, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Secrets", NULL, NULL }, + { jwin_text_proc, 165, 118, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Warp", NULL, NULL }, + { jwin_text_proc, 165, 178, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Items", NULL, NULL }, + { jwin_text_proc, 15, 68, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Combos", NULL, NULL }, + { jwin_text_proc, 15, 118, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Save", NULL, NULL }, + { jwin_text_proc, 15, 168, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "FFC", NULL, NULL }, + { jwin_text_proc, 165, 68, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Whistle", NULL, NULL }, + { jwin_text_proc, 165, 108, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Misc.", NULL, NULL }, + //128 + { jwin_check_proc, 165, 138, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "General Use 1 (Scripts)", NULL, NULL }, + { jwin_check_proc, 165, 148, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "General Use 2 (Scripts)", NULL, NULL }, + { jwin_check_proc, 165, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "General Use 3 (Scripts)", NULL, NULL }, + { jwin_check_proc, 165, 168, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "General Use 4 (Scripts)", NULL, NULL }, + { jwin_check_proc, 165, 178, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "General Use 5 (Scripts)", NULL, NULL }, + + { jwin_text_proc, 17, 160, 120, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Lens Effect:", NULL, NULL }, + { jwin_droplist_proc, 17, 168, 133, 16, 0, 0, 0, 0, 0, 0, (void *) & lenseffect_list, NULL, NULL }, + + { jwin_check_proc, 165, 158, 160+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Maze Overrides Side Warps", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onScrData() +{ + restore_mouse(); + char timedstring[6]; +// char nmapstring[4]; +// char nscrstring[3]; + char csensstring[2]; + char tics_secs_str[80]; + sprintf(tics_secs_str, "=0.00 seconds"); + char zora_str[85]; + char ctraps_str[85]; + char mtraps_str[85]; + char fallrocks_str[85]; + char statues_str[94]; + + sprintf(zora_str, "Zora"); + sprintf(ctraps_str, "Corner Traps"); + sprintf(mtraps_str, "Middle Traps"); + sprintf(fallrocks_str, "Falling Rocks"); + sprintf(statues_str, "Statues Shoot Fireballs"); + + { + bool foundzora = false; + bool foundctraps = false; + bool foundmtraps = false; + bool foundfallrocks = false; + bool foundstatues = false; + + for(int i=0; itimedwarptics); +// sprintf(nmapstring,"%d",(int)Map.CurrScr()->nextmap); +// sprintf(nscrstring,"%x",(int)Map.CurrScr()->nextscr); + sprintf(csensstring,"%d",(int)Map.CurrScr()->csensitive); + + byte f = Map.CurrScr()->flags; + + for(int i=0; i<8; i++) + { + scrdata_dlg[i+6].flags = (f&1) ? D_SELECTED : 0; + f>>=1; + } + + f = Map.CurrScr()->flags2 >> 4; + + for(int i=0; i<4; i++) + { + scrdata_dlg[i+14].flags = (f&1) ? D_SELECTED : 0; + f>>=1; + } + + f = Map.CurrScr()->flags3; + + for(int i=0; i<8; i++) + { + scrdata_dlg[i+18].flags = (f&1) ? D_SELECTED : 0; + f>>=1; + } + + f = Map.CurrScr()->flags4; + scrdata_dlg[26].flags = (f&4) ? D_SELECTED : 0; + scrdata_dlg[27].flags = (f&8) ? D_SELECTED : 0; + scrdata_dlg[29].dp=timedstring; + scrdata_dlg[30].dp=tics_secs_str; +// scrdata_dlg[34].dp=nmapstring; + scrdata_dlg[34].d1 = (Map.CurrScr()->nextmap); +// scrdata_dlg[35].dp=nscrstring; + scrdata_dlg[35].d1 = (Map.CurrScr()->nextscr); + scrdata_dlg[96].dp=csensstring; + scrdata_dlg[100].d1= (int)Map.CurrScr()->oceansfx; + scrdata_dlg[102].d1= (int)Map.CurrScr()->bosssfx; + scrdata_dlg[104].d1= (int)Map.CurrScr()->secretsfx; + scrdata_dlg[106].d1= (int)Map.CurrScr()->holdupsfx; + scrdata_dlg[36].flags = (f&16) ? D_SELECTED : 0; + //scrdata_dlg[37].flags = (f&32) ? D_SELECTED : 0; + scrdata_dlg[38].flags = (f&64) ? D_SELECTED : 0; + scrdata_dlg[39].flags = (f&128) ? D_SELECTED : 0; + f = Map.CurrScr()->flags5; + scrdata_dlg[40].flags = (f&1) ? D_SELECTED : 0; + scrdata_dlg[41].flags = (f&2) ? D_SELECTED : 0; + scrdata_dlg[37].flags = (f&4) ? D_SELECTED : 0; + scrdata_dlg[42].flags = (f&8) ? D_SELECTED : 0; + scrdata_dlg[43].flags = (f&16) ? D_SELECTED : 0; + scrdata_dlg[44].flags = (f&64) ? D_SELECTED : 0; + scrdata_dlg[53].flags = (f&128) ? D_SELECTED : 0; + f = Map.CurrScr()->flags6; + scrdata_dlg[45].flags = (f&1) ? D_SELECTED : 0; + scrdata_dlg[46].flags = (f&2) ? D_SELECTED : 0; + scrdata_dlg[47].flags = (f&4) ? D_SELECTED : 0; + scrdata_dlg[48].flags = (f&8) ? D_SELECTED : 0; + scrdata_dlg[49].flags = (f&16) ? D_SELECTED : 0; + scrdata_dlg[50].flags = (f&32) ? D_SELECTED : 0; + scrdata_dlg[51].flags = (f&64) ? D_SELECTED : 0; + scrdata_dlg[52].flags = (f&128) ? D_SELECTED : 0; + f = Map.CurrScr()->flags7; + scrdata_dlg[54].flags = (f&1) ? D_SELECTED : 0; + scrdata_dlg[55].flags = (f&2) ? D_SELECTED : 0; + scrdata_dlg[56].flags = (f&4) ? D_SELECTED : 0; + scrdata_dlg[57].flags = (f&8) ? D_SELECTED : 0; + scrdata_dlg[58].flags = (f&16) ? D_SELECTED : 0; + scrdata_dlg[59].flags = (f&64) ? D_SELECTED : 0; + scrdata_dlg[60].flags = (f&128) ? D_SELECTED : 0; + f = Map.CurrScr()->flags8; + scrdata_dlg[128].flags = (f&1) ? D_SELECTED : 0; + scrdata_dlg[129].flags = (f&2) ? D_SELECTED : 0; + scrdata_dlg[130].flags = (f&4) ? D_SELECTED : 0; + scrdata_dlg[131].flags = (f&8) ? D_SELECTED : 0; + scrdata_dlg[132].flags = (f&16) ? D_SELECTED : 0; + scrdata_dlg[135].flags = (f&32) ? D_SELECTED : 0; + + word g = Map.CurrScr()->noreset; + scrdata_dlg[74].flags = (g&mSECRET) ? D_SELECTED : 0; + scrdata_dlg[75].flags = (g&mITEM) ? D_SELECTED : 0; + scrdata_dlg[76].flags = (g&mBELOW) ? D_SELECTED : 0; + scrdata_dlg[77].flags = (g&mLOCKBLOCK) ? D_SELECTED : 0; + scrdata_dlg[78].flags = (g&mBOSSLOCKBLOCK) ? D_SELECTED : 0; + scrdata_dlg[79].flags = (g&mCHEST) ? D_SELECTED : 0; + scrdata_dlg[80].flags = (g&mLOCKEDCHEST) ? D_SELECTED : 0; + scrdata_dlg[81].flags = (g&mBOSSCHEST) ? D_SELECTED : 0; + scrdata_dlg[82].flags = (g&mDOOR_DOWN) ? D_SELECTED : 0; + scrdata_dlg[83].flags = (g&mDOOR_LEFT) ? D_SELECTED : 0; + scrdata_dlg[84].flags = (g&mDOOR_RIGHT) ? D_SELECTED : 0; + scrdata_dlg[98].flags = (g&mDOOR_UP) ? D_SELECTED : 0; + g = Map.CurrScr()->nocarry; + scrdata_dlg[85].flags = (g&mSECRET) ? D_SELECTED : 0; + scrdata_dlg[86].flags = (g&mITEM) ? D_SELECTED : 0; + scrdata_dlg[87].flags = (g&mBELOW) ? D_SELECTED : 0; + scrdata_dlg[88].flags = (g&mLOCKBLOCK) ? D_SELECTED : 0; + scrdata_dlg[89].flags = (g&mBOSSLOCKBLOCK) ? D_SELECTED : 0; + scrdata_dlg[90].flags = (g&mCHEST) ? D_SELECTED : 0; + scrdata_dlg[91].flags = (g&mLOCKEDCHEST) ? D_SELECTED : 0; + scrdata_dlg[92].flags = (g&mBOSSCHEST) ? D_SELECTED : 0; + + scrdata_dlg[94].d1 = (Map.CurrScr()->screen_midi>=0)?(Map.CurrScr()->screen_midi+1):(-(Map.CurrScr()->screen_midi+1)); + scrdata_dlg[134].d1 = Map.CurrScr()->lens_layer==llNORMAL?0:(Map.CurrScr()->lens_layer&llLENSSHOWS?6:0)+(Map.CurrScr()->lens_layer&7)+1; + + byte h=Map.CurrScr()->enemyflags; + + for(int i=0; i<8; i++) + { + scrdata_dlg[i+107].flags = (h&1)?D_SELECTED:0; + h>>=1; + } + + if(is_large) + large_dialog(scrdata_dlg); + + if(zc_popup_dialog(scrdata_dlg,-1)==2) + { + f=0; + + for(int i=7; i>=0; i--) + { + f<<=1; + f |= scrdata_dlg[i+6].flags & D_SELECTED ? 1:0; + } + + Map.CurrScr()->flags = f; + + f=0; + + for(int i=3; i>=0; i--) + { + f<<=1; + f |= scrdata_dlg[i+14].flags & D_SELECTED ? 1:0; + } + + Map.CurrScr()->flags2 &= 0x0F; + Map.CurrScr()->flags2 |= f<<4; + + f=0; + + for(int i=7; i>=0; i--) + { + f<<=1; + f |= scrdata_dlg[i+18].flags & D_SELECTED ? 1:0; + } + + Map.CurrScr()->flags3 = f; + + f=0; + f |= scrdata_dlg[26].flags & D_SELECTED ? 4:0; + f |= scrdata_dlg[27].flags & D_SELECTED ? 8:0; + f |= scrdata_dlg[36].flags & D_SELECTED ? 16:0; + //f |= scrdata_dlg[37].flags & D_SELECTED ? 32:0; + f |= scrdata_dlg[38].flags & D_SELECTED ? 64:0; + f |= scrdata_dlg[39].flags & D_SELECTED ? 128:0; + Map.CurrScr()->flags4 = f; + + f=0; + f |= scrdata_dlg[40].flags & D_SELECTED ? 1:0; + f |= scrdata_dlg[41].flags & D_SELECTED ? 2:0; + f |= scrdata_dlg[37].flags & D_SELECTED ? 4:0; + f |= scrdata_dlg[42].flags & D_SELECTED ? 8:0; + f |= scrdata_dlg[43].flags & D_SELECTED ? 16:0; + f |= scrdata_dlg[44].flags & D_SELECTED ? 64:0; + f |= scrdata_dlg[53].flags & D_SELECTED ? 128:0; + Map.CurrScr()->flags5 = f; + + f=0; + f |= scrdata_dlg[45].flags & D_SELECTED ? 1:0; + f |= scrdata_dlg[46].flags & D_SELECTED ? 2:0; + f |= scrdata_dlg[47].flags & D_SELECTED ? 4:0; + f |= scrdata_dlg[48].flags & D_SELECTED ? 8:0; + f |= scrdata_dlg[49].flags & D_SELECTED ? 16:0; + f |= scrdata_dlg[50].flags & D_SELECTED ? 32:0; + f |= scrdata_dlg[51].flags & D_SELECTED ? 64:0; + f |= scrdata_dlg[52].flags & D_SELECTED ? 128:0; + Map.CurrScr()->flags6 = f; + + f=0; + f |= scrdata_dlg[54].flags & D_SELECTED ? 1:0; + f |= scrdata_dlg[55].flags & D_SELECTED ? 2:0; + f |= scrdata_dlg[56].flags & D_SELECTED ? 4:0; + f |= scrdata_dlg[57].flags & D_SELECTED ? 8:0; + f |= scrdata_dlg[58].flags & D_SELECTED ? 16:0; + f |= scrdata_dlg[59].flags & D_SELECTED ? 64:0; + f |= scrdata_dlg[60].flags & D_SELECTED ? 128:0; + Map.CurrScr()->flags7 = f; + + f=0; + f |= scrdata_dlg[128].flags & D_SELECTED ? 1:0; + f |= scrdata_dlg[129].flags & D_SELECTED ? 2:0; + f |= scrdata_dlg[130].flags & D_SELECTED ? 4:0; + f |= scrdata_dlg[131].flags & D_SELECTED ? 8:0; + f |= scrdata_dlg[132].flags & D_SELECTED ? 16:0; + f |= scrdata_dlg[135].flags & D_SELECTED ? 32:0; + Map.CurrScr()->flags8 = f; + + g=0; + g |= scrdata_dlg[74].flags & D_SELECTED ? mSECRET:0; + g |= scrdata_dlg[75].flags & D_SELECTED ? mITEM:0; + g |= scrdata_dlg[76].flags & D_SELECTED ? mBELOW:0; + g |= scrdata_dlg[77].flags & D_SELECTED ? mLOCKBLOCK:0; + g |= scrdata_dlg[78].flags & D_SELECTED ? mBOSSLOCKBLOCK:0; + g |= scrdata_dlg[79].flags & D_SELECTED ? mCHEST:0; + g |= scrdata_dlg[80].flags & D_SELECTED ? mLOCKEDCHEST:0; + g |= scrdata_dlg[81].flags & D_SELECTED ? mBOSSCHEST:0; + g |= scrdata_dlg[82].flags & D_SELECTED ? mDOOR_DOWN:0; + g |= scrdata_dlg[83].flags & D_SELECTED ? mDOOR_LEFT:0; + g |= scrdata_dlg[84].flags & D_SELECTED ? mDOOR_RIGHT:0; + g |= scrdata_dlg[98].flags & D_SELECTED ? mDOOR_UP:0; + Map.CurrScr()->noreset = g; + + g=0; + g |= scrdata_dlg[85].flags & D_SELECTED ? mSECRET:0; + g |= scrdata_dlg[86].flags & D_SELECTED ? mITEM:0; + g |= scrdata_dlg[87].flags & D_SELECTED ? mBELOW:0; + g |= scrdata_dlg[88].flags & D_SELECTED ? mLOCKBLOCK:0; + g |= scrdata_dlg[89].flags & D_SELECTED ? mBOSSLOCKBLOCK:0; + g |= scrdata_dlg[90].flags & D_SELECTED ? mCHEST:0; + g |= scrdata_dlg[91].flags & D_SELECTED ? mLOCKEDCHEST:0; + g |= scrdata_dlg[92].flags & D_SELECTED ? mBOSSCHEST:0; + Map.CurrScr()->nocarry = g; + + Map.CurrScr()->screen_midi = (scrdata_dlg[94].d1>1)?(scrdata_dlg[94].d1-1):(-(scrdata_dlg[94].d1+1)); + Map.CurrScr()->lens_layer = scrdata_dlg[134].d1==0?0:(scrdata_dlg[134].d1>=7?(llLENSSHOWS|(scrdata_dlg[134].d1-7)):(llLENSHIDES|(scrdata_dlg[134].d1-1))); + Map.CurrScr()->nextmap = scrdata_dlg[34].d1; + Map.CurrScr()->nextscr = scrdata_dlg[35].d1; + + refresh(rMAP+rSCRMAP+rMENU); + Map.CurrScr()->timedwarptics=atoi(timedstring); + Map.CurrScr()->csensitive=(atoi(csensstring)<=8?zc_max(1,atoi(csensstring)):Map.CurrScr()->csensitive); + Map.CurrScr()->oceansfx=scrdata_dlg[100].d1; + Map.CurrScr()->bosssfx=scrdata_dlg[102].d1; + Map.CurrScr()->secretsfx=scrdata_dlg[104].d1; + Map.CurrScr()->holdupsfx=scrdata_dlg[106].d1; + + h=0; + + for(int i=7; i>=0; i--) + { + h<<=1; + h |= scrdata_dlg[107+i].flags & D_SELECTED ? 1:0; + } + + Map.CurrScr()->enemyflags=h; + + saved=false; + } + + return D_O_K; +} + +const char *nslist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,MAXSCREENS); + sprintf(ns_string, " %02X", index); + return ns_string; + } + + *list_size=MAXSCREENS; + return NULL; +} + +const char *flaglist(int index, int *list_size) +{ + if(index>=0) + { + if(index>=MAXFLAGS) + index=MAXFLAGS-1; + + return flag_string[index]; + } + + *list_size=MAXFLAGS; + return NULL; +} + +const char *roomslist(int index, int *list_size) +{ + if(index>=0) + { + if(index>=MAXROOMTYPES) + index=MAXROOMTYPES-1; + + return roomtype_string[index]; + } + + *list_size=MAXROOMTYPES; + return NULL; +} + +static char number_str_buf[32]; +int number_list_size=1; +bool number_list_zero=false; + +const char *numberlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,number_list_size-1); + sprintf(number_str_buf,"%d",index+(number_list_zero?0:1)); + return number_str_buf; + } + + *list_size=number_list_size; + return NULL; +} + +static char dmap_str_buf[37]; +int dmap_list_size=1; +bool dmap_list_zero=true; + +const char *dmaplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,dmap_list_size-1); + sprintf(dmap_str_buf,"%3d-%s",index+(dmap_list_zero?0:1), DMaps[index].name); + return dmap_str_buf; + } + + *list_size=dmap_list_size; + return NULL; +} + +char *hexnumlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,number_list_size-1); + sprintf(number_str_buf,"%X",index+(number_list_zero?0:1)); + return number_str_buf; + } + + *list_size=number_list_size; + return NULL; +} + +const char *maplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,MAXMAPS2-1); + sprintf(number_str_buf,"%d",index+1); + return number_str_buf; + } + + *list_size=MAXMAPS2; + return NULL; +} + +const char *gotomaplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,map_count-1); + sprintf(number_str_buf,"%d",index+1); + return number_str_buf; + } + + *list_size = map_count; + return NULL; +} + +const char *nextmaplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,map_count); + sprintf(number_str_buf,"%3d",index); + return number_str_buf; + } + + *list_size = map_count+1; + return NULL; +} + +const char *midilist(int index, int *list_size) +{ + if(index>=0) + + { + bound(index,0,MAXCUSTOMMIDIS_ZQ-1); + return midi_string[index]; + } + + *list_size=MAXCUSTOMMIDIS_ZQ; + return NULL; +} + +const char *screenmidilist(int index, int *list_size) +{ + if(index>=0) + + { + bound(index,0,MAXCUSTOMMIDIS_ZQ); + return screen_midi_string[index]; + } + + *list_size=MAXCUSTOMMIDIS_ZQ+1; + return NULL; +} + +const char *custommidilist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,MAXCUSTOMMIDIS_ZQ-1); + sprintf(number_str_buf,"%3d - %s",index+(number_list_zero?0:1),customtunes[index].data?customtunes[index].title:"(Empty)"); + return number_str_buf; + } + + *list_size=number_list_size; + return NULL; +} + +const char *enhancedmusiclist(int index, int *list_size) +{ + index=index; //this is here to prevent unused parameter warnings + list_size=list_size; //this is here to prevent unused parameter warnings + /*if(index>=0) + { + bound(index,0,MAXMUSIC-1); + sprintf(number_str_buf,"%3d - %s",index+(number_list_zero?0:1),enhancedMusic[index].filename[0]?enhancedMusic[index].title:"(Empty)" ); + return number_str_buf; + } + *list_size=number_list_size;*/ + return NULL; +} + + +const char *levelnumlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,0xFFF); + sprintf(number_str_buf,"%.3X - %s",index,palnames[index]); + return number_str_buf; + } + + *list_size=MAXLEVELS; + return NULL; +} + +static char shop_str_buf[40]; +int shop_list_size=1; + +const char *shoplist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,shop_list_size-1); + sprintf(shop_str_buf,"%3d: %s",index,misc.shop[index].name); + return shop_str_buf; + } + + *list_size=shop_list_size; + return NULL; +} + +static char info_str_buf[40]; +int info_list_size=1; + +const char *infolist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,info_list_size-1); + sprintf(info_str_buf,"%3d: %s",index,misc.info[index].name); + return info_str_buf; + } + + *list_size=info_list_size; + return NULL; +} + + + +int onMapCount() +{ + bool makechange=true; + bool willaffectlayers=false; + int oldmapcount=map_count-1; + + int ret = select_data("Number of Maps",map_count-1,maplist, lfont); + + if(ret == oldmapcount) + return D_O_K; //they selected the same number of maps they already have. + + { + if(ret < 0) + makechange=false; + else if(retlayermap[j]>(ret+1)) + { + willaffectlayers=true; + break; + } + } + + if(willaffectlayers) + { + break; + } + } + + if(willaffectlayers) + { + if(jwin_alert("Confirm Change", + "This change will delete maps being used for", + "layers in the remaining maps. The map numbers", + "of the affected layers will be reset to 0.", + "O&K", "&Cancel", 'o', 'c', lfont)==2) + { + makechange=false; + } + } + } + + if(makechange) + { + saved = false; + setMapCount2(ret+1); + + if(willaffectlayers) + { + for(int i=0; i<(ret+1)*MAPSCRS; i++) + { + fix_layers(&TheMaps[i], false); + } + } + } + } + + refresh(rMAP+rSCRMAP+rMENU); + return D_O_K; +} + +int onQuestRules() +{ + QuestRulesEditor qre; + gui->showDialog(qre); + return D_O_K; +} + +int onGotoMap() +{ + int ret = select_data("Goto Map",Map.getCurrMap(),gotomaplist,lfont); + + if(ret >= 0) + { + int m=Map.getCurrMap(); + Map.setCurrMap(ret); + + if(m!=Map.getCurrMap()) + { + memset(relational_tile_grid,(draw_mode==dm_relational?1:0),(11+(rtgyo*2))*(16+(rtgxo*2))); + } + } + + refresh(rALL); + return D_O_K; +} + +int onFlags() +{ + restore_mouse(); + int ret=select_cflag("Select Combo Flag",Flag); + position_mouse_z(0); + + if(ret>=0) + { + Flag=ret; + setFlagColor(); + refresh(rMENU); + doflags(); + } + + return D_O_K; +} + +static DIALOG usedcombo_list_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200+24, 148, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Combos Used", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_textbox_proc, 72-12, 60+4, 176+24+1, 92+4, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 130, 163, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + +int onUsedCombos() +{ + restore_mouse(); + usedcombo_list_dlg[0].dp2=lfont; + + int usedcombos[7][300][2]; + char combolist_text[65536]; + char temptext[80]; + + int drawmap=Map.getCurrMap(); + int drawscr=Map.getCurrScr(); + int counter[7]; + + for(int layer=0; layer<7; ++layer) + { + counter[layer]=0; + + if(layer==0) + { + drawmap=Map.getCurrMap(); + drawscr=Map.getCurrScr(); + } + else + { + if(Map.AbsoluteScr(Map.getCurrMap(), Map.getCurrScr())->layermap[layer-1]>0) + { + drawmap=Map.AbsoluteScr(Map.getCurrMap(), Map.getCurrScr())->layermap[layer-1]-1; + drawscr=Map.AbsoluteScr(Map.getCurrMap(), Map.getCurrScr())->layerscreen[layer-1]; + } + else + { + continue; + } + } + + usedcombos[layer][0][0]=Map.AbsoluteScr(drawmap, drawscr)->data[0]; + usedcombos[layer][0][1]=1; + counter[layer]=1; + + for(int i=1; i<176; ++i) + { + bool used=false; + + for(int j=0; jdata[i]) + { + ++usedcombos[layer][j][1]; + used=true; + break; + } + } + + if(!used) + { + usedcombos[layer][counter[layer]][0]=Map.AbsoluteScr(drawmap, drawscr)->data[i]; + usedcombos[layer][counter[layer]][1]=1; + ++counter[layer]; + } + } + + for(int i=0; iusedcombos[layer][j][0]) + { + zc_swap(usedcombos[layer][i][0],usedcombos[layer][j][0]); + zc_swap(usedcombos[layer][i][1],usedcombos[layer][j][1]); + } + } + } + } + + sprintf(combolist_text, " "); + + for(int layer=0; layer<7; ++layer) + { + if(counter[layer]>0) + { + if(layer>0) + { + strcat(combolist_text, "\n"); + } + + sprintf(temptext, "Combos on layer %d\n-----------------\n", layer); + strcat(combolist_text, temptext); + + for(int i=0; i0) && (((usedcombos[layer][i][1]==usedcombos[layer][i-1][1])&&((usedcombos[layer][i][0]-1==usedcombos[layer][i-1][0]))) && ((i==counter[layer]-1) || ((usedcombos[layer][i][1]!=usedcombos[layer][i+1][1])||((usedcombos[layer][i][0]+1!=usedcombos[layer][i+1][0]))))))) + { + sprintf(temptext, "- %5d (%3d)\n", usedcombos[layer][i][0],usedcombos[layer][i][1]); + strcat(combolist_text, temptext); + } + else if(((i==0) && ((usedcombos[layer][i][1]!=usedcombos[layer][i+1][1])||((usedcombos[layer][i][0]+1!=usedcombos[layer][i+1][0]))))|| + ((i==counter[layer]-1) && ((usedcombos[layer][i][1]!=usedcombos[layer][i-1][1])||((usedcombos[layer][i][0]-1!=usedcombos[layer][i-1][0]))))|| + ((i>0) && (ihasitem != 0 ? Map.CurrScr()->item : -2; + + do + { + int ret=select_item("Select Item",current_item,false,exit_status); + + if(exit_status == 5) + { + if(ret>=0) // Edit + { + current_item=ret; + build_biw_list(); + edit_itemdata(ret); + } + else exit_status = -1; + } + else if(exit_status==2 || exit_status==3) // Double-click or OK + { + if(ret>=0) + { + saved=false; + Map.CurrScr()->item=ret; + Map.CurrScr()->hasitem = true; + } + else + { + saved=false; + Map.CurrScr()->hasitem=false; + } + } + } + while(exit_status == 5); + + refresh(rMAP+rMENU); + return D_O_K; +} + +namespace +{ + +struct RoomOrGuyData // Whatever +{ + int value; + const char* name; + const char* info; +}; + +const RoomOrGuyData roomData[]={ + { rNONE, "(None)", "Select a Room Type, then click Help to find out what it does." }, + { rMUPGRADE, "1/2 magic upgrade", "When the Guy's message finishes, Link gains the 1/2 Magic Usage attribute." }, + { r10RUPIES, "10 rupees", "10 instances of item 0 appear in a diamond formation in the center of the screen. No Guy or String needs to be set for this." }, + { rWARP, "3-stair warp", "All 'Stair [A]' type combos send Link to a destination in a given Warp Ring, based on the combo's X position (<112, >136, or between)." }, + { rREPAIR, "Door repair", "When the Guy's String vanishes, Link loses a given amount of rupees." }, + { rGRUMBLE, "Feed the Goriya", "The Guy and his invisible wall won't vanish until Link uses (and thus loses) a Bait item. (Shutters won't open until the Guy vanishes, too.)" }, + { rGAMBLE, "Gamble", "The 'Money-Making Game' from The Legend of Zelda. Risk losing up to 40 rupees for a chance to win up to 50 rupees." }, + { rGANON, "Ganon", "Link holds up the Triforce and Ganon appears unless the current DMap's dungeon boss has been beaten." }, + { rLEARNSLASH, "Learn slash", "When the Guy's message finishes, Link gains the Slash attribute." }, + { rSWINDLE, "Leave money or life", "The Guy and his invisible wall won't vanish until Link pays the fee or forfeits a Heart Container. (Shutters won't open until the Guy vanishes, too.)" }, + { rTRIFORCE, "Level 9 entrance", "The Guy and his invisible wall won't vanish unless Link has Triforce pieces from levels 1-8. (Shutters won't open until the Guy vanishes, too.)" }, + { rARROWS, "More arrows", "The Guy offers to increase Link's Arrows and Max. Arrows by 10 for a fee. You can only buy it once." }, + { rBOMBS, "More bombs", "The Guy offers to increase Link's Bombs and Max. Bombs by 4 for a fee. You can only buy it once." }, + { rINFO, "Pay for info", "Pay rupees to make one of three messages appear. Messages and prices are set in Misc. Data -> Info Types." }, + { rP_SHOP, "Potion shop", "Similar to a shop, but the items and message won't appear until Link uses a Letter item (Or if Link already has a Level 2 Letter item)." }, + { rRP_HC, "Red potion or heart container", "The Guy offers item 28 and item 30 to Link. Taking one makes the other vanish forever." }, + { rMONEY, "Secret money", "If a Guy is set, he will offer rupees to Link." }, + { rSHOP, "Shop", "The Guy offers up to three items for a fee. You can use the shop as often as you want. Items and prices are set in Misc. Data -> Shop Types." }, + { rSP_ITEM, "Special item", "If a Guy is set, he will offer an item to Link. Also used for Item Cellar warps and 'Armos/Chest->Item' and 'Dive For Item' combo flags." }, + { rTAKEONE, "Take one item", "The Guy offers up to three items. Taking one makes the others vanish forever. Item choices are set in Misc. Data -> Shop Types." }, + { rZELDA, "Zelda", "Four instances of enemy 85 appear on the screen in front of the Guy. That's all it does." } +}; + +const RoomOrGuyData guyData[]={ // There's already a "guydata"... Ugh. + { gNONE, "(None)", "" }, + { gABEI, "Abei", "The old man. Uses tile 84." }, + { gABEI2, "Abei 2", "A different old man. Uses tile 87." }, + { gAMA, "Ama", "The old woman. Uses tile 85." }, + { gEMPTY, "Empty", "An invisible Guy. Uses tile 259, which is usually empty. Use it when you just want the String to appear without a visible Guy." }, + { gFAIRY, "Fairy", "A fairy. Uses tiles 63 and 64. Even if the DMap uses 'Special Rooms/Guys In Caves Only' she will still appear in regular screens." }, + { gFIRE, "Fire", "A sentient flame. Uses tile 65 and flips horizontally as it animates." }, + { gGORIYA, "Goriya", "The hungry Goriya. Uses tile 132. He isn't actually necessary to make use of the 'Feed the Goriya' Room Type." }, + { gDUDE, "Merchant", "The shopkeeper. Uses tile 86." }, + { gMOBLIN, "Moblin", "The generous Moblin. Uses tile 116." }, + { gZELDA, "Zelda", "The princess. Uses tiles 35 and 36. Approaching her won't cause the game to end (Unless you touch a Zelda combo flag)." } +}; + +} // Namespace + +std::string getRoomName(int id) +{ + return roomData[id].name; +} + +void showRoomInfo(int id) +{ + gui->alert(roomData[id].name, roomData[id].info); +} + +int onRType() +{ + int init=0; + for(int i=0; i<21; i++) + { + if(roomData[i].value==Map.CurrScr()->room) + { + init=i; + break; + } + } + + SimpleListSelector sls("Select room type", getRoomName, 21, showRoomInfo, false, init); + gui->showDialog(sls); + int ret=sls.getSelected(); + if(ret>=0) + { + Map.CurrScr()->room=roomData[ret].value; + saved=false; + if(ret==rSP_ITEM) + Map.CurrScr()->catchall=clamp(Map.CurrScr()->catchall, 0, ITEMCNT-1); + // That's the only one it checks for? The others must be handled elsewhere... + } + return D_O_K; +} + +std::string getGuyName(int id) +{ + return guyData[id].name; +} + +void showGuyInfo(int id) +{ + gui->alert(guyData[id].name, guyData[id].info); +} + +int onGuy() +{ + int init=0; + for(int i=0; i<11; i++) + { + if(guyData[i].value==Map.CurrScr()->guy) + { + init=i; + break; + } + } + + SimpleListSelector sls("Select guy", getGuyName, 11, showGuyInfo, false, init); + gui->showDialog(sls); + int ret=sls.getSelected(); + if(ret>=0) + { + Map.CurrScr()->guy=guyData[ret].value; + saved=false; + } + return D_O_K; +} + +std::string getMessage(int id) +{ + // ... + return msgList.getListMessageText(id); +} + +int onString() +{ + SimpleListSelector sls("Select screen message", + boost::bind(&MessageList::getListMessageText, &msgList, 1), + msgList.getNumMessages(), false, 0); + gui->showDialog(sls); + int ret=sls.getSelected(); + if(ret>=0) + { + Map.CurrScr()->str=msgList.getMessageNum(ret); + saved=false; + } + return D_O_K; +} + +int onEndString() +{ + SimpleListSelector sls("Select ending message", + boost::bind(&MessageList::getListMessageText, &msgList, 1), + msgList.getNumMessages(), false, 0); + gui->showDialog(sls); + int ret=sls.getSelected(); + if(ret>=0) + { + misc.endstring=msgList.getMessageNum(ret); + saved=false; + } + return D_O_K; +} + +static std::string getShopListItem(int index); // Move this... +void onCatchallShop(int roomType) +{ + const char* title; + int init=clamp(Map.CurrScr()->catchall, 0, 255); + std::string (*strFunc)(int); + switch(roomType) + { + case rINFO: + title="Select info type"; + strFunc=getShopListItem; + break; + + case rP_SHOP: + case rSHOP: + case rTAKEONE: + title="Select shop type"; + strFunc=getShopListItem; + break; + } + + SimpleListSelector sls(title, strFunc, 256, false, init); + gui->showDialog(sls); + int ret=sls.getSelected(); + if(ret>=0) + Map.CurrScr()->catchall=ret; +} + +int onCatchall() +{ + if(prv_mode) + { + Map.set_prvadvance(1); + return D_O_K; + } + + if(data_menu[13].flags==D_DISABLED) + { + return D_O_K; + } + + restore_mouse(); + int ret=-1; + int rtype=Map.CurrScr()->room; + + if(rtype==rINFO || rtype==rSHOP || rtype==rP_SHOP || rtype==rTAKEONE) + { + onCatchallShop(rtype); + return D_O_K; + } + + switch(rtype) + { + case rSP_ITEM: + int exit_status; + build_bii_list(false); + + do + { + ret=select_item("Select Special Item",Map.CurrScr()->catchall,false,exit_status); + + if(exit_status == 5 && ret >= 0) + { + build_biw_list(); + edit_itemdata(ret); + } + else exit_status = -1; + } + while(exit_status == 5); + + break; + + default: + char buf[80]="Enter "; + strcat(buf,catchall_string[rtype]); + ret=getnumber(buf,Map.CurrScr()->catchall); + break; + } + + if(ret>=0) + { + if(ret != Map.CurrScr()->catchall) + saved=false; + + Map.CurrScr()->catchall=ret; + } + + refresh(rMENU); + return D_O_K; +} + +static ListData levelnum_list(levelnumlist, &font); + +static DIALOG screen_pal_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 60-12, 40, 200-16, 96, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Palette", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_droplist_proc, 72-12, 84+4, 161, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &levelnum_list, NULL, NULL }, + { jwin_button_proc, 70, 111, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 150, 111, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 72-12, 60+4, 168, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Note: This does not affect how the", NULL, NULL }, + { jwin_text_proc, 72-12, 72+4, 168, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "room will be displayed in-game!", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; +// return list_dlg[2].d1; + +int onScreenPalette() +{ + restore_mouse(); + screen_pal_dlg[0].dp2=lfont; + screen_pal_dlg[2].d1=Map.getcolor(); + + if(is_large) + large_dialog(screen_pal_dlg); + + if(zc_popup_dialog(screen_pal_dlg,2)==3) + { + saved=false; + Map.setcolor(screen_pal_dlg[2].d1); + refresh(rALL); + } + + return D_O_K; +} + +int onDecScrPal() +{ + restore_mouse(); + int c=Map.getcolor(); + c+=255; + c=c%256; + Map.setcolor(c); + refresh(rALL); + return D_O_K; +} + +int onIncScrPal() +{ + restore_mouse(); + int c=Map.getcolor(); + c+=1; + c=c%256; + Map.setcolor(c); + refresh(rALL); + return D_O_K; +} + +int d_ndroplist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_droplist_proc(msg,d,c); + + // The only place this proc is used is in the info type editor. + // If it's ever used anywhere else, this will probably need to be changed. + // Maybe add a flag for it or something. + int msgID=msg_at_pos(d->d1); + + switch(msg) + { + case MSG_DRAW: + case MSG_CHAR: + case MSG_CLICK: + scare_mouse(); + textprintf_ex(screen,font,d->x - 48,d->y + 4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%5d",msgID); + unscare_mouse(); + } + + return ret; +} + +int d_idroplist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_droplist_proc(msg,d,c); + + switch(msg) + { + case MSG_DRAW: + case MSG_CHAR: + case MSG_CLICK: + scare_mouse(); + int tile = bii[d->d1].i >=0 ? itemsbuf[bii[d->d1].i].tile : 0; + int cset = bii[d->d1].i >=0 ? itemsbuf[bii[d->d1].i].csets&15 : 0; + int x = d->x + d->w + 4; + int y = d->y - 2; + int w = 16; + int h = 16; + + if(is_large) + { + w = 32; + h = 32; + y -= 6; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,w,h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(tile) + overtile16(buf, tile,0,0,cset,0); + + stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, w, h); + destroy_bitmap(buf); + jwin_draw_frame(screen,x,y,w+4,h+4,FR_DEEP); + blit(bigbmp,screen,0,0,x+2,y+2,w,h); + destroy_bitmap(bigbmp); + } + + unscare_mouse(); + } + + return ret; +} + +int d_nidroplist_proc(int msg,DIALOG *d,int c) +{ + int ret = d_idroplist_proc(msg,d,c); + + switch(msg) + { + case MSG_DRAW: + case MSG_CHAR: + case MSG_CLICK: + scare_mouse(); + textprintf_ex(screen,font,d->x - 48,d->y + 4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%5d",bii[d->d1].i); + unscare_mouse(); + } + + return ret; +} + +int d_ilist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_abclist_proc(msg,d,c); + + switch(msg) + { + case MSG_DRAW: + case MSG_CHAR: + case MSG_CLICK: + scare_mouse(); + + int tile = 0; + int cset = 0; + + if(bii[d->d1].i >-1) + { + tile= itemsbuf[bii[d->d1].i].tile; + cset= itemsbuf[bii[d->d1].i].csets&15; + } + + int x = d->x + d->w + 4; + int y = d->y; + int w = 16; + int h = 16; + + if(is_large) + { + w = 32; + h = 32; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,w,h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(tile) + overtile16(buf, tile,0,0,cset,0); + + stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, w, h); + destroy_bitmap(buf); + jwin_draw_frame(screen,x,y,w+4,h+4,FR_DEEP); + blit(bigbmp,screen,0,0,x+2,y+2,w,h); + destroy_bitmap(bigbmp); + } + if(bii[d->d1].i>=0) + { + textprintf_ex(screen,spfont,x,y+20*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"#%d ",bii[d->d1].i); + + textprintf_ex(screen,spfont,x,y+26*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Pow: "); + textprintf_ex(screen,spfont,x+int(16*(is_large?1.5:1)),y+26*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",itemsbuf[bii[d->d1].i].power); + } + + // Might be a bit confusing for new users + /*textprintf_ex(screen,is_large?font:spfont,x,y+32*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Cost: "); + textprintf_ex(screen,is_large?font:spfont,x+int(16*(is_large?1.5:1)),y+32*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",itemsbuf[bii[d->d1].i].magic);*/ + + unscare_mouse(); + } + + return ret; +} + +int d_wlist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_abclist_proc(msg,d,c); + + switch(msg) + { + case MSG_DRAW: + case MSG_CHAR: + case MSG_CLICK: + scare_mouse(); + + int tile = 0; + int cset = 0; + tile= wpnsbuf[biw[d->d1].i].tile; + cset= wpnsbuf[biw[d->d1].i].csets&15; + int x = d->x + d->w + 4; + int y = d->y; + int w = 16; + int h = 16; + + if(is_large) + { + w = 32; + h = 32; + } + + BITMAP *buf = create_bitmap_ex(8,16,16); + BITMAP *bigbmp = create_bitmap_ex(8,w,h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(tile) + overtile16(buf, tile,0,0,cset,0); + + stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, w, h); + destroy_bitmap(buf); + jwin_draw_frame(screen,x,y,w+4,h+4,FR_DEEP); + blit(bigbmp,screen,0,0,x+2,y+2,w,h); + destroy_bitmap(bigbmp); + } + + unscare_mouse(); + } + + return ret; +} + + +/**********************************/ +// Triforce Pieces // +/**********************************/ + +static byte triframe_points[9*4] = +{ + 0,2,2,0, 2,0,4,2, 0,2,4,2, 1,1,3,1, 2,0,2,2, + 1,1,1,2, 1,1,2,2, 3,1,3,2, 3,1,2,2 +}; + +int d_tri_frame_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg==MSG_DRAW) + { + int x[5],y[3]; + + x[0]=d->x; + x[1]=d->x+(d->w>>2); + x[2]=d->x+(d->w>>1); + x[3]=d->x+(d->w>>1)+(d->w>>2); + x[4]=d->x+d->w; + y[0]=d->y; + y[1]=d->y+(d->h>>1); + y[2]=d->y+d->h; + + byte *p = triframe_points; + + for(int i=0; i<9; i++) + { + line(screen,x[*p],y[*(p+1)],x[*(p+2)],y[*(p+3)],d->fg); + p+=4; + } + } + + return D_O_K; +} + +int d_tri_edit_proc(int msg,DIALOG *d,int c) +{ + jwin_button_proc(msg,d,c); + + if(msg==MSG_CLICK) + { + int v = getnumber("Piece Number",d->d1); + scare_mouse(); + + if(v>=0) + { + bound(v,1,8); + + if(v!=d->d1) + { + DIALOG *tp = d - d->d2; + + for(int i=0; i<8; i++) + { + if(tp->d1==v) + { + tp->d1 = d->d1; + ((char*)(tp->dp))[0] = d->d1+'0'; + jwin_button_proc(MSG_DRAW,tp,0); + } + + ++tp; + } + + d->d1 = v; + ((char*)(d->dp))[0] = v+'0'; + } + } + + d->flags = 0; + jwin_button_proc(MSG_DRAW,d,0); + unscare_mouse(); + } + + return D_O_K; +} + +static DIALOG tp_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 56, 32, 208, 160, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Triforce Pieces", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_tri_frame_proc, 64, 56, 192, 96, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, NULL, NULL, NULL }, + // 3 + { d_tri_edit_proc, 138, 82, 17, 17, vc(14), vc(1), 0, 0, 0, 0, (void *) "1", NULL, NULL }, + { d_tri_edit_proc, 166, 82, 17, 17, vc(14), vc(1), 0, 0, 0, 1, (void *) "2", NULL, NULL }, + { d_tri_edit_proc, 90, 130, 17, 17, vc(14), vc(1), 0, 0, 0, 2, (void *) "3", NULL, NULL }, + { d_tri_edit_proc, 214, 130, 17, 17, vc(14), vc(1), 0, 0, 0, 3, (void *) "4", NULL, NULL }, + // 7 + { d_tri_edit_proc, 138, 110, 17, 17, vc(14), vc(1), 0, 0, 0, 4, (void *) "5", NULL, NULL }, + { d_tri_edit_proc, 118, 130, 17, 17, vc(14), vc(1), 0, 0, 0, 5, (void *) "6", NULL, NULL }, + { d_tri_edit_proc, 166, 110, 17, 17, vc(14), vc(1), 0, 0, 0, 6, (void *) "7", NULL, NULL }, + { d_tri_edit_proc, 186, 130, 17, 17, vc(14), vc(1), 0, 0, 0, 7, (void *) "8", NULL, NULL }, + // 11 + { jwin_button_proc, 90, 166, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 166, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onTriPieces() +{ + tp_dlg[0].dp2=lfont; + char temptext[8][2]; + + for(int i=0; i<8; i++) + { + tp_dlg[i+3].d1 = misc.triforce[i]; + // ((char*)(tp_dlg[i+3].dp))[0] = misc.triforce[i]+'0'; + sprintf(temptext[i], "%d", misc.triforce[i]); + tp_dlg[i+3].dp=temptext[i]; + } + + if(is_large) + large_dialog(tp_dlg); + + if(zc_popup_dialog(tp_dlg,-1) == 11) + { + saved=false; + + for(int i=0; i<8; i++) + misc.triforce[i] = tp_dlg[i+3].d1; + } + + return D_O_K; +} + + +/**********************************/ +/*********** onDMaps ************/ +/**********************************/ + +int d_maptile_proc(int msg,DIALOG *d,int c); +bool small_dmap=false; + +static DIALOG dmapmaps_dlg[] = +{ + + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 4, 18, 313, 217, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Custom DMap Map Styles", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 93, 208, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 168, 208, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_ctext_proc, 160, 38, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Minimaps", NULL, NULL }, + { d_ctext_proc, 112, 46, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Without Map", NULL, NULL }, + { d_ctext_proc, 208, 46, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "With Map", NULL, NULL }, + + { d_ctext_proc, 162, 110, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Large Maps", NULL, NULL }, + { d_ctext_proc, 80, 118, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Without Map", NULL, NULL }, + { d_ctext_proc, 240, 118, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "With Map", NULL, NULL }, + // 5 + { d_maptile_proc, 72, 54, 80, 48, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_maptile_proc, 168, 54, 80, 48, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_maptile_proc, 8, 126, 144, 80, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_maptile_proc, 168, 126, 144, 80, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 11 + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_hexedit_proc(int msg,DIALOG *d,int c) +{ + return jwin_hexedit_proc(msg,d,c); +} + +int xtoi(char *hexstr) +{ + int val=0; + + while(isxdigit(*hexstr)) + { + val<<=4; + + if(*hexstr<='9') + val += *hexstr-'0'; + else val+= ((*hexstr)|0x20)-'a'+10; + + ++hexstr; + } + + return val; +} + +void drawgrid(BITMAP *dest,int x,int y,int grid,int fg,int bg,int div) +{ + if(div!=-1) + rectfill(dest,x-1,y-1,x+63,y+3,div); + + for(int dx=0; dx<64; dx+=8) + { + if(grid&0x80) + rectfill(dest,x+dx,y,x+dx+6,y+2,fg); + else if(bg!=-1) + rectfill(dest,x+dx,y,x+dx+6,y+2,bg); + + grid<<=1; + } +} + +void drawovergrid(BITMAP *dest,int x,int y,int grid,int color,int div) +{ + if(div!=-1) + rectfill(dest,x-1,y-1,x+63,y+3,div); + + for(int dx=0; dx<64; dx+=4) + { + rectfill(dest,x+dx,y,x+dx+2,y+2,color); + grid<<=1; + } +} + +void drawgrid(BITMAP *dest,int x,int y,int w, int h, int tw, int th, int *grid,int fg,int bg,int div) +{ + //these are here to bypass compiler warnings about unused arguments + w=w; + tw=tw; + th=th; + + rectfill(dest,x,y,x+(8*8),y+(1*4),div); + + for(int dy=0; dy>2], DMaps[dmap].flags&dmfMINIMAPCOLORFIX ? mc.cave_fg : mc.dngn_fg, -1, -1); + + c=DMaps[dmap].compass; + // rectfill(dmapbmp,(c&15)*8+3,(c>>4)*4+1,(c&15)*8+5,(c>>4)*4+3,dvc(2*4)); + rectfill(dmapbmp_small,(c&15)*8+3,(c>>4)*4+1,(c&15)*8+5,(c>>4)*4+3,vc(4)); + c=DMaps[dmap].cont; + rectfill(dmapbmp_small,(c&15)*8+3,(c>>4)*4+1,(c&15)*8+5,(c>>4)*4+3,vc(10)); + break; + + case dmOVERW: + clear_bitmap(dmapbmp_small); + + if(DMaps[dmap].minimap_2_tile) + ; + else if(!mc.overworld_map_tile) + for(int y=1; y<33; y+=4) + drawovergrid(dmapbmp_small,1,y,DMaps[dmap].grid[y>>2],mc.overw_bg,vc(0)); + + c=DMaps[dmap].cont; + rectfill(dmapbmp_small,(c&15)*4+1,(c>>4)*4+1,(c&15)*4+3,(c>>4)*4+3,vc(10)); + break; + + case dmBSOVERW: + clear_bitmap(dmapbmp_small); + + if(DMaps[dmap].minimap_2_tile) + ; + else if(!mc.overworld_map_tile) + for(int y=1; y<33; y+=4) + // drawgrid_s(dmapbmp,1,y,DMaps[dmap].grid[y>>2],dvc(2*4),dvc(2*3),dvc(3+4)); + drawgrid_s(dmapbmp_small,1,y,DMaps[dmap].grid[y>>2],mc.bs_goal,mc.bs_dk,vc(14)); + + c=DMaps[dmap].cont; + rectfill(dmapbmp_small,(c&15)*8+3,(c>>4)*4+1,(c&15)*8+5,(c>>4)*4+3,vc(10)); + break; + } +} + +void drawdmap_screen(int x, int y, int w, int h, int dmap) +{ + BITMAP *tempbmp = create_bitmap_ex(8,w,h); + clear_to_color(tempbmp, vc(0)); + zcolors mc=misc.colors; + +// rectfill(tempbmp,x,y,x+w-1,y+h-1,vc(0)); + + if(DMaps[dmap].minimap_2_tile) + { + draw_block(tempbmp,0,0,DMaps[dmap].minimap_2_tile,DMaps[dmap].minimap_2_cset,5,3); + } + else if(((DMaps[dmap].type&dmfTYPE)==dmDNGN || (DMaps[dmap].type&dmfTYPE)==dmCAVE) && mc.dungeon_map_tile) + { + draw_block(tempbmp,0,0,mc.dungeon_map_tile,mc.dungeon_map_cset,5,3); + } + else if(((DMaps[dmap].type&dmfTYPE)==dmOVERW || (DMaps[dmap].type&dmfTYPE)==dmBSOVERW) && mc.overworld_map_tile) + { + draw_block(tempbmp,0,0,mc.overworld_map_tile,mc.overworld_map_cset,5,3); + } + + masked_blit(dmapbmp_small,tempbmp,0,0,8,7,65,33); + + blit(tempbmp,screen,0,0,x,y,w,h); + destroy_bitmap(tempbmp); + +} + +int d_dmaplist_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_DRAW) + { + int dmap = d->d1; + int *xy = (int*)(d->dp3); + float temp_scale = 1; + + if(is_large) + { + temp_scale = 1.5; // Scale up by 1.5 + } + + drawdmap(dmap); + + if(xy[0]>-1000&&xy[1]>-1000) + { + int x = d->x+int((xy[0]-2)*temp_scale); + int y = d->y+int((xy[1]-2)*temp_scale); +// int w = is_large ? 84 : 71; +// int h = is_large ? 52 : 39; + int w = 84; + int h = 52; + jwin_draw_frame(screen,x,y,w,h,FR_DEEP); + drawdmap_screen(x+2,y+2,w-4,h-4,dmap); + } + + if(xy[2]>-1000&&xy[3]>-1000) + { + textprintf_ex(screen,is_large ? lfont_l : font,d->x+int((xy[2])*temp_scale),d->y+int((xy[3])*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Map: %-3d",DMaps[d->d1].map+1); + } + + if(xy[4]>-1000&&xy[5]>-1000) + { + textprintf_ex(screen,is_large ? lfont_l : font,d->x+int((xy[4])*temp_scale),d->y+int((xy[5])*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Level: %-3d",DMaps[d->d1].level); + } + } + + return jwin_list_proc(msg,d,c); +} + +int d_dropdmaplist_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_DRAW) + { + int dmap = d->d1; + int *xy = (int*)(d->dp3); + float temp_scale = 1; + + if(is_large) + { + temp_scale = 1.5; // Scale up by 1.5 + } + + drawdmap(dmap); + + if(xy[0]>-1000&&xy[1]>-1000) + { + int x = d->x+int((xy[0]-2)*temp_scale); + int y = d->y+int((xy[1]-2)*temp_scale); +// int w = is_large ? 84 : 71; +// int h = is_large ? 52 : 39; + int w = 84; + int h = 52; + jwin_draw_frame(screen,x,y,w,h,FR_DEEP); + drawdmap_screen(x+2,y+2,w-4,h-4,dmap); + } + + if(xy[2]>-1000&&xy[3]>-1000) + { + textprintf_ex(screen,is_large ? lfont_l : font,d->x+int((xy[2])*temp_scale),d->y+int((xy[3])*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Map: %-3d",DMaps[d->d1].map+1); + } + + if(xy[4]>-1000&&xy[5]>-1000) + { + textprintf_ex(screen,is_large ? lfont_l : font,d->x+int((xy[4])*temp_scale),d->y+int((xy[5])*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Level: %-3d",DMaps[d->d1].level); + } + } + + return jwin_droplist_proc(msg,d,c); +} + +int d_dropdmaptypelist_proc(int msg,DIALOG *d,int c) +{ + int d1 = d->d1; + int ret = jwin_droplist_proc(msg,d,c); + + if(msg==MSG_DRAW || d->d1!=d1) + { + scare_mouse(); + small_dmap=(d->d1!=dmOVERW); + object_message(d-3, MSG_DRAW, 0); + (d-2)->flags&=~D_DISABLED; + (d-2)->flags|=small_dmap?0:D_DISABLED; + object_message(d-2, MSG_DRAW, 0); + (d+35)->d1=small_dmap; + object_message(d+35, MSG_DRAW, 0); + unscare_mouse(); + } + + return ret; +} + +int d_grid_proc(int msg,DIALOG *d,int) +{ + int frame_thickness=int(2*(is_large?1.5:1)); + int button_thickness=2; + int header_width=int(4*(is_large?1.5:1)); + int header_height=int(6*(is_large?1.5:1)); + int cols=d->d1?8:16; +int col_width=(is_large ? d->d1 ? 22:11:(d->d1?14:7)); + int l=(is_large?10:7); + + switch(msg) + { + case MSG_DRAW: + { + BITMAP *tempbmp = create_bitmap_ex(8,SCREEN_W,SCREEN_H); + clear_bitmap(tempbmp); + int x=d->x; + int y=d->y; + int j=0, k=0; + rectfill(tempbmp,x,y,x+d->w-1,y+header_height-1,jwin_pal[jcBOX]); + + for(j=0; j<8; ++j) + { + textprintf_ex(tempbmp,is_large?nfont:spfont,x,y+header_height+frame_thickness+1+(j*l),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",j); + } + + for(j=0; jdp,8*j+k)||!d->d1?FR_MEDDARK:FR_BOX); + rectfill(tempbmp, x+header_width+(k*col_width)+frame_thickness+button_thickness, y+header_height+(j*l)+frame_thickness+button_thickness, + x+header_width+(k*col_width)+frame_thickness+col_width-button_thickness-1, y+header_height+(j*l)+frame_thickness+l-button_thickness-1, get_bit((byte *)d->dp,8*j+k)&&d->d1?jwin_pal[jcBOXFG]:jwin_pal[jcBOX]); + } + } + + masked_blit(tempbmp,screen,0,0,0,0,SCREEN_W,SCREEN_H); + destroy_bitmap(tempbmp); + } + break; + + case MSG_LPRESS: + { + int xx = -1; + int yy = -1; + int set = -1; // Set or unset + + while(gui_mouse_b()) // Drag across to select multiple + { + int x=(gui_mouse_x()-(d->x)-frame_thickness-header_width)/col_width; + int y=(gui_mouse_y()-(d->y)-frame_thickness-header_height)/l; + + if(xx != x || yy != y) + { + xx = x; + yy = y; + + if(y>=0 && y<8 && x>=0 && xdp),"%d%X",y,x); + object_message((d+2), MSG_DRAW, 0); + } + + if(key[KEY_ZC_LCONTROL]||key[KEY_ZC_RCONTROL]) + { + sprintf((char*)((d+4)->dp),"%d%X",y,x); + object_message((d+4), MSG_DRAW, 0); + } + + if(!(key[KEY_ALT]||key[KEY_ALTGR]||key[KEY_ZC_LCONTROL]||key[KEY_ZC_RCONTROL])) + { + if(set==-1) + set = !get_bit((byte *)d->dp,8*y+x); + + set_bit((byte *)d->dp,8*y+x,set); + } + } + } + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + custom_vsync(); + } + } + break; + } + + return D_O_K; +} + +void drawxmap(int themap,int xoff,bool large) +{ + int cols=(large?8:16); +int col_width=(is_large ? large ? 22:11:(large?14:7)); + int dot_width=int((large?4:3)*(is_large?1.5:1)); + int dot_offset=int((large?5:2)*(is_large?1.5:1)); + int l = is_large?10:7; + clear_to_color(dmapbmp_large,jwin_pal[jcBOX]); + + for(int y=0; y<8; y++) + { + for(int x=0; x=0 && x+xoff<=15)) + { + mapscr *scr = &TheMaps[themap*MAPSCRS + y*16+x+(large?xoff:0)]; + rectfill(dmapbmp_large,x*col_width,y*l,x*col_width+col_width-1,(y*l)+l-1,scr->valid&mVALID ? lc1((scr->color)&15) : 0); + + if(scr->valid&mVALID && ((scr->color)&15)>0) + { + rectfill(dmapbmp_large,x*col_width+dot_offset,y*l+2+is_large,x*col_width+dot_offset+dot_width-1,y*l+4+is_large*2,lc2((scr->color)&15)); + } + } + } + } +} + +int d_xmaplist_proc(int msg,DIALOG *d,int c) +{ + int d1 = d->d1; + int ret = jwin_droplist_proc(msg,d,c); + + if(msg==MSG_DRAW || d->d1!=d1) + { + scare_mouse(); + int *xy = (int*)(d->dp3); + xy[0]=d->d1; + drawxmap(xy[0],xy[1],small_dmap); + + if(xy[2]||xy[3]) + { + int frame_thickness=int(2*(is_large?1.5:1)); + int header_width=int(4*(is_large?1.5:1)); + int header_height=int(6*(is_large?1.5:1)); + int cols=small_dmap?8:16; +int col_width=(is_large ? small_dmap ? 22:11:(small_dmap?14:7)); + int x=d->x+xy[2]; + int y=d->y+xy[3]; + int j=0; + rectfill(screen,x,y-header_height-frame_thickness-is_large,int(x+116*(is_large?1.5:1)-1),y-1,jwin_pal[jcBOX]); + + for(j=0; j<8; ++j) + { + textprintf_ex(screen,is_large?nfont:spfont,x-header_width-frame_thickness,y+1+(j*(is_large?10:7)),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",j); + } + + for(j=0; jw,dmapbmp_large->h); + } + + //slider is disabled if + (d+1)->flags&=~D_DISABLED; + (d+1)->flags|=small_dmap?0:D_DISABLED; + object_message(d+1, MSG_DRAW, 0); + unscare_mouse(); + } + + return ret; +} + +int xmapspecs[4] = {0,0,2,26}; + +int onXslider(void *dp3,int d2) +{ + int *x=(int *)dp3; + int *y=x+1; + xmapspecs[1]=d2-7; + bound(xmapspecs[1],-7,15); + drawxmap(xmapspecs[0],xmapspecs[1],small_dmap); + scare_mouse(); + blit(dmapbmp_large,screen,0,0,(*x)+xmapspecs[2],(*y)+xmapspecs[3],dmapbmp_large->w,dmapbmp_large->h); + unscare_mouse(); + return D_O_K; +} + +const char *dmaptype_str[dmMAX] = { "NES Dungeon","Overworld","Interior","BS-Overworld" }; + +const char *typelist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,dmMAX-1); + return dmaptype_str[index]; + } + + *list_size=dmMAX; + return NULL; +} + +bool edit_ins_mode=true; + +void put_title_str(char *s,int x,int y,int fg,int bg,int pos,int lines,int cpl) +{ + int i=0; + + // text_mode(bg); + for(int dy=0; dy-1) + { + // text_mode(-1); + textprintf_ex(screen,zfont,x+((pos%cpl)<<3),y+((pos/cpl)<<3),vc(15),-1,"_"); + } +} + +int d_title_edit_proc(int msg,DIALOG *d,int c) +{ + char *s=(char*)(d->dp); + + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_CLICK: + d->d2=((gui_mouse_x()-d->x)>>3)+((gui_mouse_y()-d->y)>>3)*10; + bound(d->d2,0,19); + scare_mouse(); + put_title_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2,2,10); + unscare_mouse(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + break; + + case MSG_DRAW: + if(!(d->flags & D_GOTFOCUS)) + { + d->d2=-1; + } + + put_title_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2,2,10); + break; + + case MSG_CHAR: + bool used=false; + int k=c>>8; + + switch(k) + { + case KEY_INSERT: + edit_ins_mode=!edit_ins_mode; + used=true; + break; + + case KEY_HOME: + d->d2-=d->d2%10; + used=true; + break; + + case KEY_END: + d->d2-=d->d2%10; + d->d2+=9; + used=true; + break; + + case KEY_UP: + if(d->d2>=10) d->d2-=10; + + used=true; + break; + + case KEY_DOWN: + if(d->d2<10) d->d2+=10; + + used=true; + break; + + case KEY_LEFT: + if(d->d2>0) --d->d2; + + used=true; + break; + + case KEY_RIGHT: + if(d->d2<19) ++d->d2; + + used=true; + break; + + case KEY_BACKSPACE: + if(d->d2>0) + --d->d2; + + case KEY_DEL: + strcpy(s+d->d2,s+d->d2+1); + s[19]=' '; + s[20]=0; + used=true; + break; + + default: + if(isprint(c&255)) + { + if(edit_ins_mode) + { + for(int i=19; i>d->d2; i--) + s[i]=s[i-1]; + } + + s[d->d2]=c&255; + + if(d->d2<19) + ++d->d2; + + used=true; + } + } + + scare_mouse(); + put_title_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2,2,10); + unscare_mouse(); + return used?D_USED_CHAR:D_O_K; + } + + return D_O_K; +} + +void put_intro_str(char *s,int x,int y,int fg,int bg,int pos) +{ + int i=0; + + // text_mode(bg); + for(int dy=0; dy<3; dy++) + for(int dx=0; dx<24; dx++) + { + if(edit_ins_mode) + { + textprintf_ex(screen,zfont,x+(dx<<3),y+(dy<<3),fg,bg,"%c",*(s+i)); + } + else + { + // text_mode(i==pos?vc(15):bg); + textprintf_ex(screen,zfont,x+(dx<<3),y+(dy<<3),i==pos?bg:fg,i==pos?vc(15):bg,"%c",*(s+i)); + } + + ++i; + } + + if(edit_ins_mode&&pos>-1) + { + // text_mode(-1); + textprintf_ex(screen,zfont,x+((pos%24)<<3),y+((pos/24)<<3),vc(15),-1,"_"); + } +} + +int d_intro_edit_proc(int msg,DIALOG *d,int c) +{ + char *s=(char*)(d->dp); + + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_CLICK: + d->d2=((gui_mouse_x()-d->x)>>3)+((gui_mouse_y()-d->y)>>3)*24; + bound(d->d2,0,71); + scare_mouse(); + put_intro_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2); + unscare_mouse(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + + break; + + case MSG_DRAW: + + if(!(d->flags & D_GOTFOCUS)) + { + d->d2=-1; + + } + + put_intro_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2); + break; + + case MSG_CHAR: + bool used=false; + int k=c>>8; + + switch(k) + { + case KEY_INSERT: + edit_ins_mode=!edit_ins_mode; + used=true; + break; + + case KEY_HOME: + d->d2-=d->d2%24; + used=true; + break; + + case KEY_END: + d->d2-=d->d2%24; + d->d2+=23; + used=true; + break; + + case KEY_UP: + if(d->d2>=24) d->d2-=24; + + used=true; + break; + + case KEY_DOWN: + if(d->d2<48) d->d2+=24; + + used=true; + break; + + case KEY_LEFT: + if(d->d2>0) --d->d2; + + used=true; + break; + + case KEY_RIGHT: + if(d->d2<71) ++d->d2; + + used=true; + break; + + case KEY_BACKSPACE: + if(d->d2>0) + --d->d2; + + case KEY_DEL: + strcpy(s+d->d2,s+d->d2+1); + s[71]=' '; + s[72]=0; + used=true; + break; + + default: + if(isprint(c&255)) + { + if(edit_ins_mode) + { + for(int i=71; i>d->d2; i--) + s[i]=s[i-1]; + } + + s[d->d2]=c&255; + + if(d->d2<71) + ++d->d2; + + used=true; + } + } + + scare_mouse(); + put_intro_str(s,d->x,d->y,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],d->d2); + unscare_mouse(); + return used?D_USED_CHAR:D_O_K; + } + + return D_O_K; +} + +char dmap_title[21]; +char dmap_name[33]; +char dmap_intro[73]; + + +static int editdmap_mechanics_list[] = +{ + // dialog control number + 19, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1 +}; + +/* +static int editdmap_continue_list[] = +{ + 120,-1 +}; +*/ + +static int editdmap_appearance_list[] = +{ + // dialog control number + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, -1 +}; + +static int editdmap_music_list[] = +{ + // dialog control number + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, -1 +}; + +static int editdmap_subscreenmaps_list[] = +{ + // dialog control number + 6, -1 +}; + +static int editdmap_disableitems_list[] = +{ + // dialog control number + 100,101,102,103,104,105,-1 +}; + +static int editdmap_flags_list[] = +{ + 110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,-1 +}; + +static TABPANEL editdmap_tabs[] = +{ + // (text) + { (char *)"Mechanics", D_SELECTED, editdmap_mechanics_list, 0, NULL }, + { (char *)"Appearance", 0, editdmap_appearance_list, 0, NULL }, + { (char *)"Music", 0, editdmap_music_list, 0, NULL }, + { (char *)"Maps", 0, editdmap_subscreenmaps_list, 0, NULL }, + { (char *)"Flags", 0, editdmap_flags_list, 0, NULL }, + { (char *)"Disable", 0, editdmap_disableitems_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static int editdmapmap_before_list[] = +{ + // dialog control number + 7, 8, 9, 10, 11, 12, -1 +}; + +static int editdmapmap_after_list[] = +{ + // dialog control number + 13, 14, 15, 16, 17, 18, 26, 27, -1 +}; + +static TABPANEL editdmapmap_tabs[] = +{ + // (text) + { (char *)"Without Map", D_SELECTED, editdmapmap_before_list, 0, NULL }, + { (char *)"With Map", 0, editdmapmap_after_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +int dmap_tracks=0; +static char dmap_track_number_str_buf[32]; +const char *dmaptracknumlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,255); + sprintf(dmap_track_number_str_buf,"%02d",index+1); + return dmap_track_number_str_buf; + } + + *list_size=dmap_tracks; + return NULL; +} + +extern const char *subscreenlist_a(int index, int *list_size); +extern const char *subscreenlist_b(int index, int *list_size); + +static ListData subscreen_list_a(subscreenlist_a, &font); +static ListData subscreen_list_b(subscreenlist_b, &font); +static ListData midi_list(midilist, &font); +static ListData dmaptracknum_list(dmaptracknumlist, &font); +static ListData type_list(typelist, &font); +static ListData gotomap_list(gotomaplist, &font); + +static DIALOG editdmap_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) (dp2) (dp3) + { jwin_win_proc, 0, 0, 312, 221, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_EXIT, 0, 0, (void *) "DMap Editor", NULL, NULL }, + { jwin_button_proc, 89, 196, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 164, 196, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 10, 29, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Name: ", NULL, NULL }, + { jwin_edit_proc, 40, 25, 168, 16, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 20, 0, NULL, NULL, NULL }, + //5 + { jwin_tab_proc, 6, 45, 300, 144, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) editdmap_tabs, NULL, (void *)editdmap_dlg }, + { jwin_tab_proc, 10, 65, 292, 116, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) editdmapmap_tabs, NULL, (void *)editdmap_dlg }, + { jwin_ctext_proc, 67, 87, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Minimap", NULL, NULL }, + { jwin_frame_proc, 31, 95, 84, 52, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_maptile_proc, 33, 97, 80, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)0, NULL }, + //10 + { jwin_ctext_proc, 207, 87, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Large", NULL, NULL }, + { jwin_frame_proc, 133, 95, 148, 84, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_maptile_proc, 135, 97, 144, 80, 0, 0, 0, 0, 0, 0, NULL, (void*)0, NULL }, + { jwin_ctext_proc, 67, 87, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Minimap", NULL, NULL }, + { jwin_frame_proc, 31, 95, 84, 52, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + //15 + { d_maptile_proc, 33, 97, 80, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)0, NULL }, + { jwin_ctext_proc, 207, 87, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Large", NULL, NULL }, + { jwin_frame_proc, 133, 95, 148, 84, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_maptile_proc, 135, 97, 144, 80, 0, 0, 0, 0, 0, 0, NULL, (void*)0, NULL }, + { jwin_text_proc, 12, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Map:", NULL, NULL }, + //20 + { d_xmaplist_proc, 36, 65, 54, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &gotomap_list, NULL, xmapspecs }, + { jwin_slider_proc, 38, 151, 111, 10, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 22, 0, NULL, (void *) onXslider, NULL }, + { jwin_text_proc, 103, 69, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type: ", NULL, NULL }, + { d_dropdmaptypelist_proc, 132, 65, 99, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &type_list, NULL, NULL }, + { jwin_text_proc, 243, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Level:", NULL, NULL }, + //25 + { jwin_edit_proc, 274, 65, 26, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_text_proc, 28, 150, 70, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Setting this tile disables", NULL, NULL }, + { jwin_text_proc, 28, 158, 70, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "the classic NES minimap.", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //30 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //35 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //40 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //45 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //50 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //55 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_grid_proc, 162, 83, 124, 66, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 162, 155, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Compass: 0x", NULL, NULL }, + //60 + { jwin_edit_proc, 218, 151, 21, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 162, 173, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Continue: 0x", NULL, NULL }, + { jwin_edit_proc, 218, 169, 21, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76, 173, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Continue here", NULL, NULL }, + { jwin_text_proc, 12, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Color:", NULL, NULL }, + //65 + { jwin_droplist_proc, 42, 65, 161, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &levelnum_list, NULL, NULL }, + { jwin_ctext_proc, 55, 85, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "DMap Title", NULL, NULL }, + { jwin_frame_proc, 13, 93, 84, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_title_edit_proc, 15, 95, 80, 16, jwin_pal[jcTEXTBG], jwin_pal[jcTEXTFG], 0, 0, 0, 0, (void *) dmap_title, NULL, NULL }, + { jwin_ctext_proc, 201, 85, 0, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "DMap Intro", NULL, NULL }, + //70 + { jwin_frame_proc, 103, 93, 196, 28, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_intro_edit_proc, 105, 95, 192, 24, jwin_pal[jcTEXTBG], jwin_pal[jcTEXTFG], 0, 0, 0, 0, (void *) dmap_intro, NULL, NULL }, + { jwin_frame_proc, 12, 127, 223, 44, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 20, 124, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Subscreens ", NULL, NULL }, + { jwin_text_proc, 16, 137, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Active:", NULL, NULL }, + //75 + { jwin_droplist_proc, 57, 133, 174, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &subscreen_list_a, NULL, NULL }, + { jwin_text_proc, 16, 155, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Passive:", NULL, NULL }, + { jwin_droplist_proc, 57, 151, 174, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &subscreen_list_b, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //80 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 12, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Midi:", NULL, NULL }, + { jwin_droplist_proc, 35, 65, 153, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &midi_list, NULL, NULL }, + { jwin_frame_proc, 12, 86, 176, 68, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + //85 + { jwin_text_proc, 20, 83, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) " Enhanced Music ", NULL, NULL }, + { jwin_frame_proc, 16, 92, 168, 16, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { jwin_text_proc, 19, 96, 162, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 16, 114, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Track:", NULL, NULL }, + { jwin_droplist_proc, 50, 110, 134, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &dmaptracknum_list, NULL, NULL }, + //90 + { jwin_button_proc, 31, 129, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 13, D_EXIT, 0, 0, (void *) "Load", NULL, NULL }, + { jwin_button_proc, 108, 129, 61, 21, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 13, D_EXIT, 0, 0, (void *) "Clear", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //95 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //100 + { jwin_text_proc, 12, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Disabled Items:", NULL, NULL }, + { jwin_abclist_proc, 12, 81, 120, 104, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_abclist_proc, 177, 81, 120, 104, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 177, 69, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "All Items:", NULL, NULL }, + { jwin_button_proc, 146, 105, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 13, D_EXIT, 0, 0, (void *) "->", NULL, NULL }, + //105 + { jwin_button_proc, 146, 145, 20, 20, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 13, D_EXIT, 0, 0, (void *) "<-", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //110 + { jwin_check_proc, 12, 65, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Use Caves Instead Of Item Cellars", NULL, NULL }, + { jwin_check_proc, 12, 75, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Allow 3-Stair Warp Rooms", NULL, NULL }, + { jwin_check_proc, 12, 85, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Allow Whistle Whirlwinds", NULL, NULL }, + { jwin_check_proc, 12, 105, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Special Rooms And Guys Are In Caves Only", NULL, NULL }, + { jwin_check_proc, 12, 115, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Don't Display Compass Marker In Minimap", NULL, NULL }, + { jwin_check_proc, 12, 125, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Underwater Wave Effect", NULL, NULL }, + { jwin_check_proc, 12, 95, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Whistle Whirlwind Returns Link To Start", NULL, NULL }, + { jwin_check_proc, 12, 135, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Always Display Intro String", NULL, NULL }, + { jwin_check_proc, 12, 145, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "View Overworld Map By Pressing 'Map'", NULL, NULL }, + { jwin_check_proc, 12, 155, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "...But Only Show Screens Marked In Minimap", NULL, NULL }, + { jwin_check_proc, 12, 165, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Use Minimap Foreground Color 2", NULL, NULL }, + //121 + { jwin_check_proc, 230, 65, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Script 1", NULL, NULL }, + { jwin_check_proc, 230, 75, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Script 2", NULL, NULL }, + { jwin_check_proc, 230, 85, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Script 3", NULL, NULL }, + { jwin_check_proc, 230, 95, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Script 4", NULL, NULL }, + { jwin_check_proc, 230, 105, 113, 9, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 1, 0, (void *) "Script 5", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void editdmap(int index) +{ + char levelstr[4], compassstr[4], contstr[4], tmusicstr[56], dmapnumstr[60]; + char *tmfname; + byte gridstring[8]; + static int xy[2]; + sprintf(levelstr,"%d",DMaps[index].level); + sprintf(dmapnumstr,"Edit DMap (%d)",index); + sprintf(compassstr,"%02X",DMaps[index].compass); + sprintf(contstr,"%02X",DMaps[index].cont); + sprintf(dmap_title,"%s",DMaps[index].title); + sprintf(dmap_name,"%s",DMaps[index].name); + sprintf(dmap_intro,"%s",DMaps[index].intro); + sprintf(tmusicstr,"%s",DMaps[index].tmusic); + editdmap_dlg[0].dp=dmapnumstr; + editdmap_dlg[0].dp2=lfont; + editdmap_dlg[4].dp=dmap_name; + editdmap_dlg[9].d1 = DMaps[index].minimap_1_tile; + editdmap_dlg[9].fg = DMaps[index].minimap_1_cset; + editdmap_dlg[12].d1 = DMaps[index].largemap_1_tile; + editdmap_dlg[12].fg = DMaps[index].largemap_1_cset; + editdmap_dlg[15].d1 = DMaps[index].minimap_2_tile; + editdmap_dlg[15].fg = DMaps[index].minimap_2_cset; + editdmap_dlg[18].d1 = DMaps[index].largemap_2_tile; + editdmap_dlg[18].fg = DMaps[index].largemap_2_cset; + editdmap_dlg[20].d1=(DMaps[index].map>(map_count-1))?0:DMaps[index].map; + xy[0]=editdmap_dlg[20].x; + xy[1]=editdmap_dlg[20].y; + editdmap_dlg[21].dp3=xy; + xmapspecs[1]=DMaps[index].xoff; + editdmap_dlg[21].d2=DMaps[index].xoff+7; + editdmap_dlg[23].d1=(DMaps[index].type&dmfTYPE); + editdmap_dlg[25].dp=levelstr; + + for(int i=0; i<32; i++) + { + editdmap_dlg[26+i].dp2=is_large?nfont:spfont; + } + + for(int i=0; i<8; i++) + { + for(int j=0; j<8; j++) + { + set_bit(gridstring,8*i+j,get_bit((byte *)(DMaps[index].grid+i),7-j)); + } + } + + editdmap_dlg[58].dp=gridstring; + editdmap_dlg[60].dp=compassstr; + editdmap_dlg[62].dp=contstr; + editdmap_dlg[63].flags = (DMaps[index].type&dmfCONTINUE) ? D_SELECTED : 0; + editdmap_dlg[65].d1=DMaps[index].color; + editdmap_dlg[75].d1=DMaps[index].active_subscreen; + editdmap_dlg[77].d1=DMaps[index].passive_subscreen; + editdmap_dlg[83].d1=DMaps[index].midi; + editdmap_dlg[87].dp=tmusicstr; + dmap_tracks=0; + ZCMUSIC *tempdmapzcmusic = (ZCMUSIC*)zcmusic_load_file(tmusicstr); + + // Failed to load - try the quest directory + if(tempdmapzcmusic==NULL) + { + char musicpath[256]; + replace_filename(musicpath, filepath, tmusicstr, 256); + tempdmapzcmusic = (ZCMUSIC*)zcmusic_load_file(musicpath); + } + + if(tempdmapzcmusic!=NULL) + { + dmap_tracks=zcmusic_get_tracks(tempdmapzcmusic); + dmap_tracks=(dmap_tracks<2)?0:dmap_tracks; + } + + zcmusic_unload_file(tempdmapzcmusic); + editdmap_dlg[89].flags=(dmap_tracks<2)?D_DISABLED:0; + editdmap_dlg[89].d1=vbound(DMaps[index].tmusictrack,0,dmap_tracks > 0 ? dmap_tracks-1 : 0); + + build_bii_list(false); + initDI(index); + ListData DI_list(DIlist, &font); + ListData item_list(itemlist, &font); + editdmap_dlg[101].dp = (void*)&DI_list; + editdmap_dlg[101].d1 = 0; + editdmap_dlg[102].dp = (void*)&item_list; + editdmap_dlg[102].d1 = 0; + + editdmap_dlg[110].flags = (DMaps[index].flags& dmfCAVES)? D_SELECTED : 0; + editdmap_dlg[111].flags = (DMaps[index].flags& dmf3STAIR)? D_SELECTED : 0; + editdmap_dlg[112].flags = (DMaps[index].flags& dmfWHIRLWIND)? D_SELECTED : 0; + editdmap_dlg[113].flags = (DMaps[index].flags& dmfGUYCAVES)? D_SELECTED : 0; + editdmap_dlg[114].flags = (DMaps[index].flags& dmfNOCOMPASS)? D_SELECTED : 0; + editdmap_dlg[115].flags = (DMaps[index].flags& dmfWAVY)? D_SELECTED : 0; + editdmap_dlg[116].flags = (DMaps[index].flags& dmfWHIRLWINDRET)? D_SELECTED : 0; + editdmap_dlg[117].flags = (DMaps[index].flags& dmfALWAYSMSG) ? D_SELECTED : 0; + editdmap_dlg[118].flags = (DMaps[index].flags& dmfVIEWMAP) ? D_SELECTED : 0; + editdmap_dlg[119].flags = (DMaps[index].flags& dmfDMAPMAP) ? D_SELECTED : 0; + editdmap_dlg[120].flags = (DMaps[index].flags& dmfMINIMAPCOLORFIX) ? D_SELECTED : 0; + + editdmap_dlg[121].flags = (DMaps[index].flags& dmfSCRIPT1) ? D_SELECTED : 0; + editdmap_dlg[122].flags = (DMaps[index].flags& dmfSCRIPT2) ? D_SELECTED : 0; + editdmap_dlg[123].flags = (DMaps[index].flags& dmfSCRIPT3) ? D_SELECTED : 0; + editdmap_dlg[124].flags = (DMaps[index].flags& dmfSCRIPT4) ? D_SELECTED : 0; + editdmap_dlg[125].flags = (DMaps[index].flags& dmfSCRIPT5) ? D_SELECTED : 0; + + if(is_large) + { + if(!editdmap_dlg[0].d1) + { + xmapspecs[2]=int(xmapspecs[2]*1.5); + xmapspecs[3]=int(xmapspecs[3]*1.5); + editdmap_dlg[7].x+=4; + editdmap_dlg[13].x+=4; + editdmap_dlg[26].y-=12; + editdmap_dlg[27].y-=12; + editdmap_dlg[59].x+=10; + editdmap_dlg[61].x+=10; + } + + large_dialog(editdmap_dlg); + xy[0]=editdmap_dlg[20].x; + xy[1]=editdmap_dlg[20].y; + int dest[6] = { 11, 17, 14, 8, 67, 70 }; + int src[6] = { 12, 12, 9, 9, 68, 71 }; + + for(int i=0; i<6; i++) + { + editdmap_dlg[dest[i]].w = editdmap_dlg[src[i]].w+4; + editdmap_dlg[dest[i]].h = editdmap_dlg[src[i]].h+4; + editdmap_dlg[dest[i]].x = editdmap_dlg[src[i]].x-2; + editdmap_dlg[dest[i]].y = editdmap_dlg[src[i]].y-2; + } + } + + int ret=-1; + + while(ret!=0&&ret!=1&&ret!=2) + { + ret=zc_popup_dialog(editdmap_dlg,-1); + + switch(ret) + { + case 90: //grab a filename for tracker music + { + if(getname("Load DMap Music",(char*)zcmusic_types,NULL,tmusicpath,false)) + { + strcpy(tmusicpath,temppath); + tmfname=get_filename(tmusicpath); + + if(strlen(tmfname)>55) + { + jwin_alert("Error","Filename too long","(>55 characters",NULL,"O&K",NULL,'k',0,lfont); + temppath[0]=0; + } + else + { + sprintf(tmusicstr,"%s",tmfname); + editdmap_dlg[87].dp=tmusicstr; + dmap_tracks=0; + tempdmapzcmusic = (ZCMUSIC*)zcmusic_load_file(tmusicstr); + + // Failed to load - try the quest directory + if(tempdmapzcmusic==NULL) + { + char musicpath[256]; + replace_filename(musicpath, filepath, tmusicstr, 256); + tempdmapzcmusic = (ZCMUSIC*)zcmusic_load_file(musicpath); + } + + if(tempdmapzcmusic!=NULL) + { + dmap_tracks=zcmusic_get_tracks(tempdmapzcmusic); + dmap_tracks=(dmap_tracks<2)?0:dmap_tracks; + } + + zcmusic_unload_file(tempdmapzcmusic); + editdmap_dlg[89].flags=(dmap_tracks<2)?D_DISABLED:0; + editdmap_dlg[89].d1=0; + } + } + } + break; + + case 91: //clear tracker music + memset(tmusicstr, 0, 56); + editdmap_dlg[89].flags=D_DISABLED; + editdmap_dlg[89].d1=0; + break; + + case 104: // item disable "->" + deleteDI(editdmap_dlg[101].d1, index); + break; + + case 105: // item disable "<-" + { + // 101 is the disabled list, 102 the item list + insertDI(editdmap_dlg[102].d1, index); + } + break; + } + } + + if(ret==1) + { + saved=false; + sprintf(DMaps[index].name,"%s",dmap_name); + DMaps[index].minimap_1_tile = editdmap_dlg[9].d1; + DMaps[index].minimap_1_cset = editdmap_dlg[9].fg; + DMaps[index].largemap_1_tile = editdmap_dlg[12].d1; + DMaps[index].largemap_1_cset = editdmap_dlg[12].fg; + DMaps[index].minimap_2_tile = editdmap_dlg[15].d1; + DMaps[index].minimap_2_cset = editdmap_dlg[15].fg; + DMaps[index].largemap_2_tile = editdmap_dlg[18].d1; + DMaps[index].largemap_2_cset = editdmap_dlg[18].fg; + DMaps[index].map = (editdmap_dlg[20].d1>(map_count-1))?0:editdmap_dlg[20].d1; + DMaps[index].xoff = xmapspecs[1]; + DMaps[index].type=editdmap_dlg[23].d1|((editdmap_dlg[63].flags & D_SELECTED)?dmfCONTINUE:0); + + if((DMaps[index].type & dmfTYPE) == dmOVERW) + DMaps[index].xoff = 0; + + DMaps[index].level=vbound(atoi(levelstr),0,MAXLEVELS-1); + + for(int i=0; i<8; i++) + { + for(int j=0; j<8; j++) + { + set_bit((byte *)(DMaps[index].grid+i),7-j,get_bit(gridstring,8*i+j)); + } + } + + DMaps[index].compass = xtoi(compassstr); + DMaps[index].cont = vbound(xtoi(contstr), -DMaps[index].xoff, 0x7F-DMaps[index].xoff); + DMaps[index].color = editdmap_dlg[65].d1; + DMaps[index].active_subscreen=editdmap_dlg[75].d1; + DMaps[index].passive_subscreen=editdmap_dlg[77].d1; + DMaps[index].midi = editdmap_dlg[83].d1; + sprintf(DMaps[index].tmusic, "%s", tmusicstr); + sprintf(DMaps[index].title,"%s",dmap_title); + sprintf(DMaps[index].intro,"%s",dmap_intro); + DMaps[index].tmusictrack = editdmap_dlg[89].d1; + + int f=0; + f |= editdmap_dlg[110].flags & D_SELECTED ? dmfCAVES:0; + f |= editdmap_dlg[111].flags & D_SELECTED ? dmf3STAIR:0; + f |= editdmap_dlg[112].flags & D_SELECTED ? dmfWHIRLWIND:0; + f |= editdmap_dlg[113].flags & D_SELECTED ? dmfGUYCAVES:0; + f |= editdmap_dlg[114].flags & D_SELECTED ? dmfNOCOMPASS:0; + f |= editdmap_dlg[115].flags & D_SELECTED ? dmfWAVY:0; + f |= editdmap_dlg[116].flags & D_SELECTED ? dmfWHIRLWINDRET:0; + f |= editdmap_dlg[117].flags & D_SELECTED ? dmfALWAYSMSG:0; + f |= editdmap_dlg[118].flags & D_SELECTED ? dmfVIEWMAP:0; + f |= editdmap_dlg[119].flags & D_SELECTED ? dmfDMAPMAP:0; + f |= editdmap_dlg[120].flags & D_SELECTED ? dmfMINIMAPCOLORFIX:0; + + f |= editdmap_dlg[121].flags & D_SELECTED ? dmfSCRIPT1:0; + f |= editdmap_dlg[122].flags & D_SELECTED ? dmfSCRIPT2:0; + f |= editdmap_dlg[123].flags & D_SELECTED ? dmfSCRIPT3:0; + f |= editdmap_dlg[124].flags & D_SELECTED ? dmfSCRIPT4:0; + f |= editdmap_dlg[125].flags & D_SELECTED ? dmfSCRIPT5:0; + DMaps[index].flags = f; + } +} + +//int selectdmapxy[6] = {90,142,164,150,164,160}; +int selectdmapxy[6] = {44,92,128,100,128,110}; + +static ListData dmap_list(dmaplist, &font); + +static DIALOG selectdmap_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72-44, 56-30, 176+88+1, 120+74+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select DMap", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dmaplist_proc, 46, 50, 64+72+88+1, 60+24+1+2, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &dmap_list, NULL, selectdmapxy }, + { jwin_button_proc, 90, 152+44, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 152+44, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, (void *) close_dlg, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onDmaps() +{ + int ret; + char buf[40]; + dmap_list_size=MAXDMAPS; + number_list_zero=true; + selectdmap_dlg[0].dp2=lfont; + + if(is_large) + large_dialog(selectdmap_dlg); + + ret=zc_popup_dialog(selectdmap_dlg,2); + + dmap* pSelectedDmap = 0; + + while(ret!=4&&ret!=0) + { + int d=selectdmap_dlg[2].d1; + + if( key[KEY_C] ) //copy + { + pSelectedDmap = &DMaps[d]; + } + else if( key[KEY_V] && pSelectedDmap != 0 ) //paste + { + dmap* srcDmap = &DMaps[d]; + if( pSelectedDmap != srcDmap ) + { + ::memcpy(pSelectedDmap, &DMaps[d], sizeof(dmap)); + saved=false; + } + } + else if(ret==5) + { + sprintf(buf,"Delete DMap %d?",d); + + if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + reset_dmap(d); + saved=false; + } + } + else + { + editdmap(d); + } + + ret=zc_popup_dialog(selectdmap_dlg,2); + } + + return D_O_K; +} + +/*******************************/ +/********** onMidis **********/ +/*******************************/ + +static DIALOG editmidi_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 24, 20, 273, 189, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "MIDI Specs", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 2 + { jwin_text_proc, 56, 94-16, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "MIDI:", NULL, NULL }, + { jwin_text_proc, 104, 94-16, 48, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 114, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 104, 114-4, 160, 16, vc(12), vc(1), 0, 0, 35, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 124-4+12, 56, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Volume:", NULL, NULL }, + { jwin_edit_proc, 120, 124-4+12-4, 32, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + // 8 + { jwin_check_proc, 176, 124+12-4, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Loop", NULL, NULL }, + // 9 + { jwin_button_proc, 50, 72-24, 57, 21, vc(14), vc(1), 'l', D_EXIT, 0, 0, (void *) "&Load", NULL, NULL }, + { jwin_button_proc, 116, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8D", NULL, NULL }, + { jwin_button_proc, 156, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B", NULL, NULL }, + { jwin_button_proc, 196, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B\x8B", NULL, NULL }, + { jwin_button_proc, 236, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B\x8B\x8B", NULL, NULL }, + // 14 + { jwin_text_proc, 56, 134+4+12, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Start:", NULL, NULL }, + { jwin_edit_proc, 112, 134+12, 32, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 134+12+4, 56, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Loop Start:", NULL, NULL }, + { jwin_edit_proc, 240, 134+12, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 144+12+12, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Loop End:", NULL, NULL }, + { jwin_edit_proc, 240, 144+12+12-4, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + // 20 + { jwin_text_proc, 176, 94-16, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Position:", NULL, NULL }, + { jwin_text_proc, 217, 94-16, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 104-8, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Length:", NULL, NULL }, + { jwin_text_proc, 216, 104-8, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 104-8, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Time:", NULL, NULL }, + { jwin_text_proc, 104, 104-8, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + // 26 + { jwin_check_proc, 56, 144+12+12, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Disable Saving", NULL, NULL }, + { jwin_button_proc, 90, 160+12+12, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 160+12+12, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +void edit_tune(int i) +{ + // TO DO : adapt for non-midi formats + int ret,loop,volume; + byte flags; + long start,loop_start,loop_end; + + char title[36]; + char volume_str[8]; + char start_str[16]; + char loop_start_str[16]; + char loop_end_str[16]; + char len_str[16]; + char pos_str[16]; +// char format_str[8]; +// int format; + + void *data = customtunes[i].data; + + if(customtunes[i].format == MFORMAT_MIDI) get_midi_info((MIDI*) data,&Midi_Info); + + volume = customtunes[i].volume; + loop = customtunes[i].loop; + flags = customtunes[i].flags; + start = customtunes[i].start; + loop_start = customtunes[i].loop_start; + loop_end = customtunes[i].loop_end; + + strcpy(title,customtunes[i].title); + + editmidi_dlg[0].dp2=lfont; + + if(is_large) + { + large_dialog(editmidi_dlg); + editmidi_dlg[13].dp2 = font; + editmidi_dlg[12].dp2 = font; + editmidi_dlg[11].dp2 = font; + editmidi_dlg[10].dp2 = font; + } + + do + { + sprintf(volume_str,"%d",volume); + sprintf(start_str,"%ld",start); + sprintf(loop_start_str,"%ld",loop_start); + sprintf(loop_end_str,"%ld",loop_end); + sprintf(len_str,"%d",Midi_Info.len_beats); + sprintf(pos_str,"%ld",midi_pos); + + editmidi_dlg[3].dp = data?(void *) "Loaded":(void *) "Empty"; + editmidi_dlg[5].dp = title; + editmidi_dlg[7].dp = volume_str; + editmidi_dlg[8].flags = loop?D_SELECTED:0; + editmidi_dlg[10].flags = + editmidi_dlg[11].flags = + editmidi_dlg[12].flags = + editmidi_dlg[13].flags = (data==NULL)?D_DISABLED:D_EXIT; + editmidi_dlg[15].dp = start_str; + editmidi_dlg[17].dp = loop_start_str; + editmidi_dlg[19].dp = loop_end_str; + editmidi_dlg[21].dp = pos_str; + editmidi_dlg[23].dp = len_str; + editmidi_dlg[25].dp = timestr(Midi_Info.len_sec); + editmidi_dlg[26].flags = (flags&tfDISABLESAVE)?D_SELECTED:0; + + DIALOG_PLAYER *p = init_dialog(editmidi_dlg,-1); + + while(update_dialog(p)) + { + custom_vsync(); + scare_mouse(); + // text_mode(vc(1)); + textprintf_ex(screen,is_large? lfont_l : font,editmidi_dlg[0].x+int(193*(is_large?1.5:1)),editmidi_dlg[0].y+int(58*(is_large?1.5:1)),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-5ld",midi_pos); + unscare_mouse(); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + // else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + + ret = shutdown_dialog(p); + + loop = editmidi_dlg[8].flags?1:0; + volume = vbound(atoi(volume_str),0,255); // Allegro can't play louder than 255. + + start = vbound(atol(start_str),0,zc_max(Midi_Info.len_beats-4,0)); + loop_start = vbound(atol(loop_start_str),-1,zc_max(Midi_Info.len_beats-4,-1)); + loop_end = vbound(atol(loop_end_str),-1,Midi_Info.len_beats); + + if(loop_end>0) + { + loop_end = vbound(loop_end,zc_max(loop_start+4,start+4),Midi_Info.len_beats); + } + + flags = 0; + flags |= editmidi_dlg[26].flags&D_SELECTED?tfDISABLESAVE:0; + + switch(ret) + { + case 9: + if(getname("Load tune","mid;nsf",NULL,temppath,true)) + { + stop_midi(); + + if(data!=NULL && data!=customtunes[i].data) + { + destroy_midi((MIDI*)data); + } + + if((data=load_midi(temppath))==NULL) + { + jwin_alert("Error","Error loading tune:",temppath,NULL,"Dang",NULL,13,27,lfont); + } + else + { + char *t = get_filename(temppath); + int j; + + for(j=0; j<35 && t[j]!=0 && t[j]!='.'; j++) + { + title[j]=t[j]; + } + + title[j]=0; + } + + get_midi_info((MIDI*)data,&Midi_Info); + } + + break; + + case 10: + stop_midi(); + break; + + case 12: + if(midi_pos>0) + { + int pos=midi_pos; + stop_midi(); + midi_loop_end = -1; + midi_loop_start = -1; + play_midi((MIDI*)data,loop); + set_volume(-1,volume); + midi_loop_end = loop_end; + midi_loop_start = loop_start; + + if(midi_loop_end<=0) + { + pos = zc_min(pos+16,Midi_Info.len_beats); + } + else + { + pos = zc_min(pos+16,midi_loop_end); + } + + if(pos>0) + { + midi_seek(pos); + } + + break; + } + + // else play it... + + case 13: + if(midi_pos>0) + { + int pos=midi_pos; + stop_midi(); + midi_loop_end = -1; + midi_loop_start = -1; + play_midi((MIDI*)data,loop); + set_volume(-1,volume); + midi_loop_end = loop_end; + midi_loop_start = loop_start; + + if(midi_loop_end<0) + { + pos = zc_min(pos+64,Midi_Info.len_beats); + } + + else + { + pos = zc_min(pos+64,midi_loop_end); + } + + if(pos>0) + { + midi_seek(pos); + } + + break; + } + + // else play it... + + case 11: + { + int pos=midi_pos; + stop_midi(); + midi_loop_end = -1; + midi_loop_start = -1; + play_midi((MIDI*)data,loop); + set_volume(-1,volume); + midi_seek(pos<0?start:pos); + midi_loop_end = loop_end; + midi_loop_start = loop_start; + } + break; + } + } + while(ret<26&&ret!=0); + + stop_midi(); + + if(ret==27) + { + strcpy(customtunes[i].title,title); + customtunes[i].volume = volume; + customtunes[i].loop = loop; + customtunes[i].start = start; + customtunes[i].loop_start = loop_start; + customtunes[i].loop_end = loop_end; + customtunes[i].format = MFORMAT_MIDI; + customtunes[i].flags = flags; + + if(data!=customtunes[i].data) + { + if(customtunes[i].data) + destroy_midi((MIDI*)customtunes[i].data); + + customtunes[i].data = data; + } + + saved=false; + } + + if((ret==28||ret==0) && data!=customtunes[i].data) + { + if(data) + { + destroy_midi((MIDI*)data); + } + } +} + +int d_midilist_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_DRAW) + { + int i = d->d1; + int x = d->x+d->w+8; + int y = d->y+4; + + textout_right_ex(screen,font,"Volume:",x+51,y+8+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_right_ex(screen,font,"Loop:",x+51,y+16+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_right_ex(screen,font,"Start:",x+51,y+24+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_right_ex(screen,font,"Loop Start:",x+51,y+32+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + textout_right_ex(screen,font,"Loop End:",x+51,y+40+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX]); + + textprintf_ex(screen,font,x+56,y+8+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-3d",customtunes[i].volume); + textprintf_ex(screen,font,x+56,y+16+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",customtunes[i].loop?"On ":"Off"); + textprintf_ex(screen,font,x+56,y+24+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-5ld",customtunes[i].start); + textprintf_ex(screen,font,x+56,y+32+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-5ld",customtunes[i].loop_start); + textprintf_ex(screen,font,x+56,y+40+5,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%-5ld",customtunes[i].loop_end); + } + + return jwin_list_proc(msg,d,c); +} + +//static ListData custommidi_list(custommidilist, is_large ? &sfont3 : &font); +static ListData custommidi_list(custommidilist, is_large ? &lfont_l : &font); + +static DIALOG selectmidi_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 24, 20, 273, 189, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select music", NULL, NULL }, + { d_dummy_proc, 160, 56, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_midilist_proc, 31, 44, 164, (1+16)*8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &custommidi_list, NULL, NULL }, + { jwin_button_proc, 90, 160+12+12, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 160+12+12, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, (void *) close_dlg, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onMidis() +{ + stopMusic(); + int ret; + char buf[40]; + number_list_size=MAXCUSTOMTUNES; + number_list_zero=false; + strcpy(temppath,midipath); + selectmidi_dlg[0].dp2=lfont; + + + if(is_large) + large_dialog(selectmidi_dlg); + + selectmidi_dlg[2].dp2 = 0; + + go(); + ret=zc_do_dialog(selectmidi_dlg,2); + + while(ret!=4&&ret!=0) + { + int d=selectmidi_dlg[2].d1; + + if(ret==5) + { + sprintf(buf,"Delete music %d?",d+1); + + if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + customtunes[d].reset(); // reset_midi(customMIDIs+d); + saved=false; + } + } + else + { + edit_tune(d); + } + + ret=zc_do_dialog(selectmidi_dlg,2); + } + + comeback(); + return D_O_K; +} + +/*******************************/ +/****** onEnhancedMusic ******/ +/*******************************/ + +static DIALOG editmusic_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 24, 20, 273, 189, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Music Specs", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 2 + { jwin_text_proc, 56, 94-16, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Music:", NULL, NULL }, + { jwin_text_proc, 104, 94-16, 48, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 114, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 104, 114-4, 160, 16, vc(12), vc(1), 0, 0, 19, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 124-4+12, 56, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Volume:", NULL, NULL }, + { jwin_edit_proc, 120, 124-4+12-4, 32, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + // 8 + { jwin_check_proc, 176, 124+12-4, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Loop", NULL, NULL }, + // 9 + { jwin_button_proc, 50, 72-24, 57, 21, vc(14), vc(1), 'l', D_EXIT, 0, 0, (void *) "&Load", NULL, NULL }, + { jwin_button_proc, 116, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8D", NULL, NULL }, + { jwin_button_proc, 156, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B", NULL, NULL }, + { jwin_button_proc, 196, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B\x8B", NULL, NULL }, + { jwin_button_proc, 236, 72-24, 33, 21, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "\x8B\x8B\x8B", NULL, NULL }, + // 14 + { jwin_text_proc, 56, 134+4+12, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Start:", NULL, NULL }, + { jwin_edit_proc, 112, 134+12, 32, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 134+12+4, 56, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Loop Start:", NULL, NULL }, + { jwin_edit_proc, 240, 134+12, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 144+12+12, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Loop End:", NULL, NULL }, + { jwin_edit_proc, 240, 144+12+12-4, 40, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + // 20 + { jwin_text_proc, 176, 94-16, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Position:", NULL, NULL }, + { jwin_text_proc, 217, 94-16, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 176, 104-8, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Length:", NULL, NULL }, + { jwin_text_proc, 216, 104-8, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 56, 104-8, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Time:", NULL, NULL }, + { jwin_text_proc, 104, 104-8, 32, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + // 26 + { jwin_button_proc, 90, 160+12+12, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 160+12+12, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_musiclist_proc(int msg,DIALOG *d,int c) +{ + return jwin_list_proc(msg,d,c); +} + +static ListData enhancedmusic_list(enhancedmusiclist, &font); + +static DIALOG selectmusic_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 24, 20, 273, 189, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Enhanced Music", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_musiclist_proc, 31, 44, 164, (1+16)*8, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &enhancedmusic_list, NULL, NULL }, + { jwin_button_proc, 90, 160+12+12, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 160+12+12, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_DEL, (void *) close_dlg, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onEnhancedMusic() +{ + // to be taken out - the custom music can all be found in one place + /*stopMusic(); + int ret; + char buf[40]; + number_list_size=MAXCUSTOMMIDIS; + number_list_zero=false; + strcpy(temppath,midipath); + selectmusic_dlg[0].dp2=lfont; + go(); + ret=zc_do_dialog(selectmusic_dlg,2); + while(ret!=4&&ret!=0) + { + int d=selectmusic_dlg[2].d1; + if(ret==5) + { + sprintf(buf,"Delete MIDI %d?",d+1); + if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',lfont)==1) + { + reset_midi(customMIDIs+d); + saved=false; + } + } + else + { + edit_midi(d); + } + ret=zc_do_dialog(selectmusic_dlg,2); + } + comeback(); + */ + return D_O_K; +} + +/*******************************/ +/********** onWarp ***********/ +/*******************************/ + +const char *warptypelist(int index, int *list_size) +{ + if(index>=0) + { + if(index>=MAXWARPTYPES) + index=MAXWARPTYPES-1; + + return warptype_string[index]; + } + + *list_size=MAXWARPTYPES; + // *list_size=6; + return NULL; +} + +const char *warpeffectlist(int index, int *list_size) +{ + if(index>=0) + { + if(index>=MAXWARPEFFECTS) + index=MAXWARPEFFECTS-1; + + return warpeffect_string[index]; + } + + *list_size=MAXWARPEFFECTS; + return NULL; +} + +//int warpdmapxy[6] = {188,131,188,111,188,120}; +//int warpdmapxy[6] = {188-68,131-93,188-68,111-93,188-68,120-93}; +int warpdmapxy[6] = {150,38,150,18,150,27}; +//int warpdmapxy[6] = {2,25,0,17,36,17}; + +static int warp1_list[] = +{ + 2,3,4,5,6,7,8,9,10,11,12,13,53,54,63,67,-1 +}; + +static int warp2_list[] = +{ + 17,18,19,20,21,22,23,24,25,26,27,28,55,56,64,68,-1 +}; + +static int warp3_list[] = +{ + 29,30,31,32,33,34,35,36,37,38,39,40,57,58,65,69,-1 +}; + +static int warp4_list[] = +{ + 41,42,43,44,45,46,47,48,49,50,51,52,59,60,66,70,-1 +}; + +static TABPANEL warp_tabs[] = +{ + // (text) + { (char *)"A", D_SELECTED, warp1_list, 0, NULL }, + { (char *)"B", 0, warp2_list, 0, NULL }, + { (char *)"C", 0, warp3_list, 0, NULL }, + { (char *)"D", 0, warp4_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +int onTileWarpIndex(int index) +{ + int i=-1; + + while(warp_tabs[++i].text != NULL) + warp_tabs[i].flags = (i==index ? D_SELECTED : 0); + + onTileWarp(); + return D_O_K; +} + +static char warpr_buf[10]; +const char *warprlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,3); + sprintf(warpr_buf,"%c",index+0x41); + return warpr_buf; + } + + *list_size=4; + return NULL; +} + +int d_wflag_proc(int msg,DIALOG *d,int c); + +static ListData warp_dlg_list(warptypelist, &font); +static ListData warp_ret_list(warprlist, &font); + +int d_warpdestscrsel_proc(int msg,DIALOG *d,int) +{ + DIALOG *td=(DIALOG *)d->dp3; + + if(msg==MSG_CLICK) + { + bool is_overworld=((DMaps[td[d->d1].d1].type&dmfTYPE)==dmOVERW); + int x_clip = is_overworld?0x0F:0x07; + int x_scale = is_overworld?2:3; + + while(gui_mouse_b()) + { + int x = zc_min(zc_max(gui_mouse_x() - d->x,0)>>x_scale, x_clip); + int y = zc_min((zc_max(gui_mouse_y() - d->y,0)<<2)&0xF0, 0x70); +// if(x+y != d->d1) + { + custom_vsync(); + scare_mouse(); + sprintf((char *)td[d->d1+1].dp, "%02X", y+x); + object_message(&td[d->d1+1], MSG_DRAW, 0); + unscare_mouse(); + //if(zqwin_scale > 1) + { + //stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + //else + { + //blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + } + } + } + + return D_O_K; +} + +static DIALOG warp_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 302, 188, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_tab_proc, 6, 24, 290, 135, vc(14), vc(1), 0, 0, 1, 0, (void *) warp_tabs, NULL, (void *)warp_dlg }, + { jwin_text_proc, 61, 55, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 29, 73, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_text_proc, 28, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_text_proc, 146, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Triggers:", NULL, NULL }, + { jwin_frame_proc, 164, 109, 30, 30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + // 7 + { jwin_droplist_proc, 91, 51, 193, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_dlg_list, NULL, NULL }, + { d_dropdmaplist_proc, 59, 69, 225, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, warpdmapxy }, + { jwin_hexedit_proc, 77, 87, 24, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // 10 + { d_wflag_proc, 170, 106, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 170, 134, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 161, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 189, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + // 14 + { jwin_button_proc, 61, 163, 41, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 121, 163, 41, 21, vc(14), vc(1), 'g', D_EXIT, 0, 0, (void *) "&Go", NULL, NULL }, + { jwin_button_proc, 181, 163, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 17 + { jwin_text_proc, 61, 55, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 29, 73, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_text_proc, 28, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_text_proc, 146, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Triggers:", NULL, NULL }, + { jwin_frame_proc, 164, 109, 30, 30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + // 22 + { jwin_droplist_proc, 91, 51, 193, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_dlg_list, NULL, NULL }, + { d_dropdmaplist_proc, 59, 69, 225, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, warpdmapxy }, + { jwin_hexedit_proc, 77, 87, 24, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // 25 + { d_wflag_proc, 170, 106, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 170, 134, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 161, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 189, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + // 29 + { jwin_text_proc, 61, 55, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 29, 73, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_text_proc, 28, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_text_proc, 146, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Triggers:", NULL, NULL }, + { jwin_frame_proc, 164, 109, 30, 30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + // 34 + { jwin_droplist_proc, 91, 51, 193, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_dlg_list, NULL, NULL }, + { d_dropdmaplist_proc, 59, 69, 225, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, warpdmapxy }, + { jwin_hexedit_proc, 77, 87, 24, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // 37 + { d_wflag_proc, 170, 106, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 170, 134, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 161, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 189, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + //41 + { jwin_text_proc, 61, 55, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 29, 73, 40, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_text_proc, 28, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_text_proc, 146, 91, 64, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Triggers:", NULL, NULL }, + { jwin_frame_proc, 164, 109, 30, 30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + // 46 + { jwin_droplist_proc, 91, 51, 193, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_dlg_list, NULL, NULL }, + { d_dropdmaplist_proc, 59, 69, 225, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, warpdmapxy }, + { jwin_hexedit_proc, 77, 87, 24, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // 49 + { d_wflag_proc, 170, 106, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 170, 134, 18, 8, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 161, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_wflag_proc, 189, 115, 8, 18, vc(4), vc(0), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_text_proc, 29, 123, 100, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Use Warp Return:", NULL, NULL }, + { jwin_droplist_proc, 74, 133, 50, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_ret_list, NULL, NULL }, + { jwin_text_proc, 29, 123, 100, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Use Warp Return:", NULL, NULL }, + { jwin_droplist_proc, 74, 133, 50, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_ret_list, NULL, NULL }, + { jwin_text_proc, 29, 123, 100, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Use Warp Return:", NULL, NULL }, + { jwin_droplist_proc, 74, 133, 50, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_ret_list, NULL, NULL }, + { jwin_text_proc, 29, 123, 100, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Use Warp Return:", NULL, NULL }, + { jwin_droplist_proc, 74, 133, 50, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_ret_list, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 63 + { jwin_check_proc, 29, 107, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combos Carry Over", NULL, NULL }, + { jwin_check_proc, 29, 107, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combos Carry Over", NULL, NULL }, + { jwin_check_proc, 29, 107, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combos Carry Over", NULL, NULL }, + { jwin_check_proc, 29, 107, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Combos Carry Over", NULL, NULL }, + // 67 + { d_warpdestscrsel_proc, 217, 114, 64, 32, 0, 0, 0, 0, 8, 0, NULL, NULL, (void *)warp_dlg }, + { d_warpdestscrsel_proc, 217, 114, 64, 32, 0, 0, 0, 0, 23, 0, NULL, NULL, (void *)warp_dlg }, + { d_warpdestscrsel_proc, 217, 114, 64, 32, 0, 0, 0, 0, 35, 0, NULL, NULL, (void *)warp_dlg }, + { d_warpdestscrsel_proc, 217, 114, 64, 32, 0, 0, 0, 0, 47, 0, NULL, NULL, (void *)warp_dlg }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +// Side warp flag procedure +int d_wflag_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + switch(msg) + { + case MSG_DRAW: + { + int c2=(d->flags&D_SELECTED)?d->fg:d->bg; + + /*if(!(d->d2&0x80)) + { + c=d->bg; + }*/ + if(d->d1==1) + { + jwin_draw_frame(screen,d->x,d->y,d->w,d->h, FR_DEEP); + rectfill(screen,d->x+2, d->y+2, d->x+d->w-3, d->y+d->h-3,c2); + + if(d->flags&D_SELECTED) + { + int e=d->d2&3; + + if(d->w>d->h) + textprintf_centre_ex(screen,is_large ? lfont_l : font, d->x+(d->w/2),d->y,jwin_pal[jcBOXFG],-1,"%c",e+0x41); + else + textprintf_centre_ex(screen,is_large ? lfont_l : font, d->x+(d->w/2),d->y+(d->h/2)-4,jwin_pal[jcBOXFG],-1,"%c",e+0x41); + } + + } + else + { + rectfill(screen,d->x, d->y, d->x+d->w-1, d->y+d->h-1,c2); + } + } + break; + + case MSG_CLICK: + { + if(d->d1==1) + { + if(!(d->flags&D_SELECTED)) + { + d->flags|=D_SELECTED; + d->d2&=0x80; + int g; + + if(d==&warp_dlg[10]||d==&warp_dlg[25]||d==&warp_dlg[37]||d==&warp_dlg[49]) g=0; + else if(d==&warp_dlg[11]||d==&warp_dlg[26]||d==&warp_dlg[38]||d==&warp_dlg[50]) g=1; + else if(d==&warp_dlg[12]||d==&warp_dlg[27]||d==&warp_dlg[39]||d==&warp_dlg[51]) g=2; + else g=3; + + warp_dlg[10+g].flags = d->flags; + warp_dlg[10+g].d2 = d->d2; + warp_dlg[25+g].flags = d->flags; + warp_dlg[25+g].d2 = d->d2; + warp_dlg[37+g].flags = d->flags; + warp_dlg[37+g].d2 = d->d2; + warp_dlg[49+g].flags = d->flags; + warp_dlg[49+g].d2 = d->d2; + } + else + { + if((d->d2&3)==3) + { + d->flags^=D_SELECTED; + d->d2&=0x80; + int g; + + if(d==&warp_dlg[10]||d==&warp_dlg[25]||d==&warp_dlg[37]||d==&warp_dlg[49]) g=0; + else if(d==&warp_dlg[11]||d==&warp_dlg[26]||d==&warp_dlg[38]||d==&warp_dlg[50]) g=1; + else if(d==&warp_dlg[12]||d==&warp_dlg[27]||d==&warp_dlg[39]||d==&warp_dlg[51]) g=2; + else g=3; + + warp_dlg[10+g].flags = d->flags; + warp_dlg[10+g].d2 = d->d2; + warp_dlg[25+g].flags = d->flags; + warp_dlg[25+g].d2 = d->d2; + warp_dlg[37+g].flags = d->flags; + warp_dlg[37+g].d2 = d->d2; + warp_dlg[49+g].flags = d->flags; + warp_dlg[49+g].d2 = d->d2; + } + else + { + int f=d->d2&3; + d->d2&=0x80; + f++; + d->d2|=f; + int g; + + if(d==&warp_dlg[10]||d==&warp_dlg[25]||d==&warp_dlg[37]||d==&warp_dlg[49]) g=0; + else if(d==&warp_dlg[11]||d==&warp_dlg[26]||d==&warp_dlg[38]||d==&warp_dlg[50]) g=1; + else if(d==&warp_dlg[12]||d==&warp_dlg[27]||d==&warp_dlg[39]||d==&warp_dlg[51]) g=2; + else g=3; + + warp_dlg[10+g].flags = d->flags; + warp_dlg[10+g].d2 = d->d2; + warp_dlg[25+g].flags = d->flags; + warp_dlg[25+g].d2 = d->d2; + warp_dlg[37+g].flags = d->flags; + warp_dlg[37+g].d2 = d->d2; + warp_dlg[49+g].flags = d->flags; + warp_dlg[49+g].d2 = d->d2; + } + } + } + else + { + d->flags^=D_SELECTED; + } + + int c2=(d->flags&D_SELECTED)?d->fg:d->bg; + scare_mouse(); + + if(d->d1==1) + { + jwin_draw_frame(screen,d->x,d->y,d->w,d->h, FR_DEEP); + rectfill(screen,d->x+2, d->y+2, d->x+d->w-3, d->y+d->h-3,c2); + + if(d->flags&D_SELECTED) + { + int e=d->d2&3; + + if(d->w>d->h) + textprintf_centre_ex(screen,is_large? lfont_l: font,d->x+(d->w/2),d->y,jwin_pal[jcBOXFG],-1,"%c",e+0x41); + else + textprintf_centre_ex(screen,is_large? lfont_l: font,d->x+(d->w/2),d->y+(d->h/2)-4,jwin_pal[jcBOXFG],-1,"%c",e+0x41); + } + } + else + { + rectfill(screen,d->x, d->y, d->x+d->w-1, d->y+d->h-1,c2); + } + + unscare_mouse(); + + while(gui_mouse_b()) + { + /* do nothing */ + } + } + break; + } + + return D_O_K; +} + +#if 0 +static int north_side_warp_list[] = +{ + // dialog control number + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -1 +}; + +static int south_side_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int west_side_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int east_side_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_1_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_2_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_3_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_4_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_5_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_6_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_7_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_8_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_9_list[] = +{ + // dialog control number + 80, -1 +}; + + +static int tile_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int side_warp_list[] = +{ + // dialog control number + 6, -1 +}; + +static int item_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int wind_warp_list[] = +{ + // dialog control number + 7, -1 +}; + +static int special_warp_list[] = +{ + // dialog control number + 80, -1 +}; + +static int timed_warp_list[] = +{ + // dialog control number + 80, -1 +}; + + +#endif + +int d_dmapscrsel_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int ret = D_O_K; + + switch(msg) + { + case MSG_CLICK: + sprintf((char*)((d+2)->dp),"%X%X",vbound((gui_mouse_y()-d->y)/4,0,7),vbound((gui_mouse_x()-d->x)/(((DMaps[(d-1)->d1].type&dmfTYPE)==1)?4:8),0,(((DMaps[(d-1)->d1].type&dmfTYPE)==1)?15:7))); + object_message(d+2, MSG_DRAW, 0); + break; + } + + return ret; +} + +int warpdestsel_x=-1; +int warpdestsel_y=-1; +int warpdestmap=-1; +int warpdestscr=-1; + +int d_warpdestsel_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int ret=D_O_K; + static BITMAP *bmp=create_bitmap_ex(8,256,176); + static bool inrect=false; + static bool mousedown=false; + + switch(msg) + { + case MSG_START: + loadlvlpal(Map.AbsoluteScr(warpdestmap,warpdestscr)->color); + rebuild_trans_table(); + break; + + case MSG_DRAW: + { + scare_mouse(); + jwin_draw_frame(screen, d->x, d->y, d->w, d->h, FR_DEEP); + + if(AnimationOn||CycleOn) + { + if(AnimationOn) + { + animate_combos(); + } + + if(CycleOn) + { + cycle_palette(); + } + } + + animate_coords(); + Map.draw(bmp, 0, 0, 0, warpdestmap, warpdestscr); + blit(icon_bmp[ICON_BMP_WARPDEST][coord_frame], bmp, 0, 0, Map.AbsoluteScr(warpdestmap,warpdestscr)->warparrivalx, Map.AbsoluteScr(warpdestmap,warpdestscr)->warparrivaly, 16, 16); + int px2=((gui_mouse_x()-d->x-2)&0xF8); + int py2=((gui_mouse_y()-d->y-2)&0xF8); + + if(isinRect(gui_mouse_x(), gui_mouse_y(), d->x+2,d->y+2,d->x+256+1,d->y+176+1)) + { + if(gui_mouse_b()) + { + if(!mousedown||!inrect) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_BLANK][0]); + zq_set_mouse_range(d->x+2, d->y+2, d->x+256+1, d->y+176+1); + } + + rect(bmp, px2, py2, px2+15, py2+15, vc(15)); + warpdestsel_x=px2; + warpdestsel_y=py2; + mousedown=true; + } + else + { + if(mousedown||!inrect) + { + zq_set_mouse_range(0,0,zq_screen_w-1,zq_screen_h-1); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_POINT_BOX][0]); + } + + mousedown=false; + } + + inrect=true; + } + else + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + inrect=false; + } + + blit(bmp, screen, 0, 0, d->x+2, d->y+2, 256, 176); + unscare_mouse(); + } + break; + + case MSG_VSYNC: + d->flags|=D_DIRTY; + break; + + case MSG_END: + loadlvlpal(Map.CurrScr()->color); + rebuild_trans_table(); + break; + } + + return ret; +} + +int d_vsync_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + d=d; + + static clock_t tics; + + switch(msg) + { + case MSG_START: + tics=clock()+(CLOCKS_PER_SEC/60); + break; + + case MSG_IDLE: + if(clock()>tics) + { + tics=clock()+(CLOCKS_PER_SEC/60); + broadcast_dialog_message(MSG_VSYNC, c); + } + + break; + } + + return D_O_K; +} + +#if 0 +static DIALOG warpdestsel_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 297, 234, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Select Warp Destination", NULL, NULL }, + { jwin_button_proc, 6, 207, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 70, 207, 93, 21, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Use Warp Square", NULL, NULL }, + { jwin_button_proc, 166, 207, 61, 21, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Use Origin", NULL, NULL }, + { jwin_button_proc, 230, 207, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_warpdestsel_proc, 19, 23, 260, 180, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_vsync_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_warpbutton_proc(int msg,DIALOG *d,int c) +{ + int ret=jwin_button_proc(msg,d,c); + + if(ret==D_EXIT) + { + warpdestsel_dlg[0].dp2=lfont; + warpdestmap=DMaps[(d-4)->d1].map; + warpdestscr=DMaps[(d-4)->d1].xoff+xtoi((char*)((d-1)->dp)); + ret=zc_popup_dialog(warpdestsel_dlg,-1); + + switch(ret) + { + case 1: + d->d1=warpdestsel_x; + d->d2=warpdestsel_y; + sprintf((char *)d->dp, "at: %dx%d", warpdestsel_x, warpdestsel_y); + break; + + case 2: + d->d1=-1; + d->d2=-1; + sprintf((char *)d->dp, "at: warp square"); + break; + + case 3: + d->d1=-2; + d->d2=-2; + sprintf((char *)d->dp, "at: origin"); + break; + + default: + break; + } + + d->flags|=D_DIRTY; + } + + return ret?D_O_K:D_O_K; +} +#endif + +int jwin_minibutton_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_DRAW: + jwin_draw_text_button(screen, d->x, d->y, d->w, d->h, (char*)d->dp, d->flags, false); + return D_O_K; + break; + } + + return jwin_button_proc(msg,d,c); +} + +int d_triggerbutton_proc(int msg,DIALOG *d,int c) +{ + static BITMAP *dummy=create_bitmap_ex(8, 1, 1); + + switch(msg) + { + case MSG_START: + d->w=gui_textout_ln(dummy, font, (unsigned char *)d->dp, 0, 0, jwin_pal[jcMEDDARK], -1, 0)+4; + d->h=text_height(font)+5; + break; + + case MSG_GOTFOCUS: + d->flags&=~D_GOTFOCUS; + break; + + } + + return jwin_minibutton_proc(msg,d,c); +} + +int d_alltriggerbutton_proc(int msg,DIALOG *d,int c) +{ + DIALOG *temp_d; + int ret=d_triggerbutton_proc(msg,d,c); + + switch(msg) + { + case MSG_CLICK: + temp_d=d-1; + + while(temp_d->proc==d_triggerbutton_proc) + { + temp_d->flags&=~D_SELECTED; + temp_d->flags|=D_DIRTY; + + if(d->flags&D_SELECTED) + { + temp_d->flags|=D_SELECTED; + } + + --temp_d; + } + + break; + } + + return ret; +} + +int d_ticsedit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_DRAW) + { + scare_mouse(); + int tics=vbound(atoi((char*)d->dp),0,65535); + sprintf((char*)(d+1)->dp,"%s %s",ticksstr(tics),tics==0?"(No Timed Warp)":" "); + object_message(d+1,MSG_DRAW,c); + unscare_mouse(); + } + + return ret; +} + +static ListData warp_effect_list(warpeffectlist,&font); + +#if 0 +static DIALOG warp_dlg2[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 320, 240, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Edit Warps", NULL, NULL }, + { jwin_button_proc, 70, 215, 41, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 130, 215, 41, 21, vc(14), vc(1), 'g', D_EXIT, 0, 0, (void *) "&Go", NULL, NULL }, + { jwin_button_proc, 190, 215, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + //5 + { jwin_tab_proc, 6, 25, 308, 184, 0, 0, 0, 0, 0, 0, (void *) warp_tabs, NULL, (void *)warp_dlg }, + { jwin_tab_proc, 10, 45, 300, 159, 0, 0, 0, 0, 0, 0, (void *) side_warp_tabs, NULL, (void *)warp_dlg }, + { jwin_tab_proc, 10, 45, 300, 159, 0, 0, 0, 0, 0, 0, (void *) wind_warp_tabs, NULL, (void *)warp_dlg }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //10 + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + //15 + { jwin_text_proc, 14, 69, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Type:", NULL, NULL }, + { jwin_text_proc, 14, 87, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "DMap:", NULL, NULL }, + { jwin_droplist_proc, 43, 65, 111, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_dlg_list, NULL, NULL }, + { d_dropdmaplist_proc, 43, 83, 222, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &dmap_list, NULL, warpdmapxy }, + { d_dmapscrsel_proc, 45, 108, 65, 33, vc(14), vc(5), 0, 0, 1, 0, NULL, NULL, NULL }, + //20 + { jwin_text_proc, 116, 110, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_edit_proc, 166, 106, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { d_warpbutton_proc, 191, 104, 90, 21, vc(14), vc(1), 0, D_EXIT, -1, -1, NULL, NULL, NULL }, + { jwin_check_proc, 116, 121, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Enabled", NULL, NULL }, + { jwin_check_proc, 116, 132, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Full Screen", NULL, NULL }, + //25 + { jwin_text_proc, 14, 149, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Out Effect:", NULL, NULL }, + { jwin_text_proc, 14, 167, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "In Effect:", NULL, NULL }, + { jwin_droplist_proc, 68, 145, 137, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_effect_list, NULL, NULL }, + { jwin_droplist_proc, 68, 163, 137, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &warp_effect_list, NULL, NULL }, + { jwin_text_proc, 14, 185, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Tics:", NULL, NULL }, + //30 + { d_ticsedit_proc, 40, 181, 36, 16, vc(11), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { jwin_text_proc, 77, 185, 0, 8, vc(11), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_frame_proc, 211, 132, 95, 64, 0, 0, 0, 0, FR_ETCHED, 0, NULL, NULL, NULL }, + { jwin_text_proc, 215, 129, 40, 8, vc(0), vc(11), 0, 0, 0, 0, (void *) " Triggers ", NULL, NULL }, + { d_triggerbutton_proc, 215, 139, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Up", NULL, NULL }, + //35 + { d_triggerbutton_proc, 229, 139, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Down", NULL, NULL }, + { d_triggerbutton_proc, 254, 139, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Left", NULL, NULL }, + { d_triggerbutton_proc, 277, 139, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Right", NULL, NULL }, + { d_triggerbutton_proc, 221, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "A", NULL, NULL }, + { d_triggerbutton_proc, 230, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "B", NULL, NULL }, + //40 + { d_triggerbutton_proc, 239, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "X", NULL, NULL }, + { d_triggerbutton_proc, 249, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Y", NULL, NULL }, + { d_triggerbutton_proc, 259, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "L", NULL, NULL }, + { d_triggerbutton_proc, 268, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "R", NULL, NULL }, + { d_triggerbutton_proc, 277, 152, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Map", NULL, NULL }, + //45 + { d_triggerbutton_proc, 230, 165, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Select", NULL, NULL }, + { d_triggerbutton_proc, 260, 165, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "Start", NULL, NULL }, + { d_alltriggerbutton_proc, 252, 179, 129, 9, vc(14), vc(1), 0, 0, 1, 0, (void *) "All", NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; +#endif + +int onTileWarp() +{ + int tempx5=warp_dlg[5].x; + int tempx6=warp_dlg[6].x; + int tempx10=warp_dlg[10].x; + int tempx11=warp_dlg[11].x; + int tempx12=warp_dlg[12].x; + int tempx13=warp_dlg[13].x; + + int tempx20=warp_dlg[20].x; + int tempx21=warp_dlg[21].x; + int tempx25=warp_dlg[25].x; + int tempx26=warp_dlg[26].x; + int tempx27=warp_dlg[27].x; + int tempx28=warp_dlg[28].x; + + int tempx32=warp_dlg[32].x; + int tempx33=warp_dlg[33].x; + int tempx37=warp_dlg[37].x; + int tempx38=warp_dlg[38].x; + int tempx39=warp_dlg[39].x; + int tempx40=warp_dlg[40].x; + + int tempx44=warp_dlg[44].x; + int tempx45=warp_dlg[45].x; + int tempx49=warp_dlg[49].x; + int tempx50=warp_dlg[50].x; + int tempx51=warp_dlg[51].x; + int tempx52=warp_dlg[52].x; + restore_mouse(); + warp_dlg[0].dp=(void *) "Tile Warp"; + warp_dlg[0].dp2=lfont; + warp_dlg[5].x = SCREEN_W+10; + warp_dlg[6].x = SCREEN_W+10; + warp_dlg[10].x = SCREEN_W+10; + warp_dlg[11].x = SCREEN_W+10; + warp_dlg[12].x = SCREEN_W+10; + warp_dlg[13].x = SCREEN_W+10; + warp_dlg[20].x = SCREEN_W+10; + warp_dlg[21].x = SCREEN_W+10; + warp_dlg[25].x = SCREEN_W+10; + warp_dlg[26].x = SCREEN_W+10; + warp_dlg[27].x = SCREEN_W+10; + warp_dlg[28].x = SCREEN_W+10; + warp_dlg[32].x = SCREEN_W+10; + warp_dlg[33].x = SCREEN_W+10; + warp_dlg[37].x = SCREEN_W+10; + warp_dlg[38].x = SCREEN_W+10; + warp_dlg[39].x = SCREEN_W+10; + warp_dlg[40].x = SCREEN_W+10; + warp_dlg[44].x = SCREEN_W+10; + warp_dlg[45].x = SCREEN_W+10; + warp_dlg[49].x = SCREEN_W+10; + warp_dlg[50].x = SCREEN_W+10; + warp_dlg[51].x = SCREEN_W+10; + warp_dlg[52].x = SCREEN_W+10; + + for(int i=0; i<4; i++) + { + warp_dlg[10+i].d2 = 0; + warp_dlg[25+i].d2 = 0; + warp_dlg[37+i].d2 = 0; + warp_dlg[49+i].d2 = 0; + } + + char buf[10]; + char buf2[10]; + char buf3[10]; + char buf4[10]; + sprintf(buf,"%02X",Map.CurrScr()->tilewarpscr[0]); + warp_dlg[7].d1=Map.CurrScr()->tilewarptype[0]; + warp_dlg[8].d1=Map.CurrScr()->tilewarpdmap[0]; + warp_dlg[9].dp=buf; + + sprintf(buf2,"%02X",Map.CurrScr()->tilewarpscr[1]); + warp_dlg[22].d1=Map.CurrScr()->tilewarptype[1]; + warp_dlg[23].d1=Map.CurrScr()->tilewarpdmap[1]; + warp_dlg[24].dp=buf2; + + sprintf(buf3,"%02X",Map.CurrScr()->tilewarpscr[2]); + warp_dlg[34].d1=Map.CurrScr()->tilewarptype[2]; + warp_dlg[35].d1=Map.CurrScr()->tilewarpdmap[2]; + warp_dlg[36].dp=buf3; + + sprintf(buf4,"%02X",Map.CurrScr()->tilewarpscr[3]); + warp_dlg[46].d1=Map.CurrScr()->tilewarptype[3]; + warp_dlg[47].d1=Map.CurrScr()->tilewarpdmap[3]; + warp_dlg[48].dp=buf4; + + warp_dlg[63].flags = get_bit(&Map.CurrScr()->tilewarpoverlayflags,0)?D_SELECTED:0; + warp_dlg[64].flags = get_bit(&Map.CurrScr()->tilewarpoverlayflags,1)?D_SELECTED:0; + warp_dlg[65].flags = get_bit(&Map.CurrScr()->tilewarpoverlayflags,2)?D_SELECTED:0; + warp_dlg[66].flags = get_bit(&Map.CurrScr()->tilewarpoverlayflags,3)?D_SELECTED:0; + + word j=Map.CurrScr()->warpreturnc; + warp_dlg[54].d1=(j&3); + warp_dlg[56].d1=((j>>2)&3); + warp_dlg[58].d1=((j>>4)&3); + warp_dlg[60].d1=((j>>6)&3); + warp_dlg[2].fg=vc(14); + warp_dlg[17].fg=vc(14); + warp_dlg[29].fg=vc(14); + warp_dlg[41].fg=vc(14); + //warp_dlg[5].fg=vc(7); + //for(int i=0; i<4; i++) + //warp_dlg[10+i].d2 = 0; + dmap_list_size=MAXDMAPS; + dmap_list_zero=true; + + if(is_large) + { + large_dialog(warp_dlg); + + if(warp_dlg[0].d1<2) + { + warp_dlg[0].d1=2; + warp_dlg[6].x += 2; + warp_dlg[10].w -= 8; + warp_dlg[10].y -= 4; + warp_dlg[11].w -= 8; + warp_dlg[11].y -= 2; + warp_dlg[12].h -= 8; + warp_dlg[12].x -= 2; + warp_dlg[12].y -= 2; + warp_dlg[13].h -= 8; + warp_dlg[13].x += 1; + warp_dlg[13].y -= 2; + + warp_dlg[21].x += 2; + warp_dlg[25].w -= 8; + warp_dlg[25].y -= 4; + warp_dlg[26].w -= 8; + warp_dlg[26].y -= 2; + warp_dlg[27].h -= 8; + warp_dlg[27].x -= 2; + warp_dlg[27].y -= 2; + warp_dlg[28].h -= 8; + warp_dlg[28].x += 1; + warp_dlg[28].y -= 2; + + warp_dlg[33].x += 2; + warp_dlg[37].w -= 8; + warp_dlg[37].y -= 4; + warp_dlg[38].w -= 8; + warp_dlg[38].y -= 2; + warp_dlg[39].h -= 8; + warp_dlg[39].x -= 2; + warp_dlg[39].y -= 2; + warp_dlg[40].h -= 8; + warp_dlg[40].x += 1; + warp_dlg[40].y -= 2; + + warp_dlg[45].x += 2; + warp_dlg[49].w -= 8; + warp_dlg[49].y -= 4; + warp_dlg[50].w -= 8; + warp_dlg[50].y -= 2; + warp_dlg[51].h -= 8; + warp_dlg[51].x -= 2; + warp_dlg[51].y -= 2; + warp_dlg[52].h -= 8; + warp_dlg[52].x += 1; + warp_dlg[52].y -= 2; + } + + for(int i=0; i<4; i++) + { + warp_dlg[i+67].x=493; + warp_dlg[i+67].y=329; + warp_dlg[i+67].w=64; + warp_dlg[i+67].h=32; + } + } + + int ret=zc_popup_dialog(warp_dlg,-1); + + if(ret==14 || ret==15) + { + saved=false; + Map.CurrScr()->tilewarpscr[0] = xtoi(buf); + Map.CurrScr()->tilewarptype[0] = warp_dlg[7].d1; + Map.CurrScr()->tilewarpdmap[0] = warp_dlg[8].d1; + Map.CurrScr()->tilewarpscr[1] = xtoi(buf2); + Map.CurrScr()->tilewarptype[1] = warp_dlg[22].d1; + Map.CurrScr()->tilewarpdmap[1] = warp_dlg[23].d1; + Map.CurrScr()->tilewarpscr[2] = xtoi(buf3); + Map.CurrScr()->tilewarptype[2] = warp_dlg[34].d1; + Map.CurrScr()->tilewarpdmap[2] = warp_dlg[35].d1; + Map.CurrScr()->tilewarpscr[3] = xtoi(buf4); + Map.CurrScr()->tilewarptype[3] = warp_dlg[46].d1; + Map.CurrScr()->tilewarpdmap[3] = warp_dlg[47].d1; + + Map.CurrScr()->tilewarpoverlayflags=0; + set_bit(&Map.CurrScr()->tilewarpoverlayflags,0,(warp_dlg[63].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->tilewarpoverlayflags,1,(warp_dlg[64].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->tilewarpoverlayflags,2,(warp_dlg[65].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->tilewarpoverlayflags,3,(warp_dlg[66].flags & D_SELECTED)?1:0); + + j=Map.CurrScr()->warpreturnc&0xFF00; + word newWarpReturns=0; + newWarpReturns|=warp_dlg[60].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[58].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[56].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[54].d1; + j|=newWarpReturns; + Map.CurrScr()->warpreturnc = j; + refresh(rMENU); + + } + + if(ret==15) + { + int index=0; + + if(warp_tabs[0].flags & D_SELECTED) index = 0; + + if(warp_tabs[1].flags & D_SELECTED) index = 1; + + if(warp_tabs[2].flags & D_SELECTED) index = 2; + + if(warp_tabs[3].flags & D_SELECTED) index = 3; + + FlashWarpSquare = -1; + int tm = Map.getCurrMap(); + int ts = Map.getCurrScr(); + int thistype = Map.CurrScr()->tilewarptype[index]; + Map.dowarp(0,index); + + if((ts!=Map.getCurrScr() || tm!=Map.getCurrMap()) && thistype != wtCAVE && thistype != wtSCROLL) + { + FlashWarpSquare = (TheMaps[tm*MAPSCRS+ts].warpreturnc>>(index*2))&3; + FlashWarpClk = 32; + } + + refresh(rALL); + } + + warp_dlg[5].x = tempx5; + warp_dlg[6].x = tempx6; + warp_dlg[10].x = tempx10; + warp_dlg[11].x = tempx11; + warp_dlg[12].x = tempx12; + warp_dlg[13].x = tempx13; + + warp_dlg[20].x = tempx20; + warp_dlg[21].x = tempx21; + warp_dlg[25].x = tempx25; + warp_dlg[26].x = tempx26; + warp_dlg[27].x = tempx27; + warp_dlg[28].x = tempx28; + + warp_dlg[32].x = tempx32; + warp_dlg[33].x = tempx33; + warp_dlg[37].x = tempx37; + warp_dlg[38].x = tempx38; + warp_dlg[39].x = tempx39; + warp_dlg[40].x = tempx40; + + warp_dlg[44].x = tempx44; + warp_dlg[45].x = tempx45; + warp_dlg[49].x = tempx49; + warp_dlg[50].x = tempx50; + warp_dlg[51].x = tempx51; + warp_dlg[52].x = tempx52; + + for(int i=0; i<4; i++) + { + warp_dlg[10+i].d2 = 0x80; + warp_dlg[25+i].d2 = 0x80; + warp_dlg[37+i].d2 = 0x80; + warp_dlg[49+i].d2 = 0x80; + } + + return D_O_K; +} + +int onSideWarp() +{ + restore_mouse(); + warp_dlg[0].dp=(void *) "Side Warp"; + warp_dlg[0].dp2=lfont; + warp_dlg[7].flags = 0; + warp_dlg[22].flags = 0; + warp_dlg[34].flags = 0; + warp_dlg[46].flags = 0; + + char buf[10]; + char buf2[10]; + char buf3[10]; + char buf4[10]; + sprintf(buf,"%02X",Map.CurrScr()->sidewarpscr[0]); + warp_dlg[7].d1=Map.CurrScr()->sidewarptype[0]; + warp_dlg[8].d1=Map.CurrScr()->sidewarpdmap[0]; + warp_dlg[9].dp=buf; + + sprintf(buf2,"%02X",Map.CurrScr()->sidewarpscr[1]); + warp_dlg[22].d1=Map.CurrScr()->sidewarptype[1]; + warp_dlg[23].d1=Map.CurrScr()->sidewarpdmap[1]; + warp_dlg[24].dp=buf2; + + sprintf(buf3,"%02X",Map.CurrScr()->sidewarpscr[2]); + warp_dlg[34].d1=Map.CurrScr()->sidewarptype[2]; + warp_dlg[35].d1=Map.CurrScr()->sidewarpdmap[2]; + warp_dlg[36].dp=buf3; + + sprintf(buf4,"%02X",Map.CurrScr()->sidewarpscr[3]); + warp_dlg[46].d1=Map.CurrScr()->sidewarptype[3]; + warp_dlg[47].d1=Map.CurrScr()->sidewarpdmap[3]; + warp_dlg[48].dp=buf4; + + warp_dlg[63].flags = get_bit(&Map.CurrScr()->sidewarpoverlayflags,0)?D_SELECTED:0; + warp_dlg[64].flags = get_bit(&Map.CurrScr()->sidewarpoverlayflags,1)?D_SELECTED:0; + warp_dlg[65].flags = get_bit(&Map.CurrScr()->sidewarpoverlayflags,2)?D_SELECTED:0; + warp_dlg[66].flags = get_bit(&Map.CurrScr()->sidewarpoverlayflags,3)?D_SELECTED:0; + + word j=Map.CurrScr()->warpreturnc>>8; + warp_dlg[54].d1=(j&3); + warp_dlg[56].d1=((j>>2)&3); + warp_dlg[58].d1=((j>>4)&3); + warp_dlg[60].d1=((j>>6)&3); + + warp_dlg[2].fg=warp_dlg[5].fg=vc(14); + warp_dlg[17].fg=warp_dlg[20].fg=vc(14); + warp_dlg[29].fg=warp_dlg[32].fg=vc(14); + warp_dlg[41].fg=warp_dlg[44].fg=vc(14); + byte f=Map.CurrScr()->flags2; + byte h=Map.CurrScr()->sidewarpindex; + byte g=f&240; + + for(int i=0; i<4; i++) + { + warp_dlg[10+i].d2 = 0x80; + warp_dlg[25+i].d2 = 0x80; + warp_dlg[37+i].d2 = 0x80; + warp_dlg[49+i].d2 = 0x80; + + if(f&1) + { + warp_dlg[10+i].flags = D_SELECTED ; + warp_dlg[10+i].d2 |= h&3; + warp_dlg[25+i].flags = D_SELECTED ; + warp_dlg[25+i].d2 |= h&3; + warp_dlg[37+i].flags = D_SELECTED ; + warp_dlg[37+i].d2 |= h&3; + warp_dlg[49+i].flags = D_SELECTED ; + warp_dlg[49+i].d2 |= h&3; + } + else + { + warp_dlg[10+i].flags = 0; + warp_dlg[25+i].flags = 0; + warp_dlg[37+i].flags = 0; + warp_dlg[49+i].flags = 0; + } + + f>>=1; + h>>=2; + } + + dmap_list_size=MAXDMAPS; + dmap_list_zero=true; + + if(is_large) + { + large_dialog(warp_dlg); + + if(warp_dlg[0].d1<2) + { + warp_dlg[0].d1=2; + warp_dlg[6].x += 2; + warp_dlg[10].w -= 8; + warp_dlg[10].y -= 4; + warp_dlg[11].w -= 8; + warp_dlg[11].y -= 2; + warp_dlg[12].h -= 8; + warp_dlg[12].x -= 2; + warp_dlg[12].y -= 2; + warp_dlg[13].h -= 8; + warp_dlg[13].x += 1; + warp_dlg[13].y -= 2; + + warp_dlg[21].x += 2; + warp_dlg[25].w -= 8; + warp_dlg[25].y -= 4; + warp_dlg[26].w -= 8; + warp_dlg[26].y -= 2; + warp_dlg[27].h -= 8; + warp_dlg[27].x -= 2; + warp_dlg[27].y -= 2; + warp_dlg[28].h -= 8; + warp_dlg[28].x += 1; + warp_dlg[28].y -= 2; + + warp_dlg[33].x += 2; + warp_dlg[37].w -= 8; + warp_dlg[37].y -= 4; + warp_dlg[38].w -= 8; + warp_dlg[38].y -= 2; + warp_dlg[39].h -= 8; + warp_dlg[39].x -= 2; + warp_dlg[39].y -= 2; + warp_dlg[40].h -= 8; + warp_dlg[40].x += 1; + warp_dlg[40].y -= 2; + + warp_dlg[45].x += 2; + warp_dlg[49].w -= 8; + warp_dlg[49].y -= 4; + warp_dlg[50].w -= 8; + warp_dlg[50].y -= 2; + warp_dlg[51].h -= 8; + warp_dlg[51].x -= 2; + warp_dlg[51].y -= 2; + warp_dlg[52].h -= 8; + warp_dlg[52].x += 1; + warp_dlg[52].y -= 2; + } + } + + int ret=zc_popup_dialog(warp_dlg,-1); + + if(ret==14 || ret==15) + { + saved=false; + Map.CurrScr()->sidewarpscr[0] = xtoi(buf); + Map.CurrScr()->sidewarptype[0] = warp_dlg[7].d1; + Map.CurrScr()->sidewarpdmap[0] = warp_dlg[8].d1; + Map.CurrScr()->sidewarpscr[1] = xtoi(buf2); + Map.CurrScr()->sidewarptype[1] = warp_dlg[22].d1; + Map.CurrScr()->sidewarpdmap[1] = warp_dlg[23].d1; + Map.CurrScr()->sidewarpscr[2] = xtoi(buf3); + Map.CurrScr()->sidewarptype[2] = warp_dlg[34].d1; + Map.CurrScr()->sidewarpdmap[2] = warp_dlg[35].d1; + Map.CurrScr()->sidewarpscr[3] = xtoi(buf4); + Map.CurrScr()->sidewarptype[3] = warp_dlg[46].d1; + Map.CurrScr()->sidewarpdmap[3] = warp_dlg[47].d1; + + Map.CurrScr()->sidewarpoverlayflags=0; + set_bit(&Map.CurrScr()->sidewarpoverlayflags,0,(warp_dlg[63].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->sidewarpoverlayflags,1,(warp_dlg[64].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->sidewarpoverlayflags,2,(warp_dlg[65].flags & D_SELECTED)?1:0); + set_bit(&Map.CurrScr()->sidewarpoverlayflags,3,(warp_dlg[66].flags & D_SELECTED)?1:0); + + f=0; + h=0; + + for(int i=3; i>=0; i--) + { + f<<=1; + h<<=2; + //f |= warp_dlg[49+i].flags&D_SELECTED ? 1 : 0; + //f |= warp_dlg[37+i].flags&D_SELECTED ? 1 : 0; + //f |= warp_dlg[25+i].flags&D_SELECTED ? 1 : 0; + f |= warp_dlg[10+i].flags&D_SELECTED ? 1 : 0; + int t=0; + /*if(warp_dlg[10+i].flags&D_SELECTED) t=0; + else if(warp_dlg[25+i].flags&D_SELECTED) t=1; + else if(warp_dlg[37+i].flags&D_SELECTED) t=2; + else if(warp_dlg[49+i].flags&D_SELECTED) t=3;*/ + t=warp_dlg[10+i].d2&3; + h|=t; + } + + f+=g; + Map.CurrScr()->flags2 = f; + Map.CurrScr()->sidewarpindex = h; + + j=Map.CurrScr()->warpreturnc&0x00FF; + word newWarpReturns=0; + newWarpReturns|=warp_dlg[60].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[58].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[56].d1; + newWarpReturns<<=2; + newWarpReturns|=warp_dlg[54].d1; + newWarpReturns<<=8; + j|=newWarpReturns; + Map.CurrScr()->warpreturnc = j; + refresh(rMENU); + } + + if(ret==15) + { + int index=0; + + if(warp_tabs[0].flags & D_SELECTED) index = 0; + + if(warp_tabs[1].flags & D_SELECTED) index = 1; + + if(warp_tabs[2].flags & D_SELECTED) index = 2; + + if(warp_tabs[3].flags & D_SELECTED) index = 3; + + FlashWarpSquare = -1; + int tm = Map.getCurrMap(); + int ts = Map.getCurrScr(); + int thistype = Map.CurrScr()->sidewarptype[index]; + Map.dowarp(1,index); + + if((ts!=Map.getCurrScr() || tm!=Map.getCurrMap()) && thistype != wtSCROLL) + { + FlashWarpSquare = (TheMaps[tm*MAPSCRS+ts].warpreturnc>>(8+index*2))&3; + FlashWarpClk = 0x20; + } + + refresh(rALL); + } + + return D_O_K; +} + +/*******************************/ +/*********** onPath ************/ +/*******************************/ + +const char *dirlist(int index, int *list_size) +{ + if(index>=0) + { + if(index>3) + index=3; + + return dirstr[index]; + } + + *list_size=4; + return NULL; +} + +static ListData path_dlg_list(dirlist, &font); + +static DIALOG path_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 80, 57, 161, 164, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Maze Path", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 94, 106, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "1st", NULL, NULL }, + { jwin_text_proc, 94, 124, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "2nd", NULL, NULL }, + { jwin_text_proc, 94, 142, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "3rd", NULL, NULL }, + { jwin_text_proc, 94, 160, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "4th", NULL, NULL }, + { jwin_text_proc, 94, 178, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Exit", NULL, NULL }, + { jwin_droplist_proc, 140, 102, 80+1, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &path_dlg_list, NULL, NULL }, + { jwin_droplist_proc, 140, 120, 80+1, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &path_dlg_list, NULL, NULL }, + { jwin_droplist_proc, 140, 138, 80+1, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &path_dlg_list, NULL, NULL }, + { jwin_droplist_proc, 140, 156, 80+1, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &path_dlg_list, NULL, NULL }, + { jwin_droplist_proc, 140, 174, 80+1, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &path_dlg_list, NULL, NULL }, + { jwin_button_proc, 90, 194, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 194, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { jwin_text_proc, 87, 82, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "A Lost Woods-style maze screen", NULL, NULL }, + { jwin_text_proc, 87, 92, 192, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "with a normal and secret exit.", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onPath() +{ + restore_mouse(); + path_dlg[0].dp2=lfont; + + for(int i=0; i<4; i++) + path_dlg[i+7].d1 = Map.CurrScr()->path[i]; + + path_dlg[11].d1 = Map.CurrScr()->exitdir; + + if(is_large) + large_dialog(path_dlg); + + int ret; + + do + { + ret=zc_popup_dialog(path_dlg,7); + + if(ret==12) for(int i=0; i<4; i++) + { + if(path_dlg[i+7].d1 == path_dlg[11].d1) + { + if(jwin_alert("Exit Problem","One of the path's directions is","also the normal Exit direction! Continue?",NULL,"Yes","No",'y','n',lfont)==2) + ret = -1; + + break; + } + } + } + while(ret == -1); + + if(ret==12) + { + saved=false; + + for(int i=0; i<4; i++) + Map.CurrScr()->path[i] = path_dlg[i+7].d1; + + Map.CurrScr()->exitdir = path_dlg[11].d1; + + if(!(Map.CurrScr()->flags&fMAZE)) + if(jwin_alert("Screen Flag","Turn on the 'Use Maze Path' Screen Flag?","(Go to 'Screen Data' to turn it off.)",NULL,"Yes","No",'y','n',lfont)==1) + Map.CurrScr()->flags |= fMAZE; + } + + refresh(rMAP+rMENU); + return D_O_K; +} + +/********************************/ +/********* onInfoTypes **********/ +/********************************/ + +static std::string getInfoShopListItem(int index) +{ + char buf[37]; + sprintf(buf, "%d: %s", index, misc.info[index].name); + return buf; +} + +int onInfoTypes() +{ + SimpleListSelector sls("Info shop types", getInfoShopListItem, 256, true, 0); + + gui->showDialog(sls); + int ret=sls.getSelected(); + while(ret>=0) + { + InfoShopEditor ise(misc.info[ret], msgList); + gui->showDialog(ise); + + sls.setInitialSelection(ret); + gui->showDialog(sls); + ret=sls.getSelected(); + } + + return D_O_K; +} + +/********************************/ +/********* onShopTypes **********/ +/********************************/ + +static std::string getShopListItem(int index) +{ + char buf[37]; + sprintf(buf, "%d: %s", index, misc.shop[index].name); + return buf; +} + +int onShopTypes() +{ + build_bii_list(true); // ... + SimpleListSelector sls("Shop types", getShopListItem, 256, true, 0); + gui->showDialog(sls); + int ret=sls.getSelected(); + while(ret>=0) + { + ShopEditor se(misc.shop[ret], bii); + gui->showDialog(se); + + sls.setInitialSelection(ret); + gui->showDialog(sls); + ret=sls.getSelected(); + } + + return D_O_K; +} + +/***********************************/ +/********* onItemDropSets **********/ +/***********************************/ + +static char item_drop_set_str_buf[40]; +int item_drop_set_list_size=MAXITEMDROPSETS; + +const char *itemdropsetlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,item_drop_set_list_size-1); + sprintf(item_drop_set_str_buf,"%3d: %s",index,item_drop_sets[index].name); + return item_drop_set_str_buf; + } + + *list_size=item_drop_set_list_size; + return NULL; +} + +int d_itemdropedit_proc(int msg,DIALOG *d,int c); + +static int edititemdropset_1_list[] = +{ + // dialog control number + 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,24,25,26,27,28, -1 +}; + +static int edititemdropset_2_list[] = +{ + // dialog control number + 12, 13, 29, 30, 31, 32, 33,34,35,36,37,38,39,40,41,42,43, -1 +}; + +static TABPANEL edititemdropset_tabs[] = +{ + // (text) + { (char *)" Page 1 ", D_SELECTED, edititemdropset_1_list, 0, NULL }, + { (char *)" Page 2 ", 0, edititemdropset_2_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +static DIALOG edititemdropset_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 320, 240, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + // 2 + { jwin_button_proc, 89, 213, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 169, 213, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + + // 4 + { jwin_text_proc, 9, 29, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 39, 25, 275, 16, vc(12), vc(1), 0, 0, 32, 0, NULL, NULL, NULL }, + { jwin_text_proc, 9, 47, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Nothing Chance:", NULL, NULL }, + { d_itemdropedit_proc, 84, 43, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + + { jwin_tab_proc, 4, 65, 312, 143, vc(0), vc(15), 0, 0, 0, 0, (void *) edititemdropset_tabs, NULL, (void *)edititemdropset_dlg }, + { jwin_text_proc, 114, 43+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + // 10 + { jwin_text_proc, 10, 87, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Chance:", NULL, NULL }, + { jwin_text_proc, 56, 87, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Item:", NULL, NULL }, + { jwin_text_proc, 10, 87, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Chance:", NULL, NULL }, + { jwin_text_proc, 56, 87, 88, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Item:", NULL, NULL }, + + // 14 + { d_itemdropedit_proc, 9, 96, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 96, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 96+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 118, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 118, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 118+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 140, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 140, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 140+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 162, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 162, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 162+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 184, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 184, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 184+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, +// 29 + { d_itemdropedit_proc, 9, 96, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 96, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 96+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 118, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 118, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 118+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 140, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 140, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 140+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 162, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 162, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 37, 162+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_itemdropedit_proc, 9, 184, 26, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL }, + { d_idroplist_proc, 55, 184, 233, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 39, 184+4, 26, 16, vc(14), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_itemdropedit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_DRAW) + { + int t = atoi((char*)edititemdropset_dlg[7].dp); + + for(int i=0; i<10; ++i) + { + t += atoi((char*)edititemdropset_dlg[14+(i*3)].dp); + } + + scare_mouse(); + { + int t2 = (int)(100*atoi((char*)edititemdropset_dlg[7].dp) / zc_max(t,1)); + sprintf((char*)edititemdropset_dlg[9].dp,"%d%%%s",t2, is_large && t2 <= 11 ? " ":""); + object_message(&edititemdropset_dlg[9],MSG_DRAW,c); + } + + for(int i=0; i<10; ++i) + { + int t2 = (int)(100*atoi((char*)edititemdropset_dlg[14+(i*3)].dp) / zc_max(t,1)); + sprintf((char*)edititemdropset_dlg[16+(i*3)].dp,"%d%%%s",t2, is_large && t2 <= 11 ? " ":""); + object_message(&edititemdropset_dlg[16+(i*3)],MSG_DRAW,c); + } + + unscare_mouse(); + } + + return ret; +} + +void EditItemDropSet(int index) +{ + build_bii_list(true); + char chance[11][10]; + char itemdropsetname[64]; + char caption[40]; + char percent_str[11][5]; + + sprintf(caption,"Item Drop Set Data %d",index); + edititemdropset_dlg[0].dp = caption; + edititemdropset_dlg[0].dp2=lfont; + + sprintf(itemdropsetname,"%s",item_drop_sets[index].name); + edititemdropset_dlg[5].dp = itemdropsetname; + + sprintf(chance[0],"%d",item_drop_sets[index].chance[0]); + edititemdropset_dlg[7].dp = chance[0]; + + ListData item_list(itemlist, is_large ? &lfont_l : &font); + sprintf(percent_str[0]," "); + edititemdropset_dlg[9].dp = percent_str[0]; + + for(int i=0; i<10; ++i) + { + sprintf(chance[i+1],"%d",item_drop_sets[index].chance[i+1]); + edititemdropset_dlg[14+(i*3)].dp = chance[i+1]; + edititemdropset_dlg[15+(i*3)].dp = (void *) &item_list; + sprintf(percent_str[i+1]," "); + edititemdropset_dlg[16+(i*3)].dp = percent_str[i+1]; + + if(item_drop_sets[index].chance[i+1]==0) + { + edititemdropset_dlg[15+(i*3)].d1 = -2; + } + else + { + for(int j=0; j0); --count) + { + for(int i=0; (i<11); ++i) + { + if(item_drop_sets[count].chance[i]!=0) + { + found=true; + break; + } + } + + if(found) + { + break; + } + } + + return count+1; +} + +int onItemDropSets() +{ + item_drop_set_list_size = MAXITEMDROPSETS; + + int index = select_data("Item Drop Sets",0,itemdropsetlist,"Edit","Done",lfont); + + while(index!=-1) + { + EditItemDropSet(index); + index = select_data("Item Drop Sets",index,itemdropsetlist,"Edit","Done",lfont); + } + + return D_O_K; +} + +/********************************/ +/********* onWarpRings **********/ +/********************************/ + +int curr_ring; + +void EditWarpRingScr(int ring,int index) +{ + char caption[40],buf[10]; + restore_mouse(); + int tempx5=warp_dlg[5].x; + int tempx6=warp_dlg[6].x; + int tempx10=warp_dlg[10].x; + int tempx11=warp_dlg[11].x; + int tempx12=warp_dlg[12].x; + int tempx13=warp_dlg[13].x; + + int tempx[100]; + + for(int m=17; m<100; m++) + { + tempx[m-17]=warp_dlg[m].x; + + if(m!=67) + { + warp_dlg[m].x = SCREEN_W+10; + } + } + + /*int tempx20=warp_dlg[20].x; + int tempx21=warp_dlg[21].x; + int tempx25=warp_dlg[25].x; + int tempx26=warp_dlg[26].x; + int tempx27=warp_dlg[27].x; + int tempx28=warp_dlg[28].x; + + int tempx32=warp_dlg[32].x; + int tempx33=warp_dlg[33].x; + int tempx37=warp_dlg[37].x; + int tempx38=warp_dlg[38].x; + int tempx39=warp_dlg[39].x; + int tempx40=warp_dlg[40].x; + + int tempx44=warp_dlg[44].x; + int tempx45=warp_dlg[45].x; + int tempx49=warp_dlg[49].x; + int tempx50=warp_dlg[50].x; + int tempx51=warp_dlg[51].x; + int tempx52=warp_dlg[52].x;*/ + + warp_dlg[5].x = SCREEN_W+10; + warp_dlg[6].x = SCREEN_W+10; + warp_dlg[10].x = SCREEN_W+10; + warp_dlg[11].x = SCREEN_W+10; + warp_dlg[12].x = SCREEN_W+10; + warp_dlg[13].x = SCREEN_W+10; + + for(int i=0; i<4; i++) + { + warp_dlg[10+i].d2 = 0; + warp_dlg[25+i].d2 = 0; + warp_dlg[37+i].d2 = 0; + warp_dlg[49+i].d2 = 0; + } + + sprintf(caption,"Ring %d Warp %d",ring,index+1); + warp_dlg[0].dp = (void *)caption; + warp_dlg[0].dp2=lfont; + + warp_dlg[1].dp = NULL; + warp_dlg[1].dp3 = NULL; + + sprintf(buf,"%02X",misc.warp[ring].scr[index]); + warp_dlg[8].d1=misc.warp[ring].dmap[index]; + warp_dlg[9].dp=buf; + warp_dlg[24].dp=buf; + warp_dlg[36].dp=buf; + warp_dlg[48].dp=buf; + warp_dlg[2].fg=warp_dlg[5].fg=vc(7); + + for(int i=0; i<4; i++) + warp_dlg[10+i].d2 = 0; + + dmap_list_size=MAXDMAPS; + dmap_list_zero=true; + + if(is_large) + large_dialog(warp_dlg); + + int ret=zc_popup_dialog(warp_dlg,-1); + + if(ret==14 || ret==15) + { + saved=false; + misc.warp[ring].dmap[index] = warp_dlg[8].d1; + misc.warp[ring].scr[index] = xtoi(buf); + } + + if(ret==15) + { + Map.dowarp2(ring,index); + refresh(rALL); + } + + warp_dlg[5].x = tempx5; + warp_dlg[6].x = tempx6; + warp_dlg[10].x = tempx10; + warp_dlg[11].x = tempx11; + warp_dlg[12].x = tempx12; + warp_dlg[13].x = tempx13; + + for(int m=17; m<100; m++) + { + warp_dlg[m].x=tempx[m-17]; + } + + for(int i=0; i<4; i++) + { + warp_dlg[10+i].d2 = 0x80; + warp_dlg[25+i].d2 = 0x80; + warp_dlg[37+i].d2 = 0x80; + warp_dlg[49+i].d2 = 0x80; + } + + warp_dlg[1].dp = (void *) warp_tabs; + warp_dlg[1].dp3 = (void *)warp_dlg; + +} + +int d_warplist_proc(int msg,DIALOG *d,int c) +{ + if(msg==MSG_DRAW) + { + int *xy = (int*)(d->dp3); + int ring = curr_ring; + int dmap = misc.warp[ring].dmap[d->d1]; + float temp_scale = 1; + + if(is_large) + { + temp_scale = 1.5; // Scale up by 1.5 + } + + drawdmap(dmap); + + if(xy[0]||xy[1]) + { + int x = d->x+int((xy[0]-2)*temp_scale); + int y = d->y+int((xy[1]-2)*temp_scale); +// int w = is_large ? 84 : 71; +// int h = is_large ? 52 : 39; + int w = 84; + int h = 52; + jwin_draw_frame(screen,x,y,w,h,FR_DEEP); + drawdmap_screen(x+2,y+2,w-4,h-4,dmap); + } + + if(xy[2]||xy[3]) + { + textprintf_ex(screen,font,d->x+int(xy[2]*temp_scale),d->y+int(xy[3]*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Map: %d ",DMaps[dmap].map+1); + } + + if(xy[4]||xy[5]) + { + textprintf_ex(screen,font,d->x+int(xy[4]*temp_scale),d->y+int(xy[5]*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Level:%2d ",DMaps[dmap].level); + } + + if(xy[6]||xy[7]) + { + textprintf_ex(screen,font,d->x+int(xy[6]*temp_scale),d->y+int(xy[7]*temp_scale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Scr: 0x%02X ",misc.warp[ring].scr[d->d1]); + } + } + + return jwin_list_proc(msg,d,c); +} + +int d_wclist_proc(int msg,DIALOG *d,int c) +{ + int d1 = d->d1; + int ret = jwin_droplist_proc(msg,d,c); + misc.warp[curr_ring].size=d->d1+3; + + if(d->d1 != d1) + return D_CLOSE; + + return ret; +} + +const char *wclist(int index, int *list_size) +{ + static char buf[2]; + + if(index>=0) + { + if(index>6) + index=6; + + sprintf(buf,"%d",index+3); + return buf; + } + + *list_size=7; + return NULL; +} + +//int warpringdmapxy[8] = {160,116,160,90,160,102,160,154}; +int warpringdmapxy[8] = {80,26,80,0,80,12,80,78}; + +static ListData number_list(numberlist, &font); +static ListData wc_list(wclist, &font); + +static DIALOG warpring_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 0, 0, 193, 166, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 16, 33, 48, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Count:", NULL, NULL }, + { d_wclist_proc, 72, 29, 48, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &wc_list, NULL, NULL }, + // 4 + { d_warplist_proc, 16, 50, 65, 71, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &number_list, NULL, warpringdmapxy }, + { jwin_button_proc, 26, 140, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 106, 140, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int select_warp() +{ + misc.warp[curr_ring].size = vbound(misc.warp[curr_ring].size,3,9); + number_list_zero = false; + + int ret=4; + + if(is_large) + large_dialog(warpring_dlg); + + do + { + number_list_size = misc.warp[curr_ring].size; + warpring_dlg[3].d1 = misc.warp[curr_ring].size-3; + ret = zc_popup_dialog(warpring_dlg,ret); + } + while(ret==3); + + if(ret==6 || ret==0) + { + return -1; + } + + return warpring_dlg[4].d1; +} + +void EditWarpRing(int ring) +{ + char buf[40]; + sprintf(buf,"Ring %d Warps",ring); + warpring_dlg[0].dp = buf; + warpring_dlg[0].dp2 = lfont; + curr_ring = ring; + + int index = select_warp(); + + while(index!=-1) + { + EditWarpRingScr(ring,index); + index = select_warp(); + } +} + +int onWarpRings() +{ + number_list_size = 9; + number_list_zero = true; + + int index = select_data("Warp Rings",0,numberlist,"Edit","Done",lfont); + + while(index!=-1) + { + EditWarpRing(index); + number_list_size = 9; + number_list_zero = true; + index = select_data("Warp Rings",index,numberlist,"Edit","Done",lfont); + } + + return D_O_K; +} + +/********************************/ +/********** onEnemies ***********/ +/********************************/ + + +const char *pattern_list(int index, int *list_size) +{ + + if(index<0) + { + *list_size = MAXPATTERNS; + return NULL; + } + + return pattern_string[index]; +} + +static ListData pattern_dlg_list(pattern_list, &font); + +static DIALOG pattern_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 72, 56, 176+1, 164+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Enemy Pattern", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_list_proc, 80, 124, 160+1, 58, jwin_pal[jcTEXTFG],jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, (void *) &pattern_dlg_list, NULL, NULL }, + // 3 + { jwin_button_proc, 90, 190, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 170, 190, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 90, 78, 61, 10, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Classic: pseudorandom locations near", NULL, NULL }, + { jwin_text_proc, 90, 88, 61, 10, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "the middle of the screen.", NULL, NULL }, + { jwin_text_proc, 90, 102, 61, 10, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Random: any available location", NULL, NULL }, + { jwin_text_proc, 90, 112, 61, 10, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "at a sufficient distance from Link.", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onPattern() +{ + byte p=Map.CurrScr()->pattern; + pattern_dlg[0].dp2 = lfont; + pattern_dlg[2].d1 = p; + + if(is_large) + large_dialog(pattern_dlg); + + if(zc_popup_dialog(pattern_dlg,2) < 4) + { + saved=false; + Map.CurrScr()->pattern = pattern_dlg[2].d1; + } + + refresh(rMENU); + return D_O_K; +} + +// Now just calls onScrData() +int onEnemyFlags() +{ + int i=-1; + + while(scrdata_tabs[++i].text != NULL) + scrdata_tabs[i].flags = (i==2 ? D_SELECTED : 0); + + onScrData(); + return D_O_K; +} + +const char *enemy_viewer(int index, int *list_size) +{ + if(index<0) + { + *list_size=10; + + return NULL; + } + + int guy=Map.CurrScr()->enemy[index]; + return guy>=eOCTO1S ? guy_string[guy] : (char *) "(None)"; +} + +enemy_struct bie[eMAXGUYS]; +enemy_struct ce[100]; +int enemy_type=0,bie_cnt=-1,ce_cnt; + +enemy_struct big[zqMAXGUYS]; +enemy_struct cg[100]; +int guy_type=0,big_cnt=-1,cg_cnt; + +void build_bie_list(bool hide) +{ + bie[0].s = (char *)"(None)"; + bie[0].i = 0; + bie_cnt=1; + + for(int i=eOCTO1S; i= OLDMAXGUYS || old_guy_string[i][strlen(old_guy_string[i])-1]!=' ' || !hide) + { + bie[bie_cnt].s = (char *)guy_string[i]; + bie[bie_cnt].i = i; + ++bie_cnt; + } + } + + for(int i=0; i0) + { + zc_swap(bie[i],bie[j]); + } + } + } +} + +void build_big_list(bool hide) +{ + big[0].s = (char *)"(None)"; + big[0].i = 0; + big_cnt=1; + + for(int i=gABEI; i0) + { + zc_swap(big[i],big[j]); + } + } + } +} + +const char *enemylist(int index, int *list_size) +{ + if(index<0) + { + *list_size = enemy_type ? ce_cnt : bie_cnt; + return NULL; + } + + return enemy_type ? ce[index].s : bie[index].s; +} + +const char *guylist(int index, int *list_size) +{ + if(index<0) + { + *list_size = guy_type ? cg_cnt : big_cnt; + return NULL; + } + + return guy_type ? cg[index].s : big[index].s; +} + +void elist_rclick_func(int index, int x, int y); +DIALOG elist_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 50, 40, 200+24+24, 145, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_enelist_proc, 62, 68, 188, 88, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL }, + { jwin_button_proc, 90, 160, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 170, 160, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { jwin_button_proc, 220, 160, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int efrontfacingtile(int id) +{ + int anim = get_bit(quest_rules,qr_NEWENEMYTILES)?guysbuf[id].e_anim:guysbuf[id].anim; + int usetile = 0; + + switch(anim) + { + case aAQUA: + if(!(get_bit(quest_rules,qr_NEWENEMYTILES) && guysbuf[id].misc1)) + break; + + case aWALLM: + case aGHOMA: + usetile=1; + break; + + //Fallthrough + case a2FRM4DIR: + case aWALK: + usetile=2; + break; + + case aLEV: + case a3FRM4DIR: + usetile=3; + break; + + case aLANM: + usetile = !(get_bit(quest_rules,qr_NEWENEMYTILES))?0:4; + break; + + case aNEWDONGO: + case a4FRM8EYE: + case aNEWWIZZ: + case aARMOS4: + case aNEWTEK: + case aNEWWALLM: + case a4FRM4DIRF: + case a4FRM4DIR: + case a4FRM8DIRF: + case a4FRMPOS8DIR: + case a4FRMPOS8DIRF: + case a4FRMPOS4DIR: + case a4FRMPOS4DIRF: + usetile=4; + break; + + case aDONGO: + usetile=6; + break; + + case aDONGOBS: + usetile=24; + break; + + case aNEWLEV: + usetile=40; + break; + + case aNEWZORA: + if(guysbuf[id].family==eeZORA) + usetile=44; + + break; + + case aGLEEOK: + if(!get_bit(quest_rules,qr_NEWENEMYTILES)) + usetile = (guysbuf[id].s_tile - guysbuf[id].tile)+1; + else + usetile = (guysbuf[id].misc8); + + break; + } + + return zc_max(get_bit(quest_rules, qr_NEWENEMYTILES) ? -guysbuf[id].e_tile + : -guysbuf[id].tile, usetile); +} + +static ListData enemy_dlg_list(enemy_viewer, &font); + +int enelist_proc(int msg,DIALOG *d,int c,bool use_abc_list) +{ + int ret; + + /* copy/paste enemy dialog bug. -Don't change this unless you test it first! -Gleeok */ + if(use_abc_list) + ret= jwin_abclist_proc(msg,d,c); // This one's better for the full list + else + ret= jwin_list_proc(msg,d,c); + + if(msg==MSG_DRAW||msg==MSG_CHAR) + { + int id; + + // Conveniently hacking the Select Enemy and Screen Enemy dialogs together -L + if(d->dp == &enemy_dlg_list) + { + id = Map.CurrScr()->enemy[d->d1]; + } + else + { + id = bie[d->d1].i; + } + + int tile = get_bit(quest_rules, qr_NEWENEMYTILES) ? guysbuf[id].e_tile + : guysbuf[id].tile; + int cset = guysbuf[id].cset; + int x = d->x + int(195 * (is_large ? 1.5:1)); + int y = d->y + int(2 * (is_large ? 1.5:1)); + int w = 20; + int h = 20; + + if(is_large) + { + w = 36; + h = 36; + } + + BITMAP *buf = create_bitmap_ex(8,20,20); + BITMAP *bigbmp = create_bitmap_ex(8,w,h); + + if(buf && bigbmp) + { + clear_bitmap(buf); + + if(tile) + overtile16(buf, tile+efrontfacingtile(id),2,2,cset,0); + + stretch_blit(buf, bigbmp, 2,2, 17, 17, 2, 2,w-2, h-2); + destroy_bitmap(buf); + jwin_draw_frame(bigbmp,0,0,w,h,FR_DEEP); + blit(bigbmp,screen,0,0,x,y,w,h); + destroy_bitmap(bigbmp); + } + + /* + rectfill(screen, x, y+20*(is_large?2:1), x+int(w*(is_large?1.5:1))-1, y+32*(is_large?2:1)-1, vc(4)); + */ + textprintf_ex(screen,is_large?font:spfont,x,y+20*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"#%d ",id); + + textprintf_ex(screen,is_large?font:spfont,x,y+26*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"HP :"); + textprintf_ex(screen,is_large?font:spfont,x+int(14*(is_large?1.5:1)),y+26*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d ",guysbuf[id].hp); + + textprintf_ex(screen,is_large?font:spfont,x,y+32*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Dmg:"); + textprintf_ex(screen,is_large?font:spfont,x+int(14*(is_large?1.5:1)),y+32*(is_large?2:1),jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d ",guysbuf[id].dp); + } + + return ret; +} + +int select_enemy(const char *prompt,int enemy,bool hide,bool is_editor,int &exit_status) +{ + //if(bie_cnt==-1) + { + build_bie_list(hide); + } + int index=0; + + for(int j=0; jenemy,10*sizeof(word)); + restore_mouse(); + char buf[24] = " "; + int ret; + int copy=-1; + + build_bie_list(true); + + enemy_dlg[0].dp2=lfont; + + if(Map.CanPaste()) + { + enemy_dlg[3].flags=D_EXIT; + sprintf(buf,"Past&e (from %d:%02X)",(Map.CopyScr()>>8)+1,Map.CopyScr()&255); + } + else + { + enemy_dlg[3].flags=D_DISABLED; + sprintf(buf,"Past&e from screen"); + } + + enemy_dlg[3].dp=buf; + enemy_dlg[2].d1=0; + + do + { + if(copy==-1) + { + enemy_dlg[13].y=zq_screen_h; + } + else + { + enemy_dlg[13].y=(int)((copy<<3)*(is_large?1.6:1))+enemy_dlg[2].y+4; + } + + if(is_large) + { + large_dialog(enemy_dlg); + // Fix d_enelist_proc + enemy_dlg[2].dp2 = 0; + //((ListData *)enemy_dlg[2].dp)->font = &sfont3; + ((ListData *)enemy_dlg[2].dp)->font = &lfont_l; + } + + ret = zc_do_dialog(enemy_dlg,2); + + switch(ret) + { + case 2: + { + int exit_status; + int i = enemy_dlg[2].d1; + + do + { + int enemy = Map.CurrScr()->enemy[i]; + enemy = select_enemy("Select Enemy",enemy,true,false,exit_status); + + if(enemy>=0) + { + if(exit_status==5 && enemy > 0) + { + edit_enemydata(enemy); + } + else + { + saved=false; + Map.CurrScr()->enemy[i] = enemy; + } + } + } + while(exit_status==5); + } + break; + + case 3: + saved=false; + Map.PasteEnemies(); + break; + + case 5: + onEnemyFlags(); + break; + + case 6: + onPattern(); + break; + + case 7: + copy = enemy_dlg[2].d1; + break; + + case 8: + saved=false; + + if(copy>=0) + { + Map.CurrScr()->enemy[enemy_dlg[2].d1] = Map.CurrScr()->enemy[copy]; + } + + break; + + case 9: + saved=false; + Map.CurrScr()->enemy[enemy_dlg[2].d1] = 0; + break; + + case 0: + case 11: //cancel + memcpy(Map.CurrScr()->enemy,oldenemy,10*sizeof(word)); + break; + + case 10: //ok + { + bool end = false; + + for(int i=0; i<10; i++) + { + if(Map.CurrScr()->enemy[i]==0) + end = true; + else if(end) + { + if(jwin_alert("Inactive Enemies","Enemies won't appear if they're preceded"," by '(None)' in the list! Continue?",NULL,"Yes","No",'y','n',lfont)==2) + ret=-1; + + break; + } + } + + break; + } + } + } + while(ret<10&&ret!=0); + + refresh(rALL); + return D_O_K; +} + +/*******************************/ +/********** onHeader ***********/ +/*******************************/ + +char author[65],title[65],password[32]; + +int d_showedit_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_edit_proc(msg,d,c); + + if(msg==MSG_DRAW) + { + scare_mouse(); + (d+1)->proc(MSG_DRAW,d+1,0); + unscare_mouse(); + } + + return ret; +} + +static DIALOG header_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 20, 16, 280, 205, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Quest Header", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 26, 40, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "ZQ Version:", NULL, NULL }, + { jwin_text_proc, 103, 40, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, D_DISABLED, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 26, 72-16, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Quest Number:", NULL, NULL }, + { jwin_edit_proc, 100, 68-16, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 26, 90-16, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Quest Ver:", NULL, NULL }, + { jwin_edit_proc, 100, 86-16, 80, 16, vc(12), vc(1), 0, 0, 8, 0, NULL, NULL, NULL }, + { jwin_text_proc, 26, 108-16, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Min. Ver:", NULL, NULL }, + { jwin_edit_proc, 100, 104-16, 80, 16, vc(12), vc(1), 0, 0, 8, 0, NULL, NULL, NULL }, + // 10 + { jwin_text_proc, 26, 126-16, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Title:", NULL, NULL }, + { d_showedit_proc, 66, 122-16, 80, 16, vc(12), vc(1), 0, 0, 64, 0, title, NULL, NULL }, + { jwin_textbox_proc, 26, 138-16, 120, 40, vc(11), vc(1), 0, 0, 64, 0, title, NULL, NULL }, + { jwin_text_proc, 174, 126-16, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Author:", NULL, NULL }, + { d_showedit_proc, 214, 122-16, 80, 16, vc(12), vc(1), 0, 0, 64, 0, author, NULL, NULL }, + { jwin_textbox_proc, 174, 138-16, 120, 40, vc(11), vc(1), 0, 0, 64, 0, author, NULL, NULL }, + // 16 + { jwin_button_proc, 110, 204-32, 101, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Change Password", NULL, NULL }, + { jwin_button_proc, 90, 204-8, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 204-8, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG password_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 300, 111-32, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Set Password", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_text_proc, 6, 30, 96, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Enter new password:", NULL, NULL }, + { jwin_edit_proc, 104, 26, 190, 16, vc(12), vc(1), 0, 0, 255, 0, NULL, NULL, NULL }, + { jwin_check_proc, 6, 42, 128+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Save key file", NULL, NULL }, + { jwin_button_proc, 80, 54, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 160, 54, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + + +int onHeader() +{ + char zver_str[11],q_num[8],version[10],minver[10]; + + bool resize=!(get_debug()||key[KEY_LSHIFT]||key[KEY_RSHIFT]); + + if(resize) + { + for(int i=6; i<19; ++i) + { + header_dlg[i].y-=18; + } + + header_dlg[0].h-=18; + header_dlg[4].proc=d_dummy_proc; + header_dlg[5].proc=d_dummy_proc; + } + + jwin_center_dialog(header_dlg); + + sprintf(zver_str,"%d.%02X (%d)",header.zelda_version>>8,header.zelda_version&0xFF,header.build); + sprintf(q_num,"%d",header.quest_number); + strcpy(version,header.version); + strcpy(minver,header.minver); + strcpy(author,header.author); + strcpy(title,header.title); + + header_dlg[0].dp2 = lfont; + header_dlg[3].dp = zver_str; + header_dlg[5].dp = q_num; + header_dlg[7].dp = version; + header_dlg[9].dp = minver; + + password_dlg[0].dp2=lfont; + char pwd[256]; + memset(pwd,0,256); + password_dlg[3].dp=pwd; + password_dlg[4].flags=header.use_keyfile?D_SELECTED:0; + + if(is_large) + { + large_dialog(header_dlg); + large_dialog(password_dlg); + } + + int ret; + + do + { + ret=zc_popup_dialog(header_dlg,-1); + + if(ret==16) + { + ret=zc_popup_dialog(password_dlg,-1); + + if(ret==5) + { + header.use_keyfile=password_dlg[4].flags&D_SELECTED?1:0; + set_questpwd(pwd,header.use_keyfile!=0); + } + + ret=16; + } + } + while(ret==16); + + + + if(ret==17) + { + saved=false; + header.quest_number=atoi(q_num); + strcpy(header.author,author); + strcpy(header.title,title); + strcpy(header.version,version); + strcpy(header.minver,minver); + } + + if(resize) + { + for(int i=6; i<19; ++i) + { + header_dlg[i].y+=18; + } + + header_dlg[0].h+=18; + header_dlg[4].proc=jwin_text_proc; + header_dlg[5].proc=jwin_edit_proc; + } + + jwin_center_dialog(header_dlg); + + return D_O_K; +} + +int onCheats() +{ + CheatEditor ce; + gui->showDialog(ce); + return D_O_K; +} + +const char *subscrtype_str[ssdtMAX+1] = { "Original","New Subscreen","Revision 2","BS Zelda Original","BS Zelda Modified","BS Zelda Enhanced","BS Zelda Complete","Zelda 3","Custom" }; + +const char *subscrtypelist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,ssdtMAX); + return subscrtype_str[index]; + } + + *list_size=ssdtMAX+1; + return NULL; +} + +static ListData subscreen_type_dlg_list(subscrtypelist, &font); + +static DIALOG subscreen_type_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 83, 32, 154, 70, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Subscreen Type", NULL, NULL }, + { jwin_button_proc, 89, 77, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 77, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_droplist_proc, 107-8, 57, 106+15, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &subscreen_type_dlg_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onSubscreen() +{ + int tempsubscreen=zinit.subscreen; + subscreen_type_dlg[0].dp2=lfont; + subscreen_type_dlg[3].d1=zinit.subscreen; + + if(is_large) + large_dialog(subscreen_type_dlg); + + int ret = zc_popup_dialog(subscreen_type_dlg,2); + + if(ret==1) + { + if(subscreen_type_dlg[3].d1!=tempsubscreen) + { + zinit.subscreen=subscreen_type_dlg[3].d1; + + if(zinit.subscreen!=ssdtMAX) //custom + { + if(tempsubscreen==ssdtMAX) + { + if(jwin_alert("Reset Custom Subscreens","This will delete all of your custom subscreens!","Proceed?",NULL,"&OK","&Cancel",13,27,lfont)==2) + { + zinit.subscreen=ssdtMAX; + return D_O_K; + } + } + + reset_subscreens(); + setupsubscreens(); + } + + saved=false; + } + } + + return D_O_K; +} + +bool do_x_button(BITMAP *dest, int x, int y) +{ + bool over=false; + + while(gui_mouse_b()) + { + custom_vsync(); + + if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+15,y+13)) + { + if(!over) + { + scare_mouse(); + draw_x_button(dest, x, y, D_SELECTED); + unscare_mouse(); + over=true; + } + } + else + { + if(over) + { + scare_mouse(); + draw_x_button(dest, x, y, 0); + unscare_mouse(); + over=false; + } + } + } + + return over; +} + + +int d_dummy_proc(int, DIALOG*, int) +{ + return D_O_K; +} + +int d_maptile_proc(int msg, DIALOG *d, int) +{ + switch(msg) + { + case MSG_CLICK: + if(select_tile(d->d1,d->d2,1,d->fg,true, 0, true)) + return D_REDRAW; + + break; + + case MSG_DRAW: + { + int dw = d->w; + int dh = d->h; + + if(is_large && d->dp2==(void*)1) + { + dw /= 2; + dh /= 2; + } + + BITMAP *buf = create_bitmap_ex(8,dw,dh); + + if(buf) + { + clear_bitmap(buf); + + for(int y=0; yd1) + puttile16(buf,d->d1+(y>>4)*20+(x>>4),x,y,d->fg,0); + } + + if(is_large && d->dp2==(void*)1) + stretch_blit(buf,screen,0,0,dw,dh,d->x-is_large,d->y-is_large,dw*(is_large?2:1),dh*(is_large?2:1)); + else + blit(buf,screen,0,0,d->x,d->y,dw,dh); + + destroy_bitmap(buf); + } + } + } + + return D_O_K; +} + +static int last_combo=0; +static int last_cset=0; +static combo_alias temp_aliases[MAXCOMBOALIASES]; + +static char comboa_str_buf[32]; + +int d_comboalist_proc(int msg,DIALOG *d,int c) +{ + int d1 = d->d1; + int ret = jwin_droplist_proc(msg,d,c); + comboa_cnt = d->d1; + + if(d1!=d->d1) + { + set_comboaradio(temp_aliases[comboa_cnt].layermask); + return D_REDRAW; + } + + return ret; +} + +const char *comboalist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,MAXCOMBOALIASES-1); + sprintf(comboa_str_buf,"%d",index); + return comboa_str_buf; + } + + *list_size=MAXCOMBOALIASES; + return NULL; +} + +extern int scheme[jcMAX]; + +int d_comboa_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + combo_alias *combo; + combo = &temp_aliases[comboa_cnt]; + int position; + int cur_layer, temp_layer; + int lay_count=0; + int size = 1+is_large; + + int cx1=(gui_mouse_x()-d->x-(120-(combo->width*8))); + int cy1=(gui_mouse_y()-d->y-(80-(combo->height*8))); + int cx=cx1/(16*size); + int cy=cy1/(16*size); + + int co,cs; + + + switch(msg) + { + case MSG_CLICK: + Z_message("click (%d, %d) (%d, %d)\n", cx1, cy1, cx, cy); + + if((cx>combo->width)||(cx1<0)) + return D_O_K; + + if((cy>combo->height)||(cy1<0)) + return D_O_K; + + for(int j=0; jlayermask&(1<width+1)*(combo->height+1); + position+=(cy*(combo->width+1))+cx; + + if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) + { + combo->combos[position] = 0; + combo->csets[position] = 0; + + while(gui_mouse_b()) + { + /* do nothing */ + } + + return D_REDRAW; + } + + co=combo->combos[position]; + cs=combo->csets[position]; + + if((co==0)||(key[KEY_ZC_LCONTROL])) + { + co=last_combo; + cs=last_cset; + } + + if((select_combo_2(co,cs))) + { + last_combo = co; + last_cset = cs; + + combo->combos[position]=co; + combo->csets[position]=cs; + } + + return D_REDRAW; + break; + + case MSG_DRAW: + BITMAP *buf = create_bitmap_ex(8,d->w,d->h); + + if(buf) + { + clear_bitmap(buf); + + for(int z=0; z<=comboa_lmasktotal(combo->layermask); z++) + { + int k=0; + cur_layer=0; + temp_layer=combo->layermask; + + while((temp_layer!=0)&&(k>1; + } + + for(int y=0; (yh)&&((y/16)<=combo->height); y+=16) + { + for(int x=0; (xw)&&((x/16)<=combo->width); x+=16) + { + int cpos = (z*(combo->width+1)*(combo->height+1))+(((y/16)*(combo->width+1))+(x/16)); + + if(combo->combos[cpos]) + { + if(!((d-1)->flags&D_SELECTED)||(cur_layer==layer_cnt)) + { + if(z==0) + { + puttile16(buf,combobuf[combo->combos[cpos]].tile,x,y,combo->csets[cpos],combobuf[combo->combos[cpos]].flip); + } + else + { + overtile16(buf,combobuf[combo->combos[cpos]].tile,x,y,combo->csets[cpos],combobuf[combo->combos[cpos]].flip); + } + } + } + } + } + } + + rectfill(screen, d->x-2,d->y-2,d->x+256+2,d->y+176+2,jwin_pal[jcBOX]); + int dx = 120-(combo->width*8)+d->x; + int dy = 80-(combo->height*8)+d->y; + stretch_blit(buf,screen,0,0,(combo->width+1)*16,(combo->height+1)*16,dx,dy,(combo->width+1)*16*size,(combo->height+1)*16*size); + //blit(buf,screen,0,0,120-(combo->width*8)+d->x,80-(combo->height*8)+d->y,(combo->width+1)*16,(combo->height+1)*16); + (d-11)->w = (combo->width+1)*16*size+2+(is_large?0:2); + (d-11)->h = (combo->height+1)*16*size+2+(is_large?0:2); + (d-11)->x = 120-(combo->width*8)+4*size+(is_large?2:0)+(d-14)->x; + (d-11)->y = 80-(combo->height*8)+25*size+(is_large?2:0)+(d-14)->y; + object_message((d-11),MSG_DRAW,0); + + destroy_bitmap(buf); + } + + break; + } + + return D_O_K; +} + +void draw_combo_alias_thumbnail(BITMAP *dest, combo_alias *combo, int x, int y, int size) +{ + if(!combo->combo) + { + int cur_layer, temp_layer; + + int cw=combo->width+1; + int ch=combo->height+1; + int dw=cw<<4; + int dh=ch<<4; + int sw=16, sh=16, sx=0, sy=0; + + if(cw>1); + } + else + { + sh=((ch<<4)/cw); + sy=((16-sh)>>1); + } + + BITMAP *buf = create_bitmap_ex(8,dw,dh); + BITMAP *buf2 = create_bitmap_ex(8, 16*size, 16*size); + clear_bitmap(buf); + clear_bitmap(buf2); + + if(buf&&(combo->width>0||combo->height>0||combo->combos[0]>0)) + { + clear_bitmap(buf); + + for(int z=0; z<=comboa_lmasktotal(combo->layermask); z++) + { + int k=0; + cur_layer=0; + temp_layer=combo->layermask; + + while((temp_layer!=0)&&(k>1; + } + + for(int y2=0; (y2>4)<=combo->height); y2+=16) + { + for(int x2=0; (x2>4)<=combo->width); x2+=16) + { + int cpos = (z*(combo->width+1)*(combo->height+1))+(((y2/16)*(combo->width+1))+(x2/16)); + + if(combo->combos[cpos]) + { + if(z==0) + { + puttile16(buf,combobuf[combo->combos[cpos]].tile,x2,y2,combo->csets[cpos],combobuf[combo->combos[cpos]].flip); + } + else + { + overtile16(buf,combobuf[combo->combos[cpos]].tile,x2,y2,combo->csets[cpos],combobuf[combo->combos[cpos]].flip); + } + } + } + } + } + + stretch_blit(buf, buf2, 0, 0, (cw*16), (ch*16), sx*size, sy*size, sw*size, sh*size); + blit(buf2, dest, 0, 0, x, y, 16*size, 16*size); + } + else + { + rectfill(dest,x,y,x+16*size-1,y+16*size-1,0); + rectfill(dest,x+3*size,y+3*size,x+12*size,y+12*size,vc(4)); + } + + if(buf) + destroy_bitmap(buf); + + if(buf2) + destroy_bitmap(buf2); + } + else + { + if(combobuf[combo->combo].tile>0) + { + put_combo(dest,x, y, combo->combo, combo->cset,0,0); + } + else + { + rectfill(dest,x,y,x+16*size-1,y+16*size-1,0); + rectfill(dest,x+3*size,y+3*size,x+12*size,y+12*size,vc(4)); + } + } +} + +int d_comboat_proc(int msg,DIALOG *d,int) +{ + switch(msg) + { + case MSG_CLICK: + { + int c2; + int cs; + c2=temp_aliases[comboa_cnt].combo; + cs=temp_aliases[comboa_cnt].cset; + + if(gui_mouse_b()&2) //right mouse button + { + if(c2==0&&cs==0&&!(gui_mouse_b()&1)) + { + return D_O_K; + } + + temp_aliases[comboa_cnt].combo=0; + temp_aliases[comboa_cnt].cset=0; + } + + if(gui_mouse_b()&1) //left mouse button + { + if(select_combo_2(c2, cs)) + { + temp_aliases[comboa_cnt].combo=c2; + temp_aliases[comboa_cnt].cset=cs; + } + + return D_REDRAW; + } + else + { + return D_REDRAWME; + } + } + break; + + case MSG_DRAW: + draw_combo_alias_thumbnail(screen, &temp_aliases[comboa_cnt], d->x-is_large, d->y-is_large,(is_large+1)); + break; + + default: + break; + } + + return D_O_K; +} + +int d_comboa_radio_proc(int msg,DIALOG *d,int c); + +static DIALOG orgcomboa_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 200, 161, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Organize Combo Aliases", NULL, NULL }, + { jwin_button_proc, 27, 130, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 112, 130, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + + { jwin_radio_proc, 10, 40, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void*) "Copy", NULL, NULL }, + { jwin_text_proc, 10, 50, 33, 9, 0, 0, 0, 0, 0, 0, (void *) "", NULL, NULL }, + // { jwin_radio_proc, 10, 50, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void*) "Move", NULL, NULL }, + { jwin_radio_proc, 10, 60, 33, 9, vc(14), vc(1), 0, 0, 0, 0, (void*) "Swap", NULL, NULL }, + /* 6 */ { jwin_edit_proc, 110, 35, 32, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 110, 55, 32, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + { jwin_text_proc, 60, 40, 80, 8, 0, 0, 0, 0, 0, 0, (void *) "Source", NULL, NULL }, + { jwin_text_proc, 60, 60, 80, 8, 0, 0, 0, 0, 0, 0, (void *) "Dest", NULL, NULL}, + { jwin_radio_proc, 10, 80, 60, 9, vc(14), vc(1), 0, 0, 0, 0, (void*) "Insert new (before source)", NULL, NULL }, + { jwin_radio_proc, 10, 100, 60, 9, vc(14), vc(1), 0, 0, 0, 0, (void*) "Delete source", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static DIALOG newcomboa_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 200, 161, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Combo Alias Properties", NULL, NULL }, + { jwin_button_proc, 27, 130, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 112, 130, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 24, 34, 80, 8, 0, 0, 0, 0, 0, 0, (void *) "Alias Width", NULL, NULL }, + { jwin_text_proc, 24, 52, 80, 8, 0, 0, 0, 0, 0, 0, (void *) "Alias Height", NULL, NULL }, + { jwin_text_proc, 24, 70, 100, 8, 0, 0, 0, 0, 0, 0, (void *) "Layers to Draw On:", NULL, NULL }, + { jwin_edit_proc, 104, 30, 28-6, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 122, 48, 28-6, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 24, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL }, + { jwin_check_proc, 50, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL }, + { jwin_check_proc, 76, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL }, + { jwin_check_proc, 102, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL }, + { jwin_check_proc, 128, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL }, + { jwin_check_proc, 154, 86, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL }, + + + // { jwin_text_proc, 24, 106, 80, 8, 0, 0, 0, 0, 0, 0, (void *) "Copy to :", NULL, NULL }, + //15 + // { jwin_edit_proc, 100, 100, 28-6, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + // { jwin_check_proc, 84, 106, 24, 9, vc(12), vc(1), 0, 0, 1, 0, (void *) "", NULL, NULL }, + + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +bool swapComboAlias(int source, int dest) +{ + if(source==dest) return false; + + combo_alias *combo=&temp_aliases[source], *oldcombo=&temp_aliases[dest]; + + byte w=oldcombo->width; + oldcombo->width=combo->width; + combo->width=w; + + byte h=oldcombo->height; + oldcombo->height=combo->height; + combo->height=h; + + byte l=oldcombo->layermask; + oldcombo->layermask=combo->layermask; + combo->layermask=l; + + word c=oldcombo->combo; + oldcombo->combo=combo->combo; + combo->combo=c; + + c=oldcombo->cset; + oldcombo->cset=combo->cset; + combo->cset=c; + + word* cp = oldcombo->combos; + oldcombo->combos=combo->combos; + combo->combos = cp; + + byte *sp = oldcombo->csets; + oldcombo->csets=combo->csets; + combo->csets=sp; + + return true; +} + + +bool copyComboAlias(int source, int dest) +{ + if(source==dest) return false; + + // al_trace("count is %i\n", comboa_cnt); + // if (dest > comboa_cnt-1) return false; + // al_trace("Copying %i to %i\n",source, dest); + + combo_alias *combo, *oldcombo; + combo = &temp_aliases[source]; + oldcombo = &temp_aliases[dest]; + + int new_count=(comboa_lmasktotal(combo->layermask)+1)*(combo->width+1)*(combo->height+1); + + if(oldcombo->combos != NULL) delete[] oldcombo->combos; + + if(oldcombo->csets != NULL) delete[] oldcombo->csets; + + word *new_combos = new word[new_count]; + byte *new_csets = new byte[new_count]; + + memcpy(new_combos, combo->combos, sizeof(word)*new_count); + memcpy(new_csets, combo->csets, sizeof(byte)*new_count); + + oldcombo->combos=new_combos; + oldcombo->csets=new_csets; + + oldcombo->width=combo->width; + oldcombo->height=combo->height; + oldcombo->layermask=combo->layermask; + oldcombo->combo=combo->combo; + oldcombo->cset=combo->cset; + + + return true; +} + +int getcurrentcomboalias(); + +int onOrgComboAliases() +{ + char cSrc[4]; + char cDest[4]; + int iSrc; + int iDest; + + sprintf(cSrc,"0"); + sprintf(cDest,"0"); + orgcomboa_dlg[0].dp2=lfont; + orgcomboa_dlg[6].dp= cSrc; + orgcomboa_dlg[7].dp= cDest; + + if(is_large) + large_dialog(orgcomboa_dlg); + + int ret = zc_popup_dialog(orgcomboa_dlg,-1); + + if(ret!=1) return ret; + + iSrc=atoi((char*) orgcomboa_dlg[6].dp); + iDest=atoi((char*) orgcomboa_dlg[7].dp); + + if(iSrc<0 || iSrc > MAXCOMBOALIASES-1) + { + char buf[60]; + snprintf(buf, 60, "Invalid source (range 0-%d)", MAXCOMBOALIASES-1); + buf[59]='\0'; + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + return ret; + } + + // 10,11=ins, del + if(orgcomboa_dlg[10].flags & D_SELECTED) //insert + { + for(int j=MAXCOMBOALIASES-1; j>iSrc; --j) copyComboAlias(j-1,j); + + return ret; + } + + if(orgcomboa_dlg[11].flags & D_SELECTED) //delete + { + for(int j=iSrc; j MAXCOMBOALIASES-1) + { + char buf[60]; + snprintf(buf, 60, "Invalid dest (range 0-%d)", MAXCOMBOALIASES-1); + buf[59]='\0'; + + jwin_alert("Error",buf,NULL,NULL,"O&K",NULL,'k',0,lfont); + return ret; + } + + if(orgcomboa_dlg[3].flags & D_SELECTED) //copy + { + copyComboAlias(iSrc,iDest); + } + + if(orgcomboa_dlg[5].flags & D_SELECTED) //swap + { + swapComboAlias(iSrc,iDest); + } + + + return ret; +} + +int onNewComboAlias() +{ + combo_alias *combo; + combo = &temp_aliases[comboa_cnt]; + + char cwidth[3]; + char cheight[3]; + // char cp[3]; + + word temp_combos[16*11*7]; + byte temp_csets[16*11*7]; + sprintf(cwidth, "%d", combo->width+1); + sprintf(cheight, "%d", combo->height+1); + int old_count = (comboa_lmasktotal(combo->layermask)+1)*(combo->width+1)*(combo->height+1); + int old_width=combo->width; + int old_height=combo->height; + int oldlayer=combo->layermask; + + for(int i=0; icsets[i]; + temp_combos[i] = combo->combos[i]; + } + + newcomboa_dlg[0].dp2 = lfont; + newcomboa_dlg[6].dp = cwidth; + newcomboa_dlg[7].dp = cheight; + newcomboa_dlg[8].flags = (combo->layermask&1)? D_SELECTED : 0; + newcomboa_dlg[9].flags = (combo->layermask&2)? D_SELECTED : 0; + newcomboa_dlg[10].flags = (combo->layermask&4)? D_SELECTED : 0; + newcomboa_dlg[11].flags = (combo->layermask&8)? D_SELECTED : 0; + newcomboa_dlg[12].flags = (combo->layermask&16)? D_SELECTED : 0; + newcomboa_dlg[13].flags = (combo->layermask&32)? D_SELECTED : 0; + + if(is_large) large_dialog(newcomboa_dlg); + + int ret = zc_popup_dialog(newcomboa_dlg,-1); + + if(ret==1) + { + combo->width = ((atoi(cwidth)-1)<16)?zc_max(0,(atoi(cwidth)-1)):15; + combo->height = ((atoi(cheight)-1)<11)?zc_max(0,(atoi(cheight)-1)):10; + combo->layermask=0; + combo->layermask |= (newcomboa_dlg[8].flags&D_SELECTED)?1:0; + combo->layermask |= (newcomboa_dlg[9].flags&D_SELECTED)?2:0; + combo->layermask |= (newcomboa_dlg[10].flags&D_SELECTED)?4:0; + combo->layermask |= (newcomboa_dlg[11].flags&D_SELECTED)?8:0; + combo->layermask |= (newcomboa_dlg[12].flags&D_SELECTED)?16:0; + combo->layermask |= (newcomboa_dlg[13].flags&D_SELECTED)?32:0; + + int new_count = (comboa_lmasktotal(combo->layermask)+1)*(combo->width+1)*(combo->height+1); + + if(combo->combos != NULL) + { + delete[] combo->combos; + } + + if(combo->csets != NULL) + { + delete[] combo->csets; + } + + combo->combos = new word[new_count]; + combo->csets = new byte[new_count]; + + int j=1; + int old_size=(old_width+1)*(old_height+1); + int new_start[7] = + { + 0, + ((combo->width+1)*(combo->height+1)*(1)), + ((combo->width+1)*(combo->height+1)*(2)), + ((combo->width+1)*(combo->height+1)*(3)), + ((combo->width+1)*(combo->height+1)*(4)), + ((combo->width+1)*(combo->height+1)*(5)), + ((combo->width+1)*(combo->height+1)*(6)) + }; + int new_layers[6] = {0,0,0,0,0,0}; + int temp_layer = combo->layermask; + int temp_old = oldlayer; + int old_layers[6] = {0,0,0,0,0,0}; + int k=1; + + for(int i=0; (i<6)&&(temp_layer!=0); j++,temp_layer>>=1,temp_old>>=1) + { + if(temp_layer&1) + { + new_layers[i] = j; + //if(oldlayer&(1<<(j-1))) old_layers[i] = k++; + i++; + } + + if(temp_old&1) + { + if(temp_layer&1) + { + old_layers[i-1] = k; + } + + k++; + } + } + + for(int i=0; i=new_start[6]) + { + //oldl=oldlayer>>(new_layers[5]-1); + j=i-new_start[6]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[5]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[5])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[5])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[5]) + { + //oldl=oldlayer>>(new_layers[4]-1); + j=i-new_start[5]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[4]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[4])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[4])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[4]) + { + //oldl=oldlayer>>(new_layers[3]-1); + j=i-new_start[4]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[3]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[3])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[3])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[3]) + { + //oldl=oldlayer>>(new_layers[2]-1); + j=i-new_start[3]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[2]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[2])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[2])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[2]) + { + //oldl=oldlayer>>(new_layers[1]-1); + j=i-new_start[2]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[1]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[1])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[1])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[1]) + { + //oldl=oldlayer>>(new_layers[0]-1); + j=i-new_start[1]; + + if(((j/(combo->width+1))<=old_height)&&((j%(combo->width+1))<=old_width)&&(oldlayer&(1<<(new_layers[0]-1)))) + { + combo->combos[i] = temp_combos[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[0])]; + combo->csets[i] = temp_csets[((j%(combo->width+1))+((old_width+1)*(j/(combo->width+1))))+(old_size*old_layers[0])]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + else if(i>=new_start[0]) + { + if(((i/(combo->width+1))<=old_height)&&((i%(combo->width+1))<=old_width)) + { + combo->combos[i] = temp_combos[(i%(combo->width+1))+((old_width+1)*(i/(combo->width+1)))]; + combo->csets[i] = temp_csets[(i%(combo->width+1))+((old_width+1)*(i/(combo->width+1)))]; + } + else + { + combo->combos[i] = 0; + combo->csets[i] = 0; + } + } + } + + set_comboaradio(combo->layermask); + // copy aliases + /*if (newcomboa_dlg[16].flags) + { + copyComboAlias(getcurrentcomboalias(),atoi((char*) newcomboa_dlg[15].dp)); + al_trace("src: %i, dest: %i\n", getcurrentcomboalias(),atoi((char*) newcomboa_dlg[15].dp)); + }*/ + } + + return ret; +} + +int d_orgcomboa_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int down=0; + int selected=(d->flags&D_SELECTED)?1:0; + int last_draw; + + switch(msg) + { + + case MSG_DRAW: + { + FONT *tfont=font; + font=is_large?lfont_l:nfont; + jwin_draw_text_button(screen, d->x, d->y, d->w, d->h, (char*)d->dp, d->flags, true); + font=tfont; + } + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + /* close dialog? */ + onOrgComboAliases(); + return D_REDRAW; + + /* or just toggle */ + /*d->flags ^= D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + break;*/ + + case MSG_CLICK: + last_draw = 0; + + /* track the mouse until it is released */ + while(gui_mouse_b()) + { + down = mouse_in_rect(d->x, d->y, d->w, d->h); + + /* redraw? */ + if(last_draw != down) + { + if(down != selected) + d->flags |= D_SELECTED; + else + d->flags &= ~D_SELECTED; + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + last_draw = down; + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + } + + /* redraw in normal state */ + if(down) + { + if(d->flags&D_EXIT) + { + d->flags &= ~D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + } + } + + /* should we close the dialog? */ + if(down) + { + onOrgComboAliases(); + return D_REDRAW; + } + + break; + } + + return D_O_K; +} + +int d_comboabutton_proc(int msg, DIALOG *d, int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + int down=0; + int selected=(d->flags&D_SELECTED)?1:0; + int last_draw; + + switch(msg) + { + + case MSG_DRAW: + { + FONT *tfont=font; + font=is_large?lfont_l:nfont; + jwin_draw_text_button(screen, d->x, d->y, d->w, d->h, (char*)d->dp, d->flags, true); + font=tfont; + } + break; + + case MSG_WANTFOCUS: + return D_WANTFOCUS; + + case MSG_KEY: + /* close dialog? */ + onNewComboAlias(); + return D_REDRAW; + + /* or just toggle */ + /*d->flags ^= D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + break;*/ + + case MSG_CLICK: + last_draw = 0; + + /* track the mouse until it is released */ + while(gui_mouse_b()) + { + down = mouse_in_rect(d->x, d->y, d->w, d->h); + + /* redraw? */ + if(last_draw != down) + { + if(down != selected) + d->flags |= D_SELECTED; + else + d->flags &= ~D_SELECTED; + + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + last_draw = down; + } + + /* let other objects continue to animate */ + broadcast_dialog_message(MSG_IDLE, 0); + } + + /* redraw in normal state */ + if(down) + { + if(d->flags&D_EXIT) + { + d->flags &= ~D_SELECTED; + scare_mouse(); + object_message(d, MSG_DRAW, 0); + unscare_mouse(); + } + } + + /* should we close the dialog? */ + if(down) + { + onNewComboAlias(); + return D_REDRAW; + } + + break; + } + + return D_O_K; +} + +int d_comboacheck_proc(int msg, DIALOG *d, int c) +{ + int temp = d->flags&D_SELECTED; + int ret=jwin_checkfont_proc(msg,d,c); + + if(temp != (d->flags&D_SELECTED)) + { + return D_REDRAW; + } + + return ret; +} + +static ListData comboa_list(comboalist, &font); + +static DIALOG editcomboa_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 320, 240, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Combo Alias Edit", NULL, NULL }, + { jwin_button_proc, 148, 212, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_button_proc, 232, 212, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_frame_proc, 4+121, 28+81, 1, 1, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_comboabutton_proc, 25, 212, 81, 21, vc(14), vc(1), 'p', D_EXIT, 0, 0, (void *) "&Properties", NULL, NULL }, + { d_comboalist_proc, 266, 25, 50, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 0, 0, (void *) &comboa_list, NULL, NULL }, + { d_comboa_radio_proc, 285, 44, 30, 8+1, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "0", NULL, NULL }, + { d_comboa_radio_proc, 285, 54, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "1", NULL, NULL }, + { d_comboa_radio_proc, 285, 64, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "2", NULL, NULL }, + { d_comboa_radio_proc, 285, 74, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "3", NULL, NULL }, + { d_comboa_radio_proc, 285, 84, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "4", NULL, NULL }, + + { d_comboa_radio_proc, 285, 94, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "5", NULL, NULL }, + { d_comboa_radio_proc, 285, 104, 30, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "6", NULL, NULL }, + { d_comboacheck_proc, 285, 164, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { d_comboa_proc, 6, 27, 256, 176, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_ctext_proc, 290, 176, 27, 8, 0, 0, 0, 0, 0, 0, (void *) "Only Show", NULL, NULL }, + { jwin_ctext_proc, 290, 186, 27, 8, 0, 0, 0, 0, 0, 0, (void *) "Current", NULL, NULL }, + { jwin_ctext_proc, 290, 196, 27, 8, 0, 0, 0, 0, 0, 0, (void *) "Layer", NULL, NULL }, + { jwin_ctext_proc, 290, 122, 27, 8, 0, 0, 0, 0, 0, 0, (void *) "Thumbnail", NULL, NULL }, + { jwin_frame_proc, 280, 132, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_comboat_proc, 282, 134, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + + //21 + { d_orgcomboa_proc, 106, 212, 21, 21, vc(14), vc(1), 'p', D_EXIT, 0, 0, (void *) "&Org", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int getcurrentcomboalias() +{ + return editcomboa_dlg[5].d1; +} + +int d_comboa_radio_proc(int msg,DIALOG *d,int c) +{ + int temp = layer_cnt; + int ret = jwin_radiofont_proc(msg,d,c); + + if(editcomboa_dlg[6].flags&D_SELECTED) layer_cnt=0; + else if(editcomboa_dlg[7].flags&D_SELECTED) layer_cnt=1; + else if(editcomboa_dlg[8].flags&D_SELECTED) layer_cnt=2; + else if(editcomboa_dlg[9].flags&D_SELECTED) layer_cnt=3; + else if(editcomboa_dlg[10].flags&D_SELECTED) layer_cnt=4; + else if(editcomboa_dlg[11].flags&D_SELECTED) layer_cnt=5; + else if(editcomboa_dlg[12].flags&D_SELECTED) layer_cnt=6; + + if(temp != layer_cnt) + { + return D_REDRAW; + } + + return ret; +} + +int set_comboaradio(byte layermask) +{ + if(editcomboa_dlg[7].flags&D_SELECTED) editcomboa_dlg[7].flags &= ~D_SELECTED; + + if(editcomboa_dlg[8].flags&D_SELECTED) editcomboa_dlg[8].flags &= ~D_SELECTED; + + if(editcomboa_dlg[9].flags&D_SELECTED) editcomboa_dlg[9].flags &= ~D_SELECTED; + + if(editcomboa_dlg[10].flags&D_SELECTED) editcomboa_dlg[10].flags &= ~D_SELECTED; + + if(editcomboa_dlg[11].flags&D_SELECTED) editcomboa_dlg[11].flags &= ~D_SELECTED; + + if(editcomboa_dlg[12].flags&D_SELECTED) editcomboa_dlg[12].flags &= ~D_SELECTED; + + if(!(layermask&1)) editcomboa_dlg[7].flags |= D_DISABLED; + else editcomboa_dlg[7].flags &= ~D_DISABLED; + + if(!(layermask&2)) editcomboa_dlg[8].flags |= D_DISABLED; + else editcomboa_dlg[8].flags &= ~D_DISABLED; + + if(!(layermask&4)) editcomboa_dlg[9].flags |= D_DISABLED; + else editcomboa_dlg[9].flags &= ~D_DISABLED; + + if(!(layermask&8)) editcomboa_dlg[10].flags |= D_DISABLED; + else editcomboa_dlg[10].flags &= ~D_DISABLED; + + if(!(layermask&16)) editcomboa_dlg[11].flags |= D_DISABLED; + else editcomboa_dlg[11].flags &= ~D_DISABLED; + + if(!(layermask&32)) editcomboa_dlg[12].flags |= D_DISABLED; + else editcomboa_dlg[12].flags &= ~D_DISABLED; + + editcomboa_dlg[6].flags |= D_SELECTED; + layer_cnt=0; + return 1; +} + +int onEditComboAlias() +{ + reset_combo_animations(); + reset_combo_animations2(); + + for(int i=0; i=0) + { + bound(index,0,31); + sprintf(ffcombo_str_buf,"%d",index+1); + return ffcombo_str_buf; + } + + *list_size=32; + return NULL; +} + +const char *fflinklist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,32); + + if(index) + sprintf(fflink_str_buf,"%d",index); + else sprintf(fflink_str_buf,"(None)"); + + return fflink_str_buf; + } + + *list_size=33; + return NULL; +} + +static ListData ffcombo_list(ffcombolist, &font); + +static DIALOG ffcombo_sel_dlg[] = +{ + { jwin_win_proc, 0, 0, 200, 179, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Choose Freeform Combo", NULL, NULL }, + { jwin_button_proc, 35, 152, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Edit", NULL, NULL }, + { jwin_button_proc, 104, 152, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Done", NULL, NULL }, + { d_ffcombolist_proc, 11, 24, 49, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &ffcombo_list, NULL, NULL }, + { d_comboframe_proc, 68, 23, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_bitmap_proc, 70, 25, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_ffcombolist_proc(int msg,DIALOG *d,int c) +{ + int ret = jwin_droplist_proc(msg,d,c); + int d1 = d->d1; + int x=ffcombo_sel_dlg[0].x; + int y=ffcombo_sel_dlg[0].y; + FONT *tempfont=(is_large?font:spfont); + int x2=text_length(tempfont, "Move Delay:")+4; + + switch(msg) + { + case MSG_DRAW: + if(!ffcur) return D_O_K; + + BITMAP *buf = create_bitmap_ex(8,16,16); + + if(buf) + { + clear_bitmap(buf); + putcombo(buf,0,0,Map.CurrScr()->ffcs[d1].data,Map.CurrScr()->ffcs[d1].cset); + stretch_blit(buf, ffcur, 0,0, 16, 16, 0, 0, ffcur->w, ffcur->h); + destroy_bitmap(buf); + } + + object_message(&ffcombo_sel_dlg[5],MSG_DRAW,0); + + int xd = x+int(68*(is_large?1.5:1)); + int y2 = y+int(55*(is_large?1.5:1)); + int yd = is_large ? 9 : 6; + + rectfill(screen,xd,y2,x+196*int(is_large?1.5:1),y+127*int(is_large?1.5:1),jwin_pal[jcBOX]); + + textprintf_ex(screen,tempfont,xd,y2,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Combo #:"); + textprintf_ex(screen,tempfont,xd+x2,y2,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].data); + + textprintf_ex(screen,tempfont,xd,y2+yd,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"CSet #:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].cset); + + textprintf_ex(screen,tempfont,xd,y2+yd*2,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"X Pos:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*2,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].x/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*3,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Y Pos:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*3,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].y/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*4,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"X Speed:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*4,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].xVel/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*5,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Y Speed:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*5,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].yVel/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*6,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"X Accel:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*6,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].xAccel/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*7,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Y Accel:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*7,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%.4f",Map.CurrScr()->ffcs[d1].yAccel/10000.0); + + textprintf_ex(screen,tempfont,xd,y2+yd*8,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Linked To:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*8,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].link); + + textprintf_ex(screen,tempfont,xd,y2+yd*9,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Move Delay:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*9,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].delay); + + textprintf_ex(screen,tempfont,xd,y2+yd*10,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Combo W:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*10,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",(Map.CurrScr()->ffcs[d1].width&63)+1); + + textprintf_ex(screen,tempfont,xd,y2+yd*11,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Combo H:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*11,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",(Map.CurrScr()->ffcs[d1].height&63)+1); + + textprintf_ex(screen,tempfont,xd,y2+yd*12,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Tile W:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*12,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].getTileWidth()); + + textprintf_ex(screen,tempfont,xd,y2+yd*13,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"Tile H:"); + textprintf_ex(screen,tempfont,xd+x2,y2+yd*13,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%d",Map.CurrScr()->ffcs[d1].getTileHeight()); + + break; + } + + return ret; +} +int onSelectFFCombo() +{ + ffcombo_sel_dlg[0].dp2 = lfont; + ffcombo_sel_dlg[3].d1 = ff_combo; + ffcur = create_bitmap_ex(8,is_large?32:16,is_large?32:16); + + if(!ffcur) return D_O_K; + + putcombo(ffcur,0,0,Map.CurrScr()->ffcs[ff_combo].data,Map.CurrScr()->ffcs[ff_combo].cset); + ffcombo_sel_dlg[5].dp = ffcur; + + if(is_large) + { + bool resize = !(ffcombo_sel_dlg[0].d1); + large_dialog(ffcombo_sel_dlg); + + if(resize) + { + ffcombo_sel_dlg[5].x--; + ffcombo_sel_dlg[5].y--; + } + } + + int ret=zc_popup_dialog(ffcombo_sel_dlg,0); + + while(ret==1) + { + ff_combo = ffcombo_sel_dlg[3].d1; + onEditFFCombo(ff_combo); + ret=zc_popup_dialog(ffcombo_sel_dlg,0); + } + + destroy_bitmap(ffcur); + return D_O_K; +} + +static int ffcombo_data_list[] = +{ + 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,54,55,-1 +}; + +static int ffcombo_flag_list[] = +{ + 31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,-1 +}; + +static int ffcombo_arg_list[] = +{ + 56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,-1 +}; + +static TABPANEL ffcombo_tabs[] = +{ + // (text) + { (char *)"Data", D_SELECTED, ffcombo_data_list, 0, NULL }, + { (char *)"Flags", 0, ffcombo_flag_list, 0, NULL }, + { (char *)"Arguments", 0, ffcombo_arg_list , 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +const char *ffscriptlist(int index, int *list_size); + +static ListData fflink_list(fflinklist, &font); +static ListData ffscript_list(ffscriptlist, &font); + +static DIALOG ffcombo_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 240, 215, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Edit Freeform Combo ", NULL, NULL }, + { jwin_tab_proc, 10, 23, 220, 165, 0, 0, 0, 0, 0, 0, (void *) ffcombo_tabs, NULL, (void *)ffcombo_dlg }, + { jwin_button_proc, 30+10, 171+20, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 100+10, 171+20, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + // 4 + { jwin_ctext_proc, 126+10, 25+20, 70, 36, 0, 0, 0, D_DISABLED, 0, 0, (void *) "COMBO", NULL, NULL }, + { d_comboframe_proc, 116+10, 31+20, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_combo_proc, 118+10, 33+20, 16, 16, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + // 7 + { jwin_text_proc, 6+10, 29+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Link to:", NULL, NULL }, + { jwin_text_proc, 6+10, 47+20, 36, 36, 0, 0, 0, 0, 0, 0, (void *) "X Pos:", NULL, NULL }, + { jwin_text_proc, 6+10, 65+20, 36, 36, 0, 0, 0, 0, 0, 0, (void *) "Y Pos:", NULL, NULL }, + { jwin_text_proc, 6+10, 83+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "X Speed:", NULL, NULL }, + { jwin_text_proc, 6+10, 101+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Y Speed:", NULL, NULL }, + { jwin_text_proc, 6+10, 119+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "X Accel:", NULL, NULL }, + { jwin_text_proc, 6+10, 137+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Y Accel:", NULL, NULL }, + { jwin_text_proc, 112+10, 137+20, 70, 12, 0, 0, 0, 0, 0, 0, (void *) "A. Delay:", NULL, NULL }, + // 15 + { jwin_droplist_proc, 50+10, 25+20, 60, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &fflink_list, NULL, NULL }, + { jwin_edit_proc, 50+10, 43+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 50+10, 61+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 50+10, 79+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 50+10, 97+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 50+10, 115+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 50+10, 133+20, 56, 16, vc(12), vc(1), 0, 0, 9, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 156+10, 133+20, 32, 16, vc(12), vc(1), 0, 0, 4, 0, NULL, NULL, NULL }, + //23 + { jwin_text_proc, 112+10, 65+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Combo W:", NULL, NULL }, + { jwin_text_proc, 112+10, 83+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Combo H:", NULL, NULL }, + { jwin_text_proc, 112+10, 101+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Tile W:", NULL, NULL }, + { jwin_text_proc, 112+10, 119+20, 70, 36, 0, 0, 0, 0, 0, 0, (void *) "Tile H:", NULL, NULL }, + //27 + { jwin_edit_proc, 156+10, 61+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 156+10, 79+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 156+10, 97+20, 24, 16, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 156+10, 115+20, 24, 16, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + //31 + { jwin_text_proc, 6+10, 25+20, 160, 36, 0, 0, 0, 0, 0, 0, (void *) "Flags (Normal):", NULL, NULL }, + { jwin_text_proc, 6+10, 105+20, 160, 36, 0, 0, 0, 0, 0, 0, (void *) "Flags (Changer specific):", NULL, NULL }, + //33 + { jwin_check_proc, 6+10, 35+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Draw Over", NULL, NULL }, + { jwin_check_proc, 6+10, 45+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Translucent", NULL, NULL }, + { jwin_check_proc, 80+10, 35+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Carry-Over", NULL, NULL }, + { jwin_check_proc, 80+10, 45+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Stationary", NULL, NULL }, + { jwin_check_proc, 6+10, 55+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Is a Changer (Invisible, Ethereal)", NULL, NULL }, + { jwin_check_proc, 6+10, 65+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Run Script at Screen Init", NULL, NULL }, + { jwin_check_proc, 6+10, 75+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Only Visible to Lens of Truth", NULL, NULL }, + { jwin_check_proc, 6+10, 85+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Script Restarts When Carried Over", NULL, NULL }, + //41 + { jwin_check_proc, 154+10, 35+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Ethereal", NULL, NULL }, + { jwin_check_proc, 6+10, 95+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Active While Link is Holding an Item", NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + { d_dummy_proc, 6+10, 25+20, 0, 8, vc(15), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //49 + { jwin_check_proc, 6+10, 115+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Swap speed with next FFC", NULL, NULL }, + { jwin_check_proc, 6+10, 125+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Swap speed with prev. FFC", NULL, NULL }, + { jwin_check_proc, 6+10, 135+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Increase combo ID", NULL, NULL }, + { jwin_check_proc, 6+10, 145+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Decrease combo ID", NULL, NULL }, + { jwin_check_proc, 6+10, 155+20, 80+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, (void *) "Change combo/cset to this", NULL, NULL }, + //54 + { jwin_text_proc, 6+10, 155+20, 70, 12, 0, 0, 0, 0, 0, 0, (void *) "Script:", NULL, NULL }, + { jwin_droplist_proc, 50+10, 151+20, 150, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &ffscript_list, NULL, NULL }, + //56 + { jwin_text_proc, 6+10, 29+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D0:", NULL, NULL }, + { jwin_text_proc, 6+10, 47+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D1:", NULL, NULL }, + { jwin_text_proc, 6+10, 65+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D2:", NULL, NULL }, + { jwin_text_proc, 6+10, 83+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D3:", NULL, NULL }, + { jwin_text_proc, 6+10, 101+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D4:", NULL, NULL }, + { jwin_text_proc, 6+10, 119+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D5:", NULL, NULL }, + { jwin_text_proc, 6+10, 137+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "D6:", NULL, NULL }, + { jwin_text_proc, 6+10, 155+20, 24, 12, 0, 0, 0, 0, 0, 0, (void *) "D7:", NULL, NULL }, + //64 + { jwin_edit_proc, 34+10, 25+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 43+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 61+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 79+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 97+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 115+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 133+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 34+10, 151+20, 72, 16, vc(12), vc(1), 0, 0, 12, 0, NULL, NULL, NULL }, + //72 + { jwin_text_proc, 112+10, 29+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "A1:", NULL, NULL }, + { jwin_text_proc, 112+10, 47+20, 24, 36, 0, 0, 0, 0, 0, 0, (void *) "A2:", NULL, NULL }, + //74 + { jwin_edit_proc, 140+10, 25+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_edit_proc, 140+10, 43+20, 32, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_text_proc, 220, 151+20, 24, 36, 0, 0, 0, 0, 0, 0, (void*) "", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +char *strip_decimals(char *str) +{ + int len=(int)strlen(str); + char *src=(char *)zc_malloc(len+1); + char *tmpsrc=src; + memcpy(src,str,len+1); + memset(src,0,len+1); + + for(unsigned int i=0; str[i]&&i<=strlen(str); i++) + { + *tmpsrc=str[i]; + + if(*tmpsrc=='.') + { + while(str[i+1]=='.'&&i<=strlen(str)) + { + i++; + } + } + + tmpsrc++; + } + + memcpy(str,src,len); + zc_free(src); + return str; +} + +// Unused??? -L 6/6/11 +char *clean_numeric_string(char *str) +{ + bool found_sign=false; + bool found_decimal=false; + int len=(int)strlen(str); + char *src=(char *)zc_malloc(len+1); + char *tmpsrc=src; + memcpy(src,str,len+1); + memset(src,0,len+1); + + // strip out non-numerical characters + for(unsigned int i=0; str[i]&&i<=strlen(str); i++) + { + *tmpsrc=str[i]; + + if(*tmpsrc!='.'&&*tmpsrc!='-'&&*tmpsrc!='+'&&!isdigit(*tmpsrc)) + { + while(*tmpsrc!='.'&&*tmpsrc!='-'&&*tmpsrc!='+'&&!isdigit(*tmpsrc)) + { + i++; + } + } + + tmpsrc++; + } + + len=(int)strlen(src); + char *src2=(char *)zc_malloc(len+1); + tmpsrc=src2; + memcpy(src,src2,len+1); + memset(src2,0,len+1); + + // second purge + for(unsigned int i=0; src[i]&&i<=strlen(src); i++) + { + *tmpsrc=src[i]; + + if(*tmpsrc=='-'||*tmpsrc=='+') + { + if(found_sign||found_decimal) + { + while(*tmpsrc=='-'||*tmpsrc=='+') + { + i++; + } + } + + found_sign=true; + } + + if(*tmpsrc=='.') + { + if(found_decimal) + { + while(*tmpsrc=='.') + { + i++; + } + } + + found_decimal=true; + } + + tmpsrc++; + } + + sprintf(str, "%s", src2); + zc_free(src); + zc_free(src2); + return str; +} + +script_struct biffs[NUMSCRIPTFFC]; //ff script +int biffs_cnt = -1; +script_struct biitems[NUMSCRIPTFFC]; //item script +int biitems_cnt = -1; +//static char ffscript_str_buf[32]; + +void build_biffs_list() +{ + biffs[0].first = "(None)"; + biffs[0].second = -1; + biffs_cnt = 1; + + for(int i = 0; i < NUMSCRIPTFFC - 1; i++) + { + if(ffcmap[i].second.length()==0) + continue; + + std::stringstream ss; + ss << ffcmap[i].second << " (" << i+1 << ")"; // The word 'slot' preceding all of the numbers is a bit cluttersome. -L. + biffs[biffs_cnt].first = ss.str(); + biffs[biffs_cnt].second = i; + biffs_cnt++; + } + + // Blank out the rest of the list + for(int i=biffs_cnt; i 0 && strcmp(biffs[j].first.c_str(),"")) + zc_swap(biffs[i],biffs[j]); + } + } + + biffs_cnt = 0; + + for(int i = 0; i < NUMSCRIPTFFC; i++) + if(biffs[i].first.length() > 0) + biffs_cnt = i+1; +} + +void build_biitems_list() +{ + biitems[0].first = "(None)"; + biitems[0].second = -1; + biitems_cnt = 1; + + for(int i = 0; i < NUMSCRIPTITEM - 1; i++, biitems_cnt++) + { + std::stringstream ss; + + if(itemmap[i].second != "") + ss << itemmap[i].second << " (" << i+1 << ")"; + + biitems[biitems_cnt].first = ss.str(); + biitems[biitems_cnt].second = i; + } + + for(int i = 0; i < biitems_cnt - 1; i++) + { + for(int j = i + 1; j < biitems_cnt; j++) + { + if(stricmp(biitems[i].first.c_str(), biitems[j].first.c_str()) > 0 && strcmp(biitems[j].first.c_str(),"")) + zc_swap(biitems[i], biitems[j]); + } + } + + biitems_cnt = 0; + + for(int i = 0; i < NUMSCRIPTITEM; i++) + if(biitems[i].first.length() > 0) + biitems_cnt = i+1; +} + +const char *ffscriptlist(int index, int *list_size) +{ + if(index < 0) + { + *list_size = biffs_cnt; + return NULL; + } + + return biffs[index].first.c_str(); +} + +static char itemscript_str_buf[32]; + +char *itemscriptlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,255); + sprintf(itemscript_str_buf,"%d: %s",index, ffcmap[index-1].second.c_str()); + return itemscript_str_buf; + } + + *list_size=256; + return NULL; +} + +static char ffscript_str_buf2[32]; + +const char *ffscriptlist2(int index, int *list_size) +{ + if(index>=0) + { + char buf[20]; + bound(index,0,510); + + if(ffcmap[index].second=="") + strcpy(buf, ""); + else + { + strncpy(buf, ffcmap[index].second.c_str(), 19); + buf[19]='\0'; + } + + sprintf(ffscript_str_buf2,"%d: %s",index+1, buf); + return ffscript_str_buf2; + } + + *list_size=511; + return NULL; +} + +static char itemscript_str_buf2[32]; + +const char *itemscriptlist2(int index, int *list_size) +{ + if(index>=0) + { + char buf[20]; + bound(index,0,254); + + if(itemmap[index].second=="") + strcpy(buf, ""); + else + { + strncpy(buf, itemmap[index].second.c_str(), 19); + buf[19]='\0'; + } + + sprintf(itemscript_str_buf2,"%d: %s",index+1, buf); + return itemscript_str_buf2; + } + + *list_size=255; + return NULL; +} + +static char gscript_str_buf2[32]; + +const char *gscriptlist2(int index, int *list_size) +{ + if(index >= 0) + { + bound(index,0,3); + + char buf[20]; + + if(globalmap[index].second == "") + strcpy(buf, ""); + else + { + strncpy(buf, globalmap[index].second.c_str(), 19); + buf[19]='\0'; + } + + if(index==0) + sprintf(gscript_str_buf2,"Initialization: %s", buf); + + if(index==1) + sprintf(gscript_str_buf2,"Active: %s", buf); + + if(index==2) + sprintf(gscript_str_buf2,"onExit: %s", buf); + + if(index==3) + sprintf(gscript_str_buf2,"onContinue: %s", buf); + + return gscript_str_buf2; + } + + if(list_size != NULL) + *list_size=4; + + return NULL; +} + +static DIALOG compile_dlg[] = +{ + // x y w h fg bg key flags d1 d2 dp + { jwin_win_proc, 0, 0, 200, 118, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Compile ZScript", NULL, NULL }, + { jwin_button_proc, 109, 89, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_button_proc, 131, 30, 61, 21, vc(14), vc(1), 'e', D_EXIT, 0, 0, (void *) "&Edit", NULL, NULL }, + { jwin_button_proc, 30, 60, 61, 21, vc(14), vc(1), 'i', D_EXIT, 0, 0, (void *) "&Import", NULL, NULL }, + { jwin_text_proc, 8, 35, 61, 21, vc(14), vc(1), 0, 0, 0, 0, (void *) zScriptBytes, NULL, NULL }, + { jwin_button_proc, 30, 89, 61, 21, vc(14), vc(1), 'c', D_EXIT, 0, 0, (void *) "&Compile!", NULL, NULL }, + { jwin_button_proc, 109, 60, 61, 21, vc(14), vc(1), 'x', D_EXIT, 0, 0, (void *) "E&xport", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static int as_ffc_list[] = { 4, 5, 6, -1}; +static int as_global_list[] = { 7, 8, 9, -1}; //Why does putting 15 in here not place my message only on the global tab? ~Joe +static int as_item_list[] = { 10, 11, 12, -1}; + +static TABPANEL assignscript_tabs[] = +{ + // (text) + { (char *)"FFC", D_SELECTED, as_ffc_list, 0, NULL }, + { (char *)"Global", 0, as_global_list, 0, NULL }, + { (char *)"Item", 0, as_item_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +const char *assignffclist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)ffcmap.size(); + return NULL; + } + + return ffcmap[index].first.c_str(); +} + +const char *assigngloballist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)globalmap.size(); + return NULL; + } + + return globalmap[index].first.c_str(); +} + +const char *assignitemlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)itemmap.size(); + return NULL; + } + + return itemmap[index].first.c_str(); +} + +const char *assignffcscriptlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)asffcscripts.size(); + return NULL; + } + + return asffcscripts[index].c_str(); +} + +const char *assignglobalscriptlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)asglobalscripts.size(); + return NULL; + } + + return asglobalscripts[index].c_str(); +} + +const char *assignitemscriptlist(int index, int *list_size) +{ + if(index<0) + { + *list_size = (int)asitemscripts.size(); + return NULL; + } + + return asitemscripts[index].c_str(); +} + +static ListData assignffc_list(assignffclist, &font); +static ListData assignffcscript_list(assignffcscriptlist, &font); +static ListData assignglobal_list(assigngloballist, &font); +static ListData assignglobalscript_list(assignglobalscriptlist, &font); +static ListData assignitem_list(assignitemlist, &font); +static ListData assignitemscript_list(assignitemscriptlist, &font); + +static DIALOG assignscript_dlg[] = +{ + // x y w h fg bg key flags d1 d2 dp + { jwin_win_proc, 0, 0, 320, 200, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Assign Compiled Script", NULL, NULL }, + { jwin_tab_proc, 6, 25, 308, 130, 0, 0, 0, 0, 0, 0, assignscript_tabs, NULL, (void*)assignscript_dlg }, + { jwin_button_proc, 251, 171, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_button_proc, 182, 171, 61, 21, vc(14), vc(1), 'k', D_EXIT, 0, 0, (void *) "O&K", NULL, NULL }, + { jwin_abclist_proc, 10, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignffc_list, NULL, NULL }, + { jwin_abclist_proc, 174, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignffcscript_list, NULL, NULL }, + { jwin_button_proc, 154, 93, 15, 10, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "<<", NULL, NULL }, + { jwin_abclist_proc, 10, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignglobal_list, NULL, NULL }, + { jwin_abclist_proc, 174, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignglobalscript_list, NULL, NULL }, + { jwin_button_proc, 154, 93, 15, 10, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "<<", NULL, NULL }, + { jwin_abclist_proc, 10, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignitem_list, NULL, NULL }, + { jwin_abclist_proc, 174, 45, 136, 105, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0,0,0, 0, (void *)&assignitemscript_list, NULL, NULL }, + { jwin_button_proc, 154, 93, 15, 10, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "<<", NULL, NULL }, + + { jwin_check_proc, 22, 171, 90, 8, vc(14), vc(1), 0, 0, 1, 0, (void *) "Output ZASM code to allegro.log", NULL, NULL }, + { jwin_text_proc, 108, 25, 90, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Slots with matching names have been updated.", NULL, NULL }, + { jwin_text_proc, 100, 158, 90, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Global scripts named 'Init' will be appended to '~Init'", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } + +}; + +static ListData ffscript_sel_dlg_list(ffscriptlist2, &font); + +static DIALOG ffscript_sel_dlg[] = +{ + { jwin_win_proc, 0, 0, 200, 159, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Choose Slot And Name", NULL, NULL }, + { jwin_text_proc, 8, 80, 36, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 44, 80-4, 146, 16, vc(12), vc(1), 0, 0, 19, 0, NULL, NULL, NULL }, + { jwin_button_proc, 35, 132, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Load", NULL, NULL }, + { jwin_button_proc, 104, 132, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_droplist_proc, 26, 45, 146, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &ffscript_sel_dlg_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static ListData itemscript_sel_dlg_list(itemscriptlist2, &font); + +static DIALOG itemscript_sel_dlg[] = +{ + { jwin_win_proc, 0, 0, 200, 159, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Choose Slot And Name", NULL, NULL }, + { jwin_text_proc, 8, 80, 36, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 44, 80-4, 146, 16, vc(12), vc(1), 0, 0, 19, 0, NULL, NULL, NULL }, + { jwin_button_proc, 35, 132, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Load", NULL, NULL }, + { jwin_button_proc, 104, 132, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_droplist_proc, 26, 45, 146, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &itemscript_sel_dlg_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +static ListData gscript_sel_dlg_list(gscriptlist2, &font); + +static DIALOG gscript_sel_dlg[] = +{ + { jwin_win_proc, 0, 0, 200, 159, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Choose Slot And Name", NULL, NULL }, + { jwin_text_proc, 8, 80, 36, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Name:", NULL, NULL }, + { jwin_edit_proc, 44, 80-4, 146, 16, vc(12), vc(1), 0, 0, 19, 0, NULL, NULL, NULL }, + { jwin_button_proc, 35, 132, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Load", NULL, NULL }, + { jwin_button_proc, 104, 132, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_droplist_proc, 26, 45, 146, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &gscript_sel_dlg_list, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + + +int onCompileScript() +{ + ZScriptMainDialog dlg(*gui); + gui->showDialog(dlg); + return D_O_K; +} + +void compileZScript() +{ + FILE *tempfile = fopen("tmp","w"); + + if(!tempfile) + { + jwin_alert("Error","Unable to create a temporary file in current directory!",NULL,NULL,"O&K",NULL,'k',0,lfont); + return; + } + + fwrite(zScript.c_str(), sizeof(char), zScript.size(), tempfile); + fclose(tempfile); + box_start(1, "Compile Progress", lfont, sfont,true); + gotoless_not_equal = (0 != get_bit(quest_rules, qr_GOTOLESSNOTEQUAL)); // Used by BuildVisitors.cpp + ScriptsData *result = compile("tmp"); + unlink("tmp"); + box_end(true); + refresh(rALL); + + if(result == NULL) + { + jwin_alert("Error","There were compile errors.","Compilation halted.",NULL,"O&K",NULL,'k',0,lfont); + return; + } + + std::map stypes = result->scriptTypes; + std::map > scripts = result->theScripts; + delete result; + asffcscripts.clear(); + asffcscripts.push_back(""); + asglobalscripts.clear(); + asglobalscripts.push_back(""); + asitemscripts.clear(); + asitemscripts.push_back(""); + + for(std::map::iterator it = stypes.begin(); it != stypes.end(); it++) + { + switch(it->second) + { + case ScriptParser::TYPE_FFC: + { + asffcscripts.push_back(it->first); + break; + } + + case ScriptParser::TYPE_GLOBAL: + { + if(it->first != "~Init") //Don't allow assigning the allocate memory script, bad things could happen + asglobalscripts.push_back(it->first); + + break; + } + + case ScriptParser::TYPE_ITEMCLASS: //Technically they're now itemclass scripts + { + asitemscripts.push_back(it->first); + break; + } + } + } + + assignscript_dlg[0].dp2 = lfont; + assignscript_dlg[4].d1 = -1; + assignscript_dlg[5].d1 = -1; + assignscript_dlg[7].d1 = -1; + assignscript_dlg[8].d1 = -1; + assignscript_dlg[10].d1 = -1; + assignscript_dlg[11].d1 = -1; + assignscript_dlg[13].flags = 0; + + //assign scripts to slots + for(;;) //while(true) + { + char temp[100]; + + for(int i = 0; i < NUMSCRIPTFFC-1; i++) + { + sprintf(temp, "Slot %d: %s", i+1,(ffcmap[i].second == "" ? "" : ffcmap[i].second.c_str())); + ffcmap[i].first = temp; + } + + for(int i = 0; i < NUMSCRIPTGLOBAL; i++) + { + globalmap[i].first = gscriptlist2(i, NULL); //nicked this function from the ASM list + } + + for(int i = 0; i < NUMSCRIPTITEM-1; i++) + { + sprintf(temp, "Slot %d: %s", i+1, (itemmap[i].second == "" ? "" : itemmap[i].second.c_str())); + itemmap[i].first = temp; + } + + if(is_large) + large_dialog(assignscript_dlg); + + int ret2 = zc_popup_dialog(assignscript_dlg,3); + + switch(ret2) + { + case 0: + case 2: + //Cancel + return; + + case 3: + { + + //OK + bool output = (assignscript_dlg[13].flags == D_SELECTED); + + for(std::map >::iterator it = ffcmap.begin(); it != ffcmap.end(); it++) + { + if(it->second.second != "") + { + tempfile = fopen("tmp","w"); + + if(!tempfile) + { + jwin_alert("Error","Unable to create a temporary file in current directory!",NULL,NULL,"O&K",NULL,'k',0,lfont); + return; + } + + if(output) + { + al_trace("\n"); + al_trace("%s",it->second.second.c_str()); + al_trace("\n"); + } + + for(std::vector::iterator line = scripts[it->second.second].begin(); line != scripts[it->second.second].end(); line++) + { + std::string theline = (*line)->printLine(); + fwrite(theline.c_str(), sizeof(char), theline.size(),tempfile); + + if(output) + { + al_trace("%s",theline.c_str()); + } + } + + fclose(tempfile); + parse_script_file(&ffscripts[it->first+1],"tmp",false); + } + else if(ffscripts[it->first+1]) + { + delete[] ffscripts[it->first+1]; + ffscripts[it->first+1] = new ffscript[1]; + ffscripts[it->first+1][0].command = 0xFFFF; + } + } + + for(std::map >::iterator it = globalmap.begin(); it != globalmap.end(); it++) + { + if(it->second.second != "") + { + tempfile = fopen("tmp","w"); + + if(!tempfile) + { + jwin_alert("Error","Unable to create a temporary file in current directory!",NULL,NULL,"O&K",NULL,'k',0,lfont); + return; + } + + if(output) + { + al_trace("\n"); + al_trace("%s",it->second.second.c_str()); + al_trace("\n"); + } + + for(std::vector::iterator line = scripts[it->second.second].begin(); line != scripts[it->second.second].end(); line++) + { + std::string theline = (*line)->printLine(); + fwrite(theline.c_str(), sizeof(char), theline.size(),tempfile); + + if(output) + { + al_trace("%s",theline.c_str()); + } + } + + fclose(tempfile); + parse_script_file(&globalscripts[it->first],"tmp",false); + } + else if(globalscripts[it->first]) + { + delete[] globalscripts[it->first]; + globalscripts[it->first] = new ffscript[1]; + globalscripts[it->first][0].command = 0xFFFF; + } + } + + for(std::map >::iterator it = itemmap.begin(); it != itemmap.end(); it++) + { + if(it->second.second != "") + { + tempfile = fopen("tmp","w"); + + if(!tempfile) + { + jwin_alert("Error","Unable to create a temporary file in current directory!",NULL,NULL,"O&K",NULL,'k',0,lfont); + return; + } + + if(output) + { + al_trace("\n"); + al_trace("%s",it->second.second.c_str()); + al_trace("\n"); + } + + for(std::vector::iterator line = scripts[it->second.second].begin(); line != scripts[it->second.second].end(); line++) + { + std::string theline = (*line)->printLine(); + fwrite(theline.c_str(), sizeof(char), theline.size(),tempfile); + + if(output) + { + al_trace("%s",theline.c_str()); + } + } + + fclose(tempfile); + parse_script_file(&itemscripts[it->first+1],"tmp",false); + } + else if(itemscripts[it->first+1]) + { + delete[] itemscripts[it->first+1]; + itemscripts[it->first+1] = new ffscript[1]; + itemscripts[it->first+1][0].command = 0xFFFF; + } + } + + unlink("tmp"); + jwin_alert("Done!","ZScripts successfully loaded into script slots",NULL,NULL,"O&K",NULL,'k',0,lfont); + build_biffs_list(); + build_biitems_list(); + + for(map >::iterator it = scripts.begin(); it != scripts.end(); it++) + { + for(std::vector::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + delete *it2; + } + } + + return; + } + + case 6: + //<<, FFC + { + int lind = assignscript_dlg[4].d1; + int rind = assignscript_dlg[5].d1; + + if(lind < 0 || rind < 0) + break; + + if(asffcscripts[rind] == "") + { + ffcmap[lind].second = ""; + } + else + { + ffcmap[lind].second = asffcscripts[rind]; + } + + break; + } + + case 9: + //<<, Global + { + int lind = assignscript_dlg[7].d1; + int rind = assignscript_dlg[8].d1; + + if(lind < 0 || rind < 0) + break; + + if(lind == 0) + { + jwin_alert("Error","ZScript reserves this slot.",NULL,NULL,"O&K",NULL,'k',0,lfont); + break; + } + + if(asglobalscripts[rind] == "") + { + globalmap[lind].second = ""; + } + else + { + globalmap[lind].second = asglobalscripts[rind]; + } + + break; + } + + case 12: + //<<, ITEM + { + int lind = assignscript_dlg[10].d1; + int rind = assignscript_dlg[11].d1; + + if(lind < 0 || rind < 0) + break; + + if(asitemscripts[rind] == "") + { + itemmap[lind].second = ""; + } + else + { + itemmap[lind].second = asitemscripts[rind]; + } + + break; + } + } + } +} + +int onImportFFScript() +{ + char name[20]=""; + + ffscript_sel_dlg[0].dp2 = lfont; + ffscript_sel_dlg[2].dp = name; + ffscript_sel_dlg[5].d1 = 0; + + if(is_large) + large_dialog(ffscript_sel_dlg); + + int ret=zc_popup_dialog(ffscript_sel_dlg,0); + + if(ret==3) + { + if(parse_script(&ffscripts[ffscript_sel_dlg[5].d1+1])==D_O_K) + { + if(strlen((char *)ffscript_sel_dlg[2].dp)>0) + ffcmap[ffscript_sel_dlg[5].d1].second=(char *)ffscript_sel_dlg[2].dp; + else + ffcmap[ffscript_sel_dlg[5].d1].second="ASM script"; + + build_biffs_list(); + } + } + + return D_O_K; +} + +int onImportItemScript() +{ + char name[20]=""; + + itemscript_sel_dlg[0].dp2 = lfont; + itemscript_sel_dlg[2].dp = name; + itemscript_sel_dlg[5].d1 = 0; + + if(is_large) + large_dialog(itemscript_sel_dlg); + + int ret=zc_popup_dialog(itemscript_sel_dlg,0); + + if(ret==3) + { + if(parse_script(&itemscripts[itemscript_sel_dlg[5].d1+1])==D_O_K) + { + if(strlen((char *)itemscript_sel_dlg[2].dp)>0) + itemmap[itemscript_sel_dlg[5].d1].second=(char *)itemscript_sel_dlg[2].dp; + else + itemmap[itemscript_sel_dlg[5].d1].second="ASM script"; + + build_biitems_list(); + } + } + + return D_O_K; +} + +int onImportGScript() +{ + char name[20]=""; + + gscript_sel_dlg[0].dp2 = lfont; + gscript_sel_dlg[2].dp = name; + gscript_sel_dlg[5].d1 = 0; + + if(is_large) + large_dialog(gscript_sel_dlg); + + int ret=zc_popup_dialog(gscript_sel_dlg,0); + + if(ret==3) + { + if(parse_script(&globalscripts[gscript_sel_dlg[5].d1])==D_O_K) + { + if(strlen((char *)gscript_sel_dlg[2].dp)>0) + globalmap[gscript_sel_dlg[5].d1].second=(char *)gscript_sel_dlg[2].dp; + else + globalmap[gscript_sel_dlg[5].d1].second="ASM script"; + } + } + + return D_O_K; +} + +int onEditFFCombo(int ffcombo) +{ + char xystring[8][10]; + char wstring[4][10]; + char dastring[10][13]; + sprintf(xystring[0],"%.4f",Map.CurrScr()->ffcs[ffcombo].x/10000.0); + sprintf(xystring[1],"%.4f",Map.CurrScr()->ffcs[ffcombo].y/10000.0); + sprintf(xystring[2],"%.4f",Map.CurrScr()->ffcs[ffcombo].xVel/10000.0); + sprintf(xystring[3],"%.4f",Map.CurrScr()->ffcs[ffcombo].yVel/10000.0); + sprintf(xystring[4],"%.4f",Map.CurrScr()->ffcs[ffcombo].xAccel/10000.0); + sprintf(xystring[5],"%.4f",Map.CurrScr()->ffcs[ffcombo].yAccel/10000.0); + sprintf(xystring[6],"%d",Map.CurrScr()->ffcs[ffcombo].delay); + + sprintf(wstring[0],"%d",(Map.CurrScr()->ffcs[ffcombo].width&63)+1); + sprintf(wstring[1],"%d",(Map.CurrScr()->ffcs[ffcombo].height&63)+1); + sprintf(wstring[2],"%d",Map.CurrScr()->ffcs[ffcombo].getTileWidth()); + sprintf(wstring[3],"%d",Map.CurrScr()->ffcs[ffcombo].getTileHeight()); + + sprintf(dastring[0],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[0]/10000.0); + sprintf(dastring[1],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[1]/10000.0); + sprintf(dastring[2],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[2]/10000.0); + sprintf(dastring[3],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[3]/10000.0); + sprintf(dastring[4],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[4]/10000.0); + sprintf(dastring[5],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[5]/10000.0); + sprintf(dastring[6],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[6]/10000.0); + sprintf(dastring[7],"%.4f",Map.CurrScr()->ffcs[ffcombo].initd[7]/10000.0); + sprintf(dastring[8],"%ld",Map.CurrScr()->ffcs[ffcombo].inita[0]/10000); + sprintf(dastring[9],"%ld",Map.CurrScr()->ffcs[ffcombo].inita[1]/10000); + + char wtitle[80]; + sprintf(wtitle,"Edit Freeform Combo (#%d)", ffcombo+1); + ffcombo_dlg[0].dp2 = lfont; + ffcombo_dlg[0].dp = wtitle; + ffcombo_dlg[4].dp2 = spfont; + + ffcombo_dlg[6].d1 = Map.CurrScr()->ffcs[ffcombo].data; + ffcombo_dlg[6].fg = Map.CurrScr()->ffcs[ffcombo].cset; + + ffcombo_dlg[15].d1 = Map.CurrScr()->ffcs[ffcombo].link; + ffcombo_dlg[16].dp = xystring[0]; + ffcombo_dlg[17].dp = xystring[1]; + ffcombo_dlg[18].dp = xystring[2]; + ffcombo_dlg[19].dp = xystring[3]; + ffcombo_dlg[20].dp = xystring[4]; + ffcombo_dlg[21].dp = xystring[5]; + ffcombo_dlg[22].dp = xystring[6]; + + ffcombo_dlg[27].dp = wstring[0]; + ffcombo_dlg[28].dp = wstring[1]; + ffcombo_dlg[29].dp = wstring[2]; + ffcombo_dlg[30].dp = wstring[3]; + + ffcombo_dlg[64].dp = dastring[0]; + ffcombo_dlg[65].dp = dastring[1]; + ffcombo_dlg[66].dp = dastring[2]; + ffcombo_dlg[67].dp = dastring[3]; + ffcombo_dlg[68].dp = dastring[4]; + ffcombo_dlg[69].dp = dastring[5]; + ffcombo_dlg[70].dp = dastring[6]; + ffcombo_dlg[71].dp = dastring[7]; + ffcombo_dlg[74].dp = dastring[8]; + ffcombo_dlg[75].dp = dastring[9]; + + build_biffs_list(); + int index = 0; + + for(int j = 0; j < biffs_cnt; j++) + { + if(biffs[j].second == Map.CurrScr()->ffcs[ffcombo].script - 1) + { + index = j; + } + } + + ffcombo_dlg[55].d1 = index; + + int f=Map.CurrScr()->ffcs[ffcombo].flags; + ffcombo_dlg[33].flags = (f&ffOVERLAY) ? D_SELECTED : 0; + ffcombo_dlg[34].flags = (f&ffTRANS) ? D_SELECTED : 0; + ffcombo_dlg[35].flags = (f&ffCARRYOVER) ? D_SELECTED : 0; + ffcombo_dlg[36].flags = (f&ffSTATIONARY) ? D_SELECTED : 0; + ffcombo_dlg[37].flags = (f&ffCHANGER) ? D_SELECTED : 0; + ffcombo_dlg[38].flags = (f&ffPRELOAD) ? D_SELECTED : 0; + ffcombo_dlg[39].flags = (f&ffLENSVIS) ? D_SELECTED : 0; + ffcombo_dlg[40].flags = (f&ffSCRIPTRESET) ? D_SELECTED : 0; + ffcombo_dlg[41].flags = (f&ffETHEREAL) ? D_SELECTED : 0; + ffcombo_dlg[42].flags = (f&ffIGNOREHOLDUP) ? D_SELECTED : 0; + + ffcombo_dlg[49].flags = (f&ffSWAPNEXT) ? D_SELECTED : 0; + ffcombo_dlg[50].flags = (f&ffSWAPPREV) ? D_SELECTED : 0; + ffcombo_dlg[51].flags = (f&ffCHANGENEXT) ? D_SELECTED : 0; + ffcombo_dlg[52].flags = (f&ffCHANGEPREV) ? D_SELECTED : 0; + ffcombo_dlg[53].flags = (f&ffCHANGETHIS) ? D_SELECTED : 0; + + if(is_large) + large_dialog(ffcombo_dlg); + + int ret = -1; + + do + { + ret=zc_popup_dialog(ffcombo_dlg,0); + + // A polite warning about FFC 0 and scripts + if(ret==2 && !ffcombo_dlg[6].d1 && ffcombo_dlg[55].d1>0) + if(jwin_alert("Inactive FFC","FFCs that use Combo 0 cannot run scripts! Continue?",NULL,NULL,"Yes","No",'y','n',lfont)==2) + ret=-1; + } + while(ret<0); + + if(ret==2) + { + saved=false; + Map.CurrScr()->ffcs[ffcombo].data = ffcombo_dlg[6].d1; + Map.CurrScr()->ffcs[ffcombo].cset = ffcombo_dlg[6].fg; + Map.CurrScr()->ffcs[ffcombo].link = ffcombo_dlg[15].d1; + Map.CurrScr()->ffcs[ffcombo].x = vbound(ffparse(xystring[0]),-320000, 2880000); + Map.CurrScr()->ffcs[ffcombo].y = vbound(ffparse(xystring[1]),-320000, 2080000); + Map.CurrScr()->ffcs[ffcombo].xVel= vbound(ffparse(xystring[2]),-1280000, 1280000); + Map.CurrScr()->ffcs[ffcombo].yVel = vbound(ffparse(xystring[3]),-1280000, 1280000); + Map.CurrScr()->ffcs[ffcombo].xAccel = vbound(ffparse(xystring[4]),-1280000, 1280000); + Map.CurrScr()->ffcs[ffcombo].yAccel = vbound(ffparse(xystring[5]),-1280000, 1280000); + Map.CurrScr()->ffcs[ffcombo].delay = atoi(xystring[6])<10000?zc_max(0,atoi(xystring[6])):9999; + Map.CurrScr()->ffcs[ffcombo].script = biffs[ffcombo_dlg[55].d1].second + 1; + + int cw = atoi(wstring[0])<65?zc_max(1,atoi(wstring[0])):64; + int ch = atoi(wstring[1])<65?zc_max(1,atoi(wstring[1])):64; + int tw = atoi(wstring[2])<5?zc_max(1,atoi(wstring[2])):4; + int th = atoi(wstring[3])<5?zc_max(1,atoi(wstring[3])):4; + Map.CurrScr()->ffcs[ffcombo].width = (cw-1)+((tw-1)<<6); + Map.CurrScr()->ffcs[ffcombo].height = (ch-1)+((th-1)<<6); + + Map.CurrScr()->ffcs[ffcombo].initd[0] = vbound(ffparse(dastring[0]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[1] = vbound(ffparse(dastring[1]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[2] = vbound(ffparse(dastring[2]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[3] = vbound(ffparse(dastring[3]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[4] = vbound(ffparse(dastring[4]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[5] = vbound(ffparse(dastring[5]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[6] = vbound(ffparse(dastring[6]),-2147483647, 2147483647); + Map.CurrScr()->ffcs[ffcombo].initd[7] = vbound(ffparse(dastring[7]),-2147483647, 2147483647); + + Map.CurrScr()->ffcs[ffcombo].inita[0] = vbound(atoi(dastring[8])*10000,0,320000); + Map.CurrScr()->ffcs[ffcombo].inita[1] = vbound(atoi(dastring[9])*10000,0,320000); + + f=0; + f |= (ffcombo_dlg[33].flags&D_SELECTED) ? ffOVERLAY : 0; + f |= (ffcombo_dlg[34].flags&D_SELECTED) ? ffTRANS : 0; + f |= (ffcombo_dlg[35].flags&D_SELECTED) ? ffCARRYOVER : 0; + f |= (ffcombo_dlg[36].flags&D_SELECTED) ? ffSTATIONARY : 0; + f |= (ffcombo_dlg[37].flags&D_SELECTED) ? ffCHANGER : 0; + f |= (ffcombo_dlg[38].flags&D_SELECTED) ? ffPRELOAD : 0; + f |= (ffcombo_dlg[39].flags&D_SELECTED) ? ffLENSVIS : 0; + f |= (ffcombo_dlg[40].flags&D_SELECTED) ? ffSCRIPTRESET : 0; + f |= (ffcombo_dlg[41].flags&D_SELECTED) ? ffETHEREAL : 0; + f |= (ffcombo_dlg[42].flags&D_SELECTED) ? ffIGNOREHOLDUP : 0; + + f |= (ffcombo_dlg[49].flags&D_SELECTED) ? ffSWAPNEXT : 0; + f |= (ffcombo_dlg[50].flags&D_SELECTED) ? ffSWAPPREV : 0; + f |= (ffcombo_dlg[51].flags&D_SELECTED) ? ffCHANGENEXT : 0; + f |= (ffcombo_dlg[52].flags&D_SELECTED) ? ffCHANGEPREV : 0; + f |= (ffcombo_dlg[53].flags&D_SELECTED) ? ffCHANGETHIS : 0; + Map.CurrScr()->ffcs[ffcombo].flags = f; + + if(Map.CurrScr()->ffcs[ffcombo].data!=0) + { + Map.CurrScr()->ffcsUsed|=(1<ffcsUsed&=~(1<=WAV_COUNT) + return false; + + if(sfx_voice[index]==-1) + { + sfx_voice[index]=allocate_voice(&templist[index]); + } + + return sfx_voice[index] != -1; +} + +// plays an sfx sample +void sfx(int index,int pan,bool loop,bool restart) +{ + if(!sfx_init(index)) + return; + + voice_set_playmode(sfx_voice[index],loop?PLAYMODE_LOOP:PLAYMODE_PLAY); + voice_set_pan(sfx_voice[index],pan); + + int pos = voice_get_position(sfx_voice[index]); + + if(restart) voice_set_position(sfx_voice[index],0); + + if(pos<=0) + voice_start(sfx_voice[index]); +} + +// start it (in loop mode) if it's not already playing, +// otherwise just leave it in its current position +void cont_sfx(int index) +{ + if(!sfx_init(index)) + return; + + if(voice_get_position(sfx_voice[index])<=0) + { + voice_set_position(sfx_voice[index],0); + voice_set_playmode(sfx_voice[index],PLAYMODE_LOOP); + voice_start(sfx_voice[index]); + } +} + +// adjust parameters while playing +void adjust_sfx(int index,int pan,bool loop) +{ + if(index<0 || index>=WAV_COUNT || sfx_voice[index]==-1) + return; + + voice_set_playmode(sfx_voice[index],loop?PLAYMODE_LOOP:PLAYMODE_PLAY); + voice_set_pan(sfx_voice[index],pan); +} + +// pauses a voice +void pause_sfx(int index) +{ + if(index>=0 && index=0 && index=WAV_COUNT) + return; + + if(sfx_voice[index]!=-1) + { + deallocate_voice(sfx_voice[index]); + sfx_voice[index]=-1; + } +} + +void kill_sfx() +{ + for(int i=0; i>1)+68,0,255); + case 2: return vbound(((x*3)>>2)+36,0,255); + } + return vbound(x,0,255); +}*/ + + +void change_sfx(SAMPLE *sfx1, SAMPLE *sfx2) +{ + sfx1->bits = sfx2->bits; + sfx1->stereo = sfx2->stereo; + sfx1->freq = sfx2->freq; + sfx1->priority = sfx2->priority; + sfx1->len = sfx2->len; + sfx1->loop_start = sfx2->loop_start; + sfx1->loop_end = sfx2->loop_end; + sfx1->param = sfx2->param; + + if(sfx1->data != NULL) + { + zc_free(sfx1->data); + } + + if(sfx2->data == NULL) + sfx1->data = NULL; + else + { + // When quests are saved and loaded, data is written in words. + // If the last byte is dropped, it'll cause the sound to end with + // a click. It could simply be extended and padded with 0, but + // that causes compatibility issues... So we'll cut off + // the last byte and decrease the length. + + int len = (sfx1->bits==8?1:2)*(sfx1->stereo == 0 ? 1 : 2)*sfx1->len; + + while(len%sizeof(word)) + { + // sizeof(word) should be 2, so this doesn't really need + // to be a loop, but what the heck. + sfx1->len--; + len = (sfx1->bits==8?1:2)*(sfx1->stereo == 0 ? 1 : 2)*sfx1->len; + } + + sfx1->data = zc_malloc(len); + memcpy(sfx1->data, sfx2->data, len); + } +} + +int onSelectSFX() +{ + int index = select_sfx("Select SFX",0); + + while(index >= 0) + { + if(index) + onEditSFX(index); + + index = select_sfx("Select SFX",index); + } + + refresh(rMAP+rCOMBOS); + return D_O_K; +} + +int onEditSFX(int index) +{ + kill_sfx(); + stop_midi(); + set_volume(255,-1); + int ret; + sfx_edit_dlg[0].dp2=lfont; + unsigned char tempflag; + tempflag = get_bit(customsfxflag,index-1); + change_sfx(&templist[index], &customsfxdata[index]); + + char sfxnumstr[50]; + sprintf(sfxnumstr,"SFX %d: %s", index, sfx_string[index]); + sfx_edit_dlg[0].dp = sfxnumstr; + + char name[36]; + strcpy(name,sfx_string[index]); + sfx_edit_dlg[7].dp = name; + + if(is_large) + large_dialog(sfx_edit_dlg); + + do + { + ret=zc_popup_dialog(sfx_edit_dlg,1); + + switch(ret) + { + case 1: + saved= false; + kill_sfx(); + change_sfx(&customsfxdata[index],&templist[index]); + set_bit(customsfxflag,index-1,tempflag); + strcpy(sfx_string[index], name); + + case 2: + case 0: + // Fall Through + kill_sfx(); + + for(int i=1; i2); + + return D_O_K; +} + + +static DIALOG mapstyles_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 0, 0, 307, 186, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Map Styles", NULL, NULL }, + { jwin_ctext_proc, 24, 34, 36, 36, 0, 0, 0, 0, 0, 0, (void *) "Frame", NULL, NULL }, //frame + { jwin_ctext_proc, 68, 26, 20, 20, 0, 0, 0, 0, 0, 0, (void *) "Triforce", NULL, NULL }, //triforce fragment + { jwin_ctext_proc, 68, 34, 20, 20, 0, 0, 0, 0, 0, 0, (void *) "Fragment", NULL, NULL }, //triforce fragment + { jwin_ctext_proc, 152, 26, 100, 52, 0, 0, 0, 0, 0, 0, (void *) "Triforce Frame", NULL, NULL }, //triforce frame + { jwin_ctext_proc, 152, 34, 100, 52, 0, 0, 0, 0, 0, 0, (void *) "(Normal or Double Sized)", NULL, NULL }, //triforce frame + { jwin_ctext_proc, 260, 34, 84, 52, 0, 0, 0, 0, 0, 0, (void *) "Overworld Map", NULL, NULL }, //overworld map + { jwin_ctext_proc, 24, 82, 20, 20, 0, 0, 0, 0, 0, 0, (void *) "Heart", NULL, NULL }, //heart container piece + { jwin_ctext_proc, 24, 90, 20, 20, 0, 0, 0, 0, 0, 0, (void *) "Container", NULL, NULL }, //heart container piece + { jwin_ctext_proc, 24, 98, 20, 20, 0, 0, 0, 0, 0, 0, (void *) "Piece", NULL, NULL }, //heart container piece + { jwin_ctext_proc, 260, 98, 84, 52, 0, 0, 0, 0, 0, 0, (void *) "Dungeon Map", NULL, NULL }, //dungeon map + // 11 + { jwin_frame_proc, 6, 42, 36, 36, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //frame + // { jwin_frame_proc, 50, 42, 36, 52, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //bs triforce fragment + { jwin_frame_proc, 58, 42, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //normal triforce fragment + // { jwin_frame_proc, 94, 42, 116, 116, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //bs triforce frame + { jwin_frame_proc, 102, 42, 100, 52, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //normaltriforce frame + { jwin_frame_proc, 218, 42, 84, 52, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //overworld map + { jwin_frame_proc, 14, 106, 20, 20, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //heart container piece + { jwin_frame_proc, 218, 106, 84, 52, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, //dungeon map + // 17 + { d_maptile_proc, 8, 44, 32, 32, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //frame + // { d_maptile_proc, 52, 44, 32, 48, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, //bs triforce fragment + { d_maptile_proc, 60, 44, 16, 16, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //normal triforce fragment + // { d_maptile_proc, 96, 44, 112, 112, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, //bs triforce frame + { d_maptile_proc, 104, 44, 96, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //normal triforce frame + { d_maptile_proc, 220, 44, 80, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //overworld map + { d_maptile_proc, 16, 108, 16, 16, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //heart container piece + { d_maptile_proc, 220, 108, 80, 48, 0, 0, 0, 0, 0, 0, NULL, (void*)1, NULL }, //dungeon map + // 23 + { jwin_button_proc, 83, 162, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 163, 162, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int onMapStyles() +{ + if(mapstyles_dlg[0].d1<1) + { + mapstyles_dlg[12].x=mapstyles_dlg[0].x+50; + mapstyles_dlg[12].w=36; + mapstyles_dlg[12].h=52; + mapstyles_dlg[13].x=mapstyles_dlg[0].x+94; + mapstyles_dlg[13].w=116; + mapstyles_dlg[13].h=116; + mapstyles_dlg[18].x=mapstyles_dlg[12].x+2; + mapstyles_dlg[18].w=mapstyles_dlg[12].w-4; + mapstyles_dlg[18].h=mapstyles_dlg[12].h-4; + mapstyles_dlg[19].x=mapstyles_dlg[13].x+2; + mapstyles_dlg[19].w=mapstyles_dlg[13].w-4; + mapstyles_dlg[19].h=mapstyles_dlg[13].h-4; + } + + mapstyles_dlg[0].dp2 = lfont; + mapstyles_dlg[17].d1 = misc.colors.blueframe_tile; + mapstyles_dlg[17].fg = misc.colors.blueframe_cset; + mapstyles_dlg[18].d1 = misc.colors.triforce_tile; + mapstyles_dlg[18].fg = misc.colors.triforce_cset; + mapstyles_dlg[19].d1 = misc.colors.triframe_tile; + mapstyles_dlg[19].fg = misc.colors.triframe_cset; + mapstyles_dlg[20].d1 = misc.colors.overworld_map_tile; + mapstyles_dlg[20].fg = misc.colors.overworld_map_cset; + mapstyles_dlg[21].d1 = misc.colors.HCpieces_tile; + mapstyles_dlg[21].fg = misc.colors.HCpieces_cset; + mapstyles_dlg[22].d1 = misc.colors.dungeon_map_tile; + mapstyles_dlg[22].fg = misc.colors.dungeon_map_cset; + + if(is_large) + large_dialog(mapstyles_dlg,2); + + go(); + int ret = zc_do_dialog(mapstyles_dlg,-1); + comeback(); + + if(ret==23) + { + misc.colors.blueframe_tile = mapstyles_dlg[17].d1; + misc.colors.blueframe_cset = mapstyles_dlg[17].fg; + misc.colors.triforce_tile = mapstyles_dlg[18].d1; + misc.colors.triforce_cset = mapstyles_dlg[18].fg; + misc.colors.triframe_tile = mapstyles_dlg[19].d1; + misc.colors.triframe_cset = mapstyles_dlg[19].fg; + misc.colors.overworld_map_tile = mapstyles_dlg[20].d1; + misc.colors.overworld_map_cset = mapstyles_dlg[20].fg; + misc.colors.HCpieces_tile = mapstyles_dlg[21].d1; + misc.colors.HCpieces_cset = mapstyles_dlg[21].fg; + misc.colors.dungeon_map_tile = mapstyles_dlg[22].d1; + misc.colors.dungeon_map_cset = mapstyles_dlg[22].fg; + saved=false; + } + + return D_O_K; +} + +int d_misccolors_old_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + + if(msg==MSG_DRAW) + { + textout_ex(screen,font,"0123456789ABCDEF",d->x+8,d->y,d->fg,d->bg); + textout_ex(screen,font,"0",d->x,d->y+8,d->fg,d->bg); + textout_ex(screen,font,"1",d->x,d->y+16,d->fg,d->bg); + textout_ex(screen,font,"5",d->x,d->y+24,d->fg,d->bg); + + for(int i=0; i<32; i++) + { + int px2 = d->x+((i&15)<<3)+8; + int py2 = d->y+((i>>4)<<3)+8; + rectfill(screen,px2,py2,px2+7,py2+7,i); + } + + for(int i=0; i<16; i++) + { + int px2 = d->x+(i<<3)+8; + rectfill(screen,px2,d->y+24,px2+7,d->y+31,i+80); + } + } + + return D_O_K; +} + +int hexclicked=-1; + +int d_misccolors_hexedit_proc(int msg,DIALOG *d,int c) +{ + switch(msg) + { + case MSG_GOTFOCUS: + hexclicked=((int)(size_t)(d->dp3))+20; + break; + + case MSG_LOSTFOCUS: + hexclicked=-1; + break; + } + + return d_hexedit_proc(msg,d,c); +} + + +int d_misccolors_proc(int msg,DIALOG *d,int c); + +static int misccolor1_list[] = +{ + // dialog control number + 4, 5, 6, 7, 8, 20, 21, 22, 23, 24, 36, 37, 38, 39, 40, -1 +}; + +static int misccolor2_list[] = +{ + // dialog control number + 9, 10, 11, 12, 13, 25, 26, 27, 28, 29, 41, 42, 43, 44, 45, -1 +}; + +static int misccolor3_list[] = +{ + // dialog control number + 14, 15, 16, 17, 18, 30, 31, 32, 33, 34, 46, 47, 48, 49, 50, -1 +}; + +static int misccolor4_list[] = +{ + 19, 35, 51, 54, 55, 56, -1 +}; + +static TABPANEL misccolor_tabs[] = +{ + // (text) + { (char *)"1", D_SELECTED, misccolor1_list, 0, NULL }, + { (char *)"2", 0, misccolor2_list, 0, NULL }, + { (char *)"3", 0, misccolor3_list, 0, NULL }, + { (char *)"4", 0, misccolor4_list, 0, NULL }, + { NULL, 0, NULL, 0, NULL } +}; + +int d_misccolors_tab_proc(int msg,DIALOG *d,int c); + +static DIALOG misccolors_dlg[] = +{ + // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) + { jwin_win_proc, 2, 21, 316, 197-23, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Misc Colors", NULL, NULL }, + // { jwin_frame_proc, 98-84+1+2, 52+8-6+4, 132, 100, vc(15), vc(1), 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { d_misccolors_proc, 92-84+1+2, 44+8-6+4, 128+8, 96+8, vc(9), vc(1), 0, 0, 0, 0, NULL, NULL, NULL }, + //3 + { d_misccolors_tab_proc, 150+14-2+10-15, 60-14, 150-10+15, 144-20-10, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) misccolor_tabs, NULL, (void *)misccolors_dlg }, + //4 + { jwin_text_proc, 215-25-12-15, 76-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Text:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 94-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Caption:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 112-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Overworld Minmap:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 130-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Minimap Background:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 148-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Minimap Foreground 1:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 76-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Minimap Foreground 2:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 94-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "BS Minimap Dark:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 112-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "BS Minimap Goal:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 130-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Compass Mark (Light):", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 148-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Compass Mark (Dark):", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 76-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Subscreen Background:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 94-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Subscreen Shadow:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 112-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Triforce Frame:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 130-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Big Map Background:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 148-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Big Map Foreground:", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 76-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Link's Position:", NULL, NULL }, + + //20 + { d_misccolors_hexedit_proc, 294-25+14+2, 76-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)0, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 94-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)1, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 112-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)2, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 130-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)3, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 148-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)4, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 76-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)5, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 94-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)6, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 112-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)7, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 130-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)8, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 148-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)9, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 76-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)10, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 94-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)11, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 112-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)12, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 130-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)13, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 148-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)14, }, + { d_misccolors_hexedit_proc, 294-25+14+2, 76-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)15, }, + + //36 + { jwin_text_proc, 283-25+14+2, 76-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 94-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 112-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 130-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 148-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 76-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 94-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 112-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 130-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 148-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 76-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 94-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 112-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 130-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 148-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { jwin_text_proc, 283-25+14+2, 76-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + + //52 + { jwin_button_proc, 90, 190-20, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 190-20, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_text_proc, 215-25-12-15, 94-4, 0, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Message Text:", NULL, NULL }, + { d_misccolors_hexedit_proc, 294-25+14+2, 94-8, 21, 16, vc(11), vc(1), 0, 0, 2, 0, NULL, NULL, (void *)35, }, + { jwin_text_proc, 283-25+14+2, 94-4, 0, 8, vc(11), vc(1), 0, 0, 2, 0, (void *) "0x", NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +int d_misccolors_tab_proc(int msg,DIALOG *d,int c) +{ + + switch(msg) + { + case MSG_WANTFOCUS: + return D_WANTFOCUS; + break; + } + + return jwin_tab_proc(msg,d,c); +} + + +int d_misccolors_proc(int msg,DIALOG *d,int c) +{ + //these are here to bypass compiler warnings about unused arguments + c=c; + int mul=8; + + if(is_large) + mul=(int)(mul*1.5); + + switch(msg) + { + case MSG_CLICK: + if(hexclicked!=-1) + { + int color_col=vbound(((gui_mouse_x()-d->x-8)/mul),0,15); + int color_row=vbound(((gui_mouse_y()-d->y-10)/mul),0,11); + sprintf((char*)misccolors_dlg[hexclicked].dp,"%X%X",color_row,color_col); + object_message(misccolors_dlg+hexclicked,MSG_DRAW,0); + } + + break; + + case MSG_DRAW: + for(int i=0; i<10; i++) + { + textprintf_centre_ex(screen,font,d->x+8+4+(i*mul),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX], "%d", i); + } + + for(int i=0; i<6; i++) + { + textprintf_centre_ex(screen,font,d->x+8+4+((10+i)*mul),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX], "%c", i+'A'); + } + + for(int i=0; i<10; i++) + { + textprintf_right_ex(screen,font,d->x+6,d->y+(i*mul)+10,jwin_pal[jcBOXFG],jwin_pal[jcBOX], "%d", i); + } + + for(int i=0; i<2; i++) + { + textprintf_right_ex(screen,font,d->x+6,d->y+((i+10)*mul)+10,jwin_pal[jcBOXFG],jwin_pal[jcBOX], "%c", i+'A'); + } + + jwin_draw_frame(screen,d->x+6,d->y+8,int(132*(is_large?1.5:1))-(1+is_large),int(100*(is_large?1.5:1))-(1+is_large),FR_DEEP); + + for(int i=0; i<192; i++) + { + int px2 = d->x+int(((i&15)<<3)*(is_large?1.5 : 1))+8; + int py2 = d->y+int(((i>>4)<<3)*(is_large?1.5 : 1))+8+2; + rectfill(screen,px2,py2,px2+(mul-1),py2+(mul-1),i); + } + + break; + } + + return D_O_K; +} + + +int onMiscColors() +{ + char buf[17][3]; + byte *si = &(misc.colors.text); + misccolors_dlg[0].dp2=lfont; + + for(int i=0; i<16; i++) + { + sprintf(buf[i],"%02X",*(si++)); + sprintf(buf[16], "%02X", misc.colors.msgtext); + misccolors_dlg[i+20].dp = buf[i]; + misccolors_dlg[55].dp = buf[16]; + } + + if(is_large) + large_dialog(misccolors_dlg); + + if(zc_popup_dialog(misccolors_dlg,0)==52) + { + saved=false; + si = &(misc.colors.text); + + for(int i=0; i<16; i++) + { + *si = xtoi(buf[i]); + ++si; + } + + misc.colors.msgtext = xtoi(buf[16]); + } + + return D_O_K; +} + +// **** Palette cycling **** + +static int palclk[3]; +static int palpos[3]; + +void reset_pal_cycling() +{ + for(int i=0; i<3; i++) + palclk[i]=palpos[i]=0; +} + +void cycle_palette() +{ + if(!get_bit(quest_rules,qr_FADE)) + return; + + int level = Map.CurrScr()->color; + bool refreshpal = false; + + for(int i=0; i<3; i++) + { + palcycle c = misc.cycles[level][i]; + + if(c.count&0xF0) + { + if(++palclk[i] >= c.speed) + { + palclk[i]=0; + + if(++palpos[i] >= (c.count>>4)) + palpos[i]=0; + + byte *si = colordata + CSET(level*pdLEVEL+poFADE1+1+palpos[i])*3; + + si += (c.first&15)*3; + + for(int col=c.first&15; col<=(c.count&15); col++) + { + RAMpal[CSET(c.first>>4)+col] = _RGB(si); + si+=3; + } + + refreshpal = true; + } + } + } + + if(refreshpal) + { + rebuild_trans_table(); + set_palette_range(RAMpal,0,192,false); + } +} + + +/********************/ +/****** Help ******/ +/********************/ + +static DIALOG help_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ +// { jwin_textbox_proc, 4, 2+21, 320-8, 240-6-21, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { jwin_win_proc, 0, 0, 320, 240, 0, vc(15), 0, D_EXIT, 0, 0, (void *) "ZQuest Help", NULL, NULL }, + { jwin_frame_proc, 4, 23, 320-8, 240-27, 0, 0, 0, 0, FR_DEEP, 0, NULL, NULL, NULL }, + { d_editbox_proc, 6, 25, 320-8-4, 240-27-4, 0, 0, 0, 0/*D_SELECTED*/, 0, 0, NULL, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_ESC, (void *) close_dlg, NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, (void *) onSnapshot, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void doHelp(int bg,int fg) +{ + help_dlg[0].dp2= lfont; + help_dlg[2].dp = new EditboxModel(helpstr, new EditboxWordWrapView(&help_dlg[2],is_large?sfont3:font,fg,bg,BasicEditboxView::HSTYLE_EOTEXT),true); + help_dlg[2].bg = bg; + zc_popup_dialog(help_dlg,2); + delete(EditboxModel*)(help_dlg[2].dp); +} + +int onHelp() +{ + restore_mouse(); + doHelp(vc(15),vc(0)); + return D_O_K; +} + +static DIALOG layerdata_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 16-12, 20+32, 288+1+24, 200+1-32-16, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Layer Data", NULL, NULL }, + { jwin_button_proc, 170, 180, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { jwin_button_proc, 90, 180, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + // 3 + { jwin_rtext_proc, 72, 88, 40, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Map:", NULL, NULL }, + { jwin_rtext_proc, 72, 88+18, 48, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Screen:", NULL, NULL }, + { jwin_rtext_proc, 72, 88+36, 56, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "Transparent:", NULL, NULL }, + { jwin_ctext_proc, 89, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "1", NULL, NULL }, + { jwin_ctext_proc, 89+40, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "2", NULL, NULL }, + { jwin_ctext_proc, 89+80, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "3", NULL, NULL }, + { jwin_ctext_proc, 89+120, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "4", NULL, NULL }, + { jwin_ctext_proc, 89+160, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "5", NULL, NULL }, + { jwin_ctext_proc, 89+200, 76, 8, 8, vc(11), vc(1), 0, 0, 0, 0, (void *) "6", NULL, NULL }, + + //12 + { jwin_edit_proc, 76, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_edit_proc, 76+40, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76+40, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76+40, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_edit_proc, 76+80, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76+80, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76+80, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_edit_proc, 76+120, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76+120, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76+120, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_edit_proc, 76+160, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76+160, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76+160, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + { jwin_edit_proc, 76+200, 76+8, 32-6, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { d_hexedit_proc, 76+200, 76+18+8, 24-3, 16, vc(12), vc(1), 0, 0, 2, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76+200, 76+40+8, 17, 9, vc(12), vc(1), 0, 0, 1, 0, NULL, NULL, NULL }, + + //30 + { jwin_button_proc, 76, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + { jwin_button_proc, 76+40, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + { jwin_button_proc, 76+80, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + { jwin_button_proc, 76+120, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + { jwin_button_proc, 76+160, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + { jwin_button_proc, 76+200, 76+40+18+8, 30, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Auto", NULL, NULL }, + + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } + +}; + +int edit_layers(mapscr* tempscr) +{ + char buf[6][2][8]; + layerdata_dlg[0].dp2 = lfont; + + for(int x=0; x<6; x++) + { + sprintf(buf[x][0],"%d",tempscr->layermap[x]); + sprintf(buf[x][1],"%02X",tempscr->layerscreen[x]); + } + + for(int x=0; x<6; x++) + { + for(int y=0; y<2; y++) + { + layerdata_dlg[(x*3)+y+12].dp = buf[x][y]; + } + } + + for(int x=0; x<6; x++) + { + layerdata_dlg[(x*3)+2+12].flags = (tempscr->layeropacity[x]<255) ? D_SELECTED : 0; + } + + if(is_large) + large_dialog(layerdata_dlg); + + int ret=zc_popup_dialog(layerdata_dlg,0); + + if(ret>=2) + { + for(int x=0; x<6; x++) + { + + tempscr->layermap[x]=atoi(buf[x][0]); + + if(tempscr->layermap[x]>map_count) + { + tempscr->layermap[x]=0; + } + + tempscr->layerscreen[x]=xtoi(buf[x][1]); + + if(xtoi(buf[x][1])>=MAPSCRS) + { + tempscr->layerscreen[x]=0; + } + + // tempscr->layeropacity[x]=layerdata_dlg[(x*9)+8+19].flags & D_SELECTED ? 128:255; + tempscr->layeropacity[x]=layerdata_dlg[(x*3)+2+12].flags & D_SELECTED ? 128:255; + } + + // } else if (ret>72&&ret<79) { + // return (ret-72); + } + + return ret; +} + +static DIALOG autolayer_dlg[] = +{ + /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */ + { jwin_win_proc, 64, 32+48, 192+1, 184+1-64-28, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Autolayer Setup", NULL, NULL }, + { jwin_text_proc, 76, 56+48, 136, 8, vc(14), vc(1), 0, 0, 0, 0, (void *) "Map for layer ?: ", NULL, NULL }, + { jwin_edit_proc, 212, 56+48, 32, 16, vc(12), vc(1), 0, 0, 3, 0, NULL, NULL, NULL }, + { jwin_check_proc, 76, 56+18+48, 153, 8, vc(14), vc(1), 0, 0, 1, 0, (void *) "Overwrite current", NULL, NULL }, + + //5 + { jwin_button_proc, 90, 188-40, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL }, + { jwin_button_proc, 170, 188-40, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL }, + { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL }, + { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL } +}; + +void autolayer(mapscr* tempscr, int layer, int al[6][3]) +{ + char tbuf[80],mlayer[80]; + autolayer_dlg[0].dp2=lfont; + sprintf(tbuf, "Map for layer %d: ", layer+1); + autolayer_dlg[1].dp=tbuf; + sprintf(mlayer, "%d", tempscr->layermap[layer]); + autolayer_dlg[2].dp=mlayer; + + if(is_large) + large_dialog(autolayer_dlg); + + int ret=zc_popup_dialog(autolayer_dlg,0); + + if(ret==4) + { + int lmap=vbound(atoi(mlayer),0,Map.getMapCount()); + al[layer][0]=lmap; + tempscr->layermap[layer]=lmap; + tempscr->layerscreen[layer]=Map.getCurrScr(); + al[layer][1]=autolayer_dlg[3].flags & D_SELECTED?1:0; + al[layer][2]=1; + } +} + +int findblankcombo() +{ + for(int i=0; i2) //autolayer button + { + autolayer(&tempscr, ret-30, al); + } + } + while(ret>2); //autolayer button + + if(ret==2) //OK + { + saved=false; + TheMaps[Map.getCurrMap()*MAPSCRS+Map.getCurrScr()]=tempscr; + + for(int i=0; i<6; i++) + { + int tm=tempscr.layermap[i]-1; + + if(tm!=al[i][0]-1) + { + al[i][2]=0; + } + + int ts=tempscr.layerscreen[i]; + + if(tm>0) + { + if(!(TheMaps[tm*MAPSCRS+ts].valid&mVALID)) + { + TheMaps[tm*MAPSCRS+ts].valid=mVALID+mVERSION; + + for(int k=0; k<176; k++) + { + TheMaps[tm*MAPSCRS+ts].data[k]=blankcombo; + } + } + } + + if(al[i][2]>0) + { + for(int j=0; j<128; j++) + { + if((TheMaps[Map.getCurrMap()*MAPSCRS+j].layermap[i]==0) || (al[i][1])) + { + if(TheMaps[Map.getCurrMap()*MAPSCRS+j].layermap[i]==0) + { + } + + if((TheMaps[Map.getCurrMap()*MAPSCRS+j].layermap[i]==0) && (al[i][1])) + { + } + + if(al[i][1]) + { + } + + TheMaps[Map.getCurrMap()*MAPSCRS+j].layermap[i]=al[i][0]; + TheMaps[Map.getCurrMap()*MAPSCRS+j].layerscreen[i]=al[i][0]?j:0; + + if(al[i][0]) + { + if(!(TheMaps[(al[i][0]-1)*MAPSCRS+j].valid&mVALID)) + { + TheMaps[(al[i][0]-1)*MAPSCRS+j].valid=mVALID+mVERSION; + + for(int k=0; k<176; k++) + { + TheMaps[(al[i][0]-1)*MAPSCRS+j].data[k]=blankcombo; + } + } + } + } + } + } + } + + Map.Ugo(); + } + + // Check that the working layer wasn't just disabled + if(CurrentLayer>0 && tempscr.layermap[CurrentLayer-1]==0) + { + CurrentLayer=0; + } + + return D_O_K; +} + + +char *itoa(int i) +{ + static char itoaret[500]; + sprintf(itoaret, "%d", i); + return itoaret; +} + +void fps_callback() +{ + lastfps=framecnt; + framecnt=0; +} + +END_OF_FUNCTION(fps_callback) + +void create_rgb_table2(RGB_MAP *table, AL_CONST PALETTE pal, void (*callback)(int pos)) +{ +#define UNUSED 65535 +#define LAST 65532 + + /* macro add adds to single linked list */ +#define add(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ + (first != LAST ? (next[last] = (i)) : (first = (i))), \ + (last = (i))) : 0) + + /* same but w/o checking for first element */ +#define add1(i) (next[(i)] == UNUSED ? (next[(i)] = LAST, \ + next[last] = (i), \ + (last = (i))) : 0) + /* calculates distance between two colors */ +#define dist(a1, a2, a3, b1, b2, b3) \ + (col_diff[ ((a2) - (b2)) & 0x7F] + \ + (col_diff + 128)[((a1) - (b1)) & 0x7F] + \ + (col_diff + 256)[((a3) - (b3)) & 0x7F]) + + /* converts r,g,b to position in array and back */ +#define pos(r, g, b) \ + (((r) / 2) * 32 * 32 + ((g) / 2) * 32 + ((b) / 2)) + +#define depos(pal, r, g, b) \ + ((b) = ((pal) & 31) * 2, \ + (g) = (((pal) >> 5) & 31) * 2, \ + (r) = (((pal) >> 10) & 31) * 2) + + /* is current color better than pal1? */ +#define better(r1, g1, b1, pal1) \ + (((int)dist((r1), (g1), (b1), \ + (pal1).r, (pal1).g, (pal1).b)) > (int)dist2) + + /* checking of position */ +#define dopos(rp, gp, bp, ts) \ + if ((rp > -1 || r > 0) && (rp < 1 || r < 61) && \ + (gp > -1 || g > 0) && (gp < 1 || g < 61) && \ + (bp > -1 || b > 0) && (bp < 1 || b < 61)) \ + { \ + i = first + rp * 32 * 32 + gp * 32 + bp; \ + if (!data[i]) \ + { \ + data[i] = val; \ + add1(i); \ + } \ + else if ((ts) && (data[i] != val)) \ + { \ + dist2 = (rp ? (col_diff+128)[(r+2*rp-pal[val].r) & 0x7F] : r2) + \ + (gp ? (col_diff )[(g+2*gp-pal[val].g) & 0x7F] : g2) + \ + (bp ? (col_diff+256)[(b+2*bp-pal[val].b) & 0x7F] : b2); \ + if (better((r+2*rp), (g+2*gp), (b+2*bp), pal[data[i]])) \ + { \ + data[i] = val; \ + add1(i); \ + } \ + } \ + } + + int i, curr, r, g, b, val, dist2; + unsigned int r2, g2, b2; + unsigned short next[32*32*32]; + unsigned char *data; + int first = LAST; + int last = LAST; + int count = 0; + int cbcount = 0; + +#define AVERAGE_COUNT 18000 + + if(col_diff[1] == 0) + bestfit_init(); + + memset(next, 255, sizeof(next)); + memset(table->data, 0, sizeof(char)*32*32*32); + + + data = (unsigned char *)table->data; + + /* add starting seeds for floodfill */ + for(i=1; i 0) && (data[first-1] == val)) + { + b -= 2; + first--; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + dopos(-1, 0, 0, 0); + dopos(1, 0, 0, 0); + dopos(0,-1, 0, 0); + dopos(0, 1, 0, 0); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + first++; + } + + /* get next from list */ + i = first; + first = next[first]; + next[i] = UNUSED; + + /* second version of loop */ + // if (first != LAST) { + if(first < LAST) + { + + depos(first, r, g, b); + + val = data[first]; + r2 = (col_diff+128)[((pal[val].r)-(r)) & 0x7F]; + g2 = (col_diff)[((pal[val].g)-(g)) & 0x7F]; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7F]; + +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + dopos(0, 0, 1, 1); + dopos(0, 0,-1, 1); + dopos(1, 0, 0, 1); + dopos(-1, 0, 0, 1); + dopos(0, 1, 0, 1); + dopos(0,-1, 0, 1); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + if((b < 61) && (data[first + 1] == val)) + { + b += 2; + first++; + b2 = (col_diff+256)[((pal[val].b)-(b)) & 0x7f]; +#ifdef _MSC_VER +#pragma warning(disable:4127) +#endif + dopos(-1, 0, 0, 0); + dopos(1, 0, 0, 0); + dopos(0,-1, 0, 0); + dopos(0, 1, 0, 0); +#ifdef _MSC_VER +#pragma warning(default:4127) +#endif + + first--; + } + + i = first; + first = next[first]; + next[i] = UNUSED; + } + + count++; + + if(count == (cbcount+1)*AVERAGE_COUNT/256) + { + if(cbcount < 256) + { + if(callback) + callback(cbcount); + + cbcount++; + } + } + + } + + /* only the transparent (pink) color can be mapped to index 0 */ + if((pal[0].r == 63) && (pal[0].g == 0) && (pal[0].b == 63)) + table->data[31][0][31] = 0; + + if(callback) + while(cbcount < 256) + callback(cbcount++); +} + +void rebuild_trans_table() +{ + create_rgb_table2(&zq_rgb_table, RAMpal, NULL); + create_zc_trans_table(&trans_table, RAMpal, 128, 128, 128); + memcpy(&trans_table2, &trans_table, sizeof(COLOR_MAP)); + + for(int q=0; q 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + + if(Vsync) + { + //vsync(); + } +} + +void switch_out() +{ + zcmusic_pause(zcmusic, ZCM_PAUSE); + midi_pause(); +} + +void switch_in() +{ + if(quit) + return; + + BITMAP *ts=screen; + screen=menu1; + jwin_menu_proc(MSG_DRAW, &dialogs[0], 0); + screen=ts; + zcmusic_pause(zcmusic, ZCM_RESUME); + midi_resume(); +} + +void Z_eventlog(const char *format,...) +{ + format=format; //to prevent a compiler warning +} + +void PopulateInitDialog(); +int get_currdmap() +{ + return zinit.start_dmap; +} + +int get_dlevel() +{ + return DMaps[zinit.start_dmap].level; +} + +int get_currscr() +{ + return Map.getCurrScr(); +} + +int get_homescr() +{ + return DMaps[zinit.start_dmap].cont; +} + +int current_item(int item_type) +{ + //TODO remove as special case?? -DD + if(item_type==itype_shield) + { + return 2; + } + + //find lowest item of that class + int lowestid = -1; + int ret = 0; + + for(int i=0; i 60) RequestedFPS = 60; + + LOCK_VARIABLE(myvsync); + LOCK_FUNCTION(myvsync_callback); + + if(install_int_ex(myvsync_callback,BPS_TO_TIMER(RequestedFPS))) + { + Z_error("couldn't allocate timer"); + quit_game(); + } + + // 1 <= zcmusic_bufsz <= 128 + zcmusic_bufsz = vbound(get_config_int("zquest","zqmusic_bufsz",64),1,128); + int tempvalue = get_config_int("zquest","layer_mask",-1); + int usefullscreen = get_config_int("zquest","fullscreen",0); + tempmode = (usefullscreen == 0 ? GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT_FULLSCREEN); + LayerMask[0]=byte(tempvalue&0xFF); + LayerMask[1]=byte((tempvalue>>8)&0xFF); + + for(int x=0; x<7; x++) + { + LayerMaskInt[x]=get_bit(LayerMask,x); + } + + DuplicateAction[0] = get_config_int("zquest","normal_duplicate_action",2); + DuplicateAction[1] = get_config_int("zquest","horizontal_duplicate_action",0); + DuplicateAction[2] = get_config_int("zquest","vertical_duplicate_action",0); + DuplicateAction[3] = get_config_int("zquest","both_duplicate_action",0); + LeechUpdate = get_config_int("zquest","leech_update",500); + LeechUpdateTiles = get_config_int("zquest","leech_update_tiles",1); + OnlyCheckNewTilesForDuplicates = get_config_int("zquest","only_check_new_tiles_for_duplicates",0); + gui_colorset = get_config_int("zquest","gui_colorset",0); + + strcpy(last_timed_save,get_config_string("zquest","last_timed_save","")); + + midi_volume = get_config_int("zeldadx", "midi", 255); + + set_keyboard_rate(KeyboardRepeatDelay,KeyboardRepeatRate); + + if(used_switch(argc,argv,"-small") || UseSmall==1) + { + is_large=false; + BMM=1; + } + + tooltip_box.x=-1; + tooltip_box.y=-1; + tooltip_box.w=0; + tooltip_box.h=0; + + tooltip_trigger.x=-1; + tooltip_trigger.y=-1; + tooltip_trigger.w=0; + tooltip_trigger.h=0; + + if(is_large) + { + blackout_color=8; + zq_screen_w=800; + zq_screen_h=600; + + combolist_window.x=576; + combolist_window.y=0; + combolist_window.w=224; + combolist_window.h=464; + combo_preview.x=combolist_window.x+96-24; + combo_preview.y=combolist_window.y+6; + combo_preview.w=32; + combo_preview.h=32; + + combolist[0].x=combolist_window.x+8; + combolist[0].y=combolist_window.y+64; + combolist[0].w=4; + combolist[0].h=24; + combolist[1].x=combolist[0].x+72; + combolist[1].y=combolist[0].y; + combolist[1].w=combolist[0].w; + combolist[1].h=combolist[0].h; + combolist[2].x=combolist[1].x+72; + combolist[2].y=combolist[1].y; + combolist[2].w=combolist[1].w; + combolist[2].h=combolist[1].h; + + comboaliaslist[0].x=combolist[0].x; + comboaliaslist[0].y=combolist[0].y; + comboaliaslist[0].w=combolist[0].w; + comboaliaslist[0].h=combolist[0].h-5; + comboalias_preview[0].x=comboaliaslist[0].x; + comboalias_preview[0].y=comboaliaslist[0].y+(comboaliaslist[0].h<<4)+16; + comboalias_preview[0].w=comboaliaslist[0].w<<4; + comboalias_preview[0].h=64; + + comboaliaslist[1].x=combolist[1].x; + comboaliaslist[1].y=combolist[1].y; + comboaliaslist[1].w=comboaliaslist[0].w; + comboaliaslist[1].h=comboaliaslist[0].h; + comboalias_preview[1].x=comboaliaslist[1].x; + comboalias_preview[1].y=comboaliaslist[1].y+(comboaliaslist[1].h<<4)+16; + comboalias_preview[1].w=comboaliaslist[1].w<<4; + comboalias_preview[1].h=64; + + comboaliaslist[2].x=combolist[2].x; + comboaliaslist[2].y=combolist[2].y; + comboaliaslist[2].w=comboaliaslist[1].w; + comboaliaslist[2].h=comboaliaslist[1].h; + comboalias_preview[2].x=comboaliaslist[2].x; + comboalias_preview[2].y=comboaliaslist[2].y+(comboaliaslist[2].h<<4)+16; + comboalias_preview[2].w=comboaliaslist[2].w<<4; + comboalias_preview[2].h=64; + + /* + comboaliaslist[0].x=368; + comboaliaslist[0].y=172; + comboaliaslist[0].w=4; + comboaliaslist[0].h=17; + comboalias_preview[0].x=368; + comboalias_preview[0].y=388; + comboalias_preview[0].w=64; + comboalias_preview[0].h=64; + comboaliaslist[1].x=440; + comboaliaslist[1].y=172; + comboaliaslist[1].w=4; + comboaliaslist[1].h=17; + comboalias_preview[1].x=440; + comboalias_preview[1].y=388; + comboalias_preview[1].w=64; + comboalias_preview[1].h=64; + comboaliaslist[2].x=542; + comboaliaslist[2].y=172; + comboaliaslist[2].w=4; + comboaliaslist[2].h=17; + comboalias_preview[2].x=512; + comboalias_preview[2].y=388; + comboalias_preview[2].w=64; + comboalias_preview[2].h=64; + */ + mapscreen_x=0; + mapscreen_y=16; + mapscreensize=2; + showedges=1; + showallpanels=0; + + for(int i=0; i<=8; i++) + { + map_page_bar[i].x = mapscreen_x+(i*16*2*mapscreensize); + map_page_bar[i].y = mapscreen_y+((showedges?13:11)*16*mapscreensize); + map_page_bar[i].w = 64; + map_page_bar[i].h = 20; + } + + minimap.w=7+48*BMM; + minimap.h=16+27*BMM; + + layer_panel.x=map_page_bar[0].x; + layer_panel.y=map_page_bar[0].y+map_page_bar[0].h; + layer_panel.w=map_page_bar[8].x+map_page_bar[8].w; + layer_panel.h=40; + + for(int i=0; i<9; i++) + { + panel[i].x=10+48*BMM; + panel[i].y=layer_panel.y+layer_panel.h; + panel[i].w=(map_page_bar[6].x)-(minimap.w+3); + panel[i].h=76+32; + } + + minimap.x=3; + minimap.y=panel[0].y+4; + + combolistscrollers[0].w=11; + combolistscrollers[0].h=11; + combolistscrollers[0].x=combolist[0].x+21; + combolistscrollers[0].y=combolist[0].y-combolistscrollers[0].h-11; + combolistscrollers[1].w=11; + combolistscrollers[1].h=11; + combolistscrollers[1].x=combolist[1].x+21; + combolistscrollers[1].y=combolist[1].y-combolistscrollers[1].h-11; + combolistscrollers[2].w=11; + combolistscrollers[2].h=11; + combolistscrollers[2].x=combolist[2].x+21; + combolistscrollers[2].y=combolist[2].y-combolistscrollers[2].h-11; + + mouse_scroll_h=10; + + favorites_window.x=combolist_window.x; + favorites_window.y=464; + favorites_window.w=combolist_window.w; + favorites_window.h=136; + + favorites_list.x=favorites_window.x+8; + favorites_list.y=favorites_window.y+16; + favorites_list.w=(favorites_window.w-16)>>4; + favorites_list.h=(favorites_window.h-24)>>4; + + commands_window.w=combolist_window.x-(panel[0].x+panel[0].w); + commands_window.h=zq_screen_h-panel[0].y; + commands_window.x=favorites_window.x-commands_window.w; + commands_window.y=panel[0].y; + + commands_list.x=commands_window.x+8; + commands_list.y=commands_window.y+20; + commands_list.w=2; + commands_list.h=4; + + + help_dlg[0].w=800; + help_dlg[0].h=600; + help_dlg[1].w=800-8; + help_dlg[1].h=600-27; + help_dlg[2].w=800-8-4; + help_dlg[2].h=600-27-4; + + editmsg_help_dlg[0].w=800; + editmsg_help_dlg[0].h=600; + editmsg_help_dlg[1].w=800-8; + editmsg_help_dlg[1].h=600-27; + editmsg_help_dlg[2].w=800-8-4; + editmsg_help_dlg[2].h=600-27-4; + + enlargeIntegrityReportDialog(); + } + else + { + blackout_color=0; + zq_screen_w=320; + zq_screen_h=240; + minimap.x=3; + minimap.y=195; + minimap.w=55; + minimap.h=43; + combolist[0].x=256; + combolist[0].y=16; + combolist[0].w=4; + combolist[0].h=14; + combolist[1].x=-1; + combolist[1].y=-1; + combolist[1].w=-1; + combolist[1].h=-1; + combolist[2].x=-1; + combolist[2].y=-1; + combolist[2].w=-1; + combolist[2].h=-1; + + comboaliaslist[0].x=256; + comboaliaslist[0].y=16; + comboaliaslist[0].w=4; + comboaliaslist[0].h=10; + comboalias_preview[0].x=256; + comboalias_preview[0].y=176; + comboalias_preview[0].w=64; + comboalias_preview[0].h=64; + comboaliaslist[1].x=-1; + comboaliaslist[1].y=-1; + comboaliaslist[1].w=-1; + comboaliaslist[1].h=-1; + comboalias_preview[1].x=-1; + comboalias_preview[1].y=-1; + comboalias_preview[1].w=-1; + comboalias_preview[1].h=-1; + comboaliaslist[2].x=-1; + comboaliaslist[2].y=-1; + comboaliaslist[2].w=-1; + comboaliaslist[2].h=-1; + comboalias_preview[2].x=-1; + comboalias_preview[2].y=-1; + comboalias_preview[2].w=-1; + comboalias_preview[2].h=-1; + + mapscreen_x=0; + mapscreen_y=16; + mapscreensize=1; + showedges=0; + showallpanels=0; + + for(int i=0; i<9; i++) + { + panel[i].x=58; + panel[i].y=192; + panel[i].w=198; + panel[i].h=48; + } + + combolist_window.x=-1; + combolist_window.y=-1; + combolist_window.w=-1; + combolist_window.h=-1; + combo_preview.x=304; + combo_preview.y=0; + combo_preview.w=16; + combo_preview.h=16; + combolistscrollers[0].w=11; + combolistscrollers[0].h=11; + combolistscrollers[0].x=panel[0].x+panel[0].w-15; + combolistscrollers[0].y=panel[0].y+9; + combolistscrollers[1].w=-1; + combolistscrollers[1].h=-1; + combolistscrollers[1].x=-1; + combolistscrollers[1].y=-1; + combolistscrollers[2].w=-1; + combolistscrollers[2].h=-1; + combolistscrollers[2].x=-1; + combolistscrollers[2].y=-1; + + mouse_scroll_h=16; + + favorites_window.x=-1; + favorites_window.y=-1; + favorites_window.w=-1; + favorites_window.h=-1; + + favorites_list.x=-1; + favorites_list.y=-1; + favorites_list.w=-1; + favorites_list.h=-1; + + commands_window.x=-1; + commands_window.y=-1; + commands_window.w=-1; + commands_window.h=-1; + + commands_list.x=-1; + commands_list.y=-1; + commands_list.w=-1; + commands_list.h=-1; + + layer_panel.x=-1; + layer_panel.y=-1; + layer_panel.w=-1; + layer_panel.h=-1; + } + + for(int i=0; i(scale_arg+1))) + { + scale_arg = atoi(argv[scale_arg+1]); + + if(scale_arg == 0) + { + scale_arg = 1; + } + + zq_scale=scale_arg; + } + else + { + scale_arg = zq_scale; + } + + if(!is_large) zqwin_set_scale(scale_arg); + else zqwin_scale = 1; + +#endif + + if(used_switch(argc,argv,"-fullscreen")) + { + tempmode = GFX_AUTODETECT_FULLSCREEN; + } + else if(used_switch(argc,argv,"-windowed")) + { + tempmode=GFX_AUTODETECT_WINDOWED; + } + + /*if (tempmode==GFX_AUTODETECT_FULLSCREEN) + { + #ifdef ALLEGRO_MACOSX + + if(used_switch(argc,argv,"-small") || UseSmall == 1) + scale_arg=2; + else + scale_arg=1; + #else + if (scale_arg>2) + { + scale_arg=1; + } + #endif + zqwin_set_scale(scale_arg); + }*/ + + if(set_gfx_mode(tempmode,zq_screen_w*zqwin_scale,zq_screen_h*zqwin_scale,0,0)!=0) + { + Z_error(allegro_error); + quit_game(); + } + else + { + Z_message("gfx mode set at -%d %dbpp %d x %d \n", + tempmode, get_color_depth(), zq_screen_w*zqwin_scale, zq_screen_h*zqwin_scale); + //Z_message("OK\n"); + } + + scrtmp = screen; + hw_screen = create_bitmap_ex(8, zq_screen_w, zq_screen_h); + screen = hw_screen; + hw_screen = scrtmp; + scrtmp = screen; + + + position_mouse(zq_screen_w/2,zq_screen_h/2); + + center_zq_class_dialogs(); + center_zq_custom_dialogs(); + center_zq_files_dialogs(); + center_zq_subscreen_dialogs(); + center_zq_tiles_dialogs(); + center_zquest_dialogs(); + + screen2 = create_bitmap_ex(8,zq_screen_w,zq_screen_h); + tmp_scr = create_bitmap_ex(8,zq_screen_w,zq_screen_h); + menu1 = create_bitmap_ex(8,zq_screen_w,zq_screen_h); + clear_bitmap(menu1); + menu3 = create_bitmap_ex(8,zq_screen_w,zq_screen_h); + mapscreenbmp = create_bitmap_ex(8,16*(showedges?18:16),16*(showedges?13:11)); + dmapbmp_small = create_bitmap_ex(8,65,33); + dmapbmp_large = create_bitmap_ex(8,(is_large?177:113),(is_large?81:57)); + brushbmp = create_bitmap_ex(8,256*mapscreensize, 176*mapscreensize); + brushscreen = create_bitmap_ex(8,(256+(showedges?16:0))*mapscreensize, (176+(showedges?16:0))*mapscreensize); + tooltipbmp = create_bitmap_ex(8,256,256); // Decrease size at your own risk. + clear_bitmap(tooltipbmp); + + if(!screen2 || !tmp_scr || !menu1 || !menu3 || !dmapbmp_large || !dmapbmp_large || !brushbmp || !brushscreen)// || !brushshadowbmp ) + { + Z_message("Error creating bitmaps\n"); + allegro_exit(); + quit_game(); + return 1; + } + + set_palette((RGB*)zcdata[PAL_ZQUEST].dat); + get_palette(RAMpal); + + switch(gui_colorset) + { + /* + enum + { + jcBOX, jcLIGHT, jcMEDLT, jcMEDDARK, jcDARK, jcBOXFG, + jcTITLEL, jcTITLER, jcTITLEFG, jcTEXTBG, jcTEXTFG, jcSELBG, jcSELFG, + jcMAX + }; + */ + case 1: //Windows 98 + { + RAMpal[dvc(1)] = _RGB(0*63/255, 0*63/255, 0*63/255); + RAMpal[dvc(2)] = _RGB(128*63/255, 128*63/255, 128*63/255); + RAMpal[dvc(3)] = _RGB(192*63/255, 192*63/255, 192*63/255); + RAMpal[dvc(4)] = _RGB(223*63/255, 223*63/255, 223*63/255); + RAMpal[dvc(5)] = _RGB(255*63/255, 255*63/255, 255*63/255); + RAMpal[dvc(6)] = _RGB(255*63/255, 255*63/255, 225*63/255); + RAMpal[dvc(7)] = _RGB(255*63/255, 225*63/255, 160*63/255); + RAMpal[dvc(8)] = _RGB(0*63/255, 0*63/255, 80*63/255); + + byte palrstart= 0*63/255, palrend=166*63/255, + palgstart= 0*63/255, palgend=202*63/255, + palbstart=128*63/255, palbend=240*63/255, + paldivs=7; + + for(int i=0; ialert("ZQuest", + "It appears that ZQuest crashed last time. " + "Would you like to load the last timed save?", + "&Yes", "&No", 1); + if(ret==1) + { + int ret = load_quest(last_timed_save,true,true); + + if(ret == qe_OK) + { + replace_extension(filepath,last_timed_save,"qst",2047); + load_last_timed_save=true; + saved=false; + } + else + gui->alert("Error", "Unable to reload the last timed save."); + } + } + + if(!load_last_timed_save) + { + strcpy(filepath,get_config_string("zquest",last_quest_name,"")); + + if(argc>1 && argv[1][0]!='-') + { + replace_extension(temppath,argv[1],"qst",2047); + int ret = load_quest(temppath,true,true); + + if(ret == qe_OK) + { + first_save=true; + strcpy(filepath,temppath); + refresh(rALL); + } + } + else if(OpenLastQuest&&filepath[0]&&exists(filepath)&&!used_switch(argc,argv,"-new")) + { + int ret = load_quest(filepath,true,true); + + if(ret == qe_OK) + { + first_save=true; + refresh(rALL); + } + else + { + filepath[0]=temppath[0]=0; + first_save=false; +#ifdef ALLEGRO_MACOSX + sprintf(filepath, "../../../"); + sprintf(temppath, "../"); +#endif + } + } + else + { + init_quest(NULL); + + if(RulesetDialog) + PickRuleset(); + + //otherwise the blank quest gets the name of the last loaded quest... not good! -DD + filepath[0]=temppath[0]=0; + first_save=false; +#ifdef ALLEGRO_MACOSX + sprintf(filepath, "../../../"); + sprintf(temppath, "../"); +#endif + } + } + + for(int x=0; x63) + { + alignment_arrow_timer=0; + } + + if(strcmp(catchall_string[Map.CurrScr()->room]," ")) + { + static char ca_menu_str[40]; + sprintf(ca_menu_str,"%s\tA",catchall_string[Map.CurrScr()->room]); + data_menu[13].text=ca_menu_str; + data_menu[13].flags=commands[cmdCatchall].flags=0; + } + else + { + data_menu[13].text=(char *)"Catch All\tA"; + data_menu[13].flags=commands[cmdCatchall].flags=D_DISABLED; + } + + file_menu[2].flags = + file_menu[4].flags = + dialogs[18].flags = + commands[cmdSave].flags = + commands[cmdRevert].flags = (saved | disable_saving|OverwriteProtection) ? D_DISABLED : 0; + + file_menu[3].flags = + commands[cmdSaveAs].flags = disable_saving ? D_DISABLED : 0; + + edit_menu[0].flags = + commands[cmdUndo].flags = Map.CanUndo() ? 0 : D_DISABLED; + + edit_menu[2].flags = + edit_menu[3].flags = + edit_menu[4].flags = + edit_menu[5].flags = + paste_menu[0].flags = + paste_menu[1].flags = + paste_item_menu[0].flags = + paste_item_menu[1].flags = + paste_item_menu[2].flags = + paste_item_menu[3].flags = + paste_item_menu[4].flags = + paste_item_menu[5].flags = + paste_item_menu[6].flags = + paste_item_menu[7].flags = + paste_item_menu[8].flags = + paste_item_menu[9].flags = + paste_item_menu[10].flags = + commands[cmdPaste].flags = + commands[cmdPasteAll].flags = + commands[cmdPasteToAll].flags = + commands[cmdPasteAllToAll].flags = + commands[cmdPasteUnderCombo].flags = + commands[cmdPasteSecretCombos].flags = + commands[cmdPasteFFCombos].flags = + commands[cmdPasteScreenData].flags = + commands[cmdPasteWarps].flags = + commands[cmdPasteWarpLocations].flags = + commands[cmdPasteEnemies].flags = + commands[cmdPasteRoom].flags = + commands[cmdPasteGuy].flags = + commands[cmdPasteDoors].flags = + commands[cmdPasteLayers].flags = Map.CanPaste() ? 0 : D_DISABLED; + + edit_menu[1].flags = + edit_menu[6].flags = + commands[cmdCopy].flags = + commands[cmdDelete].flags = (Map.CurrScr()->valid&mVALID) ? 0 : D_DISABLED; + + tool_menu[0].flags = + data_menu[7].flags = + commands[cmdTemplate].flags = + commands[cmdDoors].flags = (Map.getCurrScr()0) ? 0 : D_DISABLED; + maps_menu[2].flags=(Map.getCurrMap()>0)? 0 : D_DISABLED; + + etc_menu[4].flags=(isFullScreen()==1)?D_SELECTED:0; + + quit = !update_dialog(player2); + + //clear_keybuf(); + if(close_button_quit) + { + close_button_quit=false; + + if(onExit()==D_CLOSE) + { + quit=true; + } + } + } + +#ifndef ALLEGRO_DOS + zqwin_set_scale(1); +#endif + + + quit_game(); + if(ForceExit) //last resort fix to the allegro process hanging bug. + exit(0); + + allegro_exit(); + + return 0; +// memset(qtpathtitle,0,10);//UNREACHABLE +} + +END_OF_MAIN() + + +void remove_locked_params_on_exit() +{ + al_trace("Removing timers. \n"); + remove_int(fps_callback); + remove_int(myvsync_callback); + remove_int(dclick_check); +} + + +void cleanup_datafiles_on_exit() +{ + al_trace("Cleaning datafiles. \n"); + + if(zcdata) unload_datafile(zcdata); + + if(fontsdata) unload_datafile(fontsdata); + + if(sfxdata) unload_datafile(sfxdata); +} + + +void destroy_bitmaps_on_exit() +{ + al_trace("Cleaning bitmaps..."); + destroy_bitmap(screen2); + destroy_bitmap(tmp_scr); + destroy_bitmap(menu1); + destroy_bitmap(menu3); + destroy_bitmap(mapscreenbmp); + destroy_bitmap(dmapbmp_small); + destroy_bitmap(dmapbmp_large); + destroy_bitmap(brushbmp); + destroy_bitmap(brushscreen); + destroy_bitmap(tooltipbmp); + al_trace("..."); + show_mouse(NULL); + + for(int i=0; i>3)&3; + + if(++coord_timer>=(1<<5)) + { + coord_timer=0; + } +} + +static int help_pos=0; + +static const char *help_list[] = +{ + "PREVIEW MODE", + "PgUp/PgDn - Scroll through hotkey list", + "Esc/Enter - Exit Preview Mode", + "R - Restore screen to original state", + "C - Toggle combo cycling On/Off", + "S - Trigger screen secrets", + "Q/W/F - These still work", + "P - Pause everything", + "A - Advance frame-by-frame", + "1-4 - Trigger tile warp A-D", + "5-8 - Trigger side warp A-D", + "9 - Enable timed warps", + "", + "", +}; + +void do_animations() +{ + if(AnimationOn||CycleOn) + { + if(AnimationOn) + { + animate_combos(); + update_freeform_combos(); + } + + if(CycleOn) + { + cycle_palette(); + } + } + + animate_coords(); + custom_vsync(); +} + +void do_previewtext() +{ + //Put in help areas + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+3,vc(0),-1,"%s",help_list[help_pos]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+8+3,vc(0),-1,"%s",help_list[help_pos+1]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+16+3,vc(0),-1,"%s",help_list[help_pos+2]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+24+3,vc(0),-1,"%s",help_list[help_pos+3]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+32+3,vc(0),-1,"%s",help_list[help_pos+4]); + + if(!is_large) return; + + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+40+3,vc(0),-1,"%s",help_list[help_pos+5]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+48+3,vc(0),-1,"%s",help_list[help_pos+6]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+56+3,vc(0),-1,"%s",help_list[help_pos+7]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+64+3,vc(0),-1,"%s",help_list[help_pos+8]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+72+3,vc(0),-1,"%s",help_list[help_pos+9]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+81+3,vc(0),-1,"%s",help_list[help_pos+10]); + textprintf_ex(menu1,font,panel[8].x+1,panel[8].y+90+3,vc(0),-1,"%s",help_list[help_pos+11]); +} + + + +int d_nbmenu_proc(int msg,DIALOG *d,int c) +{ + static int ret=D_O_K; + domouse(); + do_animations(); + refresh(rALL); + + // if (msg!=MSG_IDLE) + if(msg==MSG_GOTMOUSE||msg==MSG_XCHAR) + // if (0) + { + ComboBrushPause=1; + refresh(rMAP); + ComboBrushPause=0; + restore_mouse(); + clear_tooltip(); + } + + //YIELD(); + rest(4); + ret = jwin_menu_proc(msg,d,c); + + return ret; +} + +bool prv_press=false; + +void dopreview() +{ + //set_mouse_sprite(mouse_bmp[MOUSE_BMP_FLAG][0]); + refresh(rMAP); + + while(!(gui_mouse_b())) + { + //ret = jwin_menu_proc(msg,d,c); + if(keypressed()) + { + if(!prv_press) + { + prv_press=true; + + switch(readkey()>>8) + { + case KEY_ESC: + case KEY_ENTER: + case KEY_ENTER_PAD: + goto finished; + break; + + case KEY_F: + Flags^=cFLAGS; + refresh(rMAP); + break; + + case KEY_R: + onRType(); + break; + + case KEY_S: + onString(); + break; + + /* + case KEY_E: + Map.prv_secrets(true); + refresh(rALL); + break; + */ + case KEY_C: + onCopy(); + break; + + case KEY_A: + onCatchall(); + break; + + case KEY_P: + onP(); + break; + + case KEY_1: + Map.prv_dowarp(0,0); + prv_warp=0; + break; + + case KEY_2: + Map.prv_dowarp(0,1); + prv_warp=0; + break; + + case KEY_3: + Map.prv_dowarp(0,2); + prv_warp=0; + break; + + case KEY_4: + Map.prv_dowarp(0,3); + prv_warp=0; + break; + + case KEY_5: + Map.prv_dowarp(1,0); + prv_warp=0; + break; + + case KEY_6: + Map.prv_dowarp(1,1); + prv_warp=0; + break; + + case KEY_7: + Map.prv_dowarp(1,2); + prv_warp=0; + break; + + case KEY_8: + Map.prv_dowarp(1,3); + prv_warp=0; + break; + + case KEY_9: + if(prv_twon) + { + prv_twon=0; + Map.set_prvtime(0); + prv_warp=0; + } + else + { + Map.set_prvtime(Map.get_prvscr()->timedwarptics); + prv_twon=1; + } + + break; + + case KEY_W: + onShowWalkability(); + break; + + case KEY_Q: + onShowComboInfoCSet(); + break; + + case KEY_PGUP: + help_pos--; + + if(help_pos<0) + { + help_pos=0; + } + + break; + + case KEY_PGDN: + help_pos++; + + if(help_pos>(is_large ? 1 : 9)) + { + help_pos--; + } + + break; + } + } + else + { + readkey(); + } + } + else + { + prv_press=false; + } + + if(prv_warp) + { + Map.prv_dowarp(1,0); + prv_warp=0; + } + + if(Map.get_prvfreeze()) + { + if(Map.get_prvadvance()) + { + do_animations(); + Map.set_prvadvance(0); + } + } + else + { + do_animations(); + Map.set_prvadvance(0); + } + + refresh(rALL); + } + +finished: + //Flags=of; + reset_combo_animations(); + reset_combo_animations2(); + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + prv_mode=0; + Map.set_prvcmb(0); + Map.set_prvadvance(0); + Map.set_prvfreeze(0); + Map.set_prvtime(0); + prv_warp=0; + loadlvlpal(Map.getcolor()); + rebuild_trans_table(); + refresh(rMAP+rMENU); + + while(gui_mouse_b()) + { + /* do nothing */ + } +} + + +int onZQVidMode() +{ + char str_a[80], str_b[80], str_c[80]; + str_a[0]=0; + str_b[0]=0; + str_c[0]=0; + int mode=gfx_driver->id; +#ifdef ALLEGRO_DOS + + switch(mode) + { + case GFX_MODEX: + sprintf(str_a,"VGA Mode X"); + break; + + case GFX_VESA1: + sprintf(str_a,"VESA 1.x"); + break; + + case GFX_VESA2B: + sprintf(str_a,"VESA2 Banked"); + break; + + case GFX_VESA2L: + sprintf(str_a,"VESA2 Linear"); + break; + + case GFX_VESA3: + sprintf(str_a,"VESA3"); + break; + + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + case GFX_AUTODETECT_FULLSCREEN: + sprintf(str_a,"Autodetect Fullscreen"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_WINDOWS) + + switch(mode) + { + case GFX_DIRECTX: + sprintf(str_a,"DirectX Hardware Accelerated"); + break; + + case GFX_DIRECTX_SOFT: + sprintf(str_a,"DirectX Software Accelerated"); + break; + + case GFX_DIRECTX_SAFE: + sprintf(str_a,"DirectX Safe"); + break; + + case GFX_DIRECTX_WIN: + sprintf(str_a,"DirectX Windowed"); + break; + + case GFX_GDI: + sprintf(str_a,"GDI"); + break; + + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + case GFX_AUTODETECT_FULLSCREEN: + sprintf(str_a,"Autodetect Fullscreen"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_MACOSX) + + switch(mode) + { + case GFX_SAFE: + sprintf(str_a,"MacOS X Safe"); + break; + + case GFX_QUARTZ_FULLSCREEN: + sprintf(str_a,"MacOS X Fullscreen Quartz"); + break; + + case GFX_QUARTZ_WINDOW: + sprintf(str_a,"MacOS X Windowed Quartz"); + break; + + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + case GFX_AUTODETECT_FULLSCREEN: + sprintf(str_a,"Autodetect Fullscreen"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_LINUX) + + switch(mode) + { + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + case GFX_AUTODETECT_FULLSCREEN: + sprintf(str_a,"Autodetect Fullscreen"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#elif defined(ALLEGRO_GP2X) + + switch(mode) + { + case GFX_AUTODETECT_WINDOWED: + sprintf(str_a,"Autodetect Windowed"); + break; + + case GFX_AUTODETECT_FULLSCREEN: + sprintf(str_a,"Autodetect Fullscreen"); + break; + + default: + sprintf(str_a,"Unknown... ?"); + break; + } + +#endif + sprintf(str_c,"%dx%d 8-bit",zq_screen_w*zq_scale,zq_screen_h*zq_scale); + jwin_alert("Video Mode",str_a,str_b,str_c,"OK",NULL,13,27,lfont); + return D_O_K; +} + +bool is_zquest() +{ + return true; +} + +bool screenIsScrolling() +{ + return false; +} + +int save_config_file() +{ + char cmdnametitle[20]; + char qtnametitle[20]; + char qtpathtitle[20]; + char *datapath2=(char *)zc_malloc(2048); + char *midipath2=(char *)zc_malloc(2048); + char *imagepath2=(char *)zc_malloc(2048); + char *tmusicpath2=(char *)zc_malloc(2048); + strcpy(datapath2, datapath); + strcpy(midipath2, midipath); + strcpy(imagepath2, imagepath); + strcpy(tmusicpath2, tmusicpath); + chop_path(datapath2); + chop_path(midipath2); + chop_path(imagepath2); + chop_path(tmusicpath2); + + set_config_string("zquest",data_path_name,datapath2); + set_config_string("zquest",midi_path_name,midipath2); + set_config_string("zquest",image_path_name,imagepath2); + set_config_string("zquest",tmusic_path_name,tmusicpath2); + set_config_string("zquest",last_quest_name,filepath); + set_config_string("zquest","last_timed_save",last_timed_save); + set_config_int("zquest","mouse_scroll",MouseScroll); + set_config_int("zquest","invalid_static",InvalidStatic); + set_config_int("zquest","tile_protection",TileProtection); + set_config_int("zquest","showinfo",ShowInfo); + set_config_int("zquest","show_grid",ShowGrid); + set_config_int("zquest","grid_color",GridColor); + set_config_int("zquest","snapshot_format",SnapshotFormat); + set_config_int("zquest","save_paths",SavePaths); + set_config_int("zquest","cycle_on",CycleOn); + set_config_int("zquest","vsync",Vsync); + set_config_int("zquest","showfps",ShowFPS); + set_config_int("zquest","combo_brush",ComboBrush); + set_config_int("zquest","brush_position",BrushPosition); + set_config_int("zquest","float_brush",FloatBrush); + set_config_int("zquest","open_last_quest",OpenLastQuest); + set_config_int("zquest","show_misalignments",ShowMisalignments); + set_config_int("zquest","scale",zq_scale); + set_config_int("zquest","fullscreen", is_windowed_mode() ? 0 : 1); + set_config_int("zquest","showffscripts",ShowFFScripts); + set_config_int("zquest","showsquares",ShowSquares); + + set_config_int("zquest","animation_on",AnimationOn); + set_config_int("zquest","auto_backup_retention",AutoBackupRetention); + set_config_int("zquest","auto_save_interval",AutoSaveInterval); + set_config_int("zquest","auto_save_retention",AutoSaveRetention); + set_config_int("zquest","uncompressed_auto_saves",UncompressedAutoSaves); + set_config_int("zquest","overwrite_prevention",OverwriteProtection); + set_config_int("zquest","import_map_bias",ImportMapBias); + + set_config_int("zquest","keyboard_repeat_delay",KeyboardRepeatDelay); + set_config_int("zquest","keyboard_repeat_rate",KeyboardRepeatRate); + + set_config_int("zquest","zqmusic_bufsz",zcmusic_bufsz); + set_config_int("zquest","small",UseSmall); + set_config_int("zquest","rulesetdialog",RulesetDialog); + set_config_int("zquest","enable_tooltips",EnableTooltips); + + for(int x=0; x<7; x++) + { + set_bit(LayerMask,x, LayerMaskInt[x]); + } + + int tempvalue=LayerMask[0]+(LayerMask[1]<<8); + set_config_int("zquest","layer_mask",tempvalue); + set_config_int("zquest","normal_duplicate_action",DuplicateAction[0]); + set_config_int("zquest","horizontal_duplicate_action",DuplicateAction[1]); + set_config_int("zquest","vertical_duplicate_action",DuplicateAction[2]); + set_config_int("zquest","both_duplicate_action",DuplicateAction[3]); + set_config_int("zquest","leech_update",LeechUpdate); + set_config_int("zquest","leech_update_tiles",LeechUpdateTiles); + set_config_int("zquest","only_check_new_tiles_for_duplicates",OnlyCheckNewTilesForDuplicates); + set_config_int("zquest","gui_colorset",gui_colorset); + + for(int x=0; x0) + { + time(&auto_save_time_current); + auto_save_time_diff = difftime(auto_save_time_current,auto_save_time_start); + + if(auto_save_time_diff>AutoSaveInterval*60) + { + set_mouse_sprite(mouse_bmp[MOUSE_BMP_NORMAL][0]); + if(first_save) + replace_extension(last_timed_save, filepath, "qt0", 2047); + else + strcpy(last_timed_save, "untitled.qt0"); + go(); + + if((header.zelda_version != ZELDA_VERSION || header.build != VERSION_BUILD) && first_save) + { + jwin_alert("Auto Save","This quest was saved in an older version of ZQuest.","If you wish to use the autosave feature, you must manually","save the files in this version first.","OK",NULL,13,27,lfont); + time(&auto_save_time_start); + comeback(); + return; + } + + int ret = save_quest(last_timed_save, true); + + if(ret) + { + jwin_alert("Error","Timed save did not complete successfully.",NULL,NULL,"O&K",NULL,'k',0,lfont); + last_timed_save[0]=0; + } + +// jwin_alert("Timed Save","A timed save should happen here",NULL,NULL,"OK",NULL,13,27,lfont); + save_config_file(); + time(&auto_save_time_start); + comeback(); + } + } +} + +void flushItemCache() {} +void ringcolor(bool forceDefault) +{ + forceDefault=forceDefault; +} + +//annoying beta message :) +char *getBetaControlString() +{ + char *result = new char[11]; + const char *compiledate = __DATE__; + const char *compiletime = __TIME__; + int i=0; + byte tempbyte; + + for(i=0; ialert("Command deleted", "This command has been deleted."); + return D_O_K; +} + +//remember to adjust this number in zquest.h if it changes here! +//P.S: Must be listed in the same order as the enum in zquest.h. No exceptions! -L +command_pair commands[cmdMAX]= +{ + { "(None)", 0, NULL }, + { "About", 0, (intF) onAbout }, + { "Catch All", 0, (intF) onCatchall }, + { "Change track", 0, (intF) changeTrack }, + { "Cheats", 0, (intF) onCheats }, + { "Color Set Fix", 0, (intF) onCSetFix }, + { "Combo Alias Mode", 0, (intF) onDrawingModeAlias }, + { "Edit Combo Aliases", 0, (intF) onEditComboAlias }, + { "Combos", 0, (intF) onCombos }, + { "Compile ZScript", 0, (intF) onCompileScript }, + { "Copy", 0, (intF) onCopy }, + { "Default Combos", 0, (intF) onDefault_Combos }, + { "Delete Map", 0, (intF) onDeleteMap }, + { "Delete Screen", 0, (intF) onDelete }, + { "DMaps", 0, (intF) onDmaps }, + { "Door Combo Sets", 0, (intF) onDoorCombos }, + { "Edit Doors", 0, (intF) onDoors }, + { "Paste Doors", 0, (intF) onPasteDoors }, + { "Dungeon Carving Mode", 0, (intF) onDrawingModeDungeon }, + { "End String", 0, (intF) onEndString }, + { "Enemy Editor", 0, (intF) onCustomEnemies }, + { "Default Enemies", 0, (intF) onDefault_Guys }, + { "Set Enemies", 0, (intF) onEnemies }, + { "Paste Enemies", 0, (intF) onPasteEnemies }, + { "Enhanced Music ", 0, (intF) onEnhancedMusic }, + { "Exit", 0, (intF) onCmdExit }, + { "Export Combos", 0, (intF) onExport_Combos }, + { "Export DMaps", 0, (intF) onExport_DMaps }, + { "Export Map", 0, (intF) onExport_Map }, + { "Export Palettes", 0, (intF) onExport_Pals }, + { "Export Quest Template", 0, (intF) onExport_ZQT }, + { "Export Strings", 0, (intF) onExport_Msgs }, + { "Export Subscreen", 0, (intF) onExport_Subscreen }, + { "Export Tiles", 0, (intF) onExport_Tiles }, + { "Export Unencoded Quest", 0, (intF) onExport_UnencodedQuest }, + { "Export Graphics Pack", 0, (intF) onExport_ZGP }, + { "Flags", 0, (intF) onFlags }, + { "Paste Freeform Combos", 0, (intF) onPasteFFCombos }, + { "Freeform Combos", 0, (intF) onSelectFFCombo }, + { "Toggle Fullscreen", 0, (intF) onFullScreen }, + { "Game icons", 0, (intF) onIcons }, + { "Goto Map", 0, (intF) onGotoMap }, + { "Guy", 0, (intF) onGuy }, + { "Paste Guy/String", 0, (intF) onPasteGuy }, + { "Header", 0, (intF) onHeader }, + { "Help", 0, (intF) onHelp }, + { "Import ASM FFC Script", 0, (intF) onImportFFScript }, + { "Import ASM Global Script", 0, (intF) onImportGScript }, + { "Import ASM Item Script", 0, (intF) onImportItemScript }, + { "Import Combos", 0, (intF) onImport_Combos }, + { "Import DMaps", 0, (intF) onImport_DMaps }, + { "Import Graphics Pack", 0, (intF) onImport_ZGP }, + { "Import Map", 0, (intF) onImport_Map }, + { "Import Palettes", 0, (intF) onImport_Pals }, + { "Import Quest Template", 0, (intF) onImport_ZQT }, + { "Import Strings", 0, (intF) onImport_Msgs }, + { "Import Subscreen", 0, (intF) onImport_Subscreen }, + { "Import Tiles", 0, (intF) onImport_Tiles }, + { "Import Unencoded Quest", 0, (intF) onImport_UnencodedQuest }, + { "Info Types", 0, (intF) onInfoTypes }, + { "Init Data", 0, (intF) onInit }, + { "Integrity Check (All) ", 0, (intF) onIntegrityCheckAll }, + { "Integrity Check (Screens) ", 0, (intF) onIntegrityCheckRooms }, + { "Integrity Check (Warps) ", 0, (intF) onIntegrityCheckWarps }, + { "Set Item", 0, (intF) onItem }, + { "Item Locations Report", 0, (intF) onItemLocationReport }, + { "Item Editor", 0, (intF) onCustomItems }, + { "Layers", 0, (intF) onLayers }, + { "Paste Layers", 0, (intF) onPasteLayers }, + { "Palettes - Levels", 0, (intF) onColors_Levels }, + { "Link Sprite", 0, (intF) onCustomLink }, + { "List Combos Used", 0, (intF) onUsedCombos }, + { "Palettes - Main", 0, (intF) onColors_Main }, + { "Map Count", 0, (intF) onMapCount }, + { "Default Map Styles", 0, (intF) onDefault_MapStyles }, + { "Map Styles", 0, (intF) onMapStyles }, + { "Master Subscreen Type", 0, (intF) onSubscreen }, + { "Message String", 0, (intF) onString }, + { "MIDIs", 0, (intF) onMidis }, + { "Misc Colors", 0, (intF) onMiscColors }, + { "New", 0, (intF) onNew }, + { "Normal Mode", 0, (intF) onDrawingModeNormal }, + { "Open", 0, (intF) onOpen }, + { "Options", 0, (intF) onOptions }, + { "Palette", 0, (intF) onScreenPalette }, + { "Default Palettes", 0, (intF) onDefault_Pals }, + { "Paste", 0, (intF) onPaste }, + { "Paste All", 0, (intF) onPasteAll }, + { "Paste All To All", 0, (intF) onPasteAllToAll }, + { "Paste To All", 0, (intF) onPasteToAll }, + { "Maze Path", 0, (intF) onPath }, + { "Play Music", 0, (intF) playMusic }, + { "Preview Mode", 0, (intF) onPreviewMode }, + { "Quest Templates", 0, (intF) onQuestTemplates }, + { "Apply Template to All", 0, (intF) onReTemplate }, + { "Relational Mode", 0, (intF) onDrawingModeRelational }, + { "Revert", 0, (intF) onRevert }, + { "Room Type", 0, (intF) onRType }, + { "Paste Room Type Data", 0, (intF) onPasteRoom }, + { "DELETED", 0, (intF) disabledCommand }, + { "Save", 0, (intF) onSave }, + { "Save as", 0, (intF) onSaveAs }, + { "Paste Screen Data", 0, (intF) onPasteScreenData }, + { "Screen Data", 0, (intF) onScrData }, + { "Paste Secret Combos", 0, (intF) onPasteSecretCombos }, + { "Secret Combos", 0, (intF) onSecretCombo }, + { "SFX Data", 0, (intF) onSelectSFX }, + { "Shop Types", 0, (intF) onShopTypes }, + { "Side Warp", 0, (intF) onSideWarp }, + { "Palettes - Sprites", 0, (intF) onColors_Sprites }, + { "Default Weapon Sprites", 0, (intF) onDefault_Weapons }, + { "Stop Tunes", 0, (intF) stopMusic }, + { "Strings", 0, (intF) onStrings }, + { "Subscreens", 0, (intF) onEditSubscreens }, + { "Take Snapshot", 0, (intF) onSnapshot }, + { "The Travels of Link", 0, (intF) playTune1 }, + { "NES Dungeon Template", 0, (intF) onTemplate }, + { "Edit Templates", 0, (intF) onTemplates }, + { "Tile Warp", 0, (intF) onTileWarp }, + { "Default Tiles", 0, (intF) onDefault_Tiles }, + { "Tiles", 0, (intF) onTiles }, + { "Toggle Grid", 0, (intF) onToggleGrid }, + { "Triforce Pieces", 0, (intF) onTriPieces }, + { "Under Combo", 0, (intF) onUnderCombo }, + { "Paste Undercombo", 0, (intF) onPasteUnderCombo }, + { "Undo", 0, (intF) onUndo }, + { "Video Mode", 0, (intF) onZQVidMode }, + { "View Map", 0, (intF) onViewMap }, + { "View Palette", 0, (intF) onShowPal }, + { "View Pic", 0, (intF) onViewPic }, + { "Paste Warp Return", 0, (intF) onPasteWarpLocations }, + { "Warp Rings", 0, (intF) onWarpRings }, + { "Paste Warps", 0, (intF) onPasteWarps }, + { "Weapons/Misc", 0, (intF) onCustomWpns }, + { "View Darkness", 0, (intF) onShowDarkness }, + { "Toggle Walkability", 0, (intF) onShowWalkability }, + { "Toggle Flags", 0, (intF) onShowFlags }, + { "Toggle CSets", 0, (intF) onShowCSet }, + { "Toggle Types", 0, (intF) onShowCType }, + { "DELETED", 0, (intF) disabledCommand }, + { "DELETED", 0, (intF) disabledCommand }, + { "DELETED", 0, (intF) disabledCommand }, + { "DELETED", 0, (intF) disabledCommand }, + { "DELETED", 0, (intF) disabledCommand }, + { "DELETED", 0, (intF) disabledCommand }, + { "Default Items", 0, (intF) onDefault_Items }, + { "Paste Palette", 0, (intF) onPastePalette }, + { "DELETED", 0, (intF) disabledCommand } +}; + +/********************************/ +/***** Tool Tips ******/ +/********************************/ +int strchrnum(char *str, char c) +{ + for(int i=0; str[i]; ++i) + { + if(str[i]==c) + { + return i; + } + } + + return -1; +} + +int get_longest_line_length(FONT *f, char *str) +{ + int maxlen=0; + //char *kill=(char *)calloc(strlen(str),1); + char *tmpstr=str; + char temp=0; + //sprintf(tmpstr, "%s", str); + int t=0; + int new_t=-1; + + while(tmpstr[t]) + { + t=strchrnum(tmpstr, '\n'); + + if(t==-1) + { + t=(int)strlen(tmpstr); + } + + if((unsigned int)t!=strlen(tmpstr)) + { + new_t=t+1; + } + else + { + new_t=-1; + } + + temp = tmpstr[t]; + tmpstr[t]=0; + maxlen=zc_max(maxlen,text_length(f, tmpstr)); + tmpstr[t]=temp; + + if(new_t!=-1) + { + tmpstr+=new_t; + } + } + + //zc_free(kill); + return maxlen; +} + +int count_lines(char *str) +{ + int count=1; + + for(word i=0; i=zq_screen_w) + { + tooltip_box.x=(zq_screen_w - tooltip_box.w); + } + + if(tooltip_box.y+tooltip_box.h>=zq_screen_h) + { + tooltip_box.y=(zq_screen_h - tooltip_box.h); + } + + rectfill(tooltipbmp, 1, 1, tooltip_box.w-3, tooltip_box.h-3, jwin_pal[jcTEXTBG]); + rect(tooltipbmp, 0, 0, tooltip_box.w-2, tooltip_box.h-2, jwin_pal[jcTEXTFG]); + vline(tooltipbmp, tooltip_box.w-1, 0, tooltip_box.h-1, jwin_pal[jcTEXTFG]); + hline(tooltipbmp, 1, tooltip_box.h-1, tooltip_box.w-2, jwin_pal[jcTEXTFG]); + tooltipbmp->line[tooltip_box.w-1][0]=0; + tooltipbmp->line[0][tooltip_box.h-1]=0; + + //char *kill=(char *)calloc(strlen(tipmsg)*2,1); + char *tmpstr=tipmsg; + char temp = 0; + //sprintf(tmpstr, "%s", tipmsg); + int t=0; + int new_t=-1; + int i=0; + + while(tmpstr[t]) + { + t=strchrnum(tmpstr, '\n'); + + if(t==-1) + { + t=(int)strlen(tmpstr); + } + + if((unsigned int)t!=strlen(tmpstr)) + { + new_t=t+1; + } + else + { + new_t=-1; + } + + temp = tmpstr[t]; + tmpstr[t]=0; + textprintf_ex(tooltipbmp, font, 4, (i*text_height(font))+4, vc(0), -1, "%s", tmpstr); + tmpstr[t]=temp; + ++i; + + if(new_t!=-1) + { + tmpstr+=new_t; + t=0; + } + } + + //zc_free(kill); + } + + return; +} + +void clear_tooltip() +{ + update_tooltip(-1, -1, -1, -1, 0, 0, NULL); +} + + + + + + + + + +///////////////////////////////////////////////// +// zc_malloc +///////////////////////////////////////////////// + +//Want Logging: +//Set this to 1 to allow zc_malloc/zc_free to track pointers and +//write logging data to allegro.log +#define ZC_DEBUG_MALLOC_WANT_LOGGING_INFO 0 + + +#include +#include "vectorset.h" + +#if (defined(NDEBUG) || !defined(_DEBUG)) && (ZC_DEBUG_MALLOC_ENABLED) && (ZC_DEBUG_MALLOC_WANT_LOGGING_INFO) //this is not fun with debug +#define ZC_WANT_DETAILED_MALLOC_LOGGING 1 +#endif + +#if ZC_WANT_DETAILED_MALLOC_LOGGING +size_t totalBytesAllocated = 0; +//typedef vectorset debug_malloc_pool_type; //to slow for zquest (size is huge) +typedef std::set debug_malloc_pool_type; +debug_malloc_pool_type debug_zc_malloc_allocated_pool; +#endif + +void* __zc_debug_malloc(size_t numBytes, const char* file, int line) +{ +#ifdef ZC_WANT_DETAILED_MALLOC_LOGGING + static bool zcDbgMallocInit = false; + + if(!zcDbgMallocInit) + { + zcDbgMallocInit = true; + //debug_zc_malloc_allocated_pool.reserve(1 << 17); + //yeah. completely ridiculous... there's no reason zc should ever need this many.. + //BUT it does... go figure + } + + totalBytesAllocated += numBytes; + + al_trace("INFO: %i : %s, line %i, %u bytes, pool size %u, total %u,", + 0, + file, + line, + numBytes, + debug_zc_malloc_allocated_pool.size(), + totalBytesAllocated / 1024 + ); +#endif + + ZC_MALLOC_ALWAYS_ASSERT(numBytes != 0); + void* p = malloc(numBytes); + +#ifdef ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("at address %x\n", (int)p); + + if(!p) + al_trace("____________ ERROR: __zc_debug_malloc: returned null. out of memory.\n"); + + //debug_malloc_pool_type::insert_iterator_type it = debug_zc_malloc_allocated_pool.insert(p); + std::pair< std::set::iterator, bool > it = debug_zc_malloc_allocated_pool.insert(p); + + if(!it.second) + al_trace("____________ ERROR: malloc returned identical address to one in use... No way Jose!\n"); + +#endif + + return p; +} + + +void __zc_debug_free(void* p, const char* file, int line) +{ + ZC_MALLOC_ALWAYS_ASSERT(p != 0); + +#ifdef ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("INFO: %i : %s line %i, freeing memory at address %x\n", 0, file, line, (int)p); + + size_t numErased = debug_zc_malloc_allocated_pool.erase(p); + + if(numErased == 0) + al_trace("____________ ERROR: __zc_debug_free: no known ptr to memory exists. ..attempting to free it anyways.\n"); + +#endif + + free(p); +} + + +void __zc_debug_malloc_free_print_memory_leaks() +{ +#if ZC_WANT_DETAILED_MALLOC_LOGGING + al_trace("LOGGING INFO FROM debug_zc_malloc_allocated_pool:\n"); + + for(debug_malloc_pool_type::iterator it = debug_zc_malloc_allocated_pool.begin(); + it != debug_zc_malloc_allocated_pool.end(); + ++it + ) + { + al_trace("block at address %x.\n", (int)*it); + } + +#endif +} + + +void __zc_always_assert(bool e, const char* expression, const char* file, int line) +{ + //for best results set a breakpoint in here. + if(!e) + { + char buf[1024]; + sprintf("ASSERTION FAILED! : %s, %s line %i\n", expression, file, line); + + al_trace("%s", buf); + set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); + allegro_message("%s", buf); + //... + } +} + + +/* end */ + + diff --git a/src/zquest.h b/src/zquest.h new file mode 100644 index 0000000000..a72365c3da --- /dev/null +++ b/src/zquest.h @@ -0,0 +1,1154 @@ +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +#ifndef _ZQUEST_H_ +#define _ZQUEST_H_ + +#include +#include +#include "midi.h" +#include "jwin.h" +#include "jwinfsel.h" +#include "zcmusic.h" +#include "sprite.h" +#include "gamedata.h" + +#define INTERNAL_VERSION 0xA721 + +// the following are used by both zelda.cc and zquest.cc + +#define CSET(x) ((x)<_< + +enum +{ + m_block, m_coords, m_flags, m_guy, m_warp, m_misc, m_layers, m_coords2, + m_menucount +}; + +enum {MOUSE_BMP_NORMAL=0, MOUSE_BMP_POINT_BOX, MOUSE_BMP_FLAG, MOUSE_BMP_BOX, MOUSE_BMP_SWORD, MOUSE_BMP_POTION, MOUSE_BMP_WAND, MOUSE_BMP_LENS, MOUSE_BMP_GLOVE, MOUSE_BMP_HOOKSHOT, MOUSE_BMP_WAND2, MOUSE_BMP_BLANK, MOUSE_BMP_MAX}; +enum {ICON_BMP_ITEM=0, ICON_BMP_WARP, ICON_BMP_WARPDEST, ICON_BMP_FLAG, ICON_BMP_RETURN_A, ICON_BMP_RETURN_B, ICON_BMP_RETURN_C, ICON_BMP_RETURN_D, ICON_BMP_MAX}; + + +extern int CSET_SIZE; +extern int CSET_SHFT; + +void update_combo_cycling(); +void update_freeform_combos(); + +bool layers_valid(mapscr *tempscr); +void fix_layers(mapscr *tempscr, bool showwarning); + +extern int coord_timer, coord_frame; +extern int blackout_color, zq_screen_w, zq_screen_h; +extern int jwin_pal[jcMAX]; + +extern size_and_pos minimap; + +extern size_and_pos combolist1; +extern size_and_pos combolist1scrollers; +extern size_and_pos combolist2; +extern size_and_pos combolist2scrollers; +extern size_and_pos combolist3; +extern size_and_pos combolist3scrollers; + +extern size_and_pos comboaliaslist1; +extern size_and_pos comboalias_preview1; +extern size_and_pos comboaliaslist2; +extern size_and_pos comboalias_preview2; +extern size_and_pos comboaliaslist3; +extern size_and_pos comboalias_preview3; + +extern size_and_pos combo_preview; +extern size_and_pos combolist_window; +extern size_and_pos panel[9]; +extern size_and_pos panel_button[9]; +extern size_and_pos favorites_window; +extern size_and_pos favorites_list; + +extern size_and_pos commands_window; +extern size_and_pos commands_list; +extern size_and_pos dummy_panel; + +extern size_and_pos tooltip_box; +extern size_and_pos tooltip_trigger; + +extern int mapscreen_x, mapscreen_y, mapscreensize, showedges, showallpanels; +extern int mouse_scroll_h; +extern int tooltip_timer, tooltip_maxtimer; + +extern bool canfill; //to prevent double-filling (which stops undos) +extern bool resize_mouse_pos; //for eyeball combos + +extern int lens_hint_item[MAXITEMS][2]; //aclk, aframe +extern int lens_hint_weapon[MAXWPNS][5]; //aclk, aframe, dir, x, y +//extern int mode, switch_mode, orig_mode; +extern RGB_MAP rgb_table; +extern COLOR_MAP trans_table, trans_table2; +extern char *datafile_str; +extern RGB_MAP zq_rgb_table; +extern DATAFILE *zcdata, *fontsdata; +extern MIDI *song; +extern FONT *nfont, *zfont, *z3font, *z3smallfont, *deffont, *lfont, *lfont_l, *pfont, *mfont, *ztfont, *sfont, *sfont2, *sfont3, *spfont, *ssfont1, *ssfont2, *ssfont3, *ssfont4, *gblafont, + *goronfont, *zoranfont, *hylian1font, *hylian2font, *hylian3font, *hylian4font, *gboraclefont, *gboraclepfont, *dsphantomfont, *dsphantompfont; +extern BITMAP *menu1,*menu3, *mapscreenbmp, *tmp_scr, *screen2, *mouse_bmp[MOUSE_BMP_MAX][4], *icon_bmp[ICON_BMP_MAX][4], *panel_button_icon_bmp[m_menucount][4], *select_bmp[2],*dmapbmp_small, *dmapbmp_large; +extern BITMAP *arrow_bmp[MAXARROWS],*brushbmp, *brushscreen, *tooltipbmp; //, *brushshadowbmp; +extern byte *colordata, *trashbuf; +//extern byte *tilebuf; +extern comboclass *combo_class_buf; +extern itemdata *itemsbuf; +extern wpndata *wpnsbuf; +extern guydata *guysbuf; +extern item_drop_object item_drop_sets[MAXITEMDROPSETS]; +extern newcombo curr_combo; +extern PALETTE RAMpal; +extern midi_info Midi_Info; +extern bool zq_showpal; +extern bool combo_cols; + + +extern int alignment_arrow_timer; +extern int Flip,Combo,CSet,First[3]; +extern int Flags,Flag,menutype; +extern int MouseScroll, SavePaths, CycleOn, InvalidStatic; +extern int Frameskip, RequestedFPS, zqColorDepth, zqUseWin32Proc; +extern bool Vsync, ShowFPS; +extern int ComboBrush; //show the brush instead of the normal mouse +extern int ComboBrushPause; //temporarily disable the combo brush +extern int BrushPosition; //top left, middle, bottom right, etc. +extern int FloatBrush; //makes the combo brush float a few pixels up and left complete with shadow + +extern int OpenLastQuest; //makes the program reopen the quest that was +//open at the time you quit +extern int ShowMisalignments; //makes the program display arrows over combos that are +//not aligned with the next screen. +extern int AnimationOn; //animate the combos in zquest? +extern int AutoBackupRetention; //use auto-backup feature? if so, how many backups (1-10) to keep +extern int AutoSaveInterval; //how often a timed autosave is made (not overwriting the current file) +extern int UncompressedAutoSaves; //should timed saves be uncompressed/encrypted? +extern time_t auto_save_time_start, auto_save_time_current; +extern double auto_save_time_diff; +extern int AutoSaveRetention; //how many autosaves of a quest to keep +extern int ImportMapBias; //tells what has precedence on map importing +extern int BrushWidth, BrushHeight; +extern bool quit,saved; +extern bool __debug; +extern byte LayerMask[2]; //determines which layers are on or off. 0-15 +extern int LayerMaskInt[7]; +extern int CurrentLayer; +extern int DuplicateAction[4]; +extern int OnlyCheckNewTilesForDuplicates; +/* + , HorizontalDuplicateAction; + int VerticalDuplicateAction, BothDuplicateAction; + */ +extern word msg_count, qt_count; +extern word door_combo_set_count; +extern int LeechUpdate; +extern int LeechUpdateTiles; +extern int SnapshotFormat; +extern int memrequested; +extern byte Color; + +extern ZCMUSIC *zcmusic; +extern volatile int myvsync; +extern BITMAP *hw_screen; + +extern int fill_type; + +extern bool first_save; +extern char *filepath,*temppath,*midipath,*datapath,*imagepath,*tmusicpath,*last_timed_save; +extern char *helpbuf; +extern std::string helpstr; + +extern int rules_page, rules_pages; +extern int init_page, init_pages; +extern int doorcombos_page, doorcombos_pages; +extern bool rules_done, save_rules; +extern bool init_done, save_init; +extern bool doorcombos_done, save_doorcombos; + +void loadlvlpal(int level); + +bool get_debug(); +void set_debug(bool d); + +// quest data +extern zquestheader header; +extern byte quest_rules[QUESTRULES_SIZE]; +extern byte midi_flags[MIDIFLAGS_SIZE]; +extern byte music_flags[MUSICFLAGS_SIZE]; +extern word map_count; +extern miscQdata misc; +extern std::vector TheMaps; +extern zcmap *ZCMaps; +extern dmap *DMaps; +extern MsgStr *MsgStrings; +extern int msg_strings_size; +extern DoorComboSet *DoorComboSets; +extern class zctune *customtunes; +//extern emusic *enhancedMusic; +extern ZCHEATS zcheats; +extern byte use_cheats; +extern byte use_tiles; +extern zinitdata zinit; +extern char palnames[MAXLEVELS][17]; +extern quest_template QuestTemplates[MAXQTS]; +//extern byte *undotilebuf; +/* +extern tiledata *newtilebuf, *grabtilebuf; +extern newcombo *combobuf; +extern word animated_combo_table[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table4[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos; +extern word animated_combo_table2[MAXCOMBOS][2]; //[0]=position in act2, [1]=original tile +extern word animated_combo_table24[MAXCOMBOS][2]; //[0]=combo, [1]=clock +extern word animated_combos2; +extern bool blank_tile_table[NEWMAXTILES]; //keeps track of blank tiles +extern bool blank_tile_quarters_table[NEWMAXTILES*4]; //keeps track of blank tiles +*/ +extern char fontsdat_sig[52]; + +// qst.cc helpers +bool bad_version(int ver); +fix LinkModifiedX(); +fix LinkModifiedY(); + +extern MENU colors_menu[]; + +void rebuild_trans_table(); +void rebuild_string_list(); + +int onResetTransparency(); +int d_vsync_proc(int msg,DIALOG *d,int c); +int d_nbmenu_proc(int msg,DIALOG *d,int c); +int getnumber(const char *prompt,int initialval); +int gettilepagenumber(const char *prompt, int initialval); +int gethexnumber(const char *prompt,int initialval); + +void update_combo_cycling(); + +int onSelectSFX(); +int onOptions(); +void fix_drawing_mode_menu(); +int onDrawingMode(); +int onDrawingModeNormal(); +int onDrawingModeRelational(); +int onDrawingModeDungeon(); +int onDrawingModeAlias(); +int onReTemplate(); +int onUndo(); +int onCopy(); +int onFlipDMapHorizontal(int d); +int onFlipDMapVertical(int d); +int onFlipMapHorizontal(); +int onFlipMapVertical(); +int onFlipScreenHorizontal(); +int onFlipScreenVertical(); +int onH(); +int onPaste(); +int onPasteAll(); +int onPasteToAll(); +int onPasteAllToAll(); +int onPasteUnderCombo(); +int onPasteSecretCombos(); +int onPasteFFCombos(); +int onPasteWarps(); +int onPasteScreenData(); +int onPasteWarpLocations(); +int onPasteDoors(); +int onPasteLayers(); +int onPastePalette(); +int onPasteRoom(); +int onPasteGuy(); +int onPasteEnemies(); +int onDelete(); +int onDeleteMap(); +int onToggleDarkness(); +int onIncMap(); +int onDecMap(); +int onDefault_Pals(); +int onDefault_Combos(); +int onDefault_Items(); +int onDefault_Guys(); +int onDefault_Weapons(); +int onDefault_SFX(); +int onDefault_Tiles(); +int onDefault_MapStyles(); +int on0(); +int on1(); +int on2(); +int on3(); +int on4(); +int on5(); +int on6(); +int on7(); +int on8(); +int on9(); +int on10(); +int on11(); +int on12(); +int on13(); +int on14(); +int onLeft(); +int onRight(); +int onUp(); +int onDown(); +int onPgUp(); +int onPgDn(); +int onIncreaseCSet(); +int onDecreaseCSet(); +int onGotoPage(); + +bool getname(const char *prompt,const char *ext,EXT_LIST *list,const char *def,bool usefilename); +bool getname_nogo(const char *prompt,const char *ext,EXT_LIST *list,const char *def,bool usefilename); +//bool getname_nogo(char *prompt,char *ext,char *def,bool usefilename); + + +int playTune1(); +int playTune2(); +int playTune3(); +int playTune4(); +int playTune5(); +int playTune6(); +int playTune7(); +int playTune8(); +int playTune9(); +int playTune10(); +int playTune11(); +int playTune12(); +int playTune13(); +int playTune14(); +int playTune15(); +int playTune16(); +int playTune17(); +int playTune18(); +int playTune19(); + +int changeTrack(); +int playMusic(); +int playTune(int pos); +int stopMusic(); + +int onTemplates(); + +// +----------+ +// | | +// | View Pic | +// | | +// | | +// | | +// +----------+ + +extern BITMAP *pic; +extern PALETTE picpal; +extern int pblack,pwhite; +extern double scale; +extern bool vp_showpal, vp_showsize, vp_center; + +INLINE int pal_sum(RGB p) +{ + return p.r + p.g + p.b; +} + +void get_bw(RGB *pal,int &black,int &white); +void draw_bw_mouse(int white, int old_mouse, int new_mouse); +int load_the_pic(BITMAP **dst, PALETTE dstpal); +int onViewPic(); +int load_the_map(); +int onViewMap(); + +//static char *dirstr[4] = {"up","down","left","right"}; +//char _pathstr[25]="up,up,up,up"; + +char *pathstr(byte path[]); +void drawpanel(int panel); +void refresh(int flags); +void select_scr(); +void select_combo(int list); +void update_combobrush(); +void draw(bool); +void replace(int c); +void draw_block(int start,int w,int h); +void fill(mapscr* fillscr, int targetcombo, int targetcset, int sx, int sy, int dir, int diagonal, bool only_cset); +void fill2(mapscr* fillscr, int targetcombo, int targetcset, int sx, int sy, int dir, int diagonal, bool only_cset); +int d_wflag_proc(int msg,DIALOG *d,int c); + +/**************************/ +/***** Mouse *****/ +/**************************/ + +void doxypos(byte &px,byte &py,int color,int mask, bool immediately); +void doxypos(byte &px,byte &py,int color,int mask, bool immediately, int cursoroffx, int cursoroffy, int iconw, int iconh); +void doflags(); +void set_brush_width(int width); +void set_brush_height(int height); + +int set_brush_width_1(); +int set_brush_width_2(); +int set_brush_width_3(); +int set_brush_width_4(); +int set_brush_width_5(); +int set_brush_width_6(); +int set_brush_width_7(); +int set_brush_width_8(); +int set_brush_width_9(); +int set_brush_width_10(); +int set_brush_width_11(); +int set_brush_width_12(); +int set_brush_width_13(); +int set_brush_width_14(); +int set_brush_width_15(); +int set_brush_width_16(); + +int set_brush_height_1(); +int set_brush_height_2(); +int set_brush_height_3(); +int set_brush_height_4(); +int set_brush_height_5(); +int set_brush_height_6(); +int set_brush_height_7(); +int set_brush_height_8(); +int set_brush_height_9(); +int set_brush_height_10(); +int set_brush_height_11(); + +int set_flood(); +int set_fill_4(); +int set_fill_8(); +int set_fill2_4(); +int set_fill2_8(); + +void flood(); +void fill_4(); +void fill_8(); +void fill2_4(); +void fill2_8(); +void set_brush_width(int width); +void set_brush_height(int height); +void domouse(); +void restore_mouse(); +int onShowPal(); +int onTestGUI(); +int onCSetFix(); +int onTemplate(); +int onComboPage(); +const char *flaglist(int index, int *list_size); +int select_data(const char *prompt,int index,const char *(proc)(int,int*), FONT *title_font); +int select_data(const char *prompt,int index,const char *(proc)(int,int*), const char *b1, const char *b2, FONT *title_font); +int select_flag(int &f); +int d_scombo_proc(int msg,DIALOG *d,int c); +int d_ffcombolist_proc(int msg,DIALOG *d,int c); +int d_comboalist_proc(int msg,DIALOG *d,int c); +int onSecretF(); +int onSecretCombo(); +int onUnderCombo(); +void compileZScript(); +int onImportFFScript(); +int onImportItemScript(); +int onImportGScript(); +int onCompileScript(); + +typedef struct item_struct +{ + char *s; + int i; +} item_struct; + +extern item_struct bii[iMax+1]; + +typedef struct weapon_struct +{ + char *s; + int i; +} weapon_struct; + +extern weapon_struct biw[wMAX]; + +typedef std::pair script_struct; +void build_biitems_list(); +extern script_struct biitems[NUMSCRIPTFFC]; //item script +extern int biitems_cnt; + +//extern script_struct biffs[NUMSCRIPTFFC]; + +typedef struct command_struct +{ + char *s; + int i; +} command_struct; + +enum +{ + cmdNULL, + cmdAbout, + cmdCatchall, + cmdChangeTrack, + cmdCheats, + cmdCSetFix, + cmdDrawingModeAlias, + cmdEditComboAlias, + cmdCombos, + cmdCompileScript, + cmdCopy, + cmdDefault_Combos, + cmdDeleteMap, + cmdDelete, + cmdDmaps, + cmdDoorCombos, + cmdDoors, + cmdPasteDoors, + cmdDrawingModeDungeon, + cmdEndString, + cmdCustomEnemies, + cmdDefault_Guys, + cmdEnemies, + cmdPasteEnemies, + cmdEnhancedMusic, + cmdCmdExit, + cmdExport_Combos, + cmdExport_DMaps, + cmdExport_Map, + cmdExport_Pals, + cmdExport_ZQT, + cmdExport_Msgs, + cmdExport_Subscreen, + cmdExport_Tiles, + cmdExport_UnencodedQuest, + cmdExport_ZGP, + cmdFlags, + cmdPasteFFCombos, + cmdSelectFFCombo, + cmdFullScreen, + cmdIcons, + cmdGotoMap, + cmdGuy, + cmdPasteGuy, + cmdHeader, + cmdHelp, + cmdImportFFScript, + cmdImportGScript, + cmdImportItemScript, + cmdImport_Combos, + cmdImport_DMaps, + cmdImport_ZGP, + cmdImport_Map, + cmdImport_Pals, + cmdImport_ZQT, + cmdImport_Msgs, + cmdImport_Subscreen, + cmdImport_Tiles, + cmdImport_UnencodedQuest, + cmdInfoTypes, + cmdInit, + cmdIntegrityCheckAll, + cmdIntegrityCheckRooms, + cmdIntegrityCheckWarps, + cmdItem, + cmdItemLocationReport, + cmdCustomItems, + cmdLayers, + cmdPasteLayers, + cmdColors_Levels, + cmdCustomLink, + cmdUsedCombos, + cmdColors_Main, + cmdMapCount, + cmdDefault_MapStyles, + cmdMapStyles, + cmdSubscreen, + cmdString, + cmdMidis, + cmdMiscColors, + cmdNew, + cmdDrawingModeNormal, + cmdOpen, + cmdOptions, + cmdScreenPalette, + cmdDefault_Pals, + cmdPaste, + cmdPasteAll, + cmdPasteAllToAll, + cmdPasteToAll, + cmdPath, + cmdPlayMusic, + cmdX, + cmdQuestTemplates, + cmdReTemplate, + cmdDrawingModeRelational, + cmdRevert, + cmdRType, + cmdPasteRoom, + cmdAnimationRules, + cmdSave, + cmdSaveAs, + cmdPasteScreenData, + cmdScrData, + cmdPasteSecretCombos, + cmdSecretCombo, + cmdEditSFX, + cmdShopTypes, + cmdSideWarp, + cmdColors_Sprites, + cmdDefault_Weapons, + cmdStopMusic, + cmdStrings, + cmdEditSubscreens, + cmdSnapshot, + cmdPlayTune, + cmdTemplate, + cmdTemplates, + cmdTileWarp, + cmdDefault_Tiles, + cmdTiles, + cmdToggleGrid, + cmdTriPieces, + cmdUnderCombo, + cmdPasteUnderCombo, + cmdUndo, + cmdZQVidMode, + cmdViewMap, + cmdShowPal, + cmdViewPic, + cmdPasteWarpLocations, + cmdWarpRings, + cmdPasteWarps, + cmdCustomWpns, + cmdShowDark, + cmdShowWalkable, + cmdShowFlags, + cmdShowCSet, + cmdShowType, + cmdComboRules, + cmdItemRules, + cmdEnemyRules, + cmdFixesRules, + cmdMiscRules, + cmdDefault_Items, + cmdItemDropSets, + cmdPastePalette, + cmdCompatRules, + cmdMAX +}; + +extern command_struct bic[cmdMAX]; + +extern combo_alias combo_aliases[MAXCOMBOALIASES]; +//int combo_apos; +//int combo_alistpos; + +int set_comboaradio(byte layermask); +extern int alias_origin; +void draw_combo_alias_thumbnail(BITMAP *dest, combo_alias *combo, int x, int y, int size); + +void build_bii_list(bool usenone); +const char *itemlist(int index, int *list_size); +int select_item(const char *prompt,int item,bool is_editor,int &exit_status); + +void build_biw_list(); +const char *weaponlist(int index, int *list_size); +int select_weapon(const char *prompt,int weapon); + +void build_bir_list(); +const char *roomlist(int index, int *list_size); +int select_room(const char *prompt,int room); + + +//char *doors_string[8]={"wall","passage","locked","shutter","bombable","walk thru","1-way shutter","boss"}; +const char *doorslist(int index, int *list_size); +void edit_door(int side); +int d_combo_proc(int msg,DIALOG *d,int c); +const char *doorcombosetlist(int index, int *list_size); +int onDoors(); +int onScrData(); +const char *nslist(int index, int *list_size); +const char *flaglist(int index, int *list_size); +const char *roomslist(int index, int *list_size); +const char *guyslist(int index, int *list_size); +const char *msgslist(int index, int *list_size); + +//static char number_str_buf[32]; +//int number_list_size=1; +//bool number_list_zero=false; + +const char *numberlist(int index, int *list_size); + +//static char dmap_str_buf[37]; +//int dmap_list_size=1; +//bool dmap_list_zero=false; + +const char *dmaplist(int index, int *list_size); + +char *hexnumlist(int index, int *list_size); +const char *maplist(int index, int *list_size); +const char *gotomaplist(int index, int *list_size); +const char *nextmaplist(int index, int *list_size); +const char *midilist(int index, int *list_size); +const char *screenmidilist(int index, int *list_size); +const char *custommidilist(int index, int *list_size); +const char *enhancedmusiclist(int index, int *list_size); +const char *levelnumlist(int index, int *list_size); +int onQuestRules(); +int onMapCount(); +int onGotoMap(); +int onFlags(); +int onUsedCombos(); +int onItem(); +int onRType(); +int onGuy(); +int onString(); +int onEndString(); +int onCatchall(); +int onScreenPalette(); +int onDecScrPal(); +int onIncScrPal(); +int onFullScreen(); +int isFullScreen(); +int onToggleGrid(); +int onToggleShowScripts(); +int onToggleShowSquares(); +int onToggleShowInfo(); + +//char msgbuf[MSGSTRS*3]; + +int d_ndroplist_proc(int msg,DIALOG *d,int c); +int d_idroplist_proc(int msg,DIALOG *d,int c); +int d_nidroplist_proc(int msg,DIALOG *d,int c); +int d_ilist_proc(int msg,DIALOG *d,int c); +int d_wlist_proc(int msg,DIALOG *d,int c); +int enelist_proc(int msg,DIALOG *d,int c,bool use_abc_list); +INLINE int d_enelist_proc(int msg,DIALOG *d,int c) +{ + return enelist_proc(msg,d,c,true); +} +INLINE int d_enelistnoabc_proc(int msg,DIALOG *d,int c) +{ + return enelist_proc(msg,d,c,false); +} + + +/**********************************/ +// Triforce Pieces // +/**********************************/ + +/* + static byte triframe_points[9*4] = + { + 0,2,2,0, 2,0,4,2, 0,2,4,2, 1,1,3,1, 2,0,2,2, + 1,1,1,2, 1,1,2,2, 3,1,3,2, 3,1,2,2 + }; + */ + +int d_tri_frame_proc(int msg,DIALOG *d,int c); +int d_tri_edit_proc(int msg,DIALOG *d,int c); +int onTriPieces(); + +/**********************************/ +/*********** onDMaps ************/ +/**********************************/ + +int d_maptile_proc(int msg,DIALOG *d,int c); +int editdmapmaps(int index); +int d_hexedit_proc(int msg,DIALOG *d,int c); +int xtoi(char *hexstr); +void drawgrid(BITMAP *dest,int x,int y,int grid,int fg,int bg,int div); +void drawgrid(BITMAP *dest,int x,int y,int w, int h, int tw, int th, int *grid,int fg,int bg,int div); +void drawgrid_s(BITMAP *dest,int x,int y,int grid,int fg,int bg,int div); +void drawdmap(int dmap); +int d_dmaplist_proc(int msg,DIALOG *d,int c); +int d_dropdmaplist_proc(int msg,DIALOG *d,int c); +int d_dropdmaptypelist_proc(int msg,DIALOG *d,int c); +int d_grid_proc(int msg,DIALOG *d,int c); +void drawxmap(int map,int xoff,bool large); +int d_xmaplist_proc(int msg,DIALOG *d,int c); + +//int xmapspecs[4] = {0,0,84+58,118+32+5}; + +int onXslider(void *dp3,int d2); + +//char *dmaptype_str[dmMAX] = { "Dngn","Overw","Cave","BS-Ow" }; + +const char *typelist(int index, int *list_size); +void put_title_str(char *s,int x,int y,int fg,int bg,int pos,int lines,int cpl); +int d_title_edit_proc(int msg,DIALOG *d,int c); +void put_intro_str(char *s,int x,int y,int fg,int bg,int pos); +int d_intro_edit_proc(int msg,DIALOG *d,int c); + +//char dmap_title[21]; +//char dmap_name[33]; +//char dmap_intro[73]; + +void editdmap(int index); + +//int selectdmapxy[6] = {164-74,108+8+24,164,80+44+24,164,90+44+24}; + +int onDmaps(); +int onEditSFX(int index); + +/************************************/ +/********** onDoorCombos **********/ +/************************************/ + +void fix_dcs(int index, int dir); +void editdoorcomboset(int index); + +const char *doorcombosetlist(int index, int *list_size); + +int doorcombosetlist_del(); +int copydcs(); +int pastedcs(); +int replacedcs(); +void reset_doorcomboset(int index); +void fix_door_combo_set(word &door_combo_set, byte index); +void init_doorcombosets(); +int onDoorCombos(); + +/*******************************/ +/********** onMidis **********/ +/*******************************/ + +void edit_tune(int i); +int d_midilist_proc(int msg,DIALOG *d,int c); +int onMidis(); + +/*******************************/ +/****** onEnhancedMusic ******/ +/*******************************/ + +void edit_music(int i); +int d_musiclist_proc(int msg,DIALOG *d,int c); +int onEnhancedMusic(); + +/*******************************/ +/**** onTest/onTestOptions ***/ +/*******************************/ + +int onTest(); +int onTestOptions(); + +/*******************************/ +/********** onWarp ***********/ +/*******************************/ + +const char *warptypelist(int index, int *list_size); + +//int warpdmapxy[6] = {188,126,188,100,188,112}; + +int d_warpdestsel_proc(int msg,DIALOG *d,int c); +int onTileWarpIndex(int index); +int onTileWarp(); +int onTimedWarp(); +int onItemWarp(); +int onSideWarp(); +void EditWindWarp(int level); +int onWhistle(); + +/*******************************/ +/*********** onPath ************/ +/*******************************/ + +const char *dirlist(int index, int *list_size); + +int onPath(); + +/********************************/ +/********* onInfoTypes **********/ +/********************************/ + +void EditInfoType(int index); +int onInfoTypes(); + +/********************************/ +/********* onShopTypes **********/ +/********************************/ + +void EditShopType(int index); +int onShopTypes(); + +/***********************************/ +/********* onItemDropSets **********/ +/***********************************/ + +int count_item_drop_sets(); +void EditItemDropSet(int index); +int onItemDropSets(); + +/********************************/ +/********* onWarpRings **********/ +/********************************/ + +//int curr_ring; + +void EditWarpRingScr(int ring,int index); +int d_warplist_proc(int msg,DIALOG *d,int c); +int d_wclist_proc(int msg,DIALOG *d,int c); +const char *wclist(int index, int *list_size); + +//int warpringdmapxy[8] = {160,106,160,80,160,92,160,144}; + +int select_warp(); +void EditWarpRing(int ring); +int onWarpRings(); + +/********************************/ +/********** onEnemies ***********/ +/********************************/ + +const char *pattern_list(int index, int *list_size); +int onPattern(); +int onEnemyFlags(); +const char *enemy_viewer(int index, int *list_size); + +typedef struct enemy_struct +{ + char *s; + int i; +} enemy_struct; + +#define zqMAXGUYS gDUMMY1 + +extern enemy_struct bie[eMAXGUYS]; +extern enemy_struct big[zqMAXGUYS]; +void build_bie_list(bool hide); +void build_big_list(bool hide); +const char *enemylist(int index, int *list_size); +const char *guylist(int index, int *list_size); +int efrontfacingtile(int id); +int select_enemy(const char *prompt,int enemy,bool hide,bool edit,int& exit_status); +int select_guy(const char *prompt,int guy); + +//unsigned char check[2] = { ';'+128,0 }; + +int onEnemies(); + +/*******************************/ +/********** onHeader ***********/ +/*******************************/ + +//char author[65],title[65],password[32]; +int d_showedit_proc(int msg,DIALOG *d,int c); +int onHeader(); + +//static ZCHEATS tmpcheats; +int onCheats(); +int RulesPage_1(); +int RulesPage_2(); +int RulesPage_3(); +int RulesPage_4(); +int RulesPage_5(); +int RulesPage_6(); +int RulesPage_7(); +int RulesPage_8(); +int RulesPage_9(); +int RulesPage_10(); +int onAnimationRules(); +int onComboRules(); +int onItemRules(); +int onEnemyRules(); +int onFixesRules(); +int onMiscRules(); +int d_line_proc(int msg, DIALOG *d, int c); +const char *subscrtypelist(int index, int *list_size); +int InitPage_1(); +int InitPage_2(); +int InitPage_3(); +int InitPage_4(); +int InitPage_5(); +int InitPage_6(); +int InitPage_7(); +int InitPage_8(); +int onInit(); +int onItemProps(); +int onSubscreen(); + +void get_cset(int dataset,int row,RGB *pal); +void draw_edit_dataset_specs(int index,int copy); +void init_colormixer(); +void colormixer(int color,int gray,int ratio); +bool do_x_button(BITMAP *dest, int x, int y); +void edit_dataset(int dataset); +int pal_index(RGB *pal,RGB c); +void grab_dataset(int dataset); + +//byte cset_hold[15][16*3]; +//byte cset_hold_cnt; +//bool cset_ready = false; +//int cset_count,cset_first; +//PALETTE pal,undopal; + +//byte rc[16] = {253,248,0,0,0,0,0,246,247,249,250,251,252,240,255,254}; + +void undo_pal(); +void calc_dark(int first); +void edit_cycles(int level); +void draw_cset_proc(DIALOG *d); +int d_cset_proc(int msg,DIALOG *d,int c); + +int d_dummy_proc(int msg,DIALOG *d,int c); + +//byte mainpal_csets[30] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, 11,11,12,12,12,11, 10,10,10,12,10,10,10,10,9 }; +//byte levelpal_csets[26] = { 2,3,4,9,2,3,4,2,3,4, 2, 3, 4, 15,15,15,15, 7,7,7, 8,8,8, 0,0,0 }; +//byte levelpal2_csets[26] = { 2,3,4,9,2,0,1,2,3,4, 5, 6, 7, 15,15,15,15, 8, 9,9,9,9,9,9,9,9 }; +//byte spritepal_csets[30] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, 14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14 }; +//byte spritepal2_csets[30] = { 15,16,17,18,19,20,21,22,23,24,25,26,27,28,29, 14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14 }; + +int EditColors(const char *caption,int first,int count,byte *label); +//int onColors_Main(); +//int onColors_Levels(); +//int onColors_Sprites(); +int d_maptile_proc(int msg,DIALOG *d,int c); +int onMapStyles(); +int d_misccolors_proc(int msg,DIALOG *d,int c); +int onMiscColors(); +int onTestBox(); + + +int d_ticsedit_proc(int msg,DIALOG *d,int c); + +// **** Palette cycling **** + +//static int palclk[3]; +//static int palpos[3]; + +void reset_pal_cycling(); +void cycle_palette(); + +/********************/ +/****** Help ******/ +/********************/ + +void doHelp(int bg,int fg); +int onHelp(); +int edit_layers(mapscr* tempscr); +void autolayer(mapscr* tempscr, int layer, int al[6][3]); +int findblankcombo(); +int onLayers(); + +// **** Timers **** + +//volatile int lastfps=0; +//volatile int framecnt=0; +extern volatile int myvsync; + +void myvsync_callback(); +void fps_callback(); + +extern BITMAP *hw_screen; + +/********************/ +/****** MAIN ******/ +/********************/ + +void custom_vsync(); +void switch_out(); +void switch_in(); +void Z_eventlog(const char *format,...); +void Z_scripterrlog(const char * const format,...); +int get_currdmap(); +int current_item(int item_type); +int current_item_power(int item_type); +int current_item_id(int item_type, bool checkmagic); +bool can_use_item(int item_type, int item); +bool has_item(int item_type, int it); +int get_bmaps(int si); + +bool no_subscreen(); + +extern int Awpn, Bwpn, Bpos; +extern sprite_list Sitems; + +int main(int argc,char **argv); +int d_nbmenu_proc(int msg,DIALOG *d,int c); +void center_zquest_dialogs(); +void animate_coords(); +void do_animations(); +int onZQVidMode(); +bool is_zquest(); +int save_config_file(); +int d_timer_proc(int msg, DIALOG *d, int c); +void check_autosave(); + +void update_tooltip(int x, int y, int trigger_x, int trigger_y, int trigger_w, int trigger_h, char *tipmsg); +void clear_tooltip(); + +void cflag_help(int id); +void ctype_help(int id); + +//throw together midi_strict hack +#ifdef ALLEGRO_LINUX_GP2X +extern int midi_strict; +#endif + +// game.maps[] flags +#define mSECRET 8192 // only overworld and caves use this +#define mVISITED 16384 // only overworld uses this + +#define mDOOR_UP 1 // only dungeons use this +#define mDOOR_DOWN 2 // '' +#define mDOOR_LEFT 4 // '' +#define mDOOR_RIGHT 8 // '' + +#define mITEM 16 // item (main screen) +#define mBELOW 32 // special item (underground) +#define mNEVERRET 64 // enemy never returns +#define mTMPNORET 128 // enemies don't return until you leave the dungeon + +#define mLOCKBLOCK 256 // if the lockblock on the screen has been triggered +#define mBOSSLOCKBLOCK 512 // if the bosslockblock on the screen has been triggered + +#define mCHEST 1024 // if the unlocked check on this screen has been opened +#define mLOCKEDCHEST 2048 // if the locked chest on this screen has been opened +#define mBOSSCHEST 4096 // if the boss chest on this screen has been opened +//#define mOTHER 8192 // overwrite this value, use for expansion +//#define mOTHER2 16384 // overwrite this value, use for expansion +#define mOTHER3 32768 // overwrite this value, use for expansion +#endif +/* end */ + diff --git a/src/zquestdat.h b/src/zquestdat.h new file mode 100644 index 0000000000..3af94f4536 --- /dev/null +++ b/src/zquestdat.h @@ -0,0 +1,17 @@ +/* Allegro datafile object indexes, produced by grabber v4.2.1, MinGW32 */ +/* Datafile: c:\zc\zquest.dat */ +/* Date: Fri Aug 03 10:33:20 2007 */ +/* Do not hand edit! */ + +#define _SIGNATURE 0 /* DATA */ +#define BMP_ARROWS 1 /* BMP */ +#define BMP_ICONS 2 /* BMP */ +#define BMP_ICONS2 3 /* BMP */ +#define BMP_MOUSE 4 /* BMP */ +#define BMP_MOUSELARGE 5 /* BMP */ +#define BMP_MOUSESMALL 6 /* BMP */ +#define BMP_SELECT 7 /* BMP */ +#define PAL_ZQUEST 8 /* PAL */ +#define THETRAVELSOFLINK_MID 9 /* MIDI */ + + diff --git a/src/zscriptversion.cpp b/src/zscriptversion.cpp new file mode 100644 index 0000000000..b806d584ad --- /dev/null +++ b/src/zscriptversion.cpp @@ -0,0 +1,20 @@ +// This program is free software; you can redistribute it and/or modify it under the terms of the +// modified version 3 of the GNU General Public License. See License.txt for details. + + +#include "precompiled.h" //always first + +#include "zscriptversion.h" +#include "zelda.h" +#include "link.h" + +extern LinkClass Link; + +int (*ZScriptVersion::Interpreter)(const byte, const word, const byte) = &run_script; +void (*ZScriptVersion::onScrolling)(int, int, int, int, bool) = &ScrollingScript; +int ZScriptVersion::CurrentVersion = V_FFSCRIPT; //Set to current version by default + +void ZScriptVersion::ScrollingScript(int scrolldir, int cx, int sx, int sy, bool end_frames) +{ + Link.run_scrolling_script(scrolldir, cx, sx, sy, end_frames); +} diff --git a/src/zscriptversion.h b/src/zscriptversion.h new file mode 100644 index 0000000000..381f2ba5a4 --- /dev/null +++ b/src/zscriptversion.h @@ -0,0 +1,53 @@ +//Makes sure the correct version of the ZScript interpreter is called based on +//the quest file's version, thus allowing for a re-write of the interpreter, +//which would otherwise break scripts from the LI build +//~Joe123 + +#ifndef _ZSCRIPTVER_H +#define _ZSCRIPTVER_H + +#include "zdefs.h" +#include "ffscript.h" + +class ZScriptVersion +{ +public: + //If checks are done at setVersion rather than during play-time + static inline void setVersion(int newVersion) + { + CurrentVersion = newVersion; + + if(CurrentVersion < 6) //Old ZScript + { + onScrolling = &NullScrollingScript; + Interpreter = &run_script; + } + else + { + onScrolling = &ScrollingScript; + //Watch this space... + } + } + + //Only one if check at quest load, rather than each time we use the function + static inline int RunScript(const byte type, const word script, const byte i = -1) + { + return (*Interpreter)(type, script, i); + } + + static inline void RunScrollingScript(int scrolldir, int cx, int sx, int sy, bool end_frames) + { + (*onScrolling)(scrolldir, cx, sx, sy, end_frames); + } + +private: + static int CurrentVersion; + static int (*Interpreter)(const byte, const word, const byte); + static void (*onScrolling)(int, int, int, int, bool); + + //Couldn't do anything with old ZScript + static inline void NullScrollingScript(int, int, int, int, bool) { } + static void ScrollingScript(int scrolldir, int cx, int sx, int sy, bool end_frames); +}; + +#endif diff --git a/src/zsys.cpp b/src/zsys.cpp new file mode 100644 index 0000000000..b9b059f164 --- /dev/null +++ b/src/zsys.cpp @@ -0,0 +1,1922 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zsys.cc +// +// System functions, etc. +// +//-------------------------------------------------------- + +// +//Copyright (C) 2016 Zelda Classic Team +// +//This program is free software: you can redistribute it and/or modify +//it under the terms of the GNU General Public License as published by +//the Free Software Foundation, either version 3 of the License, or +//(at your option) any later version. +// +//This program is distributed in the hope that it will be useful, +//but WITHOUT ANY WARRANTY; without even the implied warranty of +//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +//GNU General Public License for more details. +// +//You should have received a copy of the GNU General Public License +//along with this program. If not, see . +// + +#include "precompiled.h" //always first + +#include +#include +#include +#include "zc_alleg.h" +#include +#include + + +#ifdef ALLEGRO_DOS +#include +#endif + +#include "zdefs.h" +#include "zsys.h" +#include "zc_sys.h" +#include "jwin.h" +#include "mem_debug.h" + +#ifdef _MSC_VER +#define stricmp _stricmp +#endif + +//#ifdef _ZQUEST_SCALE_ +extern volatile int myvsync; +extern int zqwin_scale; +extern BITMAP *hw_screen; +//#endif + +extern bool is_zquest(); +bool zconsole = false; + +char *time_str_long(dword time) +{ + static char s[16]; + + dword decs = (time%60)*100/60; + dword secs = (time/60)%60; + dword mins = (time/3600)%60; + dword hours = time/216000; + + sprintf(s,"%ld:%02ld:%02ld.%02ld",hours,mins,secs,decs); + return s; +} + +char *time_str_med(dword time) +{ + static char s[16]; + + dword secs = (time/60)%60; + dword mins = (time/3600)%60; + dword hours = time/216000; + + sprintf(s,"%ld:%02ld:%02ld",hours,mins,secs); + return s; +} + +char *time_str_short(dword time) +{ + static char s[16]; + + dword mins = (time/3600)%60; + dword hours = time/216000; + + sprintf(s,"%ld:%02ld",hours,mins); + return s; +} + +char *time_str_short2(dword time) +{ + static char s[16]; + + dword mins = (time/3600)%60; + dword hours = time/216000; + + sprintf(s,"%02ld%s%02ld",hours,(time%60)<30?":":";",mins); + return s; +} + +void extract_name(char *path,char *name,int type) +{ + int l=(int)strlen(path); + int i=l; + + while(i>0 && path[i-1]!='/' && path[i-1]!='\\') + --i; + + int n=0; + + if(type==FILENAME8__) + { + while(ihigh) x=high; + + return x; +} + +char *snapshotformat_str[ssfmtMAX][2]= +{ + { (char *)"BMP", (char *)"bmp"}, + { (char *)"GIF", (char *)"gif"}, + { (char *)"JPG", (char *)"jpg"}, + { (char *)"PNG", (char *)"png"}, + { (char *)"PCX", (char *)"pcx"}, + { (char *)"TGA", (char *)"tga"}, +}; + +const char *snapshotformatlist(int index, int *list_size) +{ + if(index>=0) + { + bound(index,0,ssfmtMAX); + return snapshotformat_str[index][0]; + } + + *list_size=ssfmtMAX; + return NULL; +} + + +//Allegro's make_relative_filename doesn't handle uppercase/lowercase too well for drive letters +char *zc_make_relative_filename(char *dest, const char *path, const char *filename, int size) +{ +#ifdef ALLEGRO_LINUX + return make_relative_filename(dest, path, filename, size); +#elif defined(ALLEGRO_MACOSX) + return make_relative_filename(dest, path, filename, size); +#else + char *tpath = new char[size+1]; + make_relative_filename(dest, path, filename, size); + + if(dest[0]==0) //can't make relative path + { + sprintf(tpath, "%s", path); + int temp = ugetc(tpath); + + if(ugetat(tpath, 1) == DEVICE_SEPARATOR) + { + if((temp >= 'A') && (temp <= 'Z')) + { + usetat(tpath,0,utolower(temp)); + } + else if((temp >= 'a') && (temp <= 'a')) + { + usetat(tpath,0,utoupper(temp)); + } + + make_relative_filename(dest, tpath, filename, size); + } + } + + delete[] tpath; + return dest; +#endif +} + + + +void chop_path(char *path) +{ + int p = (int)strlen(path); + int f = (int)strlen(get_filename(path)); + + if(fhigh) return high; + + return x; +} + +float vbound(float x,float low,float high) +{ + if(xhigh) return high; + + return x; +} + +int used_switch(int argc,char *argv[],const char *s) +{ + // assumes a switch won't be in argv[0] + for(int i=1; i>3; + byte mask = 1 << (bit&7); + + if(val) + *bitstr |= mask; + else + *bitstr &= ~mask; +} + +int get_bit(byte *bitstr,int bit) +{ + bitstr += bit>>3; + return ((*bitstr) >> (bit&7))&1; +} + +void Z_error(const char *format,...) +{ + char buf[256]; + + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + +#if defined(ALLEGRO_DOS ) || defined(ALLEGRO_MAXOSX) + printf("%s\n",buf); +#endif + al_trace("%s\n",buf); + exit(1); +} + +void Z_message(const char *format,...) +{ + char buf[2048]; + + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + +#if defined(ALLEGRO_DOS ) || defined(ALLEGRO_MAXOSX) + printf("%s",buf); +#endif + al_trace("%s",buf); + + if(zconsole) + printf("%s",buf); +} + +void Z_title(const char *format,...) +{ + char buf[256]; + va_list ap; + va_start(ap, format); + vsprintf(buf, format, ap); + va_end(ap); + +#ifdef ALLEGRO_DOS + text_info ti; + gettextinfo(&ti); + int w = ti.screenwidth; + + int len = strlen(buf); + + if(len>w) + printf("%s\n",buf); + else + { + char title[81]; + + for(int i=0; i> 1; + memcpy(title+center,buf,len); + + printf("\n"); + textattr(0x4E); + cprintf("%s",title); + textattr(0x07); + + for(int i=0; iw, screen->h); + blit(screen,tempbmp,0,0,0,0,screen->w,screen->h); + save_bitmap(buf,screen,temppal); + destroy_bitmap(tempbmp); + return D_O_K; +} + +void set_default_box_size() +{ + int screen_w=SCREEN_W; + int screen_h=SCREEN_H; + + if(zqwin_scale>1) + { + screen_w/=zqwin_scale; + screen_h/=zqwin_scale; + } + + box_w=MIN(512, screen_w-16); + box_h=MIN(256, (screen_h-64)&0xFFF0); + + box_l=(screen_w-box_w)/2; + box_t=(screen_h-box_h)/2; + box_r=box_l+box_w; + box_b=box_t+box_h; +} + +/* starts outputting a progress message */ +void box_start(int style, const char *title, FONT *title_font, FONT *message_font, bool log) +{ + box_style=style; + box_title_font=(title_font!=NULL)?title_font:font; + box_message_font=(message_font!=NULL)?message_font:font; + box_message_height=text_height(box_message_font); + box_titlebar_height=title?text_height(box_title_font)+2:0; + set_default_box_size(); + /* + box_w=BOX_W; + box_h=BOX_H; + box_l=BOX_L; + box_r=BOX_R; + box_t=BOX_T; + box_b=BOX_B; + */ + box_log=log; + memset(box_log_msg, 0, 480); + box_msg_pos=0; + box_store_pos=0; + scare_mouse(); + + jwin_draw_win(screen, box_l, box_t, box_r-box_l, box_b-box_t, FR_WIN); + + if(title!=NULL) + { + zc_swap(font,box_title_font); + jwin_draw_titlebar(screen, box_l+3, box_t+3, box_r-box_l-6, 18, title, false); + zc_swap(font,box_title_font); + box_titlebar_height=18; + } + + unscare_mouse(); + + box_store_x = box_x = box_y = 0; + box_active = true; + box_t+=box_titlebar_height; + box_h-=box_titlebar_height; + box_log=log; + memset(box_log_msg, 0, 480); + box_msg_pos=0; + box_store_pos=0; +} + +/* outputs text to the progress message */ +void box_out(const char *msg) +{ + std::string remainder = ""; + std::string temp(msg); + + if(box_active) + { + scare_mouse(); + //do primitive text wrapping + unsigned int i; + + for(i=0; i box_r-box_l-16) + { + i = zc_max(i-1,0); + break; + } + } + + set_clip_rect(screen, box_l+8, box_t+1, box_r-8, box_b-1); + textout_ex(screen, box_message_font, temp.substr(0,i).c_str(), box_l+8+box_x, box_t+(box_y+1)*box_message_height, gui_fg_color, gui_bg_color); + set_clip_rect(screen, 0, 0, SCREEN_W-1, SCREEN_H-1); + unscare_mouse(); + remainder = temp.substr(i,temp.size()-i); + } + + if(box_log) + { + sprintf(box_log_msg+box_msg_pos, "%s", msg); + } + + box_x += text_length(box_message_font, msg); + box_msg_pos+=(int)strlen(msg); + + if(remainder != "") + { + bool oldlog = box_log; + box_log = false; + box_eol(); + box_out(remainder.c_str()); + box_log = oldlog; + } + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + //if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif +} + +/* remembers the current x position */ +void box_save_x() +{ + if(box_active) + { + box_store_x=box_x; + } + + box_store_pos=box_msg_pos; +} + +/* remembers the current x position */ +void box_load_x() +{ + if(box_active) + { + box_x=box_store_x; + } + + box_msg_pos=box_store_pos; +} + +/* outputs text to the progress message */ +void box_eol() +{ + if(box_active) + { + box_x = 0; + box_y++; + + if((box_y+2)*box_message_height >= box_h) + { + scare_mouse(); + blit(screen, screen, box_l+8, box_t+(box_message_height*2), box_l+8, box_t+(box_message_height), box_w-16, box_y*box_message_height); + rectfill(screen, box_l+8, box_t+box_y*box_message_height, box_l+box_w-8, box_t+(box_y+1)*box_message_height, gui_bg_color); + unscare_mouse(); + box_y--; + } + } + + box_msg_pos = 0; + + if(box_log) + { + al_trace("%s", box_log_msg); + al_trace("\n"); + memset(box_log_msg, 0, 480); + } + + // #ifdef _ZQUEST_SCALE_ + if(is_zquest()) + { + //if(myvsync) + { + if(zqwin_scale > 1) + { + stretch_blit(screen, hw_screen, 0, 0, screen->w, screen->h, 0, 0, hw_screen->w, hw_screen->h); + } + else + { + blit(screen, hw_screen, 0, 0, 0, 0, screen->w, screen->h); + } + + myvsync=0; + } + } + + // #endif +} + +/* ends output of a progress message */ +void box_end(bool pause) +{ + if(box_active) + { + if(pause) + { + box_eol(); + box_out("-- press a key --"); + + do + { + // poll_mouse(); + } + while(gui_mouse_b()); + + do + { + // poll_mouse(); + } + while((!keypressed()) && (!gui_mouse_b())); + + do + { + // poll_mouse(); + } + while(gui_mouse_b()); + + clear_keybuf(); + } + + box_active = false; + } +} + +/* pauses box output */ +void box_pause() +{ + if(box_active) + { + box_save_x(); + box_out("-- press a key --"); + + do + { + // poll_mouse(); + } + while(gui_mouse_b()); + + do + { + // poll_mouse(); + } + while((!keypressed()) && (!gui_mouse_b())); + + do + { + // poll_mouse(); + } + while(gui_mouse_b()); + + clear_keybuf(); + box_load_x(); + } +} + +// Checking for double clicks is complicated. The user could release the +// mouse button at almost any point, and I might miss it if I am doing some +// other processing at the same time (eg. sending the single-click message). +// To get around this I install a timer routine to do the checking for me, +// so it will notice double clicks whenever they happen. + +volatile int dclick_status, dclick_time; + +// dclick_check: +// Double click checking user timer routine. + +void dclick_check(void) +{ + if(dclick_status==DCLICK_NOT) + { + if(gui_mouse_b()) + { + dclick_status = DCLICK_START; // let's go! + dclick_time = 0; + return; + } + } + else if(dclick_status==DCLICK_START) // first click... + { + if(!gui_mouse_b()) + { + dclick_status = DCLICK_RELEASE; // aah! released first + dclick_time = 0; + return; + } + } + else if(dclick_status==DCLICK_RELEASE) // wait for second click + { + if(gui_mouse_b()) + { + dclick_status = DCLICK_AGAIN; // yes! the second click + dclick_time = 0; + return; + } + } + else + { + return; + } + + // timeout? + if(dclick_time++ > 10) + { + dclick_status = DCLICK_NOT; + } +} + +END_OF_FUNCTION(dclick_check) + +void lock_dclick_function() +{ + LOCK_FUNCTION(dclick_check); +} + + +void textout_shadow_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + if(bg!=-1) + { + rectfill(bmp, x, y, x+text_length(f, s), y+text_height(f), bg); + } + + textout_ex(bmp, f, s, x+1, y, shadow, -1); + textout_ex(bmp, f, s, x+1, y+1, shadow, -1); + textout_ex(bmp, f, s, x, y+1, shadow, -1); +} + +void textout_shadow_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_ex(bmp, f, s, x-(text_length(f, s)/2), y, shadow, bg); +} + +void textout_shadow_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_ex(bmp, f, s, x-text_length(f, s), y, shadow, bg); +} + +void textout_shadow_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + if(bg!=-1) + { + rectfill(bmp, x-1, y, x+text_length(f, s), y+text_height(f), bg); + } + + textout_ex(bmp, f, s, x+1, y, shadow, -1); + textout_ex(bmp, f, s, x+1, y+1, shadow, -1); + textout_ex(bmp, f, s, x, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y, shadow, -1); +} + +void textout_shadow_centre_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_u_ex(bmp, f, s, x-(text_length(f, s)/2), y, shadow, bg); +} + +void textout_shadow_right_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_u_ex(bmp, f, s, x-text_length(f, s), y, shadow, bg); +} + +void textout_shadow_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + if(bg!=-1) + { + rectfill(bmp, x-1, y-1, x+text_length(f, s), y+text_height(f), bg); + } + + textout_ex(bmp, f, s, x+1, y-1, shadow, -1); + textout_ex(bmp, f, s, x+1, y, shadow, -1); + textout_ex(bmp, f, s, x+1, y+1, shadow, -1); + textout_ex(bmp, f, s, x, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y, shadow, -1); + textout_ex(bmp, f, s, x-1, y-1, shadow, -1); + textout_ex(bmp, f, s, x, y-1, shadow, -1); +} + +void textout_shadow_centre_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_o_ex(bmp, f, s, x-(text_length(f, s)/2), y, shadow, bg); +} + +void textout_shadow_right_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_o_ex(bmp, f, s, x-text_length(f, s), y, shadow, bg); +} + +void textout_shadow_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + if(bg!=-1) + { + rectfill(bmp, x-1, y-1, x+text_length(f, s), y+text_height(f), bg); + } + + textout_ex(bmp, f, s, x+1, y, shadow, -1); + textout_ex(bmp, f, s, x, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y, shadow, -1); + textout_ex(bmp, f, s, x, y-1, shadow, -1); +} + +void textout_shadow_centre_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_plus_ex(bmp, f, s, x-(text_length(f, s)/2), y, shadow, bg); +} + +void textout_shadow_right_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_plus_ex(bmp, f, s, x-text_length(f, s), y, shadow, bg); +} + +void textout_shadow_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + if(bg!=-1) + { + rectfill(bmp, x-1, y-1, x+text_length(f, s), y+text_height(f), bg); + } + + textout_ex(bmp, f, s, x+1, y-1, shadow, -1); + textout_ex(bmp, f, s, x+1, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y+1, shadow, -1); + textout_ex(bmp, f, s, x-1, y-1, shadow, -1); +} + +void textout_shadow_centre_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_x_ex(bmp, f, s, x-(text_length(f, s)/2), y, shadow, bg); +} + +void textout_shadow_right_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg) +{ + textout_shadow_x_ex(bmp, f, s, x-text_length(f, s), y, shadow, bg); +} + +void textout_shadowed_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadow_ex(bmp, f, s, x, y, shadow, bg); + textout_ex(bmp, f, s, x, y, color, -1); +} + +void textout_shadowed_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_ex(bmp, f, s, x-(text_length(f, s)/2), y, color, shadow, bg); +} + +void textout_shadowed_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_ex(bmp, f, s, x-text_length(f, s), y, color, shadow, bg); +} + +void textout_shadowed_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadow_u_ex(bmp, f, s, x, y, shadow, bg); + textout_ex(bmp, f, s, x, y, color, -1); +} + +void textout_shadowed_centre_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_u_ex(bmp, f, s, x-(text_length(f, s)/2), y, color, shadow, bg); +} + +void textout_shadowed_right_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_u_ex(bmp, f, s, x-text_length(f, s), y, color, shadow, bg); +} + +void textout_shadowed_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadow_o_ex(bmp, f, s, x, y, shadow, bg); + textout_ex(bmp, f, s, x, y, color, -1); +} + +void textout_shadowed_centre_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_o_ex(bmp, f, s, x-(text_length(f, s)/2), y, color, shadow, bg); +} + +void textout_shadowed_right_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_o_ex(bmp, f, s, x-text_length(f, s), y, color, shadow, bg); +} + +void textout_shadowed_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadow_plus_ex(bmp, f, s, x, y, shadow, bg); + textout_ex(bmp, f, s, x, y, color, -1); +} + +void textout_shadowed_centre_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_plus_ex(bmp, f, s, x-(text_length(f, s)/2), y, color, shadow, bg); +} + +void textout_shadowed_right_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_plus_ex(bmp, f, s, x-text_length(f, s), y, color, shadow, bg); +} + +void textout_shadowed_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadow_x_ex(bmp, f, s, x, y, shadow, bg); + textout_ex(bmp, f, s, x, y, color, -1); +} + +void textout_shadowed_centre_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_x_ex(bmp, f, s, x-(text_length(f, s)/2), y, color, shadow, bg); +} + +void textout_shadowed_right_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg) +{ + textout_shadowed_x_ex(bmp, f, s, x-text_length(f, s), y, color, shadow, bg); +} + +void textprintf_shadow_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_ex(bmp, f, buf, x, y, shadow, bg); +} + +void textprintf_shadow_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, shadow, bg); +} + +void textprintf_shadow_right_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_ex(bmp, f, buf, x-text_length(f, buf), y, shadow, bg); +} + + +void textprintf_shadow_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_u_ex(bmp, f, buf, x, y, shadow, bg); +} + +void textprintf_shadow_centre_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_u_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, shadow, bg); +} + +void textprintf_shadow_right_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_u_ex(bmp, f, buf, x-text_length(f, buf), y, shadow, bg); +} + + +void textprintf_shadow_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_o_ex(bmp, f, buf, x, y, shadow, bg); +} + +void textprintf_shadow_centre_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_o_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, shadow, bg); +} + +void textprintf_shadow_right_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_o_ex(bmp, f, buf, x-text_length(f, buf), y, shadow, bg); +} + + + + + + + +void textprintf_shadow_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_plus_ex(bmp, f, buf, x, y, shadow, bg); +} + +void textprintf_shadow_centre_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_plus_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, shadow, bg); +} + +void textprintf_shadow_right_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_plus_ex(bmp, f, buf, x-text_length(f, buf), y, shadow, bg); +} + +void textprintf_shadow_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_x_ex(bmp, f, buf, x, y, shadow, bg); +} + +void textprintf_shadow_centre_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_x_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, shadow, bg); +} + +void textprintf_shadow_right_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadow_x_ex(bmp, f, buf, x-text_length(f, buf), y, shadow, bg); +} + + + + + + + + + + + + + + + +void textprintf_shadowed_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_ex(bmp, f, buf, x, y, color, shadow, bg); +} + +void textprintf_shadowed_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, color, shadow, bg); +} + +void textprintf_shadowed_right_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_ex(bmp, f, buf, x-text_length(f, buf), y, color, shadow, bg); +} + +void textprintf_shadowed_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_u_ex(bmp, f, buf, x, y, color, shadow, bg); +} + +void textprintf_shadowed_centre_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_u_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, color, shadow, bg); +} + +void textprintf_shadowed_right_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_u_ex(bmp, f, buf, x-text_length(f, buf), y, color, shadow, bg); +} + +void textprintf_shadowed_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_o_ex(bmp, f, buf, x, y, color, shadow, bg); +} + +void textprintf_shadowed_centre_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_o_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, color, shadow, bg); +} + +void textprintf_shadowed_right_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_o_ex(bmp, f, buf, x-text_length(f, buf), y, color, shadow, bg); +} + +void textprintf_shadowed_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_plus_ex(bmp, f, buf, x, y, color, shadow, bg); +} + +void textprintf_shadowed_centre_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_plus_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, color, shadow, bg); +} + +void textprintf_shadowed_right_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_plus_ex(bmp, f, buf, x-text_length(f, buf), y, color, shadow, bg); +} + + +void textprintf_shadowed_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_x_ex(bmp, f, buf, x, y, color, shadow, bg); +} + +void textprintf_shadowed_centre_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_x_ex(bmp, f, buf, x-(text_length(f, buf)/2), y, color, shadow, bg); +} + +void textprintf_shadowed_right_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...) +{ + char buf[512]; + va_list ap; + ASSERT(bmp); + ASSERT(f); + ASSERT(format); + + va_start(ap, format); + uvszprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + textout_shadowed_x_ex(bmp, f, buf, x-text_length(f, buf), y, color, shadow, bg); +} +/* + void dclick_check(void) + { + if (dclick_status==DCLICK_START) { // first click... + if (!gui_mouse_b()) { + dclick_status = DCLICK_RELEASE; // aah! released first + dclick_time = 0; + return; + } + } + else if (dclick_status==DCLICK_RELEASE) { // wait for second click + if (gui_mouse_b()) { + dclick_status = DCLICK_AGAIN; // yes! the second click + dclick_time = 0; + return; + } + } + else + { + return; + } + + // timeout? + if (dclick_time++ > 10) + { + dclick_status = DCLICK_NOT; + } + } + */ + + +extern int d_alltriggerbutton_proc(int msg,DIALOG *d,int c); +#ifndef _MSC_VER +//Inconsistent DLL linkage... what the fuck +extern int d_button_proc(int msg,DIALOG *d,int c); +extern int d_check_proc(int msg,DIALOG *d,int c); +extern int d_ctext_proc(int msg,DIALOG *d,int c); +extern int d_text_proc(int msg,DIALOG *d,int c); +#endif +extern int d_comboa_radio_proc(int msg,DIALOG *d,int c); +extern int d_comboabutton_proc(int msg,DIALOG *d,int c); +extern int d_dummy_proc(int msg,DIALOG *d,int c); +extern int d_jbutton_proc(int msg,DIALOG *d,int c); +extern int d_kbutton_proc(int msg,DIALOG *d,int c); +extern int d_listen_proc(int msg,DIALOG *d,int c); +extern int d_savemidi_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssdn_btn3_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn2_proc(int msg,DIALOG *d,int c); +extern int d_sslt_btn3_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssrt_btn3_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn2_proc(int msg,DIALOG *d,int c); +extern int d_ssup_btn3_proc(int msg,DIALOG *d,int c); +extern int d_tri_edit_proc(int msg,DIALOG *d,int c); +extern int d_triggerbutton_proc(int msg,DIALOG *d,int c); +extern int jwin_button_proc(int msg,DIALOG *d,int c); +extern int jwin_check_proc(int msg,DIALOG *d,int c); +extern int jwin_ctext_proc(int msg,DIALOG *d,int c); +extern int jwin_radio_proc(int msg,DIALOG *d,int c); +extern int jwin_rtext_proc(int msg,DIALOG *d,int c); +extern int jwin_text_proc(int msg,DIALOG *d,int c); +extern int jwin_win_proc(int msg,DIALOG *d,int c); + +//extern DIALOG *sso_properties_dlg; + +void copy_dialog(DIALOG **to, DIALOG *from) +{ + int count=0; + + for(count=1; from[count].proc!=NULL; ++count) + { + /* do nothing */ + } + + (*to)=(DIALOG*)zc_malloc((count+1)*sizeof(DIALOG)); + memcpy((*to),from,sizeof(DIALOG)*(count+1)); + + for(int i=0; iw-1), vbound(y1, 0, bmp->h-1), vbound(x2, 0, bmp->w-1), vbound(y2, 0, bmp->h-1), color); +} + +//computes the positive gcd of two integers (using Euclid's algorithm) + +int gcd(int a, int b) +{ + a = abs(a); + b = abs(b); + + if(b == 0) + return a; + + int res = a%b; + + while(res != 0) + { + a = b; + b = res; + res = a%b; + } + + return b; +} + +//computes the positive lcm of two integers +int lcm(int a, int b) +{ + return a*b/gcd(a,b); +} + +//Fun fact: Allegro used to be in control of allegro.log. This caused +//problems, because it would hold on to a file handle. Even if we blank +//the contents of the log, it will still write to the end, causing +//lots of nulls. + +//No more! + + +FILE * trace_file; + +int zc_trace_handler(const char * msg) +{ + if(trace_file == 0) + { + trace_file = fopen("allegro.log", "a+"); + + if(0==trace_file) + { + return 0; // blargh. + } + } + + fprintf(trace_file, "%s", msg); + fflush(trace_file); + return 1; +} + +void zc_trace_clear() +{ + if(trace_file) + { + fclose(trace_file); + } + + trace_file = fopen("allegro.log", "w"); + ASSERT(trace_file); +} + diff --git a/src/zsys.h b/src/zsys.h new file mode 100644 index 0000000000..6dd3a4453b --- /dev/null +++ b/src/zsys.h @@ -0,0 +1,180 @@ +//-------------------------------------------------------- +// Zelda Classic +// by Jeremy Craner, 1999-2000 +// +// zsys.h +// +// System functions, etc. +// +//-------------------------------------------------------- + +#if defined(ALLEGRO_WINDOWS) +#include +#endif + +#ifndef _ZSYS_H_ +#define _ZSYS_H_ + +#include "zdefs.h" +#include "jwin.h" + +#define FILENAME8_3 0 +#define FILENAME8__ 1 +#define FILENAMEALL 2 + +extern int jwin_pal[jcMAX]; + +extern bool is_large; +extern void large_dialog(DIALOG *d); + +extern volatile int dclick_status, dclick_time; + +char *time_str_short(dword time); +char *time_str_short2(dword time); +char *time_str_med(dword time); +char *time_str_long(dword time); + +void extract_name(char *path,char *name,int type); +void temp_name(char temporaryname[]); +char *zc_make_relative_filename(char *dest, const char *path, const char *filename, int size); +void chop_path(char *path); +int vbound(int x,int low,int high); +float vbound(float x,float low,float high); +int used_switch(int argc,char *argv[],const char *s); +bool isinRect(int x,int y,int rx1,int ry1,int rx2,int ry2); + +extern char zeldapwd[8]; +extern char zquestpwd[8]; +extern char datapwd[8]; +extern char zcheat[4][8]; + +void resolve_password(char *pwd); + +void copy_file(const char *src, const char *dest); + +int get_bit(byte *bitstr,int bit); +void set_bit(byte *bitstr,int bit,byte val); + +void Z_error(const char *format,...); +void Z_message(const char *format,...); +void Z_title(const char *format,...); + +int anim_3_4(int clk, int speed); + +int bound(int &x,int low,int high); + +enum {ssfmtBMP, ssfmtGIF, ssfmtJPG, ssfmtPNG, ssfmtPCX, ssfmtTGA, ssfmtMAX }; +extern char *snapshotformat_str[ssfmtMAX][2]; +extern const char *snapshotformatlist(int index, int *list_size); + + +/*0=normal, 1=jwin*/ +void box_start(int style , const char *title, FONT *title_font, FONT *message_font, bool log); +//void box_start(); +void box_out(const char *msg); +void box_save_x(); +void box_load_x(); +void box_eol(); +void box_end(bool pause); +void box_pause(); +void dither_rect(BITMAP *bmp, PALETTE *pal, int x1, int y1, int x2, int y2, + int src_color1, int src_color2, byte dest_color1, + byte dest_color2); +void dclick_check(void); +void lock_dclick_function(); + +void textout_shadow_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_centre_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_right_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_centre_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_right_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_centre_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_right_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_centre_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadow_right_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int shadow, int bg); +void textout_shadowed_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_centre_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_right_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_centre_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_right_u_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_centre_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_right_o_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); + + + +void textout_shadowed_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_centre_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_right_plus_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_centre_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); +void textout_shadowed_right_x_ex(BITMAP *bmp, const FONT *f, const char *s, int x, int y, int color, int shadow, int bg); + + + + +void textprintf_shadow_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_right_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_centre_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_right_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_centre_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_right_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); + + + + + +void textprintf_shadow_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_centre_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_right_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_centre_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); +void textprintf_shadow_right_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int shadow, int bg, const char *format, ...); + + + +void textprintf_shadowed_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_centre_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_right_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_centre_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_right_u_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_centre_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_right_o_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); + + +void textprintf_shadowed_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_centre_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_right_plus_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_centre_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); +void textprintf_shadowed_right_x_ex(BITMAP *bmp, const FONT *f, int x, int y, int color, int shadow, int bg, const char *format, ...); + +void copy_dialog(DIALOG **to, DIALOG *from); +void free_dialog(DIALOG **dlg); + +void safe_rect(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); + +int gcd(int a, int b); +int lcm(int a, int b); + +void quit_game(); + +int zc_trace_handler(const char *); +void zc_trace_clear(); + +extern bool zconsole; + +#endif // _ZSYS_H_ + diff --git a/src/zsyssimple.h b/src/zsyssimple.h new file mode 100644 index 0000000000..2e30356841 --- /dev/null +++ b/src/zsyssimple.h @@ -0,0 +1,15 @@ +#ifndef ZSYSSIMPLE_H +#define ZSYSSIMPLE_H + +struct FONT; + +void box_out(const char *msg); +void box_start(int style, const char *title, FONT *title_font, FONT *message_font, bool log); +void box_end(bool pause); +void box_eol(); +void Z_message(char *format,...); + +extern bool gotoless_not_equal; // Used by BuildVisitors.cpp + +#endif + diff --git a/zc_icon-old.icns b/zc_icon-old.icns new file mode 100644 index 0000000000..2d3916f4b3 Binary files /dev/null and b/zc_icon-old.icns differ diff --git a/zc_icon-old.ico b/zc_icon-old.ico new file mode 100644 index 0000000000..6d225827d6 Binary files /dev/null and b/zc_icon-old.ico differ diff --git a/zc_icon.c b/zc_icon.c new file mode 100644 index 0000000000..ae749100a2 --- /dev/null +++ b/zc_icon.c @@ -0,0 +1,528 @@ +#include +/* XPM */ +static const char *allegico_xpm[] = +{ + /* columns rows colors chars-per-pixel */ + "256 256 256 2 ", + " c #383738", + ". c #2F2E30", + "X c #0F2312", + "o c #413B3E", + "O c #2C6E0C", + "+ c #224D12", + "@ c #3D3C41", + "# c #433D43", + "$ c #3E4346", + "% c #444345", + "& c #4B4A4D", + "* c #484649", + "= c #4D4D52", + "- c #484C53", + "; c #524E53", + ": c #594F56", + "> c #4D5255", + ", c #535254", + "< c #55545A", + "1 c #5B5B5D", + "2 c #58575A", + "3 c #51504D", + "4 c #615A5E", + "5 c #5A6554", + "6 c #5C5C62", + "7 c #575B62", + "8 c #625D64", + "9 c #5D6365", + "0 c #64646B", + "q c #6A6C6D", + "w c #656668", + "e c #6C6C72", + "r c #686973", + "t c #726D75", + "y c #6D7274", + "u c #6D757A", + "i c #737375", + "p c #74757A", + "a c #757A7C", + "s c #7B7B7D", + "d c #78777A", + "f c #6D726C", + "g c #636D5B", + "h c #50673A", + "j c #827D7E", + "k c #3A8F0A", + "l c #44A509", + "z c #46AA09", + "x c #49AC09", + "c c #48AE07", + "v c #4BB407", + "b c #4DBE06", + "n c #4BB308", + "m c #4EBB08", + "M c #47B007", + "N c #50BE06", + "B c #51BC09", + "V c #5CB11D", + "C c #68B230", + "Z c #5D9C2D", + "A c #4FC007", + "S c #4FC008", + "D c #52C406", + "F c #55CB07", + "G c #53C209", + "H c #57CA08", + "J c #58CC0A", + "K c #56D107", + "L c #59D507", + "P c #5CDC07", + "I c #59D708", + "U c #5ADA08", + "Y c #5BC516", + "T c #5FD410", + "R c #65D915", + "E c #63CF17", + "W c #5EE307", + "Q c #5EE308", + "! c #61E907", + "~ c #61E609", + "^ c #63EB08", + "/ c #68EE0D", + "( c #65F307", + ") c #64F208", + "_ c #68F609", + "` c #67F908", + "' c #6EF017", + "] c #6FCE2D", + "[ c #7CF929", + "{ c #7BED30", + "} c #6E9352", + "| c #77AF4C", + " . c #7A837D", + ".. c #798C69", + "X. c #7EA067", + "o. c #7CD143", + "O. c #7FE040", + "+. c #84F43B", + "@. c #84F937", + "#. c #82F237", + "$. c #8BAF70", + "%. c #82A468", + "&. c #8AD757", + "*. c #86D64E", + "=. c #89EC48", + "-. c #8CF646", + ";. c #91F94C", + ":. c #8EE853", + ">. c #93EA5A", + ",. c #93F353", + "<. c #98F659", + "1. c #90EF4F", + "2. c #97DA6A", + "3. c #9AE967", + "4. c #9CF363", + "5. c #9FF566", + "6. c #9FE571", + "7. c #A2F46B", + "8. c #A3EB73", + "9. c #A6E97A", + "0. c #A8F277", + "q. c #A1EE6D", + "w. c #A2DD7A", + "e. c #7C7C83", + "r. c #767A82", + "t. c #6E7B82", + "y. c #817D85", + "u. c #7C8284", + "i. c #7D8488", + "p. c #7F9294", + "a. c #838385", + "s. c #84858A", + "d. c #848A8C", + "f. c #8A8B8D", + "g. c #888789", + "h. c #89938C", + "j. c #8B8D92", + "k. c #868B92", + "l. c #918E93", + "z. c #8C9294", + "x. c #8C9698", + "c. c #929395", + "v. c #94959A", + "b. c #949A9C", + "n. c #9A9B9D", + "m. c #979899", + "M. c #92928E", + "N. c #99A39C", + "B. c #97AE8A", + "V. c #959CA2", + "C. c #9C9DA2", + "Z. c #999BA5", + "A. c #8E9CA2", + "S. c #A19EA3", + "D. c #9CA3A4", + "F. c #9DA4A9", + "G. c #9DAAAB", + "H. c #98A6A4", + "J. c #9EAEAF", + "K. c #A2A3A5", + "L. c #A3A5AA", + "P. c #A4AAAC", + "I. c #AAABAD", + "U. c #A6A8A8", + "Y. c #A8B3AC", + "T. c #A5ACB2", + "R. c #ABADB2", + "E. c #A6A9B3", + "W. c #B1AEB3", + "Q. c #A5B2B3", + "!. c #ACB3B4", + "~. c #ADB5BA", + "^. c #ADBABB", + "/. c #ABB9B5", + "(. c #B2B3B5", + "). c #B3B5BA", + "_. c #B4BBBC", + "`. c #BABCBD", + "'. c #B5B9B7", + "]. c #B1B5AD", + "[. c #A4B896", + "{. c #ADCF92", + "}. c #ACEB83", + "|. c #ACE586", + " X c #B1E98C", + ".X c #BBEC9C", + "XX c #B5E695", + "oX c #BEF39B", + "OX c #BFF999", + "+X c #ADF181", + "@X c #B6C8A8", + "#X c #B8C3BC", + "$X c #B9D1AA", + "%X c #BEEBA1", + "&X c #BFF0A0", + "*X c #9FC880", + "=X c #C2FD9C", + "-X c #C1F59E", + ";X c #C5D0BC", + ":X c #C2EDA5", + ">X c #C5EDAA", + ",X c #C8ECAD", + "XqXDXDXqX7X:XXXXX9.2.*.] ] Y Y G S b b A b b B S b b b b b b b b b b b S b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b b b b b b b m m S S b Y ] *.2.XX>XDXDXDXLXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXAX9X&Xw.*.] Y S m b S b b b b b b b b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b S b b b b b b b b b b S m A A B ] &.|.%XSXDXDXDXDXLXDXDXDXDXDXDXDXLXDXDXDXDXDXDXDXDXLXDXDXDXDXDXDXDXDXDXDXLXDXDXSX%X|.2.] Y b A b b b b b b b b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b b b b b A b S Y ] 2. XAXDXGXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXLXDXDXDXLXDXDXDXDXDXDXDXDXGXDXDXDX6XXX2.] Y A b A b b b b b b b b S S b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b S m S m S m b S A ] &.|.7XDXDXGXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXGXDXDXDX7X|.&.] b b S m S b b b S m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b S m S S S S ] 2.XXAXDXGXDXDXDXDXDXDXDXDXDXDXDXDXDXDXLXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXLXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXGX X2.] m S S b b m S b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b S b S S S Y &.XXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXSXXX&.] S S m S b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b b A S Y o.|.AXDXDXGXDXSXDXGXSXSXDXSXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXDXGXDXGXGXAX|.o.Y S b b b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b m b b ] 2.%XGXDXDXGXSXSXGXSXDXSXDXDXSXDXDXDXDXSXDXSXDXSXDXDXDXDXSXDXDXSXDXDXDXSXDXSXDXDXSXSXDXSXDXDXDXDXDXSXDXSXDXSXDXSXDXDXDXDXDXDXDXSXDXDXDXSXDXSXSXDXSXSXDXSXSXDXDX%X2.] b A b b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b b b m o.|.8XDXSXGXGXSXSXDXSXGXSXGXSXGXSXDXSXSXDXDXDXSXSXSXDXSXSXSXDXSXSXSXDXSXDXDXDXSXDXSXDXSXDXSXDXSXDXDXDXDXDXSXSXSXSXSXDXDXDXDXDXSXSXDXSXDXSXSXSXGXSXGXDXSXGXSXGXSXSXDXGXSX8X|.o.G b b b b b b b b b b b S b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b S b b b b b b b b S Y &. XAXSXSXSXSXSXGXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXDXSXSXDXSXSXSXDXSXSXDXSXSXDXSXSXSXSXSXSXSXDXSXDXDXSXDXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXGXSXDXGXDXGXSXGXAXGXSXSX X&.Y b S b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b B b Y &.XXAXAXGXGXAXSXAXSXSXSXAXSXSXAXSXSXSXSXSXSXGXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXDXSXSXSXSXSXSXDXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXSXAXSXSXSXAXAXSXAXAXSXSXAXAXSXGXSXXX&.Y S b b b b b b b b b S S UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b m Y &.XXGXAXAXAXAXAXAXAXAXAXAXGXAXAXAXAXAXSXAXSXAXAXSXAXSXSXSXSXSXwXSXSXSXSXSXSXSXSXSXSXSXSXwXSXSXSXSXSXSXSXSXSXSXSXwXSXSXSXSXSXSXSXSXSXSXSXSXSXAXAXSXSXAXAXAXSXAXAXSXAXSXAXSXAXAXAXAX8XAXAXAXAXGXAXAXXXo.Y S m S S b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b G o.|.SXAXAXAXAXAXGXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXSXSXSXSXSXwXSXSXSXSXSXSXSXSXwXSXSXwXSXSXwXSXSXSXSXSXwXSXSXSXSXwXSXSXSXSXSXwXSXSXSXwXwXSXSXSXwXSXSXSXwXSXAXSXAXAXAXAXAXAXAXAXAXAXAXAXAXGXGXAXAX8X8XAX8XGXGX|.o.Y S m b b b b b b b b S UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b b o.|.AXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAXAX7XAXAXAXAXwXAXAXAXwXSXwXSXSXwXSXwXwXSXwXSXwXSXSXwXSXSXwXSXwXSXwXSXwXSXSXwXwXSXSXwXSXSXwXwXSXwXSXSXSXwXAXSXwXwXAXSXwXSXSXwXAXAXSXwXAXAXAXAXAXAX8XAXAX8XAXAXAXAXAX8X7XAXGX|.o.b b b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b S ] w.7XAX6XxXAXAXAXAXxX9XAX9XxXAXAXAXAXAXAXAXAXAXAXAXAXwXSXAXwXSXwXSXSXwXSXSXSXwXSXwXSXSXwXSXSXwXSXwXSXSXwXSXSXSXSXwXSXSXSXwXSXSXwXSXSXSXSXSXSXwXSXwXSXwXSXSXAXAXSXAXAXAXAXAXAXAXAXAXAXAXAXAXqXAXAXAXAXAXAXAX8XAXAXAXAXGXAXw.] m b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b Y &.%XAXAX6XAXAXAXAXAXAXAXAXAXAXAXAX9XAXAXAXAXqXAXAXwXAXwXAXAXwXAXSXSXSXSXwXwXSXwXSXSXSXwXSXwXSXwXSXwXSXwXSXSXwXSXwXSXwXSXwXSXwXwXSXSXwXwXSXwXwXSXwXAXSXwXSXwXAXAXAXAXAXAXAXwXAXAXAXwXAXqXAXqXAXAXAXAXAXAXAX8X8XAX8XAX6XAX%XAXAX%Xo.Y b m S S m b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b b o.|.qXAX7X8XAX6XAXAX6XAX6XAXAX6XAXAX6XAXAXAX9XqXqXAXAXAXAXAXwXAXwXAXwXwXwXSXwXSXwXSXwXwXwXSXwXSXwXSXwXSXwXSXwXwXSXwXSXSXwXwXSXwXSXSXwXwXSXwXSXwXSXwXSXwXAXwXAXAXAXwXAXwXwXAXwXwXAXwXAXwX8XqXqXwX8XAXqXqX8XwX8XAXqXqXAXAX7XAXAXAXAXGXAX|.o.S m b m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b Y 2.,X8X8X7XqX8X8XAX6XAXAX6XAXAX9XAX6X6XAXAX9XwXAX9XAXAX9XwXAXAXwXwXAXwXwXwXSXwXwXwXSXwXSXwXSXwXwXwXSXwXSXSXwXwXwXwXwXSXwXwXwXwXwXwXwXSXSXSXwXSXwXwXwXwXSXAXwXwXAXwXAXqXqXAXwXAXAXAXwXAXwXAXqXqXqXqXqX8XqXwX8XqXwXwX8XqX8XAXAXAX6X%XAX6XAX7X%X2.Y b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b m o. XqX8X8XqX8X8XqX9X6XAXAX6XAX6X9XAX9XAXAX9XAX9XAX9XAX9XwXAXAXwXwXAXAXwXAXSXwXwXwXSXwXSXwXwXwXwXwXSXwXSXwXwXwXwXSXwXSXwXwXwXwXSXSXwXSXwXwXwXSXwXwXwXSXSXwXwXwXwXAXwXwXwXqXqXwXAXwXwXwXAXwXAXwX8XqXqXqXqXwXqXqXqX8XqXqXqXqXqX6XAX6X7XAXGXAX6X7XqXAX Xo.S S b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b Y 2.,X8X9X8X6X8XwX8X8X9X8X9X8XwX6XAX6XwXAX9X9X9XAXAX9XwX9XAXwXwXwXwXwXwX8XwXwXwXwXwXwXwXwXwXwXwXwXwXSXwXwXwXwXSXwXwXwXwXwXwXSXwXwXwXwXwXwXwXwXwXwXwXwXwXwXSXwXwXwXwXwXwXwXqXwXwX8XwXwXwXwXwXwX8XqXqX9XqXqXqX8XqXwX8XwXwX8X8X8XwX9XAX6X6XAX6X6XAX7XqX6XqX>X2.Y B b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b S ] 9.8X6X7X9X8X9X8X9X8X9X8X9X8XwX9X6XwXAX9X9XAXAX9X9XwXAX9XwXqXqX9XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX8XwXwXwXwX9XqXqX9X9XwXwXwXwX8XwX9XwX8X9X9XAX6XAXqX6XAX6X9X7X6X8X6X7X|.] b b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b b *..X6X6X6X6X6X8X9X9X9X8X9X9X9X8XwX8X6XAX6X9X9X9XwX9X9XwX9XwX9XwXwXwXwXwXwXwXwXwXwXqXwXwX0XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX9XwXwXwXwX9XwX9XwX9X9XwX8X9XwX8XwX9X9X6X9X9X9X6XAX9X8X9X6X6X6X8X8X.X*.b b S S b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b S b b b b Y 2.6X7X8X6X6X6X6X9X8X9X9X9X8X9X9XwX6X9X9X9X9X9XwX9X9X0XwX9XwX9XwX9XwX0XwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwXwX0XwXwXwXwXwXwXwX0XwXwXwXwXwXwX9XwX9XwXwX9XwXwX6X9XwX9X9X9X9X9X6XqX6X6X9X6X6X6X9X6X9X6X6X6X6X6X2.Y B b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b S m S Y w.6X6X6X6X6X6X9X6X9X9X9X6X9X6X3X9X9X9X9X9X9X9X9X9X9X9X9X6X9X9X0X9X0X0X9XwXwXwXwXwXwX0X0X0XwXwXwX0XwX0XwX0XwXwX0X0XwX0X0XwX0XwX0XwX0XwX0XwXwX0XwXwXwX0XwXwX0X0XwXwX0X0XwX0XwXwXwXwXwX0XwXwX0XwX0X4XwX9XwX9XwX0X9X0XwX9X9X9X9X9X9X9X9X9X9X9X,X9X9X9X9X6X9X9X9X6X9X9X6X6X6X,X6X|.] S b b b b A b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b S m b b m S ] XX6X6X6X,X6X6X,X6X9X,X6X9X6X6X9X9X6X9X9X9X9X9X9X9X9X0X9X0X9X0X0X9X0X9X0X9X4X9X4X9X0X0XwX0X0XwX0X0X0X0X0XwX0X0X0X0XwX0X0XwX0X0X0XwX0X0X0XwXwXwX0XwX0X0X0X0X0XwX0X0X0XwX0X0XwX0X4XwX4XwX0XwX4XwX0X0XwX9X0X9X0X9X9X0X9X9X9X9X9X0X9X9X9X9X9X9X9X9X9X9X9X,X9X9X6X6X6X6X6X6X,X6X6X7X%XXXo.b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b S S m S S o.%X6X,X6X,X6X3X9X,X9X6X,X6X3X6X3X3X9X3X6X3X9X9X9X9XwX9X3X9X9X0X9X4X9X9X9X0X0X9X4XwX4XwX4X4XwX0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0XwX0X0X0X0X0X0X4XwX4XwX4XwX0X0X9X0X0X0X4XwXwX4X4X0X0X4X9X4X9X9X4X9X3X9X3X9X6X3X3X9X9X,X3X,X9X,X9X9X6X,X6X6X9X,X,X6X7X,X%X&.A b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b m S S S o.6X,X,X,X,X,X,X6X,X6X,X3X,X3X6X3X6X3X6X3X3X9X9X&XwX0X&X0X9X4X9X9X0X9X4X4X0X0X3X4XwX4X9X4XwX4X4X0X0X4X0X0X0X4X0X0X0X0X0X0X0X0X0X0X0X0X0X4X0X0X0X0X4X0X0X0X0X0X4X0X0X4X0X0X0X0X0XwX4X0X4XwX3X4XwX4X0X4X9XwX4X3X3X9X9X9X4X4X9X3X4X9X4X9X4X9X9X3X3X9X3X9X3X9X9X9X,X5X,X9X,X3X,X,X,X7X%X,X,X,X%X2.S b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b S m Y &.%X7X%X%XAX%XAX%X,X,X3X3X,X3X,X3X3X3X,X3X,X3X3X3X3X3X3X3X3X3X3X3X0X3X3X3XwX4X3X3X4X4X4XwX4X4X4X4X4X0X0X4X0X0X4X0X4X0X4X0X4X0X4X4X0X4X0X4X4X4X0X4X4X4X0X4X4X4X0X4X4X4X4X0X4X0X4X4X4X0X4X4X0X0X4X0X4X4XwX3X4X4X4XwX4X4X4X4X3X4X4X9X3X3X4X3X3X3X3X3X3X,X,X3X,X3X,X3X3X,X,X,X3X,X,X,X6X,X,X,X7X%X6X2.Y S m S m b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m B &.6X6X%XAX%X%X6X,X6X,X5X5X,X3X,X3X3X,X3X,X3X5X3X3X3X3X3X3X3X4X4X3X4X4X3X0X3X4X3X4X4X6X4X4X3X4X3X4X9X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X0X4X0X4X4X0X4X4X0X4X4X0X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4XwX4X3XwX4X4X3X0X3X4X4X9X3X3X4X3X4X3X3X3X4X3X3X3X3X3X3X3X3X,X3X3X3X3X>X>X3X5X,X%X6X6X%X%XAX%X6X|.Y S S S m b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b Y &.%X6X%X%X%X6X6X%X%X6X5X,X,X5X,X5X5X5X5X5X3X3X3X3X3X3X3X3X2X3X3X3X3X3X4X3X3X2X4X4X2X3X4X4X4X4X4X4X3X4X3X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X4X3X3X4X3X4X3X4X5X4X5X5X4X4X3X3X3X2X3X3X3X5X3X3X2X3X5X3X5X3X3X3X>X>X>X3X>X>X>X&X,X,X%X%X%X7X%X%X{.Y S b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b G &.%X6X%X%X7X6X%X,X6X&X&X5X:X:X5X5X5X,X5X5X3X5X5X3XX>X2X5X5X5X5X:X9X,X%X9X6X%X&X6X%X%X|.Y b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m &.%X%X%X,X%X%X%X6X&X&X%X&X:X:XX%X%X6X&X%X%X9X&X6X:X2X5X:XX%X%X6X&X%X&X%X&X&X%X:X:XX%X%X&X6X&X&X&X6XX,X,X>X:X-X:X:X-X5X,X7X,X,X:X>X,X,X:X:X%X%X%X:X%X:X%X%X%X&X.X&X%X%X.X.X.X%X%X$X%X$X$X%X%XXXXX.X] A b A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A D Y 2.XXXX%XxXFXFXFXVXVXCXFXFXFXFXVXVXPXFXVXPXIXPXHXPXPXIXPXPXPXPXPXPXPXPXFXFXKXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXIXVXVXCXGXCXVXVXVXFXPXIXIXIXVXVXIXIXIXIXFXFXCXFXVXCXVXVXMXVXCXVXCXVXVXCXCXVXVXVXVXHXVXIXCXIXVXIXVXCXVXCXGXxXCXMXMXCXFXxXxXCXCXMXCXMXmXMXMXMXMXxXxXxXxXxXxXxXMXmXmXZXxXxXmXxXxXxXxXxXxXxXxXxXxXxXxX7X;XxXxXzX;X;X;X7X;X;XxXxXlX;X;X.XXXXX2.Y A A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A D D ] XXXXXX.X$X;XnXCXIXIXIXVXIXVXVXKXHXHXHXHXHXIXPXPXPXPXPXKXPXPXPXPXPXPXPXPXPXPXPXPXKXPXPXPXPXPXPXPXPXPXPXPXPXPXPXHXPXIXIXPXKXPXKXLXFXPXHXIXHXVXVXVXVXVXVXIXVXHXBXVXVXVXVXVXJXVXVXHXVXVXVXCXVXVXCXCXNXCXVXNXJXVXCXCXNXCXNXVXBXCXCXMXNXMXNXCXCXMXNXNXMXMXNXmXMXNXNXNXmXmXMXmXmXCXCXCXmXCXmXmXmXZXZXZXxXZXZXZXmXnXbXZXZXZXZXxXZXZXZXZXZXkXlXxXlX#XXXXX X Xo.A A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A G Y 8.XXXXXXXXXX.X$X#XlXmXCXIXPXKXKXFXKXKXKXPXPXHXPXVXPXKXPXPXKXPXPXPXPXPXPXPXPXPXKXKXPXPXPXPXPXPXPXPXPXPXLXPXPXKXLXKXKXLXKXIXHXKXKXKXKXHXHXHXHXPXKXVXIXVXIXVXKXHXVXVXVXVXVXCXBXVXVXVXVXCXIXVXVXNXVXCXHXCXHXNXNXBXVXVXCXNXNXBXbXmXmXBXmXNXMXmXmXNXMXMXBXMXmXmXNXMXMXmXmXmXMXMXmXmXmXmXmXZXmXmXZXZXZXzXZXZXZXZXkXzXZXkXZXZXZXkXkXkXkXlXlXgX;X;X{.XXXXXXXXXX2.Y S A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A A G ] XXX X X X X XXX.X$X'.#XlXMXFXLXKXIXKXKXKXPXPXKXPXHXIXKXKXPXPXPXIXIXPXPXPXKXPXPXKXKXPXPXPXKXPXPXPXPXLXPXLXLXKXKXPXPXFXPXPXKXKXKXKXPXPXPXHXIXHXIXVXHXIXVXKXPXHXVXVXVXVXVXVXVXHXNXNXVXVXVXJXNXNXCXCXHXNXNXVXCXNXNXNXCXNXNXmXBXmXNXMXmXMXMXmXMXMXMXmXbXbXMXmXmXMXbXbXmXMXZXbXbXbXZXbXmXcXZXbXcXcXcXZXZXZXzXkXcXkXkXkXkXkXlXkXkX;XgX`.(.I.].XXXXXX X|.|. X Xo.S A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b S S D D G 2. X XXX X X X X}. XXX;X'.'.'.;XkXCXPXPXPXPXIXPXKXKXKXPXPXPXKXPXPXPXPXPXPXKXKXPXPXKXPXKXKXKXKXPXPXPXIXKXPXPXPXKXPXKXPXPXPXKXPXKXPXPXHXPXPXIXIXIXHXKXKXKXFXVXKXHXVXHXJXKXBXVXCXVXVXVXCXHXCXNXVXCXHXNXCXVXCXCXCXCXNXNXNXNXNXmXmXBXMXNXmXMXmXmXMXZXMXbXbXcXNXmXmXZXMXZXZXmXZXZXbXZXmXZXZXbXcXZXcXZXkXkXZXcXkXkXkXkXkXjXlXvXzX;XuX].U.U.U.@X{.XX X X XXXXX X X2.G A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A S D G ] X X X X X X X X X X-XXX`.(.W.I.I.].gXxXmXZXCXmXMXmXMXmXmXNXNXNXNXNXVXCXBXBXBXBXVXVXBXJXHXHXVXVXCXJXJXJXJXVXJXVXBXBXBXMXNXNXNXVXVXVXHXJXNXVXJXVXVXBXBXBXVXBXBXBXBXBXBXBXBXBXBXNXNXCXNXNXJXNXNXNXNXNXNXNXCXNXNXNXmXmXmXcXmXMXbXnXbXmXmXmXcXZXkXzXzXZXzXcXZXZXZXkXkXZXkXzXkXzXkXkXkXlXkXkXkXkXkXkXlXlXlXhXjXlXjXkXlXZXkXdX'.].U.K.K.].@X|. X X X X X X X X X X] A A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b S A G G &. X X X|. X X X X}. X X X%X`.].W.I.U.L.I.Y.'.gXbXZXZXzXkXkXZXkXcXcXcXcXcXcXnXcXbXbXbXnXnXnXcXNXZXcXcXmXZXcXcXcXcXcXcXkXZXkXkXkXkXhXZXcXZXcXcXvXvXcXcXcXhXvXlXkXkXkXkXcXvXkXkXkXcXvXvXkXuXcXkXkXcXuXkXuXkXhXkXlXhXlXhXkXlXhXlXhXjXjXjXjXlXhXrX;XgXuXpXuXuXuXuXgXuXuX`.pXuXuXgX#X`.uX;XrXuX`.`.uXuXrX`.rXrXhXjXjXzXkXpXW.U.K.K.K.I.].{.XX X X X XXX|. X X|. X|.&.A A A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b D D J E |.|.|.|. X|.|.|. X X}. X X}.;X`.(.W.I.U.K.K.I.'.`.gXZXNXmXmXmXmXmXmXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXNXJXNXNXNXNXNXmXmXNXmXbXbXMXmXmXmXZXmXmXmXbXcXcXbXcXmXbXmXbXmXZXZXcXZXnXcXMXmXmXcXcXNXZXZXmXmXZXmXNXcXZXcXnXZXcXcXcXcXcXZXcXmXcXcXcXcXcXhXkXcXhXlXkXkXkXhXhXlXgXuXkXhXhXlXgXhXgXhXgXhXgXgXrXuXuXhXuXlXkXnXkXjX).K.K.K.K.K.U.K.@XXX+X X X+X+X|.|.|. X|.|.|.w.E D D b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A A D D A ] |.|.|.}.|.}.}.}. X X X0. X+X:X;X].W.W.U.U.K.S.U.(.I.I.;XNXMXMXMXBXNXMXVXCXVXVXMXMXBXVXCXVXIXIXCXHXHXFXVXVXFXVXVXVXVXFXFXBXJXMXNXVXMXVXBXMXFXVXMXBXVXFXMXmXBXNXMXMXBXMXNXMXmXmXCXmXNXNXCXNXCXNXMXNXNXNXMXMXMXMXNXNXmXMXMXmXMXMXbXmXmXmXbXmXbXbXbXmXcXbXZXZXbXzXbXZXkXkXZXkXkXkXkXkXkXzXlXzXkXlXkXlXlXkXmXmXcXkXhX'.S.S.K.K.K.U.W.].{. X X0.+X X+X}.}.|.}. X|.|.|.] D D b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A D D A 2.|.|.}.|.|.}.}.}.0. X+X X+X X}.$X;X(.(.I.U.S.S.S.I.(.U.K.I.;XFXxXZXnXzXzXkXxXzXxXbXMXMXmXxXmXmXZXmXmXMXMXMXMXMXMXNXBXMXxXxXnXbXMXbXbXnXMXnXnXxXZXmXbXnXnXMXZXMXxXbXxXMXbXmXxXxXMXNXmXMXNXMXMXFXMXNXMXMXMXMXxXxXnXbXMXMXMXbXbXMXxXMXmXbXMXbXMXbXbXbXMXMXbXbXMXbXMXZXZXZXZXMXmXZXZXZXzXzXzXzXzXlXzXbXMXMXbXnXzXlXrXW.K.K.S.U.U.W.].]. X+X X X X X}.|.|.}.|.|.|.|.|.2.D D D b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXA b b b b b A A A D D E 9.|.}.|.|.}.}.}.}.}.}.+X+X+X+X+XXX;X'.'.W.U.S.S.n.n.S.U.K.S.K.#XZXgX(.I.U.K.K.U.K.U.Y.U.I.I.I.W.W.I.I.I.R.I.(.!.Y.R.R.I.W.Q.U.I.U.Y.U.U.U.Y.L.U.U.U.K.P.U.U.K.L.U.U.K.U.K.K.I.I.I.'.#X].I.R.R.R.].W.R.R.W.Q.I.I.U.Y.I.!.I.I.R.I.Y.I.I.L.W.Y.U.Y.I.I.Y.Q.I.I.Q.I.Y.W.W.W.W.I.I.].I.U.U.U.U.U.I.I.].'.lX#X`.lXcXpXI.S.S.S.W.W.].W.'.;X X9.}.}.}.0. X}.}.}.}.|.|.|.|.|.E D D A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A A F D D O.|.|.|.|.}.}.}.}.}.9. X+X+X+X+X+X+X|.;X`.(.I.U.S.S.S.S.U.U.K.K.K.ZXNXgXR.K.n.n.S.S.S.S.S.S.U.S.S.S.K.S.K.L.K.K.U.K.K.S.K.S.D.K.K.S.K.D.C.C.N.n.n.n.n.b.n.n.n.m.m.c.m.m.n.m.n.m.n.S.U.'.].I.n.C.N.n.n.C.Z.S.m.n.n.n.n.n.n.n.n.S.S.C.n.Z.S.S.n.C.S.n.n.m.n.n.n.n.m.n.n.m.S.y.c.c.l.m.c.c.c.c.M.M.c.m.S.(.'.!.'.sX`.F.S.U.W.W.].W.(.;X|.9.}.+X+X+X}.}.}.9.|.|.}.}.|.9.|.o.D D D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b S S A A D F &.|.|.|.9.|.}.9.}.}.+X}.}.+X+X+X+X+X|.;XuX`.].I.K.K.S.S.K.].U.I.U.`.MXkXaX(.P.K.S.S.K.K.K.U.S.U.U.U.I.S.I.I.I.U.U.I.W.I.S.S.I.L.I.L.K.L.L.K.K.L.K.S.K.K.S.C.S.n.n.n.b.m.n.v.m.n.S.n.S.'.W.W.U.n.C.C.Z.S.S.S.S.S.S.S.S.S.L.S.K.L.I.S.S.E.L.S.S.S.L.S.S.S.L.K.K.S.C.C.S.Z.v.n.n.l.v.n.m.v.l.c.c.m.n.m.m.'.#X'.W.'.(.S.K.U.I.].'.uX`.XX}.+X0. X}.}.9.}.}.}.}.}.|.9.|.9.9.&.D D D N b b A b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b S F F A F Y 6.|.6.|.9.9.}.9.9.}.}.0.}.0.}.0.+X+X9.|.;XuX`.(.I.S.S.S.S.I.I.U.K.(.ZXzXgX`.).L.S.U.K.K.K.K.U.I.I.I.I.I.I.S.I.W.I.U.U.I.W.I.I.I.W.E.I.I.I.I.I.E.U.I.K.K.S.S.S.S.S.S.n.b.c.v.m.S.n.m.S.;X`.W.W.K.n.C.S.S.S.S.U.S.E.L.E.E.E.E.K.L.S.I.L.W.L.W.W.I.S.K.U.S.L.S.K.K.L.S.Z.Z.S.Z.n.n.n.l.v.c.c.l.m.n.m.m.m.'.lX`.I.(.I.U.U.I.W.'.`.uX$X9.0.+X+X+X0.}.0.}.9.}.9.9.9.|.9.|.|.6.Y D D F N N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A S D D D D ] |.6.9.}.9.|.+X}.+X9.}.+X9.+X0.+X+X0.0. X;X;XuX(.W.U.S.S.N.I.U.U.S.W.ZXMXkXpX(.).).W.W.(.].W.W.W.W.W.W.W.W.W.W.W.W.W.W.I.W.W.W.W.W.W.).W.W.R.).W.).W.W.W.W.W.W.I.S.S.S.n.n.C.n.S.m.c.U.gXuX(.E.W.rXeXtXtXuXtXuXuXrXuXuXuXuXuXuXuXuXuXuXuXuXuXuXuXhXuXuXuXrXuXuXrXrXrXuXuXrXuXuXW.yXW.W.I.L.L.S.n.m.c.m.'.kXgX(.(.W.S.W.].`.uXuX;X%X+X+X+X+X0.0.}.}.9.}.9.}.9.9.|.|.9.9.9.] F D D A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D D D F O.6.|.6.9.9.9.9.9.9.+X9.0.0.+X+X0.0.+X0.+X|.;XuX'.W.U.S.S.S.I.].U.S.W.bXMXzXgX_.rXuX).'.'.'.(.`.W.W.`.).`.rXtXuXrXrX).`.(.W.(.(.).).`.rXuXrXuXuXtXhXtXgXuXuXuXuXrX`.W.(.I.L.I.I.S.n.c.I.ZXhX`.I.~.cXcXcXNXcXZXZXZXcXZXmXmXmXmXNXNXNXJXNXNXJXmXJXHXBXNXJXNXNXNXmXCXNXNXNXNXuXNXZXZXmXmXuXuXrX`.W.S.m.c.c.'.kXgX'.'.S.I.W.].uXuXuX;X{.0.+X0.9.+X0.+X0.9.9.9.9.9.9.w.9.w.9.9.o.F D D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A A A D F F F &.9.9.9.9.9.9.9.9.9.9.0.9.0.0.0.0.0.0.0.0.9.;XlX`.(.I.K.D.N.P.!.U.K.I.nXMXbXjXrX`.uXuX`.`.`.).rXrXhXkXkXkXcXcXcXkXkXuXhXhXuXuXuXuXuXuXhXuXcXcXnXbXbXcXcXbXcXkXcXvXhXhXuX`.W.W.W.S.n.m.U.lXlXrXW.).kXmXZXmXmXmXZXmXZXZXcXZXmXmXmXcXnXNXJXJXbXJXBXBXBXBXNXBXVXBXmXmXZXmXZXCXNXMXMXbXbXkXlXhXrX`.).S.n.l.m.`.kXgX`.(.W.W.(.uXuXgXgX;X|.9.0.0.+X0.9.0.9.9.0.9.9.9.9.9.9.9.8.9.&.F A A D D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D F A F D J 3.w.9.6.9.6.9.9.8.0.9.9.0.0.0.0.0.0.0.+X0.9.$XlXrX`.W.L.K.C.I.(.W.K.W.bXMXNXvXtX`.gXhXhXhXuXuXjXcXNXNXHXNXCXNXNXNXNXNXbXcXcXZXkXcXcXcXNXNXNXJXBXBXJXNXBXNXCXBXNXNXbXcXcXuX`.W.W.S.S.m.I.kXkXgX).`.mXNXNXNXNXNXNXNXNXNXmXNXNXmXNXNXnXNXNXNXJXJXHXJXBXJXHXJXBXcXuX`.`.gXuXuXkXbXbXbXmXmXmXkXhXuX`.K.n.v.v.).kXpX).`.W.I.'.uXuXgXgX;X9.0.0.0.0.0.9.0.0.9.9.9.9.8.8.9.8.9.w.9.2.J F D D A A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b D D F D F H E 6.9.9.9.9.9.9.9.9.8.0.0.0.0.0.0.0.0.0.0.0.0.{.;XpX`.'.I.K.C.P.(.W.U.W.bXVXNXvXrXrXhXhXcXcXZXmXNXBXVXKXIXPXHXKXHXHXHXVXKXBXBXBXNXNXNXNXNXJXJXJXVXFXHXJXVXKXFXVXHXVXJXBXmXhXuX`.W.W.S.l.U.kXkXgX(.`.bXBXJXJXJXNXNXNXJXNXNXVXJXNXJXNXJXNXNXJXNXJXVXVXVXVXMXkX_.(.).rXgXkXkXkXpX(.(.gXjXbXBXbXkXgX`.I.Z.l.v.`.zXlX(.`.(.].`.;XuXgX;XXX0.0.0.0.0.0.0.9.0.8.0.9.9.9.9.8.w.8.6.9.9.E F F A A A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b D D A F D F ] 8.6.6.6.8.6.9.8.8.8.8.9.0.0.0.0.0.0.0.0.0.0.9.;XlX`.).I.K.N.K.'.W.U.R.kXBXNXcXuXrXkXkXcXNXmXJXJXFXKXKXHXVXVXNXNXbXbXNXMXMXVXVXHXCXCXIXHXNXbXvXjXpXpXuXaXkXMXVXKXPXKXKXBXNXkX).W.W.S.n.I.kXkXhX`.rXNXBXNXJXJXVXJXJXNXVXNXJXNXNXNXNXNXJXJXNXVXJXVXVXVXmXpXL.K.L.S.I.U.E.'.kXnXpXR.).jXzXMXNXkXhX`.L.n.l.v.'.zXgX`.uX`.(.`.gXtXuX;X X0.0.0.0.0.0.0.0.8.0.8.8.8.8.8.8.8.w.6.w.9.] F F A F D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b D D D D F F J ] 8.6.6.6.8.6.8.8.8.8.8.0.8.0.0.0.0.0.0.0.0.0.0.$XlXrX`.R.L.K.D.(.I.I.I.kXBXNXnXgXrXlXkXZXNXBXJXJXKXFXBXnXlX`.rX).).).`.eXpXkXMXFXFXFXBXkXrX!.R.R.R.W.W.W.W.).uXvXBXKXKXVXNXcXrXW.).U.n.(.kXzXgX`.`.mXVXNXVXIXNXJXNXHXNXJXNXJXJXJXNXJXNXVXVXHXBXJXBXmXeXL.L.S.K.E.~._.K.S.R.pXlX`.W.(.pXMXBXZXkXuXI.Z.v.c.(.zXlX`.'.'.(.rXaXhXgX;X|.0.0.0.7.0.7.8.8.8.8.8.8.8.8.w.8.6.6.6.6.6.] F A F A D D b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D D D F D F F *.6.6.6.8.6.8.8.8.8.8.8.0.8.0.q.0.7.7.0.0.0.0.|.@XrXrX`.(.L.K.L.(.!.I.I.lXBXNXvXaXrXhXZXcXJXBXVXVXbXlX'.(.E.I.R.).~.).).W.W.).rXlXnXsX).L.I.!.eXuXvXhXvXvXhXrX).).uXNXKXHXBXbXgX).W.S.m.R.zXzXgX`.uXNXJXHXIXHXHXHXNXCXJXNXJXJXNXNXJXNXJXVXVXBXBXBXNXlXI.H.U.R.`.lXkXmXcXW.S.L.R.!.lXlX#XMXVXmXcX`.U.n.l.c.].kXlX`.`.`.'.`.hXlXuX].9.7.0.0.0.0.8.7.0.7.8.8.8.6.8.6.6.8.8.6.6.6.O.F F F F D D b N A b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D F F F K =.6.6.6.6.8.6.6.q.q.8.q.q.7.7.q.0.0.7.0.0.0.7.0.{.;X;X`.(.I.D.P.(.(.P.I.sXBXNXvXaXrXhXcXbXJXNXbX#X!.K.C.K.R.rXhXvXcXvXvXhXtXR.R.!.T.L.C.K.rXcXNXJXJXHXHXHXJXNXZX).).rXbXKXmXcXuXW.W.S.n.R.zXkXgX).tXNXJXHXHXHXNXCXJXJXJXNXNXVXJXNXJXNXJXNXNXBXBXBXcX).U.D.I.).`.).kXbXBXZXeXL.Z.C.P.zXZXlXMXmXkXuXI.S.l.l.(.kXlX`.`.`.`.pXgXgX;X;X X0.7.0.7.7.7.7.0.7.8.7.8.8.8.8.8.6.6.6.6.6.*.F J F A D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D D F F F K &.6.3.6.6.3.q.q.q.q.q.q.q.q.0.7.7.7.7.7.7.7.7.7.|.;XrX`.~.P.K.K.(.W.P.I.jXFXNXzXhXpXlXnXbXNXcX(.P.n.v.S.W.`.hXjXhXvXhXvXcXcXsX).R.K.L.W.aXNXBXNXNXJXJXHXIXIXHXHXNX).(.aXBXBXZXgXW.W.S.n.I.zXkXgXrXaXBXVXJXHXJXHXHXHXHXNXJXVXNXNXNXNXNXNXNXbXNXNXNXjXW.K.K.I.L.R.W.(.kXmXNXNXhX~.Z.b.L.lXpXkXmXkXuXL.n.l.h.(.kXlX'.`.(.uXpXgX;X'.;X9.7.7.7.0.7.8.q.7.8.q.q.q.3.8.3.3.6.3.6.6.3.:.F F F A D D D N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D D F H F F K :.6.3.6.6.3.q.3.3.q.q.q.7.q.7.7.q.7.q.7.7.7.7.0.}.;XgXuX(.R.K.L.).(.I.L.vXBXNXcXhXuXcXkXZXZX'.S.n.m.S.W.`.uXjXjXcXcXcXvXhXvXsXjXhXhXhXhXjXkXkXkXvXnXbXmXJXHXHXKXHXvX).`.vXmXmXgX(.W.S.S.W.kXkXaXtXuXNXJXHXHXHXCXHXHXVXVXHXNXNXNXNXNXNXNXbXmXcXmXNXhXW.I.L.(.P.I.).W.'.bXBXVXMXnXrXK.C.R.gXpXbXbXuXK.Z.l.f.R.kXlX`.rX`.`.gXgXgXgX$X9.7.7.0.7.7.7.7.q.3.7.3.q.q.3.6.3.6.3.6.6.3.:.K D F F D D H A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D F H F K K 2.3.2.3.3.6.3.q.q.q.3.q.q.7.4.7.7.7.7.7.7.7.7.7.{.;XgXgX`.R.K.L.!.!.F.L.sXBXNXbXhXpXkXkXZX`.S.S.l.S.I.).uXkXbXbXbXbXcXcXvXsXaXaXrXhXgXpXpXpXpXuXgXgXpXkXcXVXHXVXKXVXuXW.uXmXZXgX(.(.S.m.I.zXlXpX`.rXmXJXHXNXIXHXHXVXHXHXHXJXNXHXHXNXNXNXNXNXNXNXNXZX).E.I.'.lX).I.R.(.kXMXMXMXMXbX_.S.R.uXrXkXbXgXI.S.l.M.!.zXlX`.rXpXpXgXgX;X`.{.7.7.7.7.7.7.7.q.7.7.3.q.3.q.q.3.3.3.6.6.3.3.2.K F J F D D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D A F F F K K K 3.2.3.3.3.3.q.3.3.q.q.4.q.4.q.7.7.7.7.7.7.5.7.7.{.uX;XuX`.R.K.L.~.I.L.K.pXMXmXcXhXgXkXkX;XK.n.v.n.S.W.`.hXNXNXNXNXmXmXcXvXvXhXuX`.`.).).).).'.).`.'.'.gXgXkXmXVXKXVXkX(.`.ZXcXpX(.W.S.v.I.lXkXhX).rXbXJXHXHXIXHXHXHXIXHXHXJXNXJXNXNXNXNXNXNXmXZXZXmXtXL.R.(.Q.I.R.L.I.gXdXgXlXzXzXkXU.S.`.rXlXnXrXR.C.g.f.].lXdX`.rXpX`.pXgXuXrX{.0.7.7.7.7.7.7.7.q.q.3.q.3.3.3.3.3.2.3.3.3.3.2.K F F F D D D D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D D F H F F K K 3.3.3.3.3.3.3.3.3.4.3.4.4.q.4.q.4.7.7.7.5.5.7.7.*XuXgXuX_./.L.D.!.R.I.L.pXMXBXbXhXrXhXcX).C.m.S.S.W.(.kXNXVXVXJXJXNXJXbXvXvXvXtXpXrX).eX).!.I.(.(.(.(.'.uXuXcXNXVXVXcX`.W.hXcXhX`.).S.V.I.lXvXuXrXtXcXJXNXIXHXIXHXHXHXIXHXHXJXJXJXNXJXNXNXNXNXNXmXNXbXeXK.L.F.I.R.C.N.K.I.'.`.`.rXlXI.S.).).pXvXpXI.n.f.f.Y.zXgX'.`.uX#XpXgXgXuX@X7.5.7.4.4.7.7.4.q.4.4.3.3.4.q.3.3.3.3.3.2.3.>.K F F F F D D D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b D D D F F D F K K K >.2.3.>.3.3.3.3.3.4.3.3.3.4.7.7.7.7.4.4.5.5.5.5.*X#XgXrX#X(.U.F.R.I.I.S.pXMXMXkXuXtXjXsXR.C.v.D.W.R.rXZXJXHXHXHXHXHXJXmXmXZXhXuXtXtXtX).~.R.W.R.I.W.W.'.W.`.hXbXNXBXbX_.I.uXvXtX).).S.V.U.zXzXpXrXuXmXNXJXPXKXKXIXHXPXHXHXHXHXJXCXJXJXVXJXNXNXNXNXbXBXjXF.C.E.L.K.~.N.n.I.I.(.uX'.'.K.N.!.).lXkXpXI.S.y.g.].lXgX`.'.uX`.pXpXuXrX@X8.5.5.7.4.5.4.7.4.4.3.4.3.4.3.3.3.3.3.3.2.3.3.F F K F F A D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D F D F F F K K L 3.3.3.2.3.3.3.4.4.7.4.4.7.4.<.4.<.7.4.4.5.5.<.5.9.;XkXrX'.!.P.U.!.!.U.U.pXMXMXcXuXrXhXeXL.C.c.R.).).uXNXHXKXHXHXHXHXHXJXNXZXcXcXhXrXrXrX).).W.(.W.W.(.(.(.`.pXcXNXBXbXW.S.).cXuX~.W.E.v.P.jXkXsXtXrXNXJXJXJXJXKXIXPXHXPXHXHXKXJXHXCXJXHXJXJXNXNXnXnXnXpXC.c.K.'.`.K.v.S.I.(.K.R.(.U.v.U.I.tXvXjX`.L.n.f.g.R.zXgX`.`.'.`.`.pXrX;X{.3.5.7.5.4.5.4.4.4.4.4.4.4.4.>.3.3.3.3.>.3.2.>.K K F K F F F D D A N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D F D D F F F J K K K &.3.3.3.3.3.>.3.3.>.>.4.<.4.<.7.<.7.<.7.5.5.<.5.8.;XlX;X`.!.U.L.I.R.U.S.rXNXmXkXhX`.uX(.C.Z.C.(.).).kXJXHXKXPXKXHXPXHXHXJXJXNXZXcXhXuXuX`.`.`.W.(.W.].(.(.'.rXpXhXrX`.I.Z.~.jXaX~.R.F.V.P.lXlXgXyXuXNXNXJXJXJXKXKXKXHXPXHXKXHXHXHXHXHXHXHXJXJXbXnXzXpXZ.c.c.C.K.`.`.m.n.P.).U.m.v.v.K.R.^.jXkXhXeXL.n.f.g.Y.lXdX(.`.`.`.#XgXrX`.{.4.7.<.<.7.<.4.4.3.>.4.4.4.3.3.>.3.>.3.2.>.2.2.K K F F F F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b D D D D H H K K K K J :.>.>.3.>.>.4.>.4.>.3.4.4.>.7.<.4.<.5.<.5.<.5.5.q.{.lXrX`.!.L.K.!.R.U.K.rXNXNXZXuX`.`.R.S.v.b.(.W.W.cXJXKXKXHXPXPXHXHXHXHXHXJXNXNXmXZXcXuXuX`.`.).W.(.`.(.`.aXjXtX).E.v.v.).cXaX).~.L.v.L.lXlXlXrXtXcXNXJXJXKXKXKXKXKXKXHXPXHXHXHXIXIXHXHXJXNXbXvXiXC.j.j.S.`.uXS.K.I.C.I.K.n.Z.Z.S.I.).jXlXlXjX`.P.v.f.g.R.zXdX'.'.`.`.`.gX`.'.*X7.<.4.5.<.7.<.4.4.4.4.3.>.>.4.3.>.3.>.>.3.>.:.K K K F F F D D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D D D D F F F K K L L :.>.3.3.>.3.3.>.4.4.4.>.4.>.4.4.4.<.<.5.<.<.5.5.q.$XgXrXeX!.P.I.].I.K.S.rXmXMXkXpX'.(.I.K.n.v.(.R.(.nXVXKXKXKXKXPXPXKXKXKXHXHXHXVXNXNXmXZXhXuXrXyX).eX).).`.rXvXnXnXaXL.Z.).nXpX!.R.L.c.L.lXlXgX(.uXmXCXCXIXHXHXHXHXKXKXKXKXKXKXKXPXHXHXVXNXmXkX`.D.j.c.U.`.uX(.S.l.Z.E.L.E.S.L.L.E.`.hXlXlXhXlXiXI.C.g.g.I.vXdX`.(.`.rXgXlXgX`.*X5.<.5.<.4.<.4.4.4.>.4.4.4.4.>.3.>.>.3.3.>.3.&.K K K K F H F D D D N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D D H H K K K K L L O.>.>.>.>.>.>.>.>.>.,.4.4.<.<.<.4.<.<.5.<.7.<.<.q.{.;XgXeX^.T.L.].I.S.S._.MXbXjXiX~.`.!.K.n.v.(.(.(.vXBXKXKXKXLXPXPXKXKXHXHXHXHXHXJXVXNXZXcXvXtXrX).rX).`.rXuXjXnXnXaXE.R.hXkXaX!.P.K.j.n.kXkXuX(.`.ZXCXNXIXVXVXmXVXFXIXKXKXKXKXIXVXVXVXBXNXlXI.v.d.j.F.`.lX'.S.S.`.hXuXeX).~.W.).pXhXjXjXjXsXsXpXT.v.s.a.I.zXdX'.).`.`.gXkXZX;X{.5.<.<.4.4.<.4.>.<.4.4.>.>.>.4.>.3.>.>.>.>.>.*.L K K F K H F F D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D D H H F K K L L L O.3.&.>.>.>.>.3.>.>.4.>.4.<.>.<.>.<.4.<.5.<.<.<.4. XgXrX#X(.P.P.I.I.S.C._.bXbXjXpX).(.~.I.S.M.U.].I.gXVXHXKXKXPXPXKXLXKXKXKXHXHXJXHXJXJXmXcXvXhXrXrX).`.`.rXsXzXnXvXtXK.I.pXzXhXR.I.C.j.j.F.`.rXW.`.ZXmXVXNXZXZXZXCXZXCXKXHXHXHXIXIXVXVXnXvX~.x.Z.Z.V.eXhX).S.S.`.hXZXmXmXcXhXjXkXkXkXhXvXkXjXjXeXR.V.s.d.I.zXdX_.).).`.lXzXZXzX|.<.<.<.<.<.<.<.<.<.<.<.<.>.>.>.>.>.>.>.&.>.:.{ L K K K F H H D D D N N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F H K F K K L L I ] >.3.>.>.>.>.>.<.>.4.,.>.<.<.<.<.<.<.<.<.5.<.<.>.$XlX;X`.!.P.K.I.K.S.m._.mXMXlXuX(.(.I.K.K.c.U.(.I.`.bXHXKXLXPXPXKXIXKXKXKXKXHXHXJXJXBXNXcXvXaXuXtXyXrX_.aXsXjXnXsXT.S.I.lXkXpXR.!.R.C.I.!.F.R.).rXmXBXVXNXZXZXVXCXZXZXVXKXKXHXFXVXHXmXcX_.v.j.F.).K.R.I.n.S.).uXcXmXcXcXhXlXlXkXhXhXkXjXvXhXsXiXR.Z.e.u.P.dXpX'.).(.(.pXlXnXbX{.<.<.<.<.<.<.<.<.>.>.<.<.>.>.>.>.>.>.>.>.>.2.{ L K K K K H H D D D D D b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D F F F F F K K L I I { :.:.>.>.>.>.,.>.,.>.<.<.>.<.<.<.<.;.<.<.<.<.;.7.$XkXpX^.~.H.D.U.K.n.m.).MXbXjX`.!.W.I.N.S.n.n.(.P.E.kXJXKXKXKXKXPXKXKXJXKXJXJXLXJXJXJXNXcXlXpXrXrXeXeXrXaXhXvXvX`.K.Z.`.kXlXrXR.!.L.j.T.nXaXQ.).rXNXVXNXHXHXIXPXVXZXCXKXKXKXVXKXBXBXkXW.n.l.c.c.C.W.I.S.S.W.`.hXkXlXhXuXhXgXgXhXhXkXjXvXkXhXhXeXP.C.y.e.G.sXpX`.W.W.'.#XaXzXzX$X4.<.<.<.<.<.,.<.<.>.<.>.4.,.>.>.,.>.>.>.&.>.] L L K K K F F F D D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D F H K K K K K I I R :.>.>.:.:.,.>.,.>.>.<.,.,.,.<.<.;.<.<.<.<.<.<.4.$XgXuX`./.F.D.P.K.n.m.'.MXmXjX`.).!.U.S.S.n.M.I.(.K.`.NXHXKXKXKXKXKXKXKXKXKXKXKXKXJXnXNXvXjXsXrXrX`.`.rXgXjXcXsXE.C.L.gXkXlXrXR.R.S.j.F.vXBXsX_.hXNXNXCXVXIXHXHXHXVXHXPXFXKXJXKXBXmXrXS.l.m.I.`.R.n.S.I.).uXuXhXaXhXgXuXhXpXuXhXhXhXvXvXvXjXaXpXR.Z.g.s.F.sXaX(.W.(.`.gXgXlXzX$X3.<.<.<.<.<.,.<.,.,.>.,.>.>.,.>.>.:.>.:.:.,.] I K K K K K F D F A D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D F D F K K K L L L I R :.:.:.,.:.1.>.:.,.>.,.,.<.;.<.<.<.<.<.;.<.<.<.>.@X;XuX_.!.L.D.U.K.c.c.).NXbXvXeXyX!.D.n.n.K.j.n.'.K.P.hXCXHXHXKXHXHXKXKXKXKXKXJXJXJXJXnXjXjXsXpXpX_.rXpXlXkXkX'.n.x.E.gXlXjXrXE.I.n.M.L.kXbXvXaXgXZXVXVXIXHXFXHXIXKXFXHXHXKXVXnXbXpXS.l.l.S.rX`.U.m.S.(.uXgXpXpXpXpXgXhXuXgXhXsXjXvXjXvXkXhXsX`.R.Z.y.y.L.gXuX(.W.(.).`.sXsXgX$X3.<.<.;.<.<.,.,.<.,.:.>.,.,.:.,.:.:.:.>.:.:.R I L K K K F F F F D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N N D D D F F F F K K K L I I I :.:.:.,.:.:.,.>.,.,.,.,.,.<.;.<.;.;.<.<.;.<.;.2.;X;XuX`.R.D.F.U.N.c.l.(.nXcXhXeX~.).K.n.n.n.c.f.I.(.D.!.nXBXKXHXKXPXKXKXKXKXKXKXJXJXJXcXvXjXgXpXtXtXrXhXlXkXgXF.z.Z.).vXzXdXiXR.I.n.f.K.jXjXhXrXrXmXNXVXVXHXHXIXIXVXKXHXHXVXBXbXlXL.j.l.W.uXrXI.n.I.`.uXgXpXgXgXrXgXgXuXuXgXhXhXhXvXvXvXvXvXpXrXR.C.y.y.U.kX;X(.W.(.`.pXaXpX#X@X3.;.;.<.,.,.,.,.,.,.1.,.,.,.:.:.:.,.:.:.>.O.U I I K K K F F F F D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b D D F F H F K K K I I I U I O.:.:.:.:.:.,.,.1.,.,.,.,.,.;.,.;.;.<.;.<.<.;.2.#XlXpX'.I.V.n.K.S.c.l.R.bXnXlX#X~.).L.n.m.m.S.g.c.(.K.H.#XnXFXBXKXKXKXPXKXKXHXHXJXNXmXbXvXhXsXpXrXrXaXhXzXaXI.n.c.R.sXjXjXsXiXR.L.n.f.C.gXlXpX(.`.ZXNXBXHXHXHXJXKXKXKXJXJXbXcXuXS.g.l.W.uX`.I.Z.R.`.uXgXhXgXuXrXgXgXhXuXhXuXhXuXkXcXvXnXvXjXsXrXR.Z.y.y.K.aXpX!.I.'.rXlXlX;X).[.>.,.<.;.,.;.,.,.,.,.,.1.,.:.,.1.>.,.:.:.:.{ U U L I K K K F H F D D D D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D F F F K K K I I I U U { =.:.1.:.1.:.1.1.1.1.1.1.;.,.<.;.;.<.;.;.;.<.2.@XlXpX`.!.V.b.S.n.M.f.Y.bXnXsX_.W.).R.n.l.m.m.c.u.N.I.n.F.iXMXJXKXFXKXHXKXKXHXVXJXNXmXkXhXhXhXuXrXgXgXkXsX^.D.j.S.).vXsXjXsX`.R.U.n.l.n.gXlX`.(.).cXCXVXHXHXHXJXKXKXJXJXbXvXS.f.y.f.I.`.uXL.n.W.`.uXuXhXhXaXtXrXpXsXhXvXjXjXvXZXvXcXNXcXvXhXhX).W.Z.y.e.P.lXpX~.R.'.pXkXzXlX].w.1.;.;.,.,.<.;.,.;.,.,.1.1.1.1.1.O.1.:.:.:.] P I U K I K K F F F D D D D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D F F F F L K K I I U U U R 1.1.=.:.1.=.1.;.1.1.1.;.1.;.;.;.,.;.;.;.<.;.>.@XlXaX`.!.D.n.K.m.f.f.!.nXnXzX`.R.`.R.K.c.c.z.v.f.a.N.D.b.J.jXJXJXKXFXHXHXJXVXJXNXmXZXkXlXhXgXgXgXhXkXlX_.F.j.x.T.sXsXsXsXpXiXI.K.v.g.D.pXhX`.(.'.bXNXVXJXHXJXHXKXHXBXNXvXI.f.y.y.K.#XuXS.S.W.rXhXgXpXaXtXtXiXaXpXsXsXvXvXvXcXcXbXnXbXnXcXhXpX).E.v.y. .U.sX#X).R._.#XjXzXvX`.*X;.;.<.;.;.;.;.;.,.1.1.,.1.1.1.1.:.O.,.:.=.R I I I L K K K F F F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D A D F F F K K K I I U U U ~ O.=.=.=.1.1.O.,.,.O.1.;.;.1.;.;.;.;.;.;.;.;.>.{.aXpX`.!.F.D.K.m.f.g.I.bXbXlX(.I.(.W.U.v.d.z.c.m.u.s c.m.z.Y.fXBXVXFXHXHXVXVXVXNXNXZXkXuXhXuXuXhXlXhXpXP.j.k.L.tXsXdXaXsXpX`.R.L.v.s.N.sXsX`.!.).cXMXBXVXJXKXHXJXHXVXcXR.f.a.I.U.N.W.S.n.W.uXaXrXpXpXtXaXaXaXaXaXhXhXvXjXvXcXbXbXbXnXbXcXlXpXtXR.l.y.e.P.dXpX(.(.).rXjXzXnXlX{.<.;.;.;.;.;.;.-.1.;.-.=.,.=.1.O.:.,.O.=.=.R P I I L I L K K H K F D D D b N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N N G D F F F F K K K L K I I U U Q { ;.,.O.O.1.,.1.1.O.1.;.-.;.;.;.;.;.;.;.;.;.>.@XgXpX`.R.F.D.D.v.f.g.I.nXnXsX).E.(.~.U.b.d.g.c.c.v.j .y.l.l.Y.lXMXFXBXKXKXBXBXNXNXcXkXhXgXaXgXsXlXdXQ.v.k.Z.).vXsXaXsXaXhX).I.K.v.g.C.gXaXrXR.).nXNXBXVXJXJXJXVXBXbXW.g.l.S.n.'.].c.l.R.gXhXpXrXrXeXiXiXaXaXuXuXhXkXvXcXjXcXbXNXbXNXbXvXlXpX_.R.l.y.r.U.dX#X(.W.(.`.hXnXbXbX].:.;.;.;.;.;.;.,.,.1.;.;.,.-.1.,.,.1.O.=.{ K I I I L L K K K F H D D D D N N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D A F F F F K K L I I I U U Q ] O.O.1.1.1.;.-.;.,.1.-.;.-.;.;.@.;.;.;.;.;.>.@XlXpX_.R.D.n.H.x.g.a.I.nXnXhX).R.(.I.P.D.z.d.a.M.l.M.%.r.l.c.h.P.lXMXBXJXJXBXBXBXNXcXbXcXlXjXkXsX#XY.x.e.z.R.rXhXrXtXhXvXrX`.L.S.v.a.D.lXaXeX~.).nXBXBXJXJXJXBXBXnX_.j.y.y.n.S.m.m.c.Z.rXsXpXrX_.eXeXtXtXaXaXvXcXvXcXcXcXbXbXbXNXNXbXnXcXhXpX).I.l.r.r.P.aX`.W.I.!.'.pXjXcXcX;X2.-.;.;.;.-.-.;.O.-.-.;.O.1.,.-.O.O.,.:.' L I I I I L K K K F F F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D F F F K K K K L U U U U U Q ' 1.;.O.-.-.O.;.O.;.-.-.;.;.;.+.;.;.;.;.;.;.>.'.lXpX_.T.V.b.N.c.s.a.I.cXbXaX).E.).(.U.F.m.f.d a.m.c.j.d j f.f.z.!.jXnXFXBXJXVXBXNXNXbXcXkXkXjXpXQ.b.i.k.K.pXgXrXrXrXhXhXgX).K.S.l.s.K.hXaX`.E.).vXnXnXFXBXFXBXcX).l.s.v.n.z.v.M.e.z.!.aXaXtX~.eX).eXrXrXtXaXvXvXcXcXcXcXbXNXbXNXNXNXnXkXlXrX_.I.c.j y.K.gX`.I.R.(.(.`.lXkXZXgX2.;.-.;.-.-.-.O.;.;.;.O.;.-.O.;.O.;.O.=.T P P U U I L K K F K F F H D D D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D H K F K K L L I U U U U Q U { O.;.;.O.;.;.O.;.-.-.-.@.;.;.;.@.;.;.@.;.2.@XlXpX_.R.D.n.D.z.u.u.L.vXnXsX).R._.).Q.F.n.z.g.d g.c.c.j.d y.s.f.z.L.sXnXBXBXBXVXBXNXNXbXnXkXpX~.C.s.d.C.pXsX`.'.tXrXhXvXsX).L.C.c.y.D.sXpX).I.(.vXnXNXMXBXNXcX).l.y.f.L.'.R.a.s.j.P.lXsXpXeX).)._.).uXtXhXtXhXvXcXbXcXmXNXNXNXnXcXbXcXjXhXrXrXE.v.y.s K.pXiX(.R.R.~.`.lXkXZXkXw.;.-.-.-.;.;.-.-.O.;.;.O.;.;.O.;.O.1.{ W P P U U I L L K K F H F D D D N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N A D D D F F F F L K L L I U U P W P W ' =.=.=.+.=.=.-.-.-.-.-.-.-.-.-.-.;.;.;.;.>.@XlXgXeXE.C.b.n.f.u.s.L.zXnXsX~.T._.).~.P.C.v.z.d.p d.M.M.c.d y u.s.a.H.dXnXMXCXMXFXBXnXnXnXsX!.C.y.y.v.^.sX`._.).eXrXhXjXaX_.F.b.j.y.D.dXpX'.P.~.kXbXZXMXNXkXtXA.k.y.b.(.L.l.a.d.c.n.W.lXdXpX`.~.'.`.rXrXpXlXjXcXmXcXmXmXmXNXNXmXbXbXvXvXhXtX`.E.c.e.s K.pX#XQ.T.Q.(.).pXkXcXgXw.-.-.;.+.;.;.+.;.+.1.=.=.=.+.=.=.=.O.' P P P U I I L K K K F F F F F A A A b b A b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F H F F K K L L I I U U P W Q R { +.=.=.+.=.=.+.=.+.@.-.-.-.;.@.@.;.@.;.&.@XlXgX).E.n.c.m.s.a.a.K.cXvXdX~.J._.`.^.!.F.V.z.d.e.s g.M.z.h.e.p e.s.d.b.`.zXMXFXBXnXzXzX#X!.b.s.e.f.!.hX'.(.!.).).rXsXhXtX~.D.C.g.e.n.aXiX^.L.P.lXzXnXzXlX~.k.e.y.Z.R.C.f.g.f.s.f.l.m.'.zXjXsXpXrX`.rXtXpXaXkXcXkXmXmXmXmXcXmXbXmXbXvXvXdXeXyXL.c.d d K.iX_.Q.I.!.R.).pXlXkXuX2.-.-.@.;.@.+.;.+.-.+.=.+.+.=.=.+.=.{ R Q Q U P I I U L L K F K F D D F A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b D D D D D H F K F K L L I U U U P P Q Q { =.=.+.+.=.+.=.+.-.@.-.;.@.@.-.;.@.;.@.&.].;X`.(.I.n.j.b.f.r.s C.jXkXgX~.T._.iX)./.T.D.S.f.s.e.s a.m.c.z.u.p r.d.g.c./.dXnXnXjXsX'.R.v.e.d j.Q.gX'.(.(.R.).`.rXsXhXrX!.S.C.f.y.n.aXdX^.F.I.gXjX;X#XI.i.r.y.S.W.S.y.a.l.j.j.f.f.m.Y./.aXlXsXsXpXpXsXsXaXjXkXcXcXcXmXmXcXZXZXcXvXcXjXdXeXeXL.c.d a D.iX_.P.L.Q.!.(.`.pXlX;X2.@.;.;.;.@.;.-.+.+.-.+.=.+.=.+.=.{ { Q Q P P P I I U L K K K F H D D A D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F K F F L K L L I U U U W Q Q Q R +.+.=.=.+.-.+.-.+.-.+.@.-.-.@.@.;.@.;.2.@XuXuX!.U.m.j.c.f.u.e.C.lXkXrX!.P._.tX`.).R.I.S.n.g.a.s i .b.H.z.s.s a d.d.h.G.^.`.^.R.D.k.e.p c.eXpX~.I.I.!.~.R.rXrXhXlXrXW.C.n.g.r.n.pXpX'.F.I.`.#X/.n.y.r.y.m.W.L.g.a.g.l.z.b.c.c.z.z.z.K.'.sXkXlXlXhXhXsXjXjXkXcXvXcXvXcXkXkXcXjXhXsXiXtX).L.z.a d D.iX^.L.L.U.W.(.`.pXlX;X2.;.@.@.@.;.@.-.+.-.+.=.+.=.+.=.+.=.R W Q P P P I I I L K K K F F K D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F H F K K L L I I I P P P P W ~ ~ { =.+.{ =.+.-.+.+.;.@.@.@.@.;.;.@.@.@.*.@XgX`.!.P.b.f.c.g. .s b.lXjXtX~.I.rXpXrX_.).E.K.S.c.g.y.y.t p b.H.v.d.d d g.j.h.b.F.H.v.y.r.r.z._.pX'.U.L.R.R.R.!.yX`.aXhXrXR.n.b.s.a N.sXaX~.P.F.).U.f.t d j m.Q.n.y.s g.j.j.j.m.m.b.v.z.c.c.C.(.pXzXfXjXjXvXsXsXsXjXhXhXjXjXsXvXhXjXsXiXtXeX~.F.z.r.y H.#X).I.K.I.I.).`.`.;X@X2.@.;.@.;.+.;.+.+.+.+.=.{ =.=.#.=.{ W W P P I P I I I L K K K F F F D D D D b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D D F F F K K K L I I I P P W W W W Q ' { =.=.+.+.+.+.+.@.+.;.@.@.@.@.@.;.@.-.{.gX`.(.K.b.d.z.d.s d v.hXfXdX~.I._.aXpX).).W.E.U.S.c.l.y.y.d a c.L.n.f.y.j g.f.u.z.z.y.r.y.Z.yXpX).E.I.I.I.I.R.~._.rXjXjX`.I.b.m.a.u b.iXiX~.G.C.I.j.d t i m.K.n.%.r.g.g.c.v.u.s.z.v.V.a.g.D.K.K.L.'.sXjXjXsXtXaXaXpXtXhXhXsXsXdXsXsXtXeX^.~.!.F.z.p i m.`.'.I.U.U.I.(.'.`.gX#X>.@.;.@.@.@.@.+.+.+.+.+.+.+.+.#.#.' W W W ~ P P I I I K L K F F F H D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D D D F H F K K K L I P P P P P W W W Q / { =.{ -.+.+.+.+.@.+.@.@.@.;.@.;.@.@.=.{.;X'.Q.D.c.f.c.d.d i n.aXvXpX~.E.tXlXsXrX).~.~.R.L.S.Z.m.l.g.e.d a.K.S.c.g.t p d p s r.i.F.`.pX).I.I.R.P.P.R.!.~._.iXjXjXeXL.x.c.a.i b.iXrX~.K.C.C.e.g.S.f.M.y.y.y.v.m.f.f.n.V.i.e.j.c.l.j.k.V.I.D.U.gXlXlXaXhXrXiXeXtXiXiXpXpXiXdXpXiX`._.~.Q.D.f.p t n.`.'.T.F.L.P.W.`.`.`.@X>.@.@.@.;.@.+.+.@.+.+.+.+.=.#.#.{ ! W W W P P P P I I L L K K K H F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F F F F K K K L I I P P P W W W W Q Q ' { +.{ +.+.+.@.@.@.;.@.@.@.@.-.@.@.&.Y.gX'.!.K.z.f.b.f. .d n.lXjXeX~.R.tXvXlXpXtX).~.W.W.I.S.S.S.n.m.f.y.y.K.I.n.k.y.d d s.V.T.aXtXR.I.I.P.P.P.Q.I.~.^.iXsXjXlX_.C.c.c.e.i c.`.pX(.S.n.N.e.d.(.(.g.t q l.l.n.K.n.c.v.V.k.i a.v.x.j.D.F.N.'.`.rXpXrXrX_.^.#X_.`.eXeXtXtXtXpX`.`.'.^.Q.D.f.t t m.#X'.P.K.I.P.(.).`.uX@X&.+.@.@.@.@.;.@.+.+.+.+.#.#.#.=.R W W W W P W P P I I L K K K F K F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A F A D K F F K F L L I I U P P P W Q W Q ^ ^ { +.{ +.+.+.@.@.+.@.@.@.@.@.@.@.@.*.{.uX`.W.K.M.M.c.s.s i c.;XhXeX~.R.hXcXcXhXrXrX`.).).W.R.R.E.E.Z.F.Z.A.j.Z.T.F.v.V.V.E.rXhXeXT.G.T.E.L.P.T.Q.!.~.^.iXsXjXhXrXK.l.f.d e c.rX_./.C.b.D.s.t j.b.k.r.r.e.k.V.b.b.V.b.v.C.z.u.d.k.Z.L.n.I.`.`.`.`.).).).).).^._._.)._._.rXrX`.).).!.T.C.k.t t c.`.'.W.I.I.I.Q.~.).uX@X:.@.@.@.@.@.@.@.@.#.#.#.#.#.#.{ ~ W W W W W P P U I I L K K K F F F D F A D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D F F F K K K K L I I P P W W W Q W Q ^ W ' { +.+.{ @.@.@.@.@.@.@.@.@.@.@.@.=.*XuX'.].n.M.f.c.d.a t c.pXlXrXR.R.hXcXcXkXuXuXrXrX`.).).~.~.).yXyXyXE.T.F.J.yX~.~.rXaXaX'.!.!.T.R.R.E.T.E.!.~.).eXpXdXsXvX`.I.l.l.d q c.`.#X!.C.b.P.m.y.r.s.k.Z.~.E.Z.z.d.s.F.D.i.s.b.D.V.k.j.x.L.`._.).^.~.~.~.).~.).).~.^.~.).^.).'._.).(.!.I.V.y.r q m.`.].I.W.E.G.Q.~.rX;X@X1.@.@.@.@.@.@.@.@.#.#.#.{ #.#.' ~ ~ W W W P W P U U I L L K F K F F F D D A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A A A F F F F K L L L I I P I W W W Q W ~ ~ ! ^ [ { #.@.#.@.+.@.@.@.' @.@.@.@.@.=.{.gX'.I.D.j.g.c.g.s i z.pXlX`.R.I.fXnXnXbXbXjXhXrXtXaXeXeXtXeXyXyXyXtXeXeX).eXaXaXrX`.).).).).(.W.).!.R.R.(.)._.eXpXsXvXvXrXK.j.g.d w j.`.#XY.n.v.T.Q.v.v.E.~.tXsXsXsX~.Z.j.Z.F.b.v.n.D.F.V.b.K.].(.!.!.!.R.W.R.].(.).~.~.~.(.(.).(.`.'.~.!.R.W.Z.e.r w m.`.].I.E.I.L.Q.^.uXuX{.1.@.@.@.@.@.@.@.@.#.#.#.#.{ { ~ ~ ~ W W W P P P U U I L L F K K F F D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A A F F F F F K L L L L I I P P W W Q W ~ ^ ^ ^ ' { { { #.#.@.@.@.@.@.@.@.@.@.@.*.Y.#X/.Q.n.z.a.z.d.s p j.pXdX#XQ.P.iXnXnXNXbXcXvXhXsXaXaXaXaXaXiXaXaXtXrXuXaXaXpXrX).).`.`.`.rX`.`.).~.).).).rXtXpXdXjXvXsX).D.g.a.t 8 f.'./.L.n.m.~.^.~.).rXiXhXsXsXvXsX~.f.g.C.P.L.F.L.D.n.F.L.I.U.U.I.L.L.R.R.(.).'._.).eX)._.(.(.(.^./.R.I.E.n.y.0 8 M.;X'.U.W.I.K.!.).uXuX{.=.@.@.@.@.@.@.#.@.#.#.{ #.{ ' ~ ~ ~ ~ W W W W P U I I L L K L F F F F A D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A A D F F F K K K L P L U U P W W W W ! Q ^ ^ ^ ^ ' #.{ #.@.@.@.@.@.@.@.@.@.@.@.*.[.`.~.Y.n.j.a.z.s.r.p l.pXdX_.P.D.).jXnXbXNXnXnXnXnXfXvXsXsXvXsXvXvXaXkXjXhXkXsXaX`.rXrXrX`.uXrXrX`.`.rX`.`.rXaXpXsXjXjXiXQ.v.e.s t 8 h.'.^.L.z.m.(.'.'.#X#XdXsXjXvXfXvXaXR.j.a.n.P.K.V.b.D.L.I.U.U.U.I.L.R.!.~.^.`.pXaXsXtXhXuXuX`.).^.^.Q.E.W.c.d 8 w M.`.'.U.P.U.U.!.).rXgX@X&.#.@.@.' @.@.@.@.#.#.#.{ ' ^ ^ ^ ! ! W W P P P U I I L L K K F K H D D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F H K F K K L L L U U P P P W W W ~ ! ~ ^ ^ ' [ { @.#.@.@.#.[ @.@.@.@.` @.*.[.;X'.P.n.d.d.s.d.s e f.`.iX/.F.m.L.`.hXvXzXvXvXvXfXfXfXsXsXvXvXsXsXvXvXhXjXlXgXpXuXuXuX`.rX`.pXpXiXdXpXrXpXtXsXhXsXdXdX'.K.z.p q 0 8 f.'./.L.f.z.I.Q.Q.Q.Y./.^.`.tXaXaXaXpX).m.y.f.c.v.D.I.I.P.L.S.I.E.~._.eXrXpXsXjXvXnXmXcXkXgXuXrXiX`.^./.I.f.e 8 4 l.'.].I.Q.U.D.!.).#XgX@X2.#.@.@.@.@.@.@.' ' @.{ [ / ~ ~ ^ Q W W W P W P P I I L L K K F K H F D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D D D H F K K K K L L I U P P W W W W ~ ! ^ ^ ^ ^ ' { ' #.[ ' @.@.@.@.@.@.@.@.*.[.;X].P.n.z.s.d.s.y.i d.^.iXQ.C.j.K.(.'.`.rXpXiXiXiXiXaXaXiXiXeXiXiXaXrXrXrX`.#XrX).).).).rX`.`.iX_.#X`.).yXeX).).)./.Q.F.n.f.e 0 8 4 f.'.~.K.s.z.!.L.F.I.E.R.I.!.~.~._._.`.).(.C.f.n.I.!.Q.!.!.!.R.(._.eXpXlXkXkXzXzXvXzXvXkXlXlXgXaXpXeX_.~.F.u 0 2 2 M.`.Y.U.K.K.U.Y.(.#XgX].*.@.@.@.@.' @.[ #.@.#.#.' ^ ^ ^ ~ ~ W Q W W P P P I I L L K K K F H D D D D A b A b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F H K F K K L L L U U P W P W W W ~ ! ~ ^ ! ^ ( ' @.@.[ @.' @.@.' @.@.@.@.#.[.uX`.Q.D.j.u.f.s.e.i s.'.^.Q.D.K.).R.E.R.R.!.~.Q.~.!.~.R.~.T.E.~.~.~.~.E.E.I.I.I.I.S.S.L.L.E.T.P.T.J.T.J.E.L.F.C.C.V.z.f.f.a.s t 8 4 d.].Y.C.u.p.G.F.D.L.K.S.S.K.L.L.F.F.F.L.D.L.K.S.K.K.L.I.E.P.T.!.!././.).(.(.(.Q.Q.Q.P.R.Y.L.K.L.D.V.x.x.z.r 6 2 2 M.`.'.K.N.K.K.R.^.`.gX{.#.@.@.' @.@.#.[ #.[ [ ' ^ ^ ^ ^ ~ ^ W Q W W P P P I L L L K L F F H F D D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D A K F F K K L I I I I P P W W Q W ~ ~ ^ ~ ^ / ) ) ' @.' @.` @.@.` [ @.[ @.#.{.#X'.T.V.k.y.j.s.s q a.(.R.L.T.pX'./.).~._.#X_._._.).)._.'.'._.#X_.)._.).~.~.~.~.~./.Q.~.~.Q.Q.Q./.^.Q.T.Q.].R.L.L.F.F.C.m.c.j.j.p 6 ./.P.c.d.z.D.L.P.P.Y.I.I.I.I.I.K.I.L.E.L.P.R.L.I.E.P.U.I.L.L.E.J.H.J.G.F.F.P.F.F.D.F.C.n.C.b.b.v.x.z.j.j.j.e < 1 M.`./.P.U.K.U.U.~.#XgX@X*.[ @.[ [ @.[ [ #.[ ' ) ^ ^ ^ ^ ! ~ ~ W W P P P U I I U L K K F F K D D D A A A A b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D D F H F K K K L L I P P P P W W Q ! ~ ^ ~ ^ ^ ) ) Q _ ' @.@.@.@.@.@.[ [ @.[ #.*X#X^.E.V.s.k.l.s.y.q .I.E.E./.'.'.#X#XdXdXdXlXsXgX;XlXlXjXfXjXjXsXsXlXaXgXdXpXpXpXpXaXsXiXdXaXiXpXaXpXiX#X#X`.`.^.^.!.P.I.H.m.l.j.s i.G.V.b.n.C.P./.^./.`.pX`.`.`.#X`.`.`.rXiX#X#XeX_.`.dX#X#XrXeX_.#X#XyXyXyXyX_.^.).^.~.(.Q.J.P.P.L.L.K.D.b.v.c.q w z.'.^.P.P.K.K.Y.Y.#XpX@X*.[ [ [ @.#.[ ' @.[ _ ^ / ^ ^ ^ ! ~ W W W W W P P U I L K K K K F H F F D A A b A b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D F D F H H F K L L L I I P P W W W W W ~ ! ^ ^ ^ ^ ) ) _ _ @.' @.@.@.@.[ [ [ @.{ [.`.~.P.C.j.s.m.s.j q %.E.rXR.Y.Q.!.'.#X#X#XdXdXgXdXlXlXdXfXzXvXfXzXzXkXjXdXzXzXdXzXzXzXfXfXfXfXsXlXdXsXdXdXfXdX#X#X#X#X/./.Y.U.N.N.N.N.H.N.H.D.H.P.P.Q./.'.#X#X#X#X#X#X#XdXpX#XfX#XdXdXdX#X#X#X#XdX#X#XfXdXdXpXdXdXdXdX#X#X#X#X#X#X/./.^./.Y.Y.H.D.j.y x._./.D.D.D.K.I.(.`.;X@X#.[ [ [ [ [ [ [ [ / ( ( ^ Q ^ ~ ^ ~ ~ W W P P P I I I L K K K K F H F D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D A F H K F K K L L I U P P P P W W W ~ ~ ^ ^ ^ ) ^ ) _ _ _ @.@.` ` @.@.[ [ [ *.U.#X~.I.v.g.a.c.g.j j r.y.y.r.%.s s a.d.i.h.h.M.N.b.x.x.N.N.N.H.N.H.D.N.N.N.N.N.N.n.C.N.b.b.N.H.n.b.v.N.x.x.x.z.h.z.z.h.i. . . . . . .h.d. .u a s a i . .a.g.d.h.h.h.M.h.M.m.m.b.N.z.z.c.N.x.N.x.N.x.x.b.b.b.x.N.x.h.N.m.c.x.x.h.h.z.h.h.h.h.h.d.a.a.a z.#X~.K.S.S.n.L.).`.uX{.{ [ [ [ [ [ [ [ ' ( ^ ^ ) ) ^ ^ ~ ~ ~ W ~ ~ P P P U I U L K K F F H D D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D F F F K K K L L I U I P W P W W W ~ ~ ! ^ Q ( ) ^ / ( _ ' @.@.` @.' @.' @.*.K.`./.E.v.s.s c.g.s f j y.8 : - * * = 3 < > < < < : ; 2 > < 2 2 6 2 2 2 , , , ; ; : : < , > ; < ; ; = > & & > = = = - * & $ $ * # - , q h.q - * * * % * * * * & & ; * & , = ; - ; > = = > , = > > - > - ; ; ; - - - & & & = * - * - - * * & % % * * * 3 h./.Q.K.n.S.C.P.~.#XaX{.*.[ [ [ [ [ [ ' _ ) / ) ^ ^ ^ ^ ^ Q W W P P W P I U L L L L K K F F F D D D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D F D F K K K L L I I U P P P W W W ! ! ! ! ) ( ) ) _ _ _ _ ' ' @.' @.' ` @.] [.`./.L.v.a.d f. .d f t l.r.8 7 2 < 2 1 1 1 < : 8 6 7 9 1 1 2 6 8 w 2 2 1 7 2 < 4 2 : : : ; < ; : < = * , & & = - = * - $ % % # * ; = r x.i.e < , ; - = - ; ; 3 & : ; : ; ; : , , < , ; = , ; > & & * ; * ; * & - * - & * = * * * @ % $ % % # o o % 3 3 h.@XJ.N.n.n.D.P.~.#X#X[.*.[ [ [ [ [ ' _ _ ( ^ ) ( ^ ^ W Q ) W W W P ~ P P U I L L F K F F F F D D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D D F H F K K K L L U P P P W W W W ~ ^ ! ^ ) Q ^ ) ( ( _ _ ` @.` @.@.` @.@.#.[.#X~.L.m.a.j f.g. .q r.x.r.r 6 0 0 0 8 8 0 r 8 r r t e t y p p t t t t r r r t 0 0 8 8 w 0 7 2 < : 8 : 8 2 , 7 - - ; ; & & % * - ; * q N.d.d e 6 7 6 1 2 2 2 : : 2 4 1 8 2 6 4 1 4 6 8 6 1 8 6 6 5 1 7 2 : 7 2 2 < < , , ; - - $ > - & * % % o $ % & 3 h./.Y.D.n.D.n.P./.#X#X@X*.[ [ [ ' [ _ ( ` ( ( ^ Q ^ ^ ( ! ^ W ~ P W P P P I I L L K K F F D F D D A b b b b b A UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D H F F F K K L L L I P P P P W W W ~ ~ ! ^ Q ) ^ ) ( ( ( _ ` ` @.` @.@.` @.#.*X'.Y.I.m.s s f.d.u.r p Z.x.r.r r e t t r r p r.r.y.r.y.r.e.e.y.e.r.e.e.r.r.r.r.d t t q r t r r t r r r 0 r r r r 0 0 8 1 < > ; ; & # q H.z.a p e 6 6 6 6 7 1 1 8 6 6 8 6 8 0 8 8 0 9 0 0 w 4 8 0 9 9 6 8 6 6 6 7 9 6 2 7 7 < < > < - & - * & % & & % & h./.Y.H.b.V.N.F.(.'.#X@X] [ [ ' [ _ ` ( ( ( Q ( ^ ^ ^ W ^ W Q W W P P P I I I L K K K F F F D D A A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D D F F H K K K L L U U U P W W W W ! ^ ~ ^ ! ^ ^ ) ^ ( ( _ ` ` _ [ [ [ [ ' @.w.#XY.F.v.u.p z.d.u.u a H.H.d.r a x.F.L.F.S.E.E.W.R.R.E.I.L.E.E.E.E.E.E.E.L.Z.Z.V.V.Z.Z.v.Z.Z.Z.Z.Z.Z.Z.Z.F.F.Z.F.F.F.V.j.e.t 8 7 & * y P.N.u.e e t e y y y u t.r.r.r.r.s.k.s.k.s.i.i.e.y.y.a.y.j y.j e.e.u.y.e.d r.s p p p t t t r 0 8 8 2 w 4 3 * * : M.'./.V.b.b.n.S.].].`.{.#.[ [ ' ` _ _ _ ( ^ ( ^ Q ) ^ ^ ^ W W W W W P P U U I L K K K F K F D F D N N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D D D F F K K K L L L I U P W P W W W W ! ! ^ ^ ^ ^ ) ( ( ( ` _ ` ` ` ' [ ' @.#.$.].R.D.z.s.p k.i.a e s P.P.x.e.d.E.eXhXvXvXvXhXhXvXhXaXsXhXhXhXhXvXfXhXuXhXgXtXaXW.).).~.yXW.E.yXyXtXtXtXiXtXtXtXtXtXeXT.F.k.r 6 : & y G.U.d.i i k.k.j.k.j.z.z.c.v.A.Z.Z.Z.C.Z.L.Z.C.Z.Z.S.C.S.n.v.v.n.n.C.n.S.C.C.D.Z.v.v.v.l.j.k.s.e.i q w q : 3 # : v./.Y.D.V.V.b.K.I.'.;X*X{ [ ' ` ` _ _ _ ( ^ ( ( ( ^ ^ W ~ W W W W P P P P K I L L K K F F F D N D D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b A b D D D D H F K K K L L I I I U P W W W ! ~ ~ ^ ^ Q ( ) ( ( ( ( ( _ ` ` ' [ [ ' #.$.`.W.K.c.y.i s.a.d w d U.!.F.k.j.yXsXnXnXnXNXmXmXNXnXnXcXcXbXNXbXNXMXvXtXhXnXjXsXaXrXpXiXaXaXtXvXvXvXbXNXcXcXcXmXNXNXvXtX~.C.p 8 : * i U.U.m.p p v.V.C.C.D.D.D.F.G.L.R.E.!.!.~.).(.(.~.R.E.E.E.E.S.E.I.I.I.R.!.).!.~.!.L.L.I.E.S.F.V.v.f.y.d 0 2 ; * 2 c.'./.V.D.H.x.N.I.(.#X[.*.[ ` ` _ _ ` ) ( ( ( / W ^ ^ ! ^ W Q W W W P P U U L L K K F K H F D D D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D D F F K F F K K L L I U U P P W W W W ~ ! ^ ^ ^ ) ) ^ ( ( ( _ _ ` ` ` ` ` [ *.$.'.].D.c.a.i d.p w 1 u Q.'.T.v.A.tXvXnXJXnXnXmXnXvXvXkXmXmXMXNXNXvXpX~.x.L.hXjXpXpXpXpXdXsXjXcXNXnXNXvXcXNXmXmXcXmXmXcXaX~.K.d 8 : % i Q.Q.C.e.e.C.L.F.L.I.E.R.!.~./._.eXeXeXeXrX`.gXrX`.`.#X`.rX).`.`.`.(.W.).^.^.~.'.eX`.).).tX~.Q.E.Z.l.y.t 2 ; = , x.^.!.H.n.n.c.n.U./.'.].*._ ` ` _ _ ` ( ( ( ^ ( ^ ! ^ ! ! W Q W P P P U U L U L K K K F F F D D D A N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b D D D D D F F K K K L L I P P P P P W ~ W ^ ! ^ ^ ^ ^ ( ( ( ( ` _ _ ` ` ` ` ` [ { $./.Y.F.c.e.e.g.i w > 0 E.eX!.A.F.tXfXnXJXNXbXlX`.K.F.!.lXbXbXMXcXR.x.A.j.z.P.eX^.eXrXaXsXsXhXvXnXNXjX).pXnXzXaXhXnXmXnXsX_.F.r.8 : = y Y.Q.S.y.u.F.P.R.Q.Q.~.~.^.eX^.R.L.F.F.C.F.U.E.W.`.uXhXlXsXdXiX).L.S.l.v.v.V.V.F.!.'.pXsXsXeX_.W.L.Z.l.p 8 6 < 2 x.^.Y.F.n.v.c.N.G./.#XY.| ` ` ` _ ` ( ( ( ) / ^ ^ ^ ^ ! W W W W P P P U U L L L K K K F F D D D N D b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b D N D F F F K K K L L I I I P W W W W W ^ ! ! W ^ ^ ^ ^ ( ( ( ( ` ` ` ` ` ` ` ] B.Y.Y.D.z.e.a a.a 0 ; 6 v.eX^.F.A.iXnXnXNXnXjXW.b.z.F.L.!.vXbXzX(.v.s.k.n.I.Q.D.I.eXhXiXiXeXrXrXjXvX^.R._.pXtXR.Z.~.jXvXdX_.K.r.8 < - y Y.].N.s.i.I.R.~.~.^.yXyX#XP.v.V.V.H.F.F.F.S.S.S.S.W.yXtXpX#XP.l.e.y.y.j.x.V.C.C.Z.Z.I._.jXsX#X).R.C.Z.p e 0 2 1 z./.Q.C.v.x.z.N.L.!./.Y.] ` ` ` ` ( ( ( ) ( ^ ( ^ ^ W ! ! W W W W P P U U L L L K K K F H F A D D b N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N D D A F F F K K L L I I P P P ~ W W W W ! ! ( ^ ^ ( ( ( ( _ _ _ _ ` ` ` ` ` ] B./.G.b.j.i t u.a 9 2 - v.aXiXJ.J.aXvXnXJXnXrXC.j.K.T.G.~.lXsXP.n.n.l.z.!.Y.U.(.!.).eXaXiXeX_.).eXsXeXT.E.T.~.F.j.K.sXvXiX).S.e.8 < # i R.].K.f.d.T.).(.^._.#X~.F.n.C.L.T.~.`.eXeXtXtX).E.Z.Z.Z.Z.x.t.t e.k.C.R.)._.rXyXE.E.C.v.R.aXsXeX!.F.v.i.s e 1 2 M.@XY.n.z.z.j.n.K.Y.Y.Y.| ( ` _ _ ( ( ( ) ( ^ ^ ^ ! ! ^ ~ W W W P W U U U I L K K K F F D F D N D N N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D N D D F F F K K K L L U I P P P P W W W ! ! ! ^ ^ ^ ( ^ ( ( ( ( ` ` ` ` ` ` ' %./.G.m.s.i f i.a w < - r.yXaXE.Z.tXnXnXnXnX).c.n.I.tX^.~.jX`.z.n.S.y.s U.`.W.(.`.!.F.eXaX_.~.~.~.iXvXT.b.!.~.G.F.).jXvXaX~.S.e.8 < ; u /.!.U.f.k.R._.'.iXiXY.x.z.m.P.^.iXaXsXhXhXhXjXjXhXyXE.A.e.u r s.S.~.tXaXhXhXlXhXvXpXT.C.c.K.sXdX~.I.C.s.a p 0 1 x./.Y.x.z.x.d.v.N.U.Y.U.| _ ` ` _ ( ( ( ( ( ^ ^ ! ^ ! ! ~ W W W W P P U U I L K K K F H F A A D N N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A N D D F F F F K L L I U I P P W W W W W ! ! ^ ^ ^ / ( ) ( ( ( ( _ ` ` ` ` ` ' $.J.G.x.u.q y i. .9 < > s ).pXR.U.pXnXnXNXcX!.c.v.W.kXsX^.sXaXb.e.g.v.c.L.#Xn.a.c.z.d.~.I.L.Q.R.!.'.iXT.G.L.F.I.I.(.kXzXdX~.Z.r.r < - y /.^.P.j.v.^.^.^.iX~.x.i.k.F.R.eXeX~.eXeX).rXtXaXsXsXaXE.A.p.Z.Q._.iX`.iXeXpXgXgXkXjXdX~.F.v.R.sX#XR.S.g.s s q 1 i.Y.Y.x.x.k.d.g.m.N.I.[.] ` ` _ _ ( ( ( ( ^ ) ^ ^ ^ ! ~ W W W W P P P I U I L L K K F F D D b D A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D A D D H K K K K L I I I P P P W W W W ! ! ~ ^ ^ ^ ^ ) ( ( ` ( _ ` ` ` ` ` ' &.[.N.z.u.q 0 . .y 9 , u.`.sXI.K.pXkXnXNXcX).v.C.C.'.fXdXfXiXx.p z.).~.N.'.!.f.g.s.z.F.D.P.I.!.~.G.H.J.Q.k.p e.s.I.kXcXaXyXF.t.0 < - u Q.~.L.j.x.^.iXiX^.V.d.e.C.I.T.E.T.E.~.W.W.W.).iX_.tXaXaXtXyXyX~.~.!.T.P.Q.)._.`.pXsXsXjX^.D.b.~.#X(.K.l.j s r > 2 z.D.x.i.u.s g.c.N.[.B.] ` ` _ _ ( ( ( ( ) ) ^ ^ ^ ! ~ W W W W P P I U U L L K K K F H H D D D A b b b A b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A D D D H H K K K L L I I U P P W W W W ! ! ^ ^ ^ ( ^ ) ( ( ( ( _ ` ` ` ` ` / | N.N.i.u 0 1 u.u.r 6 < i.iXsXQ.F.`.vXNXNXbX_.j.S.Z.a.P.sXfX#Xb.e.C.'.'.m.m.D.z.n.b.f.F.`.!.L.~.Q.H.J.^.Q.k.e.V.Z.~.vXbXuXyXZ.r.0 2 - i Q.Q.E.v.V.iXdXdXH.a.t s.K.G.E.T.!.~.~.).).).~.~.~.yX~.).^.!.Q.T.P.G.C.D.L.E.T.!.'.eXpXlXtXL.n.K.'.~.K.l.d d r w 0 .z.i.r.a e.h.n.N.U.B.' ` ` _ _ ( _ ( ( ^ ( Q ^ W ! ^ W Q W W P P U U I L L K K K F H D D D N A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A D D D D H F F K K L U I P U P P P W W W W ! W Q ( W ^ ) ( ( ( ` _ ` ` ` ` ` ' | H.x.u.f 2 2 i.u.y 1 < z.iXiX!.G.eXzXnXNXbX`.m.f.S.m.m.Y.^.Q.z.e e.n.P.E.b.z.x.F.c.c.~.Q.G.Y.H.H.G.x.j.Z.E.x.T.tXvXmXcXtXW.Z.d 0 < & p !.~.F.z.V.iXpX!.s.t s Z.S.Z.E.~.!.!.).`.).).eXeXeX_.).R.T.E.L.G.D.F.C.D.K.K.D.L.Q.^.tXiXaXR.n.b./.!.S.j.d i 0 s D./.H.p.u.s r.d.z.N.U.[.] ` ` ` ( ( ( ( ^ ^ W ) ^ ^ ^ W W W W W P P U L L U K K K K F H D D N D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b N D A D D H F L K K L L U U P P P W W W W Q ( ^ ^ ) ^ ) ( ( ( ( ( _ ` ` ` ` ( | N.p.u.q 1 2 . .q w 2 z.iX^.P.Z.).cXbXNXbXgXn.d m.U.z.z.L.D.e.t y.y.s.x.j.Z.D.!.n.x.G.x.x.x.H.Y.G.i.u k.A.z.E.vXNXNXcXtXE.Z.e.0 2 * t Q.^.P.l.Z.iXeXC.t 0 s.C.V.F.Q.!.~.).)._.eXrXrXrXtXtXtX~.E.E.K.D.C.H.H.F.Z.K.S.F.P.Q._.iXsXeXC.v.P.(.D.j.e.p 6 1 N./.H.g.s r.u.d.z.N.N.B.*._ _ ( ( ( ( ) ) ( Q ^ ^ ! Q W W W W W P P U U I L K K K K H F D b D N b N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N N D D D F F K K K L I K U P P P W W Q ^ Q W ^ ^ ^ ( ^ ^ ( ` ( _ _ ` ` ` ` / ] B.p.u 9 > > u a q 2 2 x.J.G.H.n.).jXmXbXbXjXP.e.u.b.x.b.V.E.F.e.e 0 t i r r.u j.~.V.p.h.p.H.'.P.z.i.v.~.~.).aXcXbXnXvXtXR.C.r.9 2 & t I.'.I.c.n.rXrXz.r t l.x.x.G.R.~.).).eXuXtXhXhXhXuXuXtX~.Q.E.T.F.F.F.F.G.F.F.L.F.F.T.~.iXiXrXI.v.P.(.L.l.r.t 2 , h./.N.M.d p s i.z.M.K.B.] _ _ ( ` ` ( ) ) ) ) ^ ^ ! ^ W Q W W P P P I L L L L K F F H D D D N D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A D A D F F F F L K L I I U U P W W W W W ^ ^ ^ ^ ! ) ( ^ ( ( ( _ ` ` ` ` ` _ C N. .f 9 > & y i q , < j.F.H.b.v.).vXnXmXbXvXP.r.e.k.H.D.D.).aXR.e.e j t a.v.x.u.i.x.V.P.k.h.H.z.u z.`.zXkXsXpXjXnXnXnXeXE.v.p 9 7 & i !.~.K.m.n.eX).y.0 r.v.z.x.J.Q.~._.eXrXaXaXhXvXvXhXuXuXeX~.Q.Q.T.P.L.P.E.F.F.G.G.G.G.E.#XiXpXR.v.D./.F.j.e.d 2 3 g./.K.f.t i d .M.m.N.B.R _ _ ( ( ( ( Q ( ) Q ^ ~ ^ Q W W W W W P U I I L L K K K F H F D N N D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N A N A A A H K F K K K L I U U P P P W W W W ! W ^ ^ W ^ ( ( ( _ ( _ ` ` ` ` ' | N. .9 > * * q i 9 3 > k.H.x.z.z.).cXnXMXnXvXR.u.e.v.V.a.n.(.sXsXF.r.f.s.%.l.b.x.p.i.x.F.u 7 0 y.V._.nXzXvXpXP.Q.aXzXsX^.P.b.p 0 < - t I.~.U.l.m.`.R.e.8 y.V.k.A.E.~.yX_.eXaXhXvXvXcXcXcXcXuXuXyXyXyX~.T.T.E.L.E.G.E.G.T.S.L.R.^.).E.v.b.E.G.k.y.t : ; h.Q.N.g.d q t .h.M.S.$./ _ _ ( ( ( ) ) ) ^ ^ ^ ! ^ W W W W W P P U U L U K K K F F H D N D D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b A b D D A D D H F K K L L I I I P W P W W Q W ^ ! ^ ^ ) ) ^ ) ( ) ( ` ( ` ` ` ) | h. .5 & % & i f 5 , ; a.c.z.k.k.^.jXnXbXMXvXE.s.y.l.l.l.S.rXvXvXeXk.e.c.z.d.a.u x.F.p.z.x.r.0 e.S.aXfXfXsXE.j.k.F.lXvX^.T.v.t r 8 : q R./.L.z.m.'.D.d 8 k.V.k.x.G.~.eXtXtXhXcXcXcXbXnXvXvXvXtXtXtXtX).R.Q.E.L.G.S.F.L.E.L.I.).dXsXtXC.c.E.I.z.y.p 8 > h.Q.N.f.p q w d %.j.Z.$.] _ ` _ _ ( ( ( ^ ^ ! ^ ! ~ ~ W ~ P P W P L U I L L K K F H D D A A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A b A A D D H F K K K L I I I P I P W W W W W ^ ! ^ W ) ) ) ( ( ( ( ( ` ` ` ` ] .f 9 3 & * f y w 3 & y.z.j.s.z.^.jXbXbXzXsXZ.y.g.Z.S.S.W.rXvXvXuXv.6 8 g.j.z.u.e x.z.H.iX^.D.s.f.C.Q.iXQ.x.z.v.c.`.jX~.L.V.d 8 8 # f L.!.L.z.x.!.D.t 8 j.V.i.p.F./.eXtXvXvXcXcXbXbXcXnXNXvXvXuXtXtX`.~.~.~.T.I.W.E.L.I.E.~.eXvXnXyXj.Z.R.P.v.g.d 8 > d.Q.G.k.e.e q a .f.n.$.] _ _ _ _ ^ ^ ^ ) W ( ~ ~ ! W W W W P P P I L L L K K K F H D D A N D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A N D A D H F K K K L I I I P P W W W W W ~ ~ ! ^ ^ ^ ^ ) ( ( ( ` ( ` ` ` ` ] ..q 2 3 % * w w 2 & , a.c.z.g.j.~.hXbXbXzXaXC.s.K.n.y.L.).rXjXjXsXL.y = r y.e.t - 0 x.H./.Q.!.^.T.H.b.V.x.x.E.Z.c.).jX^.G.x.p r 8 # r P.!.U.z.v./.C.t 8 j.b.u.k.F.Q.~.iXaXvXvXcXcXcXbXcXcXcXcXvXuXuXhXuXtX).T.I.I.I.I.L.P.J._.vXsXQ.d.c.~.T.V.s.d 6 > d./.H.d.e.e q t y.f.m.B.] ( ( ( ( ( ( ^ ^ ^ ~ ! ! ~ W ~ P W P P P U L U K K K K F H D D N N A A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A N b A D D H F K K K L U I P P P P W W W W ~ ~ ^ ^ ^ ^ ( ^ ( ( ( ( ` ` ` ( ] ..w 3 % % * 1 1 5 > & s.H.m.j.j.!.aXzXnXnX_.v.v.).R.Z.W.rXpXhXjXsX_.s.0 v.eXR.j.u.0 e.F.A. .u r.H./.Q.P.T.~.T.V.).vXjX^.F.z.u 0 8 # q L.!.F.z.z.Q.n.q 6 a.b.d.a.H.Q._.tXuXvXvXcXNXcXbXNXNXcXcXcXvXuXhXuXrX).(.R.I.S.I.E.T.~.tXsXaXG.d.V.!.P.b.y.r.8 > h.Y.H.u.d p 0 p y.%.h.$.] ( _ ( ( ( ^ / ^ ^ ^ ! ! W W W ~ P W P P I L L K K K F F F N b N D A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b N N N D D F H K K K L L I I P P P P W Q W ! ! ^ ! ^ ^ ^ ^ ( ( ( ( ( ` ` ` C ..w & * * o 9 7 > > & i.F.n.n.l.R.aXZXnXlX!.k.j.).!.S.W.tXuXhXhXhX~.r.u T.sXdXiX~.u.< 0 t.t 1 < d.I.b.H._./.J.Z.).cXsX/.G.x.t r 4 # w U.Q.H.z.z.Q.D.e.6 r.H.j.s.b.Q._.pXhXkXcXvXNXNXcXNXcXNXbXcXvXvXhXaXrXrX).W.I.I.I.W.E.).eXdX^.A.x.Q./.P.C.j.r.4 , f.Q.D.a.d i w t s u.d.%.] _ ( ( ( ( ^ W ( ^ ! ! ~ W W W W W I P I I I L K K F K F D A b N N A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b D N N A D F H F K K L I I P P P ~ P W W W W ! ! ^ ^ ( ^ ( ( ( ( ` ( ( ` R C q 2 3 * % o 1 5 > % - d.U.S.n.v.R.gXkXkXpXK.e.j.E.n.S.rXrXtXvXsXtXL.u r.Q.sXdXsX/.t.7 r.V.E.g.w z.n.y r.P.j.e.j.!.vXsX/.G.x.r.r : # w F.Q.H.c.k.Q.F.r.6 0 b.c.s.j.I.).pXsXkXvXcXcXbXNXNXNXcXbXcXcXvXhXsXaXrX).R.E.E.I.S.E.).iXdXQ.x.k.J./.U.Z.l.y.8 , d.Y.N.f.j e 6 q a a.a.%./ _ ( ( ^ ( ^ ( ^ ^ ! ! ~ W W W W P P U I I L L K K K F G D D N N D b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b D N A A H F F K K K L I I I P P P W W Q W ! ! ! ^ ^ ^ ^ ( ( ( ( ` ` ` / C g 3 & * % % 5 2 - $ - d.I.K.n.n.W.gXkXgX_.V.p f.C.c.K.!.tXsXdXiX~.x.e d.Q.Q.P.H.i.r j.~.iXjXeXe.e.T.Z.r.y.y.V.E.pXfXtX~.T.v.r.r 7 @ 4 D.Q.K.z.k.P.G.d.0 w f.n.j s.K.).pXsXlXnXNXNXcXNXNXNXNXNXNXvXvXjXjXuXrXeX~.Q.E.I.L.R._.dXtXH.z.V.T.!.F.C.d.e.8 < d.P.H.s.d r 7 q .u.y.| _ _ ( ( ( ^ ^ W ^ ^ ! ~ W W W W ~ P P U I I U K K K K F G D b N D b N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b N b b A D D F K K K L I I I P P P W W Q W W ^ ! ^ ^ ^ ^ ( ( ( ( ( _ ( ( Q | 3 & % % % 2 2 > $ > h.R.U.S.S.).uXjXhX).s.t V.C.j.K.eXsXtXrX#XE.u.p D.n.u.e.r.i.V.R.!.T.E.tXE.J.iXsXZ.k.F.lXkXzXsXiX~.E.v.r.r 7 @ w U.!.G.j.x.J.Y.x.t 8 s n.f.a v.!.`.lXcXvXcXNXbXNXNXNXNXcXcXvXvXvXhXuXtXyXW.~.E.G.Q.^.tXeX!.c.g.K.).Q.L.F.d.a 8 > f.G.H.i.t 9 2 9 f i %.| _ ( ( ( ^ ( ^ ( W ^ ! W W W W P P I P I I I I K K K F H D N b b N b N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A b N N N D G K K K K L L I I P P W P W W W W ! ! ^ ^ ^ / ( ^ ( ( ( ` _ ` / V 5 % % % % 4 5 & $ > c.Q.I.L.F.).hXvXvXR.r.k.E.~.G.~.dXiX^.~.!.m.s l.U.g.d d d n.(.Q.D.z.k.T.vXvXvXpXQ.R.pXnXkXkXlXhXrXK.A.r.0 < @ f P./.H.j.x.T.J.H.e.8 r x.x.r.a.L.#XjXvXnXNXNXNXNXNXNXNXNXcXcXcXjXhXhXtX).).T.T.J.Q._.iX~.C.j.l.P./.P.P.D.d.e.2 > i.J.N.u.y 7 , 8 q t %.] ) ( ) ( ^ ( ^ ! ! ! ~ W W W W P W P U I I L L K K H F N D N N N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A N b b b N H F K K K L I I P P P P W W W W ! ! ! ! ^ ^ ^ ) ( ( ( ( ` _ C 5 3 * % % * w 1 - * , c.'.!.L.C.W.hXcXvX~.e.e.E.!.F.^.iX#X/.P.V.y.y.U.I.g.d.p y.N.D.U.Q.yXJ.Q.vXxXjXeXP.C.(.uXkXlXkXhXtXE.V.t.0 7 $ y J.Y.H.j.x.R.I.D.j.i 7 t.H.d.u z.'.pXkXnXnXbXbXNXNXNXZXNXcXvXhXjXjXrXtX).~.Q.Q.Q.~.^.^.L.v.s.C.Q.J.Q.G.H.k.r.7 > i.J.A.i.t < , : q t } ] ) ) ) ( ^ ^ ^ ^ ! ! ! W W W P W P P U U L L K K K F F G N b N N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb A b b b b b N N N G G F K K K L L I I P P P W W W W ! ~ ! ^ ^ Q ( ^ ) ( ( ( ` R } < > 3 & # * 9 2 > % , m.^.~.F.S.).lXcXvXtXx.r.G.H.x.~.iX^.Q.N.p e v.'.Q.k.k.j.c.D.P.Q.T.~.~.~.lXjXdXP.D.R.L.K.eXzXzXhXyXT.H.t.9 7 $ u J.Q.H.j.k.L.I.D.x.s.r 9 i.z.a s K.#XfXnXbXbXbXmXNXNXZXbXmXvXhXhXhXrXrXyXE.R.Q.yXiXyXQ.V.i.k.J.Q.J.J.G.G.x.i.0 > p.[.A.s.r.2 ; , 4 q f C ' ( ) ^ ^ ^ ^ ^ ~ ! W W W W W P P I I L L L K K F H F D N N N b A N b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A b b N G G F F K K K L I I I P P P W W W W ~ ! ! ^ ( ) W ) ( ( ( ( ' } 2 > 3 & & 3 g 1 2 % , N._.^.Q.L.rXvXcXvXvXyXt.p.i.i.G.^.^.A.u 6 0 D.#X^.z.u.L.E.D.z.f.r.x.J.T.sXlX~.m.K.(.g.e.L.kXnXvXyXJ.V.t.9 > $ y Q.J.G.j.k.G.F.F.A.k.u 9 0 z.s.q a.Q.dXfXnXmXNXNXNXNXNXbXbXcXvXhXuXrXyX~.~.!.Q.yXyX~.V.s.i.H.Q.L.P.T.P.F.x.i.8 3 .J.N.g.d 8 = 3 2 w f } R ) ) ^ ( ^ ^ ~ ^ ! ! W W P W P P P U L U L L K F H G N N N N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b N N m N D F H F K K L I I I P P W P W W W W ^ ! ^ Q Q ( ) ( ( ( ` ' C g , , & & , q 6 ; % , m.#XpX~.E.pXcXnXNXnXvXV.r.d.a i.x.k.e 0 e 8 u.!.#XN.e 0 u 9 7 - 7 v.F.H.!.P.C.x.V.b.a d.T.sXnXvXtXQ.b.u 0 6 * y T.Q.D.j.z.J.J.F.D.A.k.u 7 y c.s q h.'.aXnXnXNXNXNXNXNXvXcXvXvXuXuXeX~.~.!.!.).eX~.C.a.d s.P.T.F.P.I.T.F.b.i.8 , u.U.m.%.t 2 * 3 3 5 q } E / ^ ^ ) W ^ ! ~ ~ W W W W P U U U I I L K K K F D D N m N N D N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b N b D N m N N N H K K K L I I I P I W P W W W W ~ ^ Q ) ^ ^ ) W ( ( ( ` C g w 1 2 2 1 q 6 ; % 3 n.`.pX_.Q.tXkXnXnXnXnXyXe.e.z.z.s.r.y.r.p 4 8 d.I.`.v.6 9 u.r - 6 C.U.d.z.V.J.~.F.H.G.P.G.iXfXvXiXQ.V.r.r < # p !.Q.L.l.A.J.J.J.G.b.v.i.e 6 s f.i i m.#XfXnXMXZXNXNXnXnXnXsXsXrXrX~.!.Q.!.~.'.!.K.f.j e.V.Q.F.G.P.Q.I.F.x.u.8 , a.Y.m.y.t < - * & < 9 ..E ^ ^ ^ ^ ^ ^ ! ~ W W W W P W P P U I L L K K K F G D N m N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b B B m b b G F F K K L K L I U P P P W W W W W ^ ^ ) Q Q ( / ( ) ` / } i f q w w w t 4 : * : n.#XpX`.I.`.kXbXcXvXvXrXs.0 p a.d.y.y.4 = 0 t 9 e.!.iXV.Z.~.Q.r.0 Z.Y.N.H.^.dXF.p.C.`.yXV.J.fXjXpXR.Z.y.r : # u Y.!.F.A.A.E.Q.J.J.F.V.z.i.q < r.g.q y N.iXjXnXbXNXnXNXnXvXfXaXrX).~.~.R.W.(.'.P.l.p t x.P.F.F.P.~.!.Q.F.z.s 2 3 a.K.N.y.p < * * & > 5 } ~ ^ ( W ^ ^ W ! ~ W ~ W W P P U I I L L K K K J D G m m b N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b B b m b G D D K K K L L I I U P W P P W Q ! Q ^ ^ ^ ^ ) ^ ) ( ( R | d.d.u.d y q i 4 ; # = n.hXgX#X!.`.hXcXcXnXvX).k.p y.t d t t y.r 0 s.f.a f.).rXG.~.rXj.8 a.I.N.N.^.^.z.8 0 y.d.i.H.sXvXrX~.Z.y.q 8 * i Y.R.L.v.Z.Q.yXQ.T.L.Z.v.z.i.q 6 e.f.q y D.iXjXnXbXnXnXvXsXtXtX`.~.~.Q.!.`.(.I.f.t e r.H.G.H.P.~.^.~.P.D.g.d 2 ; g.G.x.y.t : # % * 3 5 V ) ^ ) ( ^ ^ ^ ~ W W W P W P P U I I L L K K K H G G m b m b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b A A m m b S B H F K K L L I K I P P P P W W W W ^ ! ^ ^ ^ ^ ^ ( ( ~ %.m.x.b.d.a u r.0 * @ ; V.tXsXiX~.iXvXkXjXhXuX).y.d y.l.I.~.yXsXG.u i.h.j.d.Q.`.P.L.).S.t : y.e.9 t.i.V.v.p r.p i.E.vXcXrX~.C.y.t 4 * p Q.T.F.b.V.^.iX~.Q.E.I.C.x.x.i.8 8 y.y.r.r.H.#XsXzXzXjXjXdXiXiX).(.~./.^._.P.z.8 1 a H.G.F.Q.!.).rX^.Q.D.y.e : ; d.F.A.u 0 3 o % % ; 5 V / ( ! ^ ^ ! ~ ~ W W W W P P U U I I L K K K F H G b b m N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A b m m b B G H K K K L U U U U P P W W W W W ^ ! ! ~ ^ ^ ( ( ^ / | N.D.D.c.j.i.e.6 - # < A.iXaXaX~._.jXjXtXpXrX`.n.y.s v.^.fXfXfXdXk.9 r.D.G.Q.T.x.j.L.S.r.7 r.r.r t.r r.x.x.b.F.V.aXcXvXtX!.L.e.r 8 * u Q.Q.H.x.H.^._.^.~.~.T.T.F.A.x.y.r 8 y.y.r u D.).dXpXsXaXiX^.^.).(.(.!.~.F.d.0 6 i A.G.G.T.'.`.rXpX'.^.D.s 8 ; > u.Z.y.u i : * & & & h E ^ ! ! ! ! ^ ~ ~ W W P W P P U L L L L K K F F D N b m m N N b b b b b A UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b N N m b b B F F K K K L L I I I P P W W W W W ~ ! ^ ! ) Q ^ ( ^ *.P.Q.E.F.V.k.s.r ; ; > b.dXsXdX^.iXhXpXiXrXeXrX`.).I.P.Q.yXiXiXK.e.y D.Q.Q.eXV.r.L.pXtXL.A.e.x.E.^.G.x.r.i.T._.pXvXcXvXeX/.D.e.0 6 = p ~.Q.G.A.F.^.eXeX).~.~.Q.E.E.Z.Z.y.t 8 d i.e y h.Q.#XpXiXiXiX#X).'.(.!.F.i.9 6 e.V.H.G.P.~.rXrXrXtXiX).K.t 2 & * u M.%.y d 8 : & & : h E ^ ( ! ^ ! ! W W W W W P P P U L U L K K K F H B S b m N N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b m N N m b B B G F K K K K U I U U P P P W W Q W ~ ~ ! ^ ^ ) ^ ^ Q $.'.^.E.F.V.x.j.0 ; # > b.aXdXdX~._.hXpXpXeXrX).`.rXrX).H.p.k.k.t u H./.^.G.D.e.j.rXvXhXeX~.yXyXyX#XiXyXF.D.).hXhXhXvXhXeX~.F.e.r 6 - u Q.Q.J.x.H.^._.).)._.^.yXyXE.E.S.E.y.r.8 t e.r 9 .H./.#XiXiX#XiX#X!.n.a 9 9 s V.D.V.P.Q._.eXaXpXaXiX~.n.0 : & * e s y w d q 8 2 , : 5 V ^ ^ ! ! ! W W W W W P P P I U L L L K K K F B N B b m B b N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b N m m b b B D F K K K L I I I U P W W W W W ~ ~ ~ ! ^ ^ Q ( R $.`.#X^.R.C.b.z.f ; # > x.#XiXdX/._.gXrX`.).eX).'.eXsXrXZ.y.t p k.x.A.V.k.r.a j.).lXsXtXaXtXyX~.Q.P.Y.#X_.rXpX`.'.pXdXvXtXyXZ.r.y 6 - u Y.Q.J.x.G.iX_.).).eX^.yXyXyX~.E.S.S.v.y.r r.r.0 2 q b./.#X#X#XiX/.x.a = 9 u.x.C.v.n.L.!._.iXaXaXtXtX^.Z.8 ; # * y .9 9 d d y q 9 2 4 C ~ ^ ! ! ~ ~ W W W W P P U I I I L K K K F D G b m N v m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b N v m b B A F K K K L L I U I P P P W W Q W W ~ ! ^ ^ ^ ) R $.pXiXeXR.K.b.S.j : # - k.#X#XiX~.#XgXrX_.).).).!.~._.rX).k.r u L.H.u 6 q f.G.iXsXeX).R.E.yXaX^.T.F.U.Y.(.`.).^.~.eXsXaXeX~.C.r.r 6 - u Q.@XH.b.L._.#X).).eX).yXyXyXyXyXW.E.S.l.y.r 8 e 8 > 9 e.D.J.Y.G.k.0 > r i.x.H.z.c.C.L.R._.iXiXaXsXaXyXc.6 # & i.s.y q a.g.a.a y y w C ~ ^ ! ! ! W W W W P P P U U I U L K K K J D b b m v N N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N b N m m m m N D F K K K L I I P I W P W P W W W ! ^ W ^ ^ ^ R $.pXsXeX!.L.V.K.j & # * g.K.].dX'.'.iX`.'.(.W.(.R.~.!._.).v.r t S.).v.0 f.).#X#X^.Q.P.K.k.j.~.pXT.L.K.L.L.I.L.T.~.).pXsXeX~.C.p e 8 * y /.Q.H.b.L.#X^.^.`.eXrXpXiXeXyXyXyXyXR.E.S.l.t 4 4 4 , = 6 e.e.i 9 7 r p.x.x.k.z.b.F.E.).tXaXaXaXsXtXyXk.; # @ > h.N.k.a.v.c.M.d.u.r.t C ~ ! ! ! W W W P P P P I U I I L L K K F D B b m m v N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N m v m m N D F K K K K L I I I U P P W W W W ~ ! ^ ^ ! ^ / | #XdX`.~.T.H.C.a ; ; ; j M.N.!.^.^._.).(.!.W.R.R.!.!.Q.!.K.y.r j S.I.i.u n.H.H.H.Q.tX!.s.e.F.rX~.L.F.D.D.F.L.I.!.).iXaXeX^.D.a e 8 - y Q.^.L.m.L.tXiX^.^._.rXrXrXtXeXtXyX).W.yXE.S.y.r.e 2 ; ; - 7 7 2 6 t.A.H.x.d.k.c.n.P.!._.tXaXsXhXvXtXW.y.# @ w H.Y.b.k.n.N.n.M.f.y.%.| ~ ! ~ W W W W W P P U U U I L K K K F H B B m m v N N A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A N v v m b B B F K K K L L I I U P P P W W W W W ~ ^ ~ ^ / C ].#X'.~.L.H.H.u.2 < : j y.j c.C.T._.!.Q.P.Q.Q.E.~.Q.~.Q.yX~.y.r r.E.G.k.i.i.k.b.F.z.e.d.F.~.eX~.P.F.F.F.J.E.T.Q.Q.eXaXtX(.F.d r 7 * y Q./.G.H.F.rXrXtXyXtXtXuXtXaXaXtXtX).)._.).E.C.v.y.r.8 - - @ 7 9 r.V.C.k.k.k.l.v.D.T.~.pXsXhXhXhXhXpXI.t # o # .!./.H.z.b.H.D.n.x.j.%.] ! ~ ~ W ~ ~ P W P P P I I I L K K F F D B b m v m N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b N B v m B B F F K K K L I I I P P P P W W W W ~ ~ ^ ^ ^ ] {.`.'.Y.F.V.N.i.7 w t l.l.d t r.j.yXQ.Q././.~.~.~.T.Q.yXeXaXuXk.t l.v.j.N.H.F.P.D.r.t.G.iXeXR.G.L.D.F.E.E.Q.Q.Q.~.#XsXpX^.H.e.u 6 % y Q.Q.G.x.F.`.pXtXtXtXuXvXuXhXuXhXtXtXrX_.).).R.Z.Z.l.r.t.7 < t.k.G.C.x.d.k.x.V.K.E.~._.tXsXvXkXhXpXtXC.6 # # : z.^./.H.V.G.G.F.H.H.v.h.] ^ ~ P ~ P P W P P U L I I L L K K H F B m m v v N N N A b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b N N v m m b B H K K K L L I I I P P W W W W W ~ ~ ^ ~ ^ ] [.!./.P.H.x.x.i.0 y y.S.R.a.e q t.Q.iXJ.Q./.~.^.).).).~.yXtXvXyXs.t 7 < Z.yXQ.K.^.!.H.).pX_.E.E.F.F.E.E.Q.~.~.^.^.pXsXpX^.A.r.r.6 * f J./.G.V.J.pXsXtXvXhXuXuXhXvXhXsXaXtXtXrXeXrXeXyXyXE.Z.y.e.y.Z.L.v.j.k.z.A.D.J.Q.~.eXaXhXjXvXjXhXtX).d.: # # r P.#X(.C.C.R.!.!.G.F.Z.N.%.~ ~ W W W P W U U U U I L K K K K H N m m m m v b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b N N v m v m m B D F K K K L I I I P P P P P W W W ~ ~ ^ ^ R 2./.Y.H.b.k.j.d.p s.n.I.R.F.v.s.i.F.#XQ.Q./.).rX'.`.eXeXtXrXhXvX~.k.r 7 r.E./.H.d.D.P.~.pXeXR.E.K.G.L.J.E.Q.~.~.`.aXhXaX^.A.r.p 6 # f J./.G.V.J.aXdXuXuXvXvXbXcXhXvXvXaXhXsXaXpXpXtXtXtXyXyXE.E.tXyXC.V.H.V.V.F.J.Q._.eXaXhXjXjXjXjXsXeXF.r # # : l.#X'.(.C.V.!.(.~.R.L.D.N.C ~ P W W P P P P U U L L L K K K F D m m m m v b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m v m m m m m D K K K K L L I I P P P W W W W W W ! ! R $.@XY.G.b.i.s a.u.n.L.Q.^._.G.V.k.k.J.iX).(.).pXrX`.rXrXrXtXaXkXcX_.T.k.t.t.j.j.d y.j.I.pXrX!.L.E.I.F.I.R.).)._.pXaXjXhX).v.r.d 8 * y P./.F.V.T.sXvXvXvXvXvXvXcXcXjXkXhXvXhXhXhXsXsXsXtXhXuXrXrXeX).~.).!.E.R.~.~.eXiXsXjXkXhXkXvXsXiXT.j.p 0 8 y.tXiX_.T.v.P.^.'.^.~.R.U.B.] P P ~ W W P U U U L L L K K K K D B b m m v v N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m v v v m B D H K K K L L I I U P P P P W W W W W ~ R %.[.H.N.x.u.y d s x.R.~._.eX~.G.F.j.x.^.pX_._.iXiXeXtXpXrXrXgXlXjXvXnXtXF.i.u k.K.I.K.I.`.'.R.I.~.~.~._.yXeX^.eXpXpXjXrXW.v.r.t : # y P.Q.L.A.E.fXnXnXvXvXvXcXbXcXcXcXcXcXhXhXhXvXsXaXsXvXuXhXuXrXrXeX).).).yX~.eXtXjXjXvXcXkXhXaXpX~.v.v.j.y.y.yXtXpX).K.n.~._.yX^.~.R.U.2.T P W W P P P U U U U L L K K K H B B m v v v m A N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v v m m N B G H K K L L I I U U P P P P W W W ! ~ ~ | V.H.N.h.u.w i .z.P.'.^.rXeXyXT.F.V.S.W.`.rX`._.#X_.rXpXhXrXgXhXlXjXvXaXR.Z.~.pXaX#X'.).I.P.T.R._.`._.yXyXyXyXeXsXhXuXE.c.e.t 7 # r Y.Q.K.v.E.sXnXvXnXcXcXcXnXbXbXcXvXjXvXvXvXhXvXvXvXvXhXaXhXsXtX).eX_.rX_.eXiXsXvXvXcXvXkXaX`./.F.F.L.C.V.Q.yXtX_.R.n.L.`._.'.'._./.Y.$.R ~ ~ W P P P U L U L L L K K F G B B v m v m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b G b v v v v m B D F K K K K I I I P P P P W W W W ~ ! C $.N.x.i.a w 1 p f.D.Y./.^.pXtX/.U.L.K.K.I.#X`.).).'.'._.`.eXiXrXtXeXeXeX_.eXrXeX^.).(.~.Q.T.Q.~.E./.~.eXeXiX_._.aXvXrXR.l.e.r > $ q G.E.S.v.E.vXnXnXNXnXnXnXnXbXbXcXcXvXvXvXvXaXhXhXhXrXaXtXtX#X).eX_._.pXpXpXsXjXjXkXvXjXsX).I.D.L.I.L.F.T.yXyXyX^.H.F.).rX`.#X`.).'./.%.P P W P P P P L U L L K K K F D N m m m v v m b N b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v v m v m B m H K K K K I I I I U P W W P W W W W ^ ] B.M.s.i 0 < 9 .x.Y.Y.Q./././.Y.U.U.U.D.F.L.L.~.^.!.~.~.~.yX~.~.^.~.)._.~.).^.~.~.~.!.~.^.^./.~._.rXtXiXiXiXiXaXaXiXT.z.e.e > @ 9 G.!.N.l.S.kXZXbXnXnXnXcXvXbXbXbXcXcXcXhXkXhXlXuXhXpX'.'.'.~.^.~.#X^.iXiXiXdXdXsXlXpX!.P.P.F.I.L.U.G.J./.#X#X/.G.V.~._.#X`.#X'.@X].[.C W W W P P U U L U L K K K K G N m m v v v v b b A b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v v v v v B A F K K K L L L I P P I P W W W Q W W R | N.u.i 9 < & q u.N.J.G.L.G.Y.P.P.N.N.N.H.x.z.h.x.C.K.F.E.E.E.~.!.T.T.E.~.~.).).~././.^._.)._.^.).eXrXsXdXaXiXsXdXyXE.j.e 0 > 9 J.Q.n.f.S.kXkXcXcXnXcXnXnXvXbXcXcXcXhXkXgXgX#X`.'.).'.].(.'./.'.#X/.^.#X#X#X/./.F.n.c.m.F.K.D.D.L.H.N.Y./.J.H.x.G.~._.`.`.`.`.).].$.R P P P W U U L U L L K K K K N B m n v v v m A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b A m v v m m m B D J K K K L L I U U U P P P W W W W Q ] %.e.t 1 > * - q .x.D.H.N.x.h.N.J.N.K.n.V.b.m.v.v.b.F.I.P.~.E.E.L.L.D.L.Z.Z.V.H.H.F.G.!.~.'.'.'.`.#XrXsXsXfXsXdX^.P.k.r 9 , 9 H.Y.n.s.n.gXkXcXbXbXcXnXkXnXnXvXkXuXjX;X`.!.I.F.N.b.z.c.m.c.M.M.z.h.a.a.i.a.g.a.a.y.g.z.z.b.b.m.M.f i d.v.f.g.b.P.'.`.#XpX`.).'.*XE Q P W U U U U L L L K K K K B m N v v v m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v v v v v m v D K K K K L I I U U P P P W W W Q W R | e.e 5 3 3 @ $ 1 f u.g.a.a.w 9 y i.n.N.H.N.Y.L.P.!._.dXaXsXaXpXrX_.(.R.F.Z.V.x.i.d.d.k.z.D.K./.'.#X;XaXiXdXsXaX~.D.i.w 1 % 5 H.Y.n.s.m.rXkXcXcXcXcXvXjXjXsXaXtXyXS.n.g.d e w 1 > > * & & 3 3 3 1 1 9 w q q i s s g.h.z.b.b.j 4 & & 2 8 d l.H.Y.!.'.`.#X`.`.Y.| Q P W I P U U L L L K K K K G m v m v v v v b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v n v v v B b D K K K K K I I I U U P P P W W W W C ..q 7 - % % @ 3 g q 9 5 5 * $ & w f .M.N.Y.#XiXdXfXfXdXfXfXdXaXiXiX#X/.Q.G.C.v.f.a.u.u.s.c.K.R.).).iX#X#XQ.H.u.6 6 # 4 D.Y.N. .f.).pXhXgXsXpXpX#X'.U.n.s.e.d t w w w 6 w 2 : 3 3 3 * 2 1 w f a r.u.u.d.d.d.h.M.N.N.M.j q 8 : : q k.Z.F.J./.^.^.`.(.].&.E ~ P P P P I I I L K K K F F B m n v v v v b A b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N b m n v v v m m B D K K K L L I U U U U P P P W W Q T C f 1 > % % $ . $ w 5 - 3 % $ . . . % , w y s s.b.N.N.H.J.@X^.#X#X#X#XiX^.^./.Y.F.D.z.e.a p u.z.D.F.J.P.F.k.y 6 < * . 1 N.H.h.u s.U.].!.~.~.~.T.x.r.e r t r.a.f.j.M.z.h.g.g.j d i d . .s i .f.f.s a q g w w .d.M.x.M.a.d d %.a.g.n.D.G.J.@X'./.(.2.E P P I P P I I I L K L K K F b m m n n n v m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b N b v n v v v m m A K K K K L L I I U P P P P W W W W I Z 5 & % % . . * $ $ $ @ # o o # & & , < 3 & , 1 9 9 u .d.N.N.K.Y././.'.Q.L.n.j.u.p t u r.z.z.s 7 7 > @ . 1 N.H.p.0 a.D.b.K.L.D.u.0 9 r p i.b.V.H.F.D.N.b.d. .d t w w t i q 9 1 1 , & * @ @ * & 4 f u.u.s a s y.y.l.n.H.P.Y.Y.'.].B.C P P P P P I I I I L K K K F D v v m v v v v b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m n n v v v v m A F K K K L L I I U P P P W W W W W V Z 5 3 * $ . . $ $ $ # # # & = , , & * % o @ @ @ $ % & , 1 q .i.b.H.Y.Q.Q.I.V.z.r.r 0 0 0 9 > - . 2 N.A. .9 u.L.D.f.0 > > 9 u k.D.F.G.G.x.u.f 1 & & * * & , 5 w w w w w q 9 1 2 > > , ; , , 2 w f e y e q r.y.l.n.N.Y.Y.Y.[.$.] I ~ P P P I I I L L K K K F D v m v v c v v m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m v v v v v v m G F K K K L L L I I P P P P W W W P Y Z h 3 o o o o 3 * * 3 : , < 7 < ; & = - * * * * & * - < ; 7 9 6 , 2 5 2 q u.x.F.Q.Q.D.c.a 0 , 9 9 $ . > N.x.f 1 s i.g $ $ > y p.A.H.h.d.i 5 % . o * > 7 q f . ... . . . .f f 1 5 1 2 1 1 1 4 1 5 1 w e t a.f.M.N.N.N.N.N.X.E P W I P P I I I L L K K K K D v m n v v v x m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b M v c M v v m m D K K K K L L I I U P P P P W W W W W G Z h % % % o o o o o o o o # & & & : 7 7 2 2 ; , : < : : ; : 1 6 7 9 0 g q q 9 > & & % $ > f h.N.U.N.h.y , 1 & . . 5 x.h.a y 2 $ > y d.p. .7 $ . . . o o $ $ $ > < & % * $ $ $ $ $ * * % * & - > , , 3 , w q d y.g.M.M.M.m.M.%.| T W P U P I P I I L L L K K F D m m v n M c v v b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v x v v n v v B D K K K I L L L I U U P P P P W W W W P V h 5 & * & # 3 3 & : 3 : : 2 4 8 8 9 6 8 8 6 8 8 : 2 2 : , , & $ > < 2 2 > > > , & % # 2 q N.H.x.i > 7 $ . 5 p. .y , % 7 f f 1 % . . . . . . o @ . . @ @ @ $ % % % & , > & , 1 9 q t i y.y.a.h.h.h.%.C Y T P P P P P I I I L L L K K K D m m v n v v v v b N b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m v x v v n m v m H J K K K L L I U U U P P P W W W W W ! Y Z h 2 4 4 2 4 4 4 w f t y.g.k.A.x.p.j.l.f.g.y.y.e.8 8 4 2 ; > * * % * * & & & * % $ # . & q h.N. .9 < . 5 h.u , & , g 3 + . . . . . o . @ o o $ $ * $ * & & 3 , 2 < 7 5 w 9 f f s %...| | } } V P W ~ P P U U I I I I L K K K F D b m n c v n x v m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b A b b b b b m x v x v n v v B D K K K K I I I I U U P P W P W W W W W P V Z C } f f . .u.M.v.b.H.J.J.J.J.P.K.K.P.K.Z.g.t w 8 r p r.r 0 9 < - # @ # # * - * # o o . $ .p.g 5 $ 9 s.w % & & . . . . . . . o . o % % $ & 3 3 , , 2 4 1 w 4 w q q f f . .X.C R P T T Q Q P P U P U U I I L L L K K F D B v v n v v c M m A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m c c n v n v v B D K K K K K I I I U U P U P P P W W W W W Q R E C X.x.N.N.N.U.Y.Y.J./.Q.^.`.#X#X^.`.`.I.K.K.k.r i.x.k.k.u.t.e 8 < # # # $ * * & % % $ . $ .f > 9 u.3 $ & > % @ @ * * @ . . . . o @ o % % % & & > , 1 g w 4 g q q f f f f ..| | C C T W ~ ~ ~ P Q P Q P P U U I I I L K K K K D B m v n v x x c v A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b A v x n n v v v n m A K K K K I I I I I U P P P W W W W W W ~ ~ ~ T C | %.h.B.N.Y.Y.$X#X#XiX#X#XiXdX`.;XuX#XpX#XH.h.D.G.L.D.n.z.k.p 6 = . o % - > $ $ $ . $ .f f q & < > > > < > > & @ o o o o # # * % h % h 3 3 5 5 9 w q g f f ....} C C V E T ~ ~ W ~ W ~ P Q Q P P P P P U I U I L K K K K D m v n n n c v v n A b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b v x c x n n v m m D F K K K L L I I I P P P P W W W W W ~ Q ~ ~ W W E Y V C C | X.X.$.$.B.B.[.@XY.[./.'.^.'./.Q./.~.!.I.P.F.H.v.s.e > % % % 5 9 > $ $ 9 a q 9 r r y u 9 2 3 % % o # # # $ @ % % % & 3 3 & 3 h Z V C Z Z V C Z Z } } C V E R ~ ~ ~ ^ ^ ! ~ W W W P Q Q P P P P P L I I L L L K K K A m v v n n c c x n N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b m n c c n M n n n v B J K K L L L U I I I U U P P W P W W W W W W ! ! ! ! ! ~ R T T E E E E V V C ] C | | %.%.B.[.G.].[.].Y.Y.Y.P.K.z.9 , 3 * . % 3 3 3 o . 1 a h.x.p.p.u 9 : & * * & % * & = > - > , 5 5 5 h C E Q / / ^ ^ ~ ^ ~ ~ R R Q ) ^ ~ ^ ~ ~ ^ ! W W W W W P ~ P P P U U I I I L L K K K F G B n v n n c x n n m b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m n c x M x n v v m B F K K K L L I I I I I W P P P W W W W W W ! ^ ! ! ! ~ ^ ^ ^ ^ ^ ^ ( _ / ( ) ~ ^ ( ^ R E Y E ] o.$.[.Y.Y.P.F.F.x.a w 3 * o o 3 3 % . % h.A.G.A.u 9 9 : 3 3 3 3 : 1 1 1 9 1 w g 5 Z V E ^ ( ( ( ( ) ( / / ^ ) ^ ^ ^ ^ ^ ! ~ ^ ~ ~ W W W W W ~ P P P P P P U I I I K K K K F B n n v M c c c c n m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m x c x x n n n n n b D K K K K L I I I U U P P W P W W W W Q W W ~ ~ ! ! ! ^ ! ^ ^ ( ^ ^ ^ ^ ) ( Q ( ( ( ( / ) ) ) R ] X.B.P.G.N.b.v.u.w 2 h o o 3 & & b.Y.H.r.w 9 9 8 4 4 8 g w w w f g } Z V E ~ / ( ) ( ( ^ ( ^ ( ^ W ) ^ ^ ^ ^ Q ! ! ! ! ~ W W W W W W P P P P U I I I I K I K K K H B n n n n M x x x n m N b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m n c c M c n n n v m A K K K K L I I I I I P P I W P P W W W W W ~ ~ ! ! ! ! ! ^ ^ ^ ^ ! ( ^ ( ^ ^ ( ) ) / ) ) _ ( Q T C | $.N.D.b.k.u.q 4 3 % 3 % , M.x. .s a e q f i i t q f ..} } C Y R _ ( ) ^ ( ( W ^ ^ ( ^ W ^ ^ ^ ^ ^ ! ^ ^ ! ! W W W W W W P P P P P U U L I I L K K K K K G m n n n n M x c x n m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m M x x n x n v n n v B J K K L L L I I I I P P U W W W W W W W W ~ W ~ ! ^ ! ! ^ ^ ^ ^ W ( W ( ^ ) ^ ) ) ) ) ) ) ` ( ) ~ E C $.N.v.k.a g 4 3 % o . 3 , .u.i.f. . .%. . .a.%.%.} ] R / ) ) ) / ) ) ) ^ ( ^ ( ( ^ ^ ^ ^ ^ ^ ! W ^ ~ Q W W W W W W W P P W P P U U L L I I I K K J K B v n n n n x x x c c m b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b m M x x x x x n n x m b D K K K L I I I I I P U P P P P W W W W W W ~ ~ ~ ! ! ! ! ^ ^ ^ ^ ( ^ ) ) ) ^ Q ^ ) ) ) Q ) ( ) ( ^ E C $.N.d.d g 1 : % # 3 .N.x.z.d.l.y.h.f.h.%.| R W ) ^ ( Q ) ^ ^ ^ ^ ( ^ ^ ^ ^ ^ ^ ^ ~ ! ! ^ ^ ^ ! W W W W W W W P W P P I P U U L U I I K K K F B n n n n c x x x x c b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b n x x x x n x v n v m A K K K K L I I I I I U P I P P W ~ W W W W W ~ W ! ~ ! ! ! ^ ^ W ^ ^ Q Q ) ) ) ( ) ^ ) Q ( ( ) ^ ( _ E | $.%.s w 1 & % . , S.K.N.b.b.V.c.b.B.| R ) ) ) ) ^ ) ) ) ) ( ) Q ^ ^ ^ ^ W ^ ! ! ! ^ ^ ^ ! W W Q W W W W P P W I P I U L I I L L K K K F D m n n n x c c c c z v b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b v l x x x x n x n M m A D K K L L I I I I U U U P P P P P W W W W W W W ~ ~ ~ ! ! ! ! ^ ^ ^ ) ^ ) Q Q ) ^ ^ ) ) ^ ) ^ ^ ) / R E | X. .w 5 3 o 2 M.D.b.N.D.H.C.B.| R ) ^ ) / ) ^ ^ ) Q ) Q ^ ) ^ ! ! ! ! ^ ! ! ~ Q W W W W W W W W P W P P P P P I U L U L L K K K F b n n n x n x c x z z v b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b v z z c c x M n n n n v D J K I K L L I I I U U P U P P W W P W W W W Q W W Q W ^ ^ ! ! ~ ^ ~ ^ ^ ^ ^ ^ ^ ^ ^ ) Q ( ^ ^ ^ ) ^ Q C ..g w , & @ w N.F.H.D.D.Y.$.C ~ / ^ ^ ( W ) ^ ^ ^ ) ^ ^ ! ^ ~ ! ! ! ! ~ ~ W W ! W Q W W W P W P P P P P U I I I I L L L K K K D m n n x n n x x x x x v b b b b b b b A b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b A m c z z z x M M x n n n G G K K K L I I I I I U U P P P P W P W W W W Q W W ! W Q ^ ^ ^ ! ! W ^ ^ ^ ^ ^ ^ ^ ^ ) ^ ^ ^ ) ( Q ( R Y | } 5 > % f F.U.K.N.[.*.E ^ ^ / ^ ^ ^ ( W ^ ^ ^ Q ^ ^ ! ! ! ~ ^ ~ ! ~ ~ W W W W W W W P W W P P P P I I I I L I L K K F F b M n n n x x x x z x c v b b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXb b b b b b b b b m n z x z z x x v n n n m S F K I I I I I I U I P I P P W P W W P W W W Q Q W W W W ! ~ ! ^ ^ ^ ^ W ! ! ^ ^ ^ ^ ^ ^ ^ ) Q ^ ^ ^ Q V Z g & f P./.Y.[.%.R ^ ^ ^ ^ ~ ^ ^ ^ ^ ^ ^ ^ W W ! ^ ^ ~ ! ~ W W W P ~ W W W W W P P W I P I P U I I I L L K I K J D m n n n x n x z x z z c m S b b b b b b b b UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXm b b b b b b b b m n x z x z x x x n x n v b D J K K K U I I I I I P U P P P P W W W Q Q W W W Q W ~ W ~ ^ W W ^ ^ ^ ! ! Q ^ ^ ^ ^ ^ ^ ) ^ ^ ~ ^ ^ R C 5 .P.(.*X] ~ ! ^ ~ / ~ ^ ^ ^ ^ W ! ! ^ ^ ^ Q ^ W W ~ W W P ~ ~ P W P W P P P P P P P I P I I I I K I K J D b M n n x n x z z z z x n m b b b b b b b b m UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXv A b b b b b b b b v z z z z z c c x n n M n m H K K K L I I I I I I P I P P W W P Q Q P W ~ W W W W W W W W Q ! ! W ! ^ ^ ^ W Q Q ! ! ! ! ! ^ ~ ^ R Z ..F.[.] R ^ ! ! ^ ^ ^ W ! ^ ! ^ ^ Q ^ W W W W W W W W W W P W W P ~ W P P P P U I I I I I I L K K K H b v x c v x x x z z x x x v A b b b b b b b b v UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXM b b b b b b b b b m x x z x z x c x x n n n n m H K K L L I I L I I I P P I P P P P W P P W W W W W Q W W W W ! W W W W ^ ^ ^ ^ ^ ^ ! ! ^ ~ ~ ~ ~ E C *.] ~ ! ^ ^ ^ ! ^ Q ^ Q Q ! W W W W W W W W W W W W W P W W P P P P P P I U I I I I I L L K K H B v n n n n c x x z z z z c m A b b b b b b b b v UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXz b b b b b b b b N b n x x z z z x x x n n n n n m F K K L L L I I I I I P U P P P W P P ~ P W W W W W W W W W W W W W ^ W W W W W W ! ~ ~ ~ ~ ! ! R ~ ~ ~ ~ ^ W W W W W ! W W W W W Q W W W W W W W W P ~ P P ~ P P P P P I I I I I I L L K K F A v n x n x n x z x z z z x n b b b b b b b b b b l UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXM b b b b b b b B b v c l x x l x x x x n n n n M A F K L L L I I I I I I U U P P P I ~ P P P W P W W W W W W W W Q Q Q Q Q W W W W W ~ ~ ~ W W Q Q ~ Q W W W W W W Q Q Q W W W W W W W W W W P W P P P P P P I I I I I I I I I L L K K F A m M n n x x x x z z z z x x n S b b b b b b b A v UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXM b b b b b b b b b b v z z x z x x x x x x n M M n m J K I K I I I L U L I I L P U P U P P P P W P W W P W W W W W W W W W W W W W W W W W W W W W W W W W W W W W W ~ W W W W W P P W P P W W P U U U U U U L U I I I I K I K K F m n n n x x c x x x z z z z c M b A b b b b b b b b c UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXl A b b b b b b b b A v x x z l z z x x x x n v n n n b D K K I K L L I I L L P U U U U P P P P P P P W P W W W W P P W W W W W W W W W W W ~ W W W P W W W W W W W P P W P P W P W P P P P I U U U U U I I I I I I K I K J A b n n n n x x x x x z z z z z M M A b b b b b b b b b l UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXk M b b b b b b b b b b v x l l x x z z x c x x n x n n m G K K K L I I L I L L L I U U U P P P P P P U W W P P W P W P W P ~ P W W W W W P W W P W P W W W W P P P P P W U U P U P P P P U U I U K U I I L L I K K J G m M v M n x x x x z z z z z l z v b b b b b b b b A A M k UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXl b b b b b b b b b b m c l x l l z l z c x x x x n x n n m F K K K L L L U I I I U I U I I P U U P U I P P I U W P P P P P P P P P P P P P W P P P P W P P P P P P P W U U I P I I I I I I I I I U I L K F F S v n n v M c x x x x z z z l l l v m N b b b b b b b A b l UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXk b b b b b b b b b b S m x x l x x z x z x x x n x x n n n v S H K L L L L L I I I U I I I I I U U P P P P P P W P P P P P P P W U P P P P U P P P P P P P I I P I U U U I I I I I I L L I I K K K F S m n n n x x x x x x x x z z l z l x v b b b b b b b b b b v k UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO l b b b b b b b b B b b v x l l l l z z z x z x x x x x n c n B b F K K L L I I I I I U I I I I I I I I U I U U P P P P U I U U P P P I U U U U P I I U I P U U I I L I I I I I L L L K K F S n M M M z x z x x x x z x z l l l z x v D A b b b b b b b b m l O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXk v b b b b b b b b b b b m x l z l z z z z x x l x x c c c c M n v b F F K K I I L L I I I I I I I I I I I I I I I U I U U I I P I I U U U U I U I I I L L I I I L I L K I K K K F b n n n n n x x x x z x z z z z l z z l x v b A b A b b b b b b b v k UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO l b b b b b b b b b b b m n z l l l l l z x x l x x x x x c c M n x n b S A K L K L L L L I L I I I I I I L I I I I I I I I I I I I L L I I I I I L L U L L L L K K K F S m M M x n x z x x x x z x x z z l l l l l x n m b b b b b b b b b b b l O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXk z m b b b b b b b b A A b v c l l l z l z l z z x x x x x x x n x n x n n m b D H K K K I K I L L L I I I L L I L L L I I L L L U L L L K L L K L K K K F D S m n x n n x x x x x x x x x z z z l l l l z l x v A A A b b b b b b b b b M k UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k v b b b b b b b b b b A b m M l l l z l l z z z z x x x x x x x x x M x n v x v m b S F F K K K K K I L K L L L K L L K I L K K K L K K J F G b m n n z n x x x x x x x x x x x x z z z l l z l z z c m N b A b b b b b b b b b b k + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO k b b b b b b A b b b b b b b v c l l l l l l l z x x l x x x x x z c c x c x z x x n x n n m b b S D F F F F K F F F F D S S b m n x x x M x M x M M x z x x z z z x x x x l l z l l l l l x c b N N N b b b b b b b b b b k O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO l b b b b A b b b b b N b b N v c l l l z l l l l x l l l x x z z z x x x z x x x n x x x x M x M x c n n c M M M x n n x M c c c x x x x x x x x z x x x z z z z l l l l l l l l l x v N N b N b b b b b b b b b b l O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXX O x A A A b b b b b b b b A b A b v x l l l l l l l l x l z x l x z l z x z z x x x x l x x x z x x z z z x z z z l x z x x x x x x z l z z z z z z z z z l x l l l l l l l z v N A A A b b b b b b b b b A A z O X UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXX O z A b b b b b b b b b b b A b b m M x l l l l l l l l l z l l l z x z z l x x l x l z z x z x x x x z x x x z z z z l l x x x z z z z z l l l l l l l l l l l l x V m A N b b b b b b b b b b b b b z O X UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO l b A A b b b b b b b b b b b b B N x x l l l l l l l l l l l l l l l x l x x l x l l x x l z l x l l x z z z z x z z l l l l l l l l l l l l l l l l x v m b b A b b b b b b b b b b b b b l O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO k b b b b b b b b b b b b b N B G B b B x l l l l l l l l l l l l l l l l l l z l l l l l l z l z l l l l l l l l l l l l l l l l l l l l z n v b N N b b N b b b b b b b b b b b v k O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k z b A A b b b b b b b b b b b A A b A b b M x z l l l l l l l l l l l l l l k z l l l l l l l l l l l l l l l l l l l l l z c M v b A N A b b N b b b b b b b b b A b b c k + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO k b b b b b b b b b b b b b b N b b A b A b b b v n z z l l l l l l l l l l l l l l l l l l l k z l l l l z c x v v b A A A b A b b b b b b b b b b b b b b b b k O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k l b v b b b b b b b b b b b b b b b N b b A b B S S m m x x M c z z l l l l l l l l z c x n v m v b A A b b b A b b A A b b b b b b b b b b A b b b l k + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k l b A b b b b b b b b b A b b b b b b b b b B b b N N b b b A b b b b b b b m A b A b N b b b b b b b b b b b b A b b b b b b b b b b A k k + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ O k x b b b b b b A A b b b b b b b b b b b b b b b b b b N b b b b B b b b b b b b b b b b b b b b b b b b b b b b b A A b M k O + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO k l v b b A A b b b A b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b A A A b A m l k O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k k M b A b b A b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b A A b b A M k k + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ k k l M v b b b b b b b b b b b b b b b b b b b b b b b b b b b b b m M l k O O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO O k k l l c M v m m b b b b b m m v M c l l k k O O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX" +}; +#if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR +extern void *allegro_icon; +CONSTRUCTOR_FUNCTION(static void _set_allegro_icon(void)); +static void _set_allegro_icon(void) +{ + allegro_icon = allegico_xpm; +} +#endif diff --git a/zc_icon.icns b/zc_icon.icns new file mode 100644 index 0000000000..f0e7004b2a Binary files /dev/null and b/zc_icon.icns differ diff --git a/zc_icon.ico b/zc_icon.ico new file mode 100644 index 0000000000..43942f16bc Binary files /dev/null and b/zc_icon.ico differ diff --git a/zc_icon.rc b/zc_icon.rc new file mode 100644 index 0000000000..dde7bb6188 --- /dev/null +++ b/zc_icon.rc @@ -0,0 +1 @@ +allegro_icon ICON MOVEABLE PURE LOADONCALL DISCARDABLE "./zc_icon.ico" diff --git a/zc_icon.xpm b/zc_icon.xpm new file mode 100644 index 0000000000..a02fd47c96 --- /dev/null +++ b/zc_icon.xpm @@ -0,0 +1,569 @@ +/* XPM */ +static const unsigned char * zc_icon_xpm[] = { +"32 32 534 2", +" c None", +"! c black", +"# c #50BF09", +"$ c #53C00C", +"% c #6CCA30", +"& c #83D350", +"' c #91D763", +"( c #90D761", +") c #82D24D", +"* c #69C92B", +"+ c #52C00B", +", c #51C00B", +"- c #50BF08", +". c #71CC36", +"0 c #A9E185", +"1 c #D3F1BF", +"2 c #DAF4C9", +"3 c #DAF5C9", +"4 c #CFEFBA", +"5 c #A3DE7C", +"6 c #69C92C", +"7 c #51C00A", +"8 c #65C726", +"9 c #B2E490", +": c #D3F2BF", +"; c #D4F3BF", +"< c #D4F5BF", +"= c #D5F5BF", +"> c #D5F6BF", +"? c #D4F4BF", +"@ c #D3F1BE", +"A c #A9E184", +"B c #5EC51C", +"C c #82D24E", +"D c #C8EDB0", +"E c #CDF1B5", +"F c #CEF3B4", +"G c #CEF5B4", +"H c #CFF7B5", +"I c #CFF8B5", +"J c #D0F8B5", +"K c #D0F9B5", +"L c #CDF3B4", +"M c #CDF1B4", +"N c #C5ECAA", +"O c #77CE3F", +"P c #4FBF07", +"Q c #87D455", +"R c #C4EDA9", +"S c #C5F0A9", +"T c #C7F3A9", +"U c #C8F6A9", +"V c #C9F8A9", +"W c #C9F9A9", +"X c #CAFAA9", +"Y c #CAFBA9", +"Z c #CAFCA9", +"[ c #C8F8A9", +"] c #C6F3A9", +"^ c #C3ECA8", +"_ c #7ED148", +"` c #4EBF06", +"a c #6CCA2F", +"b c #BEE8A2", +"c c #C0ECA2", +"d c #C3F0A4", +"e c #C3F3A3", +"f c #C4F6A2", +"g c #C6F7A4", +"h c #C4FAA0", +"i c #C5FBA2", +"j c #C6FBA2", +"k c #C6FAA3", +"l c #C5FAA2", +"m c #C4F8A0", +"n c #C3F79F", +"o c #C2F4A0", +"p c #C0F19F", +"q c #BEED9E", +"r c #BBE89D", +"s c #4FC006", +"t c #A1E077", +"u c #C2D9B3", +"v c #CCD0CF", +"w c #D8DBDC", +"x c #DADCDE", +"y c #DADEDF", +"z c #DBDDDF", +"{ c #D9DBDC", +"| c #D7DADB", +"} c #D5D8D9", +"~ c #D5D7D8", +" ! c #D4D5D7", +"!! c #D1D4D4", +"#! c #CFD3D3", +"$! c #CDD1D1", +"%! c #CCCFCE", +"&! c #CBCECD", +"'! c #CACCCB", +"(! c #C2C5C3", +")! c #B9CFAB", +"*! c #A0DF76", +"+! c #4FBF06", +",! c #62CA1D", +"-! c #ABE882", +".! c #AEED84", +"0! c #B0BAAB", +"1! c #ADAEAF", +"2! c #BCBFC0", +"3! c #B5B6B7", +"4! c #B7B9BA", +"5! c #B5B7B9", +"6! c #B4B7B8", +"7! c #B1B3B4", +"8! c #ABACAD", +"9! c #B8BABB", +":! c #B7B9BB", +";! c #B8BBBD", +"! c #B3B4B6", +"?! c #A9ABAC", +"@! c #B8BBBC", +"A! c #B1B6AD", +"B! c #ADEA85", +"C! c #AAE782", +"D! c #62C91D", +"E! c #74D534", +"F! c #A3EA75", +"G! c #A6F075", +"H! c #B2D89A", +"I! c #A9ABAD", +"J! c #C7CBCD", +"K! c #C8CBCD", +"L! c #C6CACC", +"M! c #C4C7CA", +"N! c #C8CCCF", +"O! c #CDD0D2", +"P! c #B7B7BA", +"Q! c #C2C6C7", +"R! c #D6D9DB", +"S! c #D3D7DA", +"T! c #D1D5D7", +"U! c #BABDBF", +"V! c #BDC1C2", +"W! c #B6B8B9", +"X! c #B8D2A9", +"Y! c #A3E975", +"Z! c #74D334", +"[! c #52C406", +"]! c #77DA36", +"^! c #9CEC66", +"_! c #9FF367", +"`! c #ADE18C", +"a! c #AAADAF", +"b! c #C6CACB", +"c! c #ADAEB1", +"d! c #D4D7DA", +"e! c #C4C8CB", +"f! c #B8BABC", +"g! c #C5C8CA", +"h! c #B2B5B9", +"i! c #DBDEE0", +"j! c #D8DBDE", +"k! c #C9CDD0", +"l! c #A8AAAD", +"m! c #B1B4B6", +"n! c #B1B4B7", +"o! c #B5B8B8", +"p! c #B2D59C", +"q! c #9FF267", +"r! c #9BEB67", +"s! c #77D936", +"t! c #51C306", +"u! c #54C906", +"v! c #71DC2B", +"w! c #95ED5A", +"x! c #98F55A", +"y! c #A7E67F", +"z! c #A5A9AB", +"{! c #BBC0C2", +"|! c #A9AAAC", +"}! c #DBDFE0", +"~! c #D9DEE0", +" # c #BFC4C7", +"!# c #B8BDC0", +"## c #B0B3B6", +"$# c #BEC2C4", +"%# c #D9DBDB", +"&# c #D5D9DA", +"'# c #A9AAAE", +"(# c #B9BABD", +")# c #BFC2C5", +"*# c #B2B6B9", +"+# c #B0B3B4", +",# c #B1DA99", +"-# c #97F45A", +".# c #94EC59", +"0# c #71DB2B", +"1# c #54C706", +"2# c #56CD06", +"3# c #66DD17", +"4# c #8DEE4D", +"5# c #91F64D", +"6# c #A2E479", +"7# c #9C9FA1", +"8# c #B8BDBF", +"9# c #939596", +":# c #ADB2B1", +";# c #D5DADB", +"<# c #C0C4C6", +"=# c #ACB1B4", +"># c #ACAFB2", +"?# c #BABFC1", +"@# c #D1D6D8", +"A# c #A0A2A5", +"B# c #B5B9BC", +"C# c #BFC5C8", +"D# c #CBCFD2", +"E# c #B1B4B8", +"F# c #ACB0B2", +"G# c #B0D998", +"H# c #90F54D", +"I# c #8DED4D", +"J# c #65DB17", +"K# c #55CB06", +"L# c #50C106", +"M# c #57CF06", +"N# c #5DDD07", +"O# c #81EE38", +"P# c #89F73F", +"Q# c #9DE36F", +"R# c #919496", +"S# c #B5BBBD", +"T# c #A2A5A9", +"U# c #888A8D", +"V# c #9DA1A2", +"W# c #A0A4A8", +"X# c #B0B5B8", +"Y# c #A3A6A9", +"Z# c #ACB1B3", +"[# c #96989A", +"]# c #8F9093", +"^# c #A8ACAE", +"_# c #C1C6C8", +"`# c #C5CACD", +"a# c #A7ADB1", +"b# c #A4A8A9", +"c# c #ABD293", +"d# c #89F63F", +"e# c #80ED38", +"f# c #5CDC07", +"g# c #50C206", +"h# c #57D006", +"i# c #5DDF07", +"j# c #6DEC18", +"k# c #82F733", +"l# c #96E166", +"m# c #8B8D90", +"n# c #AEB4B5", +"o# c #BEC4C7", +"p# c #B4BDC1", +"q# c #B4B8BC", +"r# c #B3B7BA", +"s# c #B3B9BC", +"t# c #909295", +"u# c #A0A6A7", +"v# c #A6ACAF", +"w# c #9EA1A5", +"x# c #A2A6A9", +"y# c #B3B8BA", +"z# c #B7BCBE", +"{# c #989B9F", +"|# c #A0A2A2", +"}# c #A4D18B", +"~# c #81F633", +" $ c #6CEB17", +"!$ c #5CDD07", +"#$ c #4FC106", +"$$ c #5DDE07", +"%$ c #63EB08", +"&$ c #74F61D", +"'$ c #90E15D", +"($ c #88898C", +")$ c #848789", +"*$ c #888C8E", +"+$ c #8F9294", +",$ c #8B8E91", +"-$ c #868A8C", +".$ c #7F8486", +"0$ c #6E7172", +"1$ c #7D8184", +"2$ c #7D8081", +"3$ c #828486", +"4$ c #818586", +"5$ c #7D8285", +"6$ c #777C7E", +"7$ c #6C6E6F", +"8$ c #989D9D", +"9$ c #9FD083", +":$ c #73F51D", +";$ c #62E907", +"<$ c #56CF06", +"=$ c #62EA07", +">$ c #67F508", +"?$ c #84DD4C", +"@$ c #7C7F82", +"A$ c #9CA3A7", +"B$ c #BBC1C4", +"C$ c #ADB2B5", +"D$ c #B7BEC2", +"E$ c #B6BCC0", +"F$ c #85868B", +"G$ c #909497", +"H$ c #9DA4A7", +"I$ c #A6ABAF", +"J$ c #A3A6AB", +"K$ c #9EA0A4", +"L$ c #A2A6AA", +"M$ c #79787D", +"N$ c #929899", +"O$ c #94C677", +"P$ c #66F308", +"Q$ c #61E807", +"R$ c #5CDB07", +"S$ c #5BDB07", +"T$ c #61E707", +"U$ c #66F207", +"V$ c #75DA35", +"W$ c #696C6E", +"X$ c #9EA3A6", +"Y$ c #AFB3B5", +"Z$ c #9AA0A2", +"[$ c #909597", +"]$ c #99A2A4", +"^$ c #ADB3B6", +"_$ c #888B91", +"`$ c #A0A5A8", +"a$ c #92979C", +"b$ c #B5BABE", +"c$ c #B2B9BE", +"d$ c #A5ABAF", +"e$ c #AEB5B7", +"f$ c #8F9194", +"g$ c #828788", +"h$ c #85BB63", +"i$ c #65F107", +"j$ c #60E607", +"k$ c #5BD907", +"l$ c #53C606", +"m$ c #59D707", +"n$ c #5FE407", +"o$ c #64EF07", +"p$ c #69CF25", +"q$ c #515252", +"r$ c #939699", +"s$ c #AAADB1", +"t$ c #B1B5B9", +"u$ c #888D91", +"v$ c #92989C", +"w$ c #A2A9AC", +"x$ c #84878B", +"y$ c #979D9F", +"z$ c #86898D", +"{$ c #C4C9CC", +"|$ c #C9CDD1", +"}$ c #B2B6BA", +"~$ c #ACB3B6", +" % c #8F9296", +"!% c #7D8183", +"#% c #78AF53", +"$% c #63EE07", +"%% c #5FE207", +"&% c #59D507", +"'% c #50BF06", +"(% c #57D107", +")% c #66C724", +"*% c #565558", +"+% c #A4A8AA", +",% c #A5ACB0", +"-% c #888B8F", +".% c #929699", +"0% c #9DA5A7", +"1% c #A7ADAF", +"2% c #858A8F", +"3% c #97A0A2", +"4% c #83898D", +"5% c #ABB1B2", +"6% c #CBD0D3", +"7% c #999FA3", +"8% c #939A9C", +"9% c #747879", +":% c #629D3A", +";% c #56CE06", +"<% c #4EBE06", +"=% c #53C607", +">% c #5AD807", +"?% c #60E407", +"@% c #7AD63F", +"A% c #808287", +"B% c #A4ABAC", +"C% c #B1B5B8", +"D% c #969C9F", +"E% c #9DA3A6", +"F% c #9BA0A5", +"G% c #A8AEB1", +"H% c #8A8D93", +"I% c #9EA8A9", +"J% c #ACB4B8", +"K% c #8A8C92", +"L% c #939999", +"M% c #8B9295", +"N% c #A2A8AB", +"O% c #8E9195", +"P% c #757879", +"Q% c #63A139", +"R% c #5FE307", +"S% c #5AD707", +"T% c #52C307", +"U% c #4EBC07", +"V% c #56CF07", +"W% c #70D92B", +"X% c #888E8F", +"Y% c #9A9FA3", +"Z% c #AEB6B8", +"[% c #B1B6BA", +"]% c #AEB7BA", +"^% c #898C91", +"_% c #A2AAAC", +"`% c #C4C9CD", +"a% c #BEC3C7", +"b% c #A3A7AE", +"c% c #A3A9AD", +"d% c #BCC2C5", +"e% c #8F9196", +"f% c #A8AFB0", +"g% c #80C358", +"h% c #55CC07", +"i% c #4EBC06", +"j% c #4EBD06", +"k% c #4FBC07", +"l% c #58D307", +"m% c #5DDE08", +"n% c #61804E", +"o% c #696E6D", +"p% c #6E7272", +"q% c #8D9294", +"r% c #969C9E", +"s% c #9CA3A4", +"t% c #A6ADAE", +"u% c #717578", +"v% c #959A9A", +"w% c #9EA2A4", +"x% c #7E8080", +"y% c #7E8282", +"z% c #828586", +"{% c #868989", +"|% c #A9B6A9", +"}% c #69D521", +"~% c #4EBA07", +" & c #4DBA06", +"!& c #4FBD07", +"#& c #58D407", +"$& c #5CD70A", +"%& c #569629", +"&& c #6C7D63", +"'& c #868D89", +"(& c #7B7C7F", +")& c #6A6E71", +"*& c #545557", +"+& c #575B5B", +",& c #5D6161", +"-& c #4A4C4D", +".& c #3D3B3D", +"0& c #495044", +"1& c #566152", +"2& c #607D4D", +"3& c #70AD47", +"4& c #64D11C", +"5& c #58D207", +"6& c #4DBC06", +"7& c #4BB906", +"8& c #4CB806", +"9& c #4DB908", +":& c #62E509", +";& c #66E411", +"<& c #72DD2C", +"=& c #77A959", +">& c #4C4D4A", +"?& c #7F8585", +"@& c #698F4E", +"A& c #61C022", +"B& c #63E80A", +"C& c #62E808", +"D& c #56CE07", +"E& c #4CB608", +"F& c #4CB906", +"G& c #4AB706", +"H& c #31790B", +"I& c #4AB108", +"J& c #52C407", +"K& c #60C51C", +"L& c #7AC649", +"M& c #62E708", +"N& c #51C207", +"O& c #2C6B0C", +"P& c #1D490F", +"Q& c #49B107", +"R& c #4AB207", +"S& c #4AB008", +"T& c #51C107", +"U& c #56D007", +"V& c #49AF08", +"W& c #4AB307", +"X& c #46AB07", +"Y& c #173810", +"Z& c #071313", +"[& c #2E720B", +"]& c #4BB606", +"^& c #48AC08", +"_& c #48AD08", +"`& c #4BB408", +"a& c #49AD08", +"b& c #49B307", +"c& c #29660C", +"d& c #040B14", +"e& c #061013", +"f& c #21530E", +"g& c #388A0A", +"h& c #48B007", +"i& c #4BB506", +"j& c #47AC07", +"k& c #36840A", +"l& c #1E4A0F", +" ", +" ", +" # $ % & ' ( ) * + , ", +" - . 0 1 2 2 3 3 2 2 4 5 6 # ", +" 7 8 9 : ; < = > > > > = ? ; @ A B ", +" # C D E F G H I J K K J I H G L M N O + ", +" P Q R S T U V W X Y Z Z Y X W [ U ] S ^ _ 7 ", +" ` a b c d e f g h i j j j k l h m n o p q r 6 ", +" s t u v w x y z w { | } ~ !!!#!$!%!&!'!(!)!*!+! ", +" ` ,!-!.!0!1!2!3!4!5!6!7!8!9!:!;!!?!@!A!B!C!D!` ", +" s E!F!G!H!I!J!K!L!M!N!O!P!Q!R!S!T!U!V!:!W!X!G!Y!Z!s ", +" ` [!]!^!_!`!a!b!c!d!e!f!g!h!Q!i!j!k!l!m!n!o!p!q!r!s!t!` ", +" ` u!v!w!x!y!z!{!|!}!~! #!###$#%#&#'#(#)#*#+#,#-#.#0#1#` ", +" s 2#3#4#5#6#7#8#9#:#;#<#=#>#?#@#A#B#C#D#E#F#G#H#I#J#K#+! ", +" L#M#N#O#P#Q#R#S#T#U#V#W#X#Y#Z#[#]#^#_#`#a#b#c#d#e#f#2#s ", +" g#h#i#j#k#l#m#n#o#p#q#r#s#t#u#v#w#x#y#z#{#|#}#~# $!$M##$ ", +" g#h#$$%$&$'$($)$*$+$,$-$.$0$1$2$3$4$5$6$7$8$9$:$;$!$<$#$ ", +" L#M#!$=$>$?$@$A$B$z#C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$2#s ", +" +!K#S$T$U$V$W$X$Y$Z$[$]$^$_$`$a$b$c$d$e$f$g$h$i$j$k$u!` ", +" ` l$m$n$o$p$q$r$s$t$u$v$w$x$y$z${$|$}$~$ %!%#%$%%%&%[!` ", +" ` '%(%i#=$)%*%+%,%-%.%0%1%2%3%4%5%6%s#7%8%9%:%;$!$;%+! ", +" <%=%>%?%@%A%B%C%D%E%F%G%H%I%J%K%L%M%N%O%P%Q%R%S%T%<% ", +" <%U%V%!$W%X%Y%Z%[%7%G%]%^%_%`%a%b%c%d%e%f%g%R$h%i%<% ", +" j%k%l%m%n%o%p%q%r%s%t%u%v%C$w%x%y%z%{%|%}%(%~%<% ", +" &!&#&$&%&&&'&(&)&*&+&,&-&.&0&1&2&3&4&5&~%6& ", +" 7&8&9&(%f#R%:&;&<&=&>&?&@&A&B&C&R%R$D&E&F&G& ", +" H&F&I&J&S%$$R%j$Q$K&L&M&j$%%!$&%N&I&F&O& ", +" P&Q&R&S&T&U&k$f#!$!$R$>%D&- V&W&X&Y& ", +" Z&[&]&R&^&_&`&9&9&`&^&a&W&b&c&d& ", +" e&f&g&h&8&i&i&8&j&k&l&d& ", +" ", +" "}; \ No newline at end of file diff --git a/zc_icon_old.xpm b/zc_icon_old.xpm new file mode 100644 index 0000000000..3aa0c2e5a2 --- /dev/null +++ b/zc_icon_old.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * zc_icon_xpm[] = { +"32 32 5 1", +" c None", +"! c black", +"# c #C0C0C0", +"$ c white", +"% c #808080", +" ############################## ", +" #$$$$$$$$$$$$$$$$$$$$$$$$$$$$# ", +" #$########################%# ", +" #$########################%# ", +" #$##%%%%%%%%##%%%%%%%%##%# ", +" #$##% $##%####%%$##%# ", +" #$##% $##%###%##%##%# ", +" #$##% $##%###%##%##%# ", +" #$##% $##%###%%%$##%# ", +" #$##% $##%##%%##$##%# ", +" #$##% $##%##%###$##%# ", +" #$##% $##%#%#%##$##%# ", +" #$##% $##%%%####$##%# ", +" #$##%$$$$$$$##%$$%$$$$##%# ", +" #$######################%# ", +" #$######################%# ", +" #$##%%%%%%%%##%%%%%%%%##%# ", +" #$##%###%%#$##%######$##%# ", +" #$##%##%#%%$##%#%%#%%$##%# ", +" #$##%#%#%#%%##%%##%##%##%# ", +" #$##%##%##%$##%%#####%##%# ", +" #$##%#%####$##%%#####%##%# ", +" #$##%%###%%$##%#%###%$##%# ", +" #$##%%#%###$##%##%#%#$##%# ", +" #$##%%%%%##$##%###%##$##%# ", +" #$##%#%####$##%######$##%# ", +" #%##$$%###$##%####$$##%# ", +" ##%###$$$$$##%$$$$###%## ", +" ##%%##############%%## ", +" ##%%%%%%##%%%%%%## ", +" ######%%###### ", +" ## "}; \ No newline at end of file diff --git a/zc_icon_small.xpm b/zc_icon_small.xpm new file mode 100644 index 0000000000..98533b2e81 --- /dev/null +++ b/zc_icon_small.xpm @@ -0,0 +1,170 @@ +/* XPM */ +static const unsigned char * zc_icon_small_xpm[] = { +"16 16 151 2", +" c None", +"! c black", +"# c #6FCB33", +"$ c #9BDC71", +"% c #B2E591", +"& c #B1E490", +"' c #99DB6E", +"( c #6CCA2F", +") c #5DC41A", +"* c #ABE287", +"+ c #D1F3BA", +", c #D2F6BA", +"- c #D3F7BA", +". c #D2F7BA", +"0 c #A6E180", +"1 c #5BC318", +"2 c #56C211", +"3 c #B2E590", +"4 c #C4F2A6", +"5 c #C7F7A6", +"6 c #C7FAA5", +"7 c #C8FBA6", +"8 c #C6F7A4", +"9 c #C3F2A4", +": c #AFE58B", +"; c #7FD447", +"< c #BBD4AC", +"= c #C7C9CA", +"> c #C8CACC", +"? c #C2C4C5", +"@ c #C6C8C9", +"A c #C4C7C8", +"B c #C1C3C4", +"C c #BDC0C0", +"D c #B6CDA8", +"E c #7FD347", +"F c #4FC006", +"G c #8BE151", +"H c #A9E780", +"I c #B8BBBD", +"J c #C4C7C9", +"K c #C2C5C8", +"L c #BFC1C4", +"M c #CDD1D3", +"N c #D1D5D7", +"O c #B4B7B9", +"P c #B5B7B9", +"Q c #ABE288", +"R c #8AE051", +"S c #52C506", +"T c #7EE53A", +"U c #9CED68", +"V c #ADB1B3", +"W c #B1B4B5", +"X c #CBD0D2", +"Y c #B0B4B7", +"Z c #C9CCCE", +"[ c #B5B7BA", +"] c #C0C4C7", +"^ c #B0B3B6", +"_ c #A2E776", +"` c #7EE43A", +"a c #51C406", +"b c #54C906", +"c c #6AE517", +"d c #8FED52", +"e c #A0A4A6", +"f c #A7ACAF", +"g c #A9ADB0", +"h c #A5A9AD", +"i c #A2A7A9", +"j c #9EA1A4", +"k c #BCC1C3", +"l c #A1A5A7", +"m c #96E464", +"n c #69E417", +"o c #53C706", +"p c #53C806", +"q c #5FE407", +"r c #7CEA33", +"s c #898C90", +"t c #9DA2A5", +"u c #8A8E91", +"v c #8A8E90", +"w c #93969A", +"x c #8D9194", +"y c #848788", +"z c #83E047", +"{ c #5FE207", +"| c #5DDF07", +"} c #6AE31A", +"~ c #7B7E80", +" ! c #91979A", +"!! c #979BA0", +"#! c #94999C", +"$! c #BDC2C6", +"%! c #ACB2B6", +"&! c #878B8D", +"'! c #71D231", +"(! c #5DDE07", +")! c #51C306", +"*! c #4EBF06", +"+! c #58D307", +",! c #68DB1C", +"-! c #9DA2A6", +".! c #9AA0A3", +"0! c #989CA1", +"1! c #99A1A4", +"2! c #A5A9AC", +"3! c #9EA4A8", +"4! c #838689", +"5! c #61C320", +"6! c #58D107", +"7! c #50C106", +"8! c #61DA10", +"9! c #7B877B", +":! c #969C9E", +";! c #9DA3A6", +"! c #989D9E", +"?! c #99A09E", +"@! c #67D121", +"A! c #50C006", +"B! c #4CBB06", +"C! c #50C007", +"D! c #59C710", +"E! c #6DB53F", +"F! c #6FAB4B", +"G! c #5C6955", +"H! c #647060", +"I! c #528D2B", +"J! c #5EAA2B", +"K! c #61CA1C", +"L! c #50BF07", +"M! c #275E0D", +"N! c #4CB607", +"O! c #54CA07", +"P! c #5CDC07", +"Q! c #5ED90C", +"R! c #65D918", +"S! c #54C807", +"T! c #4BB407", +"U! c #23570D", +"V! c #0D2112", +"W! c #2F730C", +"X! c #44A508", +"Y! c #4CB707", +"Z! c #43A208", +"[! c #2D6F0C", +"]! c #0B1C12", +" ", +" # $ % & ' ( ", +" ) * + , - . , + 0 1 ", +" 2 3 4 5 6 7 7 6 8 9 : 2 ", +" ; < = > = ? @ A B C D E ", +" F G H I J K L M N O P Q R F ", +" S T U V W X Y Z [ ] ^ _ ` a ", +" b c d e f g h i j k l m n o ", +" p q r s i t u v w x y z { o ", +" a | } ~ g !!!#!$!%!&!'!(!)! ", +" *!+!,!&!-!.!0!1!2!3!4!5!6!*! ", +" 7!8!9!:!;!#!!?!@!A! ", +" B!C!D!E!F!G!H!I!J!K!L!B! ", +" M!N!O!P!Q!R!P!S!T!U! ", +" V!W!X!Y!N!Z![!]! ", +" "}; \ No newline at end of file diff --git a/zc_icon_small_old.xpm b/zc_icon_small_old.xpm new file mode 100644 index 0000000000..88873bdb3d --- /dev/null +++ b/zc_icon_small_old.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * zc_icon_small_xpm[] = { +"16 16 5 1", +" c None", +"! c #C0C0C0", +"# c white", +"$ c black", +"% c #808080", +"!!!!!!!!!!!!!!!!", +"!##############!", +" !#%%%%!!%%%%%! ", +" !#% #!!%!%#%! ", +" !#% #!!%!%%%! ", +" !#% #!!%%!#%! ", +" !#%###!!%###%! ", +" !#!!!!!!!!!!%! ", +" !#%%%%!!%%%%%! ", +" !#%!%%!!%!!#%! ", +" !#%!%%!!%%!%%! ", +" !#%%%#!!%!%#%! ", +" !#%%##!!%###%! ", +" !%%%%!!%%%%! ", +" !!!!%%!!!! ", +" !! "}; \ No newline at end of file diff --git a/zl_icon.icns b/zl_icon.icns new file mode 100644 index 0000000000..8dc84ca7d9 Binary files /dev/null and b/zl_icon.icns differ diff --git a/zl_icon.ico b/zl_icon.ico new file mode 100644 index 0000000000..4f423ce88a Binary files /dev/null and b/zl_icon.ico differ diff --git a/zl_icon.xpm b/zl_icon.xpm new file mode 100644 index 0000000000..6dbc52f4b1 --- /dev/null +++ b/zl_icon.xpm @@ -0,0 +1,553 @@ +/* XPM */ +static const unsigned char * zl_icon_xpm[] = { +"32 32 518 2", +" c None", +"! c black", +"# c #07B0C9", +"$ c #0AB1CA", +"% c #2EBCD3", +"& c #4FC7DA", +"' c #61CDDE", +"( c #60CDDE", +") c #4CC6D9", +"* c #29BBD2", +"+ c #09B0CA", +", c #06AFC9", +"- c #34BED4", +". c #83D8E6", +"0 c #BFECF4", +"1 c #C9F0F7", +"2 c #C9F1F8", +"3 c #BAEBF3", +"4 c #7AD5E4", +"5 c #2ABBD2", +"6 c #08B0CA", +"7 c #24B9D0", +"8 c #8FDDE9", +"9 c #BFEDF5", +": c #BFEFF8", +"; c #BFF1F9", +"< c #BFF2FA", +"= c #BFF2FB", +"> c #BFF3FB", +"? c #C0F0F8", +"@ c #BFEFF7", +"A c #BEEDF5", +"B c #82D8E6", +"C c #1AB6CE", +"D c #07AFC9", +"E c #4CC6DA", +"F c #AFE8F2", +"G c #B5EDF6", +"H c #B5EFF9", +"I c #B5F1FB", +"J c #B5F3FD", +"K c #B6F4FE", +"L c #B6F5FE", +"M c #B7F3FC", +"N c #BFE6EB", +"O c #BFE5E9", +"P c #B6F2FB", +"Q c #B5ECF6", +"R c #AAE6F0", +"S c #3DC1D6", +"T c #05AFC9", +"U c #53C9DC", +"V c #A9E7F2", +"W c #A9EBF6", +"X c #A9EFFA", +"Y c #AAF1FD", +"Z c #ABF4FE", +"[ c #ADF5FF", +"] c #AEF5FF", +"^ c #AFF2FC", +"_ c #C0E4E7", +"` c #AEDADD", +"a c #AFF5FE", +"b c #ACF4FF", +"c c #ABF3FE", +"d c #A9EEFA", +"e c #A8E6F1", +"f c #47C5D9", +"g c #04AFC9", +"h c #2CBDD4", +"i c #9CE4F0", +"j c #9DE9F6", +"k c #9DEDFB", +"l c #9EF1FE", +"m c #A1F3FF", +"n c #A4F3FF", +"o c #A6F4FF", +"p c #A7F4FF", +"q c #ABEAF2", +"r c #B9E2E4", +"s c #A3D8DD", +"t c #A8F4FF", +"u c #A3F3FF", +"v c #A0F3FF", +"w c #9DEDFA", +"x c #9DE8F5", +"y c #9AE3EF", +"z c #04AFCA", +"{ c #74D7E8", +"| c #90E5F4", +"} c #90EBFA", +"~ c #92F0FE", +" ! c #95F2FF", +"!! c #9AF2FF", +"#! c #9CF3FF", +"$! c #9EF3FF", +"%! c #A2E7EF", +"&! c #AEDEE1", +"'! c #A6D6DA", +"(! c #A8DBE0", +")! c #A7DDE3", +"*! c #A4DFE5", +"+! c #A0E1E8", +",! c #99E1EA", +"-! c #93E8F3", +".! c #91EFFE", +"0! c #90EAFA", +"1! c #90E5F3", +"2! c #74D6E7", +"3! c #03AFC9", +"4! c #1CBAD5", +"5! c #83E1F1", +"6! c #83E7F8", +"7! c #84EDFE", +"8! c #89F0FF", +"9! c #8EF1FF", +":! c #92F2FF", +";! c #97F3FF", +"! c #B1E2E6", +"?! c #E6F9FA", +"@! c #D4F1F4", +"A! c #CBEDF0", +"B! c #C1E9EB", +"C! c #B7E4E7", +"D! c #ACDEE1", +"E! c #89CBD0", +"F! c #88F0FF", +"G! c #84EDFD", +"H! c #83E7F7", +"I! c #82E0EF", +"J! c #1CB9D4", +"K! c #03AEC9", +"L! c #03B0CB", +"M! c #34C7E1", +"N! c #75E2F4", +"O! c #76E9FC", +"P! c #7BEEFF", +"Q! c #81EFFF", +"R! c #87F1FF", +"S! c #8BF1FF", +"T! c #8DF2FF", +"U! c #8FF2FF", +"V! c #8FEBF7", +"W! c #99CFD3", +"X! c #D9F5F7", +"Y! c #F3FAFB", +"Z! c #C2CADD", +"[! c #C9D2DF", +"]! c #D0DDE5", +"^! c #D7E9EE", +"_! c #E1F9FB", +"`! c #84C4C8", +"a! c #80ECFB", +"b! c #7AEEFE", +"c! c #76E8FB", +"d! c #75E1F3", +"e! c #33C6DF", +"f! c #03AFCA", +"g! c #04B3D1", +"h! c #37CEE8", +"i! c #68E3F8", +"j! c #6BEBFE", +"k! c #72EDFF", +"l! c #79EFFF", +"m! c #7EF0FF", +"n! c #82F0FF", +"o! c #85F0FF", +"p! c #86F0FF", +"q! c #88DBE5", +"r! c #9CD7DB", +"s! c #F1FCFC", +"t! c #A3B0CC", +"u! c #949BD5", +"v! c #8991D3", +"w! c #979ED7", +"x! c #8990C0", +"y! c #D2F3F5", +"z! c #89CDD1", +"{! c #73DCE9", +"|! c #71EDFF", +"}! c #6AEAFE", +"~! c #68E2F7", +" # c #37CCE6", +"!# c #04B2CF", +"## c #06B8D7", +"$# c #2CD0EC", +"%# c #5BE4FB", +"&# c #60EBFF", +"'# c #69ECFF", +"(# c #70EEFF", +")# c #76EFFF", +"*# c #7CEFFF", +"+# c #7DEFFF", +",# c #7BCDD5", +"-# c #ADE3E7", +".# c #B3C5D7", +"0# c #838ACD", +"1# c #A2B0EB", +"2# c #B9C6F6", +"3# c #A0AFED", +"4# c #6F76BF", +"5# c #ACD4DA", +"6# c #99DADE", +"7# c #64CAD5", +"8# c #68ECFF", +"9# c #5FEBFF", +":# c #5BDEF4", +";# c #2CC8E2", +"<# c #05B6D5", +"=# c #03AFCB", +"># c #07BDDC", +"?# c #18D0EF", +"@# c #4FE5FD", +"A# c #57EAFF", +"B# c #60ECFF", +"C# c #67EDFF", +"D# c #6CEEFF", +"E# c #72EEFF", +"F# c #73EEFF", +"G# c #66C2CB", +"H# c #A9E3E7", +"I# c #ADC1D5", +"J# c #7C86CF", +"K# c #AABBF5", +"L# c #ADBEF7", +"M# c #8492CA", +"N# c #636BB2", +"O# c #8BB4C5", +"P# c #A6E6EB", +"Q# c #57BAC3", +"R# c #5FECFF", +"S# c #55EAFF", +"T# c #5ACEDE", +"U# c #1AB2C9", +"V# c #06BAD9", +"W# c #04B1CD", +"X# c #07BFDF", +"Y# c #09D0F1", +"Z# c #3CE4FE", +"[# c #4DE9FF", +"]# c #56EBFF", +"^# c #5DECFF", +"_# c #63EDFF", +"`# c #69EDFF", +"a# c #5AC7D3", +"b# c #8AD2D7", +"c# c #A7C0D1", +"d# c #6068B9", +"e# c #6671B1", +"f# c #6A76B7", +"g# c #51578F", +"h# c #5A6C89", +"i# c #A0D3D7", +"j# c #AEF0F5", +"k# c #59B2B9", +"l# c #54E6F9", +"m# c #4ED8EA", +"n# c #5CAFB5", +"o# c #07B4CF", +"p# c #08C1E1", +"q# c #09D1F3", +"r# c #1CE0FE", +"s# c #42E7FF", +"t# c #4CEAFF", +"u# c #54EBFF", +"v# c #59ECFF", +"w# c #5EECFF", +"x# c #57D0DE", +"y# c #6EC3C9", +"z# c #BEEAF0", +"{# c #6382A4", +"|# c #52668D", +"}# c #4D5D8B", +"~# c #59738E", +" $ c #96D1D6", +"!$ c #B7F8FD", +"#$ c #B1F7FD", +"$$ c #82D4DA", +"%$ c #6FBBC0", +"&$ c #6AB9BF", +"'$ c #1D99A6", +"($ c #09CDEE", +")$ c #07BFDE", +"*$ c #03B0CC", +"+$ c #0DDEFE", +",$ c #2DE5FF", +"-$ c #42E9FF", +".$ c #4AEAFF", +"0$ c #50EBFF", +"1$ c #55EBFF", +"2$ c #57EBFF", +"3$ c #56C7D4", +"4$ c #66C2C8", +"5$ c #A2E9EE", +"6$ c #9EE7EC", +"7$ c #A8ECF1", +"8$ c #A5E7ED", +"9$ c #8DDAE0", +":$ c #87DBE1", +";$ c #94E6EC", +"<$ c #94E7EE", +"=$ c #8BE1E8", +">$ c #67C5CB", +"?$ c #2A9EA7", +"@$ c #0ACDEB", +"A$ c #09CFF1", +"B$ c #04B0CC", +"C$ c #0CDDFE", +"D$ c #18E2FF", +"E$ c #32E7FF", +"F$ c #41E9FF", +"G$ c #47EAFF", +"H$ c #4EEAFF", +"I$ c #4DCAD9", +"J$ c #57B3B9", +"K$ c #58BBC2", +"L$ c #2F9CA4", +"M$ c #319EA7", +"N$ c #4BB1B7", +"O$ c #7DD7DD", +"P$ c #52B1B8", +"Q$ c #31ABB7", +"R$ c #31A4AD", +"S$ c #2FA1AB", +"T$ c #2CA5B0", +"U$ c #24B7C8", +"V$ c #15D7F2", +"W$ c #0BDCFD", +"X$ c #09CEEF", +"Y$ c #06BBDA", +"Z$ c #0BDBFC", +"[$ c #15E2FF", +"]$ c #22E5FF", +"^$ c #31E6FF", +"_$ c #3EE9FF", +"`$ c #43E9FF", +"a$ c #44C7D7", +"b$ c #50AFB6", +"c$ c #4FB7BE", +"d$ c #259FAB", +"e$ c #46E4F9", +"f$ c #48E8FE", +"g$ c #3AC8DA", +"h$ c #32ADBA", +"i$ c #4DC8D6", +"j$ c #46E9FF", +"k$ c #3DE9FF", +"l$ c #30E6FF", +"m$ c #21E4FF", +"n$ c #13E2FF", +"o$ c #0AD9FB", +"p$ c #08CBEB", +"q$ c #06B9D8", +"r$ c #05B5D3", +"s$ c #08C8E9", +"t$ c #0AD7F9", +"u$ c #11E1FF", +"v$ c #1EE3FF", +"w$ c #28E6FF", +"x$ c #31E7FF", +"y$ c #39C7D8", +"z$ c #48ABB2", +"{$ c #4FB9C1", +"|$ c #209DA8", +"}$ c #40E3F9", +"~$ c #42E8FF", +" % c #41E8FF", +"!% c #3EE8FF", +"#% c #39E8FF", +"$% c #30E7FF", +"%% c #27E6FF", +"&% c #1CE3FF", +"'% c #0FE1FE", +"(% c #09D5F7", +")% c #08C6E6", +"*% c #05B3D1", +"+% c #04AFCB", +",% c #08C2E1", +"-% c #0CDEFE", +".% c #24E5FF", +"0% c #2FCADD", +"1% c #42A8AF", +"2% c #4AB7BF", +"3% c #1A9BA6", +"4% c #3AE2F8", +"5% c #3DE8FF", +"6% c #3CE8FF", +"7% c #3AE8FF", +"8% c #37E8FF", +"9% c #2BE6FF", +":% c #16E2FF", +";% c #0CDDFD", +"<% c #08BFDE", +"=% c #04AECA", +">% c #04AEC9", +"?% c #07B6D4", +"@% c #08CAEB", +"A% c #0AD7FA", +"B% c #11E1FE", +"C% c #22C7DD", +"D% c #40A8B0", +"E% c #67CBD2", +"F% c #16949E", +"G% c #34E2F8", +"H% c #38E8FF", +"I% c #35E8FF", +"J% c #2DE6FF", +"K% c #25E5FF", +"L% c #1BE2FF", +"M% c #0FE0FE", +"N% c #09D6F8", +"O% c #08C9E9", +"P% c #06B3D0", +"Q% c #05ABC7", +"R% c #08BFDF", +"S% c #09CFF0", +"T% c #14C1DA", +"U% c #3EA6AE", +"V% c #AEE8EC", +"W% c #5DBEC4", +"X% c #159EAB", +"Y% c #33E7FF", +"Z% c #34E8FF", +"[% c #1DE3FF", +"]% c #12E1FF", +"^% c #0ADAFC", +"_% c #08BCDB", +"`% c #04ABC7", +"a% c #03AEC8", +"b% c #04ADC8", +"c% c #06ACC8", +"d% c #0BB3CE", +"e% c #2F9AA1", +"f% c #76CED4", +"g% c #D7FAFD", +"h% c #68CBD1", +"i% c #15939D", +"j% c #27E1F9", +"k% c #2EE6FF", +"l% c #2CE6FF", +"m% c #2AE6FF", +"n% c #09D0F2", +"o% c #08C2E2", +"p% c #06AAC6", +"q% c #04AAC5", +"r% c #06A5C1", +"s% c #059AAD", +"t% c #2998A1", +"u% c #51B6BC", +"v% c #5FC7CE", +"w% c #209199", +"x% c #1DE1FD", +"y% c #23E5FF", +"z% c #08C4E3", +"{% c #07AAC7", +"|% c #04ABC6", +"}% c #04A9C2", +"~% c #04A8C2", +" & c #07A9C5", +"!& c #09BEDC", +"#& c #21B6CD", +"$& c #24B7CC", +"%& c #0EA7BB", +"&& c #10E1FF", +"'& c #14E2FF", +"(& c #08C0DF", +")& c #07A7C3", +"*& c #04A9C4", +"+& c #04A8C1", +",& c #096E7F", +"-& c #04A9C3", +".& c #07A2BD", +"0& c #08B6D4", +"1& c #09D5F8", +"2& c #08C7E7", +"3& c #08B3D0", +"4& c #06A1BC", +"5& c #04AAC4", +"6& c #0B6271", +"7& c #0E434D", +"8& c #05A2BB", +"9& c #05A2BD", +":& c #08A2BD", +";& c #09B3D0", +"<& c #09C2E1", +"=& c #09CBEC", +">& c #09CBEB", +"?& c #09C0DF", +"@& c #09B1CE", +"A& c #08A1BB", +"B& c #05A3BE", +"C& c #059CB4", +"D& c #0F333B", +"E& c #131114", +"F& c #0A6978", +"G& c #04A6C0", +"H& c #05A3BD", +"I& c #079EB8", +"J& c #089FB9", +"K& c #08A6C2", +"L& c #08ABC7", +"M& c #09AAC6", +"N& c #08A6C1", +"O& c #089EB8", +"P& c #05A4BE", +"Q& c #04A4BD", +"R& c #0B5D6B", +"S& c #130A0C", +"T& c #130F11", +"U& c #0D4C57", +"V& c #087E91", +"W& c #05A1B9", +"X& c #04A5C0", +"Y& c #059EB6", +"Z& c #09798B", +"[& c #0E444E", +" ", +" ", +" # $ % & ' ( ) * + + ", +" , - . 0 1 2 2 2 2 1 3 4 5 # ", +" 6 7 8 9 : ; < = > > ? ; ; @ A B C ", +" D E F G H I J K L M N O P J I H Q R S + ", +" T U V W X Y Z [ ] ^ _ ` a ] b c Y d W e f 6 ", +" g h i j k l m n o p q r s t p o u v l w x y * ", +" z { | } ~ !!!#!$!v %!&!'!(!)!*!+!,!-!.!0!1!2!z ", +" 3!4!5!6!7!8!9!:! !;!!?!@!A!B!C!D!E!F!G!H!I!J!K! ", +" L!M!N!O!P!Q!R!S!T!U!V!W!X!Y!Z![!]!^!_!`!a!b!c!d!e!f! ", +" K!g!h!i!j!k!l!m!n!o!p!q!r!s!t!u!v!w!x!y!z!{!|!}!~! #!#K! ", +" 3!##$#%#&#'#(#)#l!*#+#,#-#.#0#1#2#3#4#5#6#7#8#9#:#;#<#K! ", +" =#>#?#@#A#B#C#D#(#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#f! ", +" W#X#Y#Z#[#]#^#_#C#`#`#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#>#L! ", +" W#p#q#r#s#t#u#v#w#B#B#x#y#z#{#|#}#~# $!$#$$$%$&$'$($)$*$ ", +" W#p#q#+$,$-$.$0$1$2$2$3$4$5$6$7$8$9$:$;$<$=$>$?$@$A$)$*$ ", +" B$)$Y#C$D$E$F$G$t#H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$>#=# ", +" f!Y$($Z$[$]$^$_$`$a$b$c$d$e$f$g$h$i$j$`$k$l$m$n$o$p$q$f! ", +" K!r$s$t$u$v$w$x$y$z${$|$}$~$~$~$~$ %!%#%$%%%&%'%(%)%*%K! ", +" K!+%,%q#-%D$.%0%1%2%3%4%5%5%5%5%6%7%8%E$9%]$:%;%Y#<%=% ", +" >%?%@%A%B%C%D%E%F%G%H%#%7%7%#%H%I%E$J%K%L%M%N%O%P%K! ", +" K!Q%R%S%T%U%V%W%X%$%Y%Z%I%I%Z%E$$%9%K%[%]%^%X$_%`%a% ", +" b%c%d%e%f%g%h%i%j%9%J%k%k%l%m%%%]$L%]%Z$n%o%p%a% ", +" q%r%s%t%u%v%w%x%m$y%.%.%y%m$&%:%M%^%n%z%{%|% ", +" }%~% &!&#&$&%&&&'&:%D$D$:%n$'%;%N%X$(&)&*&+& ", +" ,&-&.&0&O%n%1&^%W$C$C$W$o$(%Y#2&3&4&5&6& ", +" 7&8&9&:&;&<&=&X$Y#A$X$>&?&@&A&B&C&D& ", +" E&F&G&H&I&J&K&L&M&N&O&I&P&Q&R&S& ", +" T&U&V&W&~%X&G&~%Y&Z&[&S& ", +" ", +" "}; \ No newline at end of file diff --git a/zl_icon_small.xpm b/zl_icon_small.xpm new file mode 100644 index 0000000000..baf9b2f821 --- /dev/null +++ b/zl_icon_small.xpm @@ -0,0 +1,167 @@ +/* XPM */ +static const unsigned char * zl_icon_small_xpm[] = { +"16 16 148 2", +" c None", +"! c black", +"# c #31BDD3", +"$ c #70D2E2", +"% c #91DEEA", +"& c #90DDEA", +"' c #6DD1E1", +"( c #2DBCD2", +") c #18B5CD", +"* c #86DBE8", +"+ c #BAEFF8", +", c #BAF2FC", +"- c #BBF3FC", +". c #BFEBF2", +"0 c #BBF1FA", +"1 c #7FD8E7", +"2 c #16B4CD", +"3 c #0EB2CB", +"4 c #8DDFED", +"5 c #A4EEFA", +"6 c #A6F3FE", +"7 c #AAF4FF", +"8 c #B5E8EE", +"9 c #AAE7EE", +": c #89DDEB", +"; c #0FB2CB", +"< c #46C8DE", +"= c #8AE9F9", +"> c #8FF1FE", +"? c #97F2FF", +"@ c #9BF3FF", +"A c #A5E0E5", +"B c #C2E7EA", +"C c #B6E5E9", +"D c #A7E1E7", +"E c #8DE4F0", +"F c #8AE9F8", +"G c #45C7DD", +"H c #03B0CB", +"I c #52D7ED", +"J c #73ECFE", +"K c #80F0FF", +"L c #88F1FF", +"M c #8BEAF6", +"N c #C0E6E8", +"O c #BBC4DE", +"P c #AEB7DB", +"Q c #C5D9E8", +"R c #80D6DF", +"S c #73EBFE", +"T c #52D5EC", +"U c #03AFCB", +"V c #05B5D2", +"W c #3CDAF5", +"X c #60EBFF", +"Y c #6EEEFF", +"Z c #76EFFF", +"[ c #74DBE7", +"] c #AED3DF", +"^ c #939EDF", +"_ c #A3B1E9", +"` c #829AC4", +"a c #7ED1D8", +"b c #5FEBFF", +"c c #3FCADF", +"d c #04B3D0", +"e c #05B8D6", +"f c #1BD9F8", +"g c #4CE9FF", +"h c #5BECFF", +"i c #63ECFF", +"j c #5FDCEC", +"k c #97D0D9", +"l c #5F70A7", +"m c #586798", +"n c #92C2CD", +"o c #8FDBE1", +"p c #5FCDD9", +"q c #22B2C6", +"r c #05B7D4", +"s c #0BD7F8", +"t c #2EE5FF", +"u c #49EAFF", +"v c #51EAFF", +"w c #54CCD9", +"x c #64C0C7", +"y c #70C8CF", +"z c #80D2D8", +"{ c #5FC4CC", +"| c #32BCCB", +"} c #0AD1F2", +"~ c #05B3D0", +" ! c #09D2F3", +"!! c #19E3FF", +"#! c #32E7FF", +"$! c #42C9D8", +"%! c #44AFB7", +"&! c #3CD4E7", +"'! c #42E0F5", +"(! c #40D1E3", +")! c #40E9FF", +"*! c #31E7FF", +"+! c #18E2FE", +",! c #09D0F1", +"-! c #04B2CF", +".! c #04AEC9", +"0! c #08C5E5", +"1! c #10DEFD", +"2! c #2DC8DA", +"3! c #42B0B8", +"4! c #30D2E5", +"5! c #3BE8FF", +"6! c #39E8FF", +"7! c #24E5FF", +"8! c #0FDDFD", +"9! c #08C2E2", +":! c #03AEC9", +";! c #05B1CE", +"! c #3CAEB7", +"?! c #2DE5FD", +"@! c #2DE6FF", +"A! c #13E0FE", +"B! c #09CEEF", +"C! c #05B0CC", +"D! c #04ABC5", +"E! c #06A4BD", +"F! c #29B0C2", +"G! c #2CADBC", +"H! c #1DE3FF", +"I! c #06AFCC", +"J! c #0C5664", +"K! c #06A7C2", +"L! c #08BBDA", +"M! c #09CFF0", +"N! c #0AD6F7", +"O! c #0AD5F6", +"P! c #08BAD8", +"Q! c #06A5C0", +"R! c #0C505C", +"S! c #111E23", +"T! c #0A6979", +"U! c #0797AF", +"V! c #06A8C3", +"W! c #0795AC", +"X! c #0B6575", +"Y! c #121A1E", +" ", +" # $ % & ' ( ", +" ) * + , - . 0 + 1 2 ", +" 3 4 5 6 7 8 9 7 6 5 : ; ", +" < = > ? @ A B C D E F G ", +" H I J K L M N O P Q R S T U ", +" V W X Y Z [ ] ^ _ ` a b c d ", +" e f g h i j k l m n o p q r ", +" e s t u v w x y z { { | } r ", +" ~ !!!#!$!%!&!'!(!)!*!+!,!-! ", +" .!0!1!2!3!4!5!5!6!#!7!8!9!:! ", +" ;!!?!*!*!@!7!A!B!C! ", +" D!E!F!G!+!H!H!+!8!B!I!D! ", +" J!K!L!M!N!O!B!P!Q!R! ", +" S!T!U!V!K!W!X!Y! ", +" "}; \ No newline at end of file diff --git a/zq_icon-old.icns b/zq_icon-old.icns new file mode 100644 index 0000000000..5eb32b748c Binary files /dev/null and b/zq_icon-old.icns differ diff --git a/zq_icon-old.ico b/zq_icon-old.ico new file mode 100644 index 0000000000..fcad1f1c06 Binary files /dev/null and b/zq_icon-old.ico differ diff --git a/zq_icon.c b/zq_icon.c new file mode 100644 index 0000000000..3cbe2f2fa5 --- /dev/null +++ b/zq_icon.c @@ -0,0 +1,528 @@ +#include +/* XPM */ +static const char *allegico_xpm[] = +{ + /* columns rows colors chars-per-pixel */ + "256 256 256 2 ", + " c #686813", + ". c #787814", + "X c #7B7D24", + "o c #172473", + "O c #111956", + "+ c #1D233D", + "@ c #7E8125", + "# c #8E8E18", + "$ c #878716", + "% c #939319", + "& c #9B9B19", + "* c #A3A31B", + "= c #ACAC1C", + "- c #A7A717", + "; c #B6B61F", + ": c #B9B91F", + "> c #B6B617", + ", c #888927", + "< c #979829", + "1 c #979738", + "2 c #8D8D32", + "3 c #A8A829", + "4 c #B6B622", + "5 c #BBBB23", + "6 c #BCBC2B", + "7 c #B3B42C", + "8 c #A7A837", + "9 c #BDBD32", + "0 c #B7B739", + "q c #AFB12C", + "w c #9FA12B", + "e c #C5C51D", + "r c #C3C322", + "t c #CBCB23", + "y c #C2C22C", + "u c #CCCC2B", + "i c #D2D225", + "p c #D4D42B", + "a c #DADA2C", + "s c #D9D925", + "d c #C3C333", + "f c #CBCB34", + "g c #C4C43A", + "h c #CBCB3B", + "j c #C6C836", + "k c #DBDB34", + "l c #DDDD3C", + "z c #D3D338", + "x c #CED03A", + "c c #E0E03D", + "v c #BABA45", + "b c #ACAE47", + "n c #BCBC6C", + "m c #B3B569", + "M c #B4B572", + "N c #96A172", + "B c #BDC363", + "V c #C8C846", + "C c #DDDD44", + "Z c #DDDD4B", + "A c #D4D448", + "S c #DADA57", + "D c #CACA54", + "F c #E1E14C", + "G c #E0E045", + "H c #E1E153", + "J c #E3E35C", + "K c #C7C76D", + "L c #D9DA66", + "P c #CACA74", + "I c #D8D875", + "U c #CDD16D", + "Y c #E4E464", + "T c #E5E56B", + "R c #E9E96A", + "E c #E6E673", + "W c #E9E974", + "Q c #E5E57A", + "! c #E9E97C", + "~ c #E7E877", + "^ c #DFE077", + "/ c #BFC131", + "( c #1D2D89", + ") c #21349A", + "_ c #2439A6", + "` c #263BAC", + "' c #2337A2", + "] c #273DB1", + "[ c #283FB4", + "{ c #293FB8", + "} c #2840B6", + "| c #2A41BB", + " . c #2F48BF", + ".. c #334BB9", + "X. c #5A6FB1", + "o. c #2C45C3", + "O. c #2D46C9", + "+. c #2E48CE", + "@. c #2E48C2", + "#. c #354CC3", + "$. c #2F49D1", + "%. c #304BD5", + "&. c #314DDB", + "*. c #3B53C9", + "=. c #334FE3", + "-. c #3350E4", + ";. c #3552EB", + ":. c #3C58E8", + ">. c #3754F3", + ",. c #3857F9", + "<. c #3B5AFE", + "1. c #3B58F5", + "2. c #445BCC", + "3. c #5569CF", + "4. c #6679D4", + "5. c #415EFE", + "6. c #445EE8", + "7. c #4562FF", + "8. c #4B67FE", + "9. c #516DFE", + "0. c #546EF5", + "q. c #5B74F4", + "w. c #5571FF", + "e. c #5A75FE", + "r. c #5E79FF", + "t. c #5771F6", + "y. c #536BE9", + "u. c #667BEC", + "i. c #647BF4", + "p. c #637CFE", + "a. c #667DF7", + "s. c #77879C", + "d. c #7788D8", + "f. c #7589D8", + "g. c #6D81EB", + "h. c #7285EC", + "j. c #7B8DEC", + "k. c #788AE8", + "l. c #7E90EA", + "z. c #6D82F3", + "x. c #6B84FE", + "c. c #6680FF", + "v. c #7A8DF4", + "b. c #7087FE", + "n. c #748BFF", + "m. c #798EFE", + "M. c #7488F3", + "N. c #7D92FF", + "B. c #7E91F4", + "V. c #B0B890", + "C. c #98A6AF", + "Z. c #AFB9B1", + "A. c #8B9AA1", + "S. c #B9C2B8", + "D. c #BBC28E", + "F. c #C6C787", + "G. c #D8D988", + "H. c #DADA97", + "J. c #CACC94", + "K. c #EAEA84", + "L. c #EBEB8C", + "P. c #E4E487", + "I. c #ECEC94", + "U. c #EEEE9C", + "Y. c #E3E399", + "T. c #F0F09B", + "R. c #D9D9A7", + "E. c #D1D5B2", + "W. c #EEEEA2", + "Q. c #ECECAB", + "!. c #E4E4A8", + "~. c #F0F0A5", + "^. c #F1F1AB", + "/. c #ECECB4", + "(. c #E7E7B8", + "). c #F2F2B4", + "_. c #F3F3BB", + "`. c #DEE19E", + "'. c #8897D8", + "]. c #96A6D3", + "[. c #8394EB", + "{. c #8C9BEB", + "}. c #8897E6", + "|. c #919EE8", + " X c #8395F4", + ".X c #8C9CF4", + "XX c #8296FE", + "oX c #8599FF", + "OX c #8B9DFE", + "+X c #8798F4", + "@X c #909FF2", + "#X c #95A2E4", + "$X c #94A2EB", + "%X c #9DAAEB", + "&X c #9AA7E8", + "*X c #8FA0FE", + "=X c #8FA0F7", + "-X c #94A3F4", + ";X c #9CAAF4", + ":X c #93A4FE", + ">X c #9CABFE", + ",X c #98A7F7", + "X8X>X8X8X8X8X8X8X8XeXeX>XeX8X8X8XeX8XeXeXeXeXeXeXeXeXeXeX0X!.^.xX~.^.bXMX~.G.Y.~.xXI.P.H.I.I.U.U.U.W.U.W.W.W.W.W.W.T.W.U.W.U.U.U.U.U.U.U.U.)._.U.H.F.J.!.Y.H.W.cXbX~.G.H.U.zX8XeXeXeXeXeXeX8XeX8X8X8X8X8X8X8X8X8X8X8X8X8X;X8X8X;X8X8X;X8X8X9X,X;X9X;X;X;X;X;X;X;X;X;X%X;X%X%X%X$X%X&X&X&X&X&X#X&X#X4.o. .{ o.{ { o.| | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | { { .o.o.o.o.'.#X&X#X#X&X&X$X%X|.1X&X-X%X&X%X-X,X;X,X%X;X;X,X,X,X9X,X>X;X>X;X8X;X>X8X>X>X8X>X>X>X>X8X8X>X8X8XeX8X8X8XeX8XeXeX8XeX8XeXzX~._.^.W.xXMXxXH.H.I._.^.Y.H.P.I.U.W.W.U.U.W.U.W.W.W.W.T.U.W.W.U.U.W.U.U.U.U.I.U.W.).^.Y.J.D.G.^.H.P.).MXcXY.H.L.!.qX8XeXeXeXeXeXeX8X8X8X8X8X8X>X8X8X8X>X8X8X>X8X8X>X,X>X9X8X,X;X>X9X9X,X;X;X;X;X%X;X%X;X;X%X%X%X$X%X$X%X&X&X%X$X#X&X&X&Xd.o.o.o.{ .{ { | | .UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | { o.| o.o.o.2.|.#X#X&X&X$X&X&X%X|.1X%X-X&X,X%X,X%X,X%X,X;X;X,X,X>X9X,X9X>X;X>X>X>X>X;X>X>X>X>X>X>X>X>X8X8X8XeX>X8X8X8X8X8X8X8XeXeXeXwXY._.xXU.).bXbXW.G.G.)._.I.H.H.Y.U.U.T.U.U.U.U.W.W.W.W.W.W.W.U.W.U.U.U.U.U.U.U.U.U.U.Q._.~.G.F.F.Y.^.G.U.xXnX_.G.G.I.E.eXeX8XeX8X8X8X8X8X8X8X8X8X>X>X8X>X8X>X>X8X>X,X>X8X>X,X,X,X>X,X8X,X9X,X;X,X;X;X,X;X$X;X;X$X$X$X%X%X$X$X&X$X&X&X&X#X#X|.2.o.o. .o.{ { o.{ { { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | { o.o.o. .O.3.&X#X&X|.&X&X$X$X$X1X@X-X%X-X%X,X%X,X,X%X,X;X,X,X,X,X,X,X>X,X>X,X,X;X>X>X>X>X>X>X>X>X>X8X>X8X>X>X8X8X8X8X8X8X8XeX8XeXeXE.~.xX^.W.xXnX_.H.G.I._.~.P.P.P.I.U.U.U.U.W.W.W.T.W.W.~.T.W.W.U.U.W.U.W.T.U.U.U.U.U.T.W.).).Y.F.D.J.~.Y.G.~.nXbXY.J.P.T.7XeX8X8X8X8X8X8X8X8X8X8X>X8X>X>X>X>X>X>X>X>X8X>X>X,X>X8X,X>X,X;X,X,X;X,X;X;X$X,X,X%X$X;X$X;X;X$X%X$X&X&X$X&X#X#X#X#X&X3.O.o. .{ o.{ { { { o.UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.o.o.o.4.#X#X#X#X&X$X&X$X$X|.@X%X-X-X%X&X-X-X%X%X,X-X,X,X,X,X,X,X,X>X,X,X>X>X,X:X>X>X>X>X>X>X>X>X>X8X>X8X8X8X8X8X>X8X8X8X8XeXaXU._.).U.).nXvXY.G.P.).).L.H.H.L.I.U.U.U.U.U.U.W.W.W.W.W.W.T.W.W.U.U.U.U.U.U.U.U.I.I.I.U.Q._.Q.G.F.D.H.W.G.Y._.nX_.G.G.I.R.8X8X8X8X>X8X8X8X>X:X8X8X8X8X>X>X>X>X>X,X>X>X>X>X>X>X>X,X,X,X,X,X,X,X,X,X$X$X,X$X$X,X$X$X;X$X$X$X%X$X#X&X#X#X|.#X#X|.d.O.o.o.o.{ { | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | { | | | o.o.o.o.2.}.#X#X#X|.|.$X$X|.&X|.&X|.-X-X-X-X-X-X-X-X,X-X,X,X,X,X,X,X:X,X>X>X,X>X>X>X>X:X>X>X:X>X>X>X>X>X>X>X>X>X8X>X8X8X8X8X8X8XR.~.xXU.W.cXMX^.G.G.U.xXU.P.G.P.L.T.I.U.T.U.W.W.U.T.W.T.W.W.W.W.T.W.W.W.U.T.U.U.I.U.U.U.I.U.)._.L.F.F.F.Y.I.G.W.cXvXW.G.P.I.aX>X8X8X8X8X>X8X8X8X8X>X>X:X>X>X>X:X,X>X>X>X,X>X:X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X$X,X$X-X$X$X$X$X$X$X$X|.#X#X|.#X|.'.2.o.o.o.{ o.{ o.| { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo.{ | { | | | | o.o.O.O.3.#X|.#X&X|.$X|.$X$X$X&X|.-X%X-X%X-X-X-X-X-X-X,X,X,X,X,X:X,X,X:X>X,X>X>X>X>X>X>X>X:X>X>X>X>X>X>X>X8X>X>X8X>X8X8X8X8X8XaXU._.).U._.nXxXP.G.Y._.).P.G.P.I.I.U.U.U.U.U.U.U.W.W.T.W.W.W.W.W.U.W.U.U.W.U.U.U.U.U.I.I.U.U.W._.Q.G.F.D.G.~.G.P.).bXxXH.F.L.!.0X8X>X8X8X>X>X8X>X>X>X8X8X>X>X>X>X>X,X,X,X>X,X:X,X,X,X,X,X:X,X,X,X,X-X-X-X-X,X-X-X,X-X$X$X$X$X$X$X$X$X|.#X|.|.#X|.|.2.o.o.o.o.{ | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | { o.{ { #.o.o.o.O.+.3.|.|.|.|.|.|.$X|.|.@X-X-X|.-X|.-X-X-X-X-X-X,X-X,X=X,X:X,X:X,X,X:X:X:X:X:X:X:X:X>X>X>X>X>X>X>X>X>X>X>X>X>X8X>X>X>X8X0XY.).xXU.~.cXbXW.G.G.T._.I.P.G.P.I.U.U.U.U.U.U.W.W.U.W.W.W.~.W.W.W.W.U.W.U.U.U.U.U.U.U.U.U.I.U.I.^.xXI.F.F.F.Y.W.G.I.xXbXW.G.G.I.E.>X8X8X>X>X>X>X8X8X:X>X>X:X:X>X>X:X,X,X,X:X>X:X:X,X:X,X:X:X:X@X,X,X@X,X-X-X$X@X-X$X$X-X@X$X$X@X|.$X|.#X|.|.|.|.|.{.4.o.o.o.o.{ | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | @.o.o.O.O.O.d.|.|.|.#X|.|.|.@X|.|.|.@X@X@X@X@X-X-X@X-X,X@X@X,X@X:X:X=X,X:X:X:X:X:X:X:X:X>X:X:X:X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>X>XE.U._.~.U._.nX).G.G.L.).U.P.G.P.L.I.T.U.U.U.U.U.U.W.U.W.W.W.W.W.W.W.W.U.W.U.U.U.U.U.U.U.I.U.U.I.U.W._.).G.F.F.F.T.H.G.~.bXxXP.F.K.U.3X>X>X>X>X>X>X>X:X>X>X:X>X:X>X,X,X,X:X:X:X:X:X:X@X:X:X:X,X:X,X@X:X-X:X-X-X@X-X@X@X@X$X-X$X@X|.|.|.|.|.|.|.|.|.'.|.d.O.o.o.o.o.o.| { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | { | | | o.o.o.O.O.O.}.|.}.|.}.|.|.|.|.|.@X@X@X|.@X@X@X@X@X-X@X@X:X:X@X:X@X=X=X:X=X,X:X:X:X:X:X:X:X>X>X:X>X:X:X:X>X:X>X>X:X>X>X>X>X>X>X0XU.^.).I.^.bXvXY.G.P.~.).P.G.P.K.I.U.U.U.T.U.U.W.U.U.W.U.W.W.~.W.W.T.W.W.U.W.U.T.U.U.U.U.I.I.I.I.I.U.~.xXU.G.M n H.T.G.I.).bX^.G.G.L.E.>X>X>X:X>X>X>X>X>X>X>X:X>X:X,X:X,X:X,X:X:X:X:X:X:X:X:X@X@X:X:X@X@X:X@X@X@X@X@X@X@X@X@X@X@X|.@X@X|.|.{.|.|.}.|.|.d.+.O.O.o.o.| { .| | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | | | @.o.o.O.O.O.2.|.}.|.|.|.}.|.|.{.{.@X|.@X@X@X@X@X@X@X@X*X@X@X@X:X@X:X:X,X*X:X:X:X:X:X:X:X:X:X:X:X:X:X:X>X>X:X:X>X>X>X>X>X>X>X>X:XE.U.xXW.U._.nX).G.I L._.U.P.G.K.L.I.T.U.U.U.U.W.W.W.~.W.W.W.W.~.W.W.W.W.W.W.W.U.W.U.U.T.T.U.T.U.U.I.I.W._.).P.F.M F.Q.P.G.T.cXcXY.P P.L.dX:X>X>X>X>X>X:X>X:X>X:X:X>X,X,X:X:X:X:X:X:X:X:X@X:X:X*X:X@X@X:X@X@X*X@X@X@X@X@X@X@X@X@X@X|.|.@X|.|.|.}.|.}.|.}.|.2.o.o.o.o.o.| | | { | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.o.o.O.O.2.}.}.|.}.}.|.}.{.{.{..X|.@X{.@X@X@X.X@X@X@X*X@X:X@X:X:X=X*X=X:X*X:X*X:X:X:X:X:X:X:X:X:X>X:X:X>X>X>X:X:X:X>X>X:X>XaXI./.).I.).vXxXP.F.P.^.~.P.G.G.L.I.U.U.U.U.U.U.U.U.W.U.W.W.W.~.~.~.W.W.W.W.T.U.W.U.U.U.U.T.I.I.U.I.U.I.I.~.xX~.G.F.M G.W.I P.).nX_.G.P K.`.9X>X>X:X>X:X>X:X>X:X>X:X:X:X:X:X:X:X:X:X:X:X:X:X:X@X:X:X*X*X@X:X@X@X@X@X*X.X@X{.@X@X{.{.{.{.{.{.}.}.|.}.|.|.}.}.2.O.O.O.o.@.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | | o.o.o.O.O.O.+.3.}.}.}.}.|.}.{.{.{.{.{.{.{.{.{..X.X@X.X.X@X*X.X@XOX@X@X*X*X*X=X*X*X*X*X:X*X:X:X:X:X:X:X:X:X:X>X:X>X:X>X>X:X:X>X>XY.T._.I.W.xXvXW.G.^ I.).L.^ G.P.L.I.U.U.U.U.U.U.W.U.U.W.U.~.~.W.~.W.~.W.W.W.U.W.U.U.U.U.U.U.U.U.I.U.I.I.U.U.).xXL.P M M I.Y.I I.cXcXI.F.P.K.S.>X>X>X:X>X:X:X>X:X:X:X:X:X:X:X:X:X*X:X*XOX:X:XOX@X:X@X*X*XOX@X*X*X.X@X.X.X{..X{..X{..X{.{.{.{.{.{.|.}.}.}.}.'.3.O.o.O.o.@.o.| { | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | @.@.o.o.o.O.O.+.4.}.}.}.}.}.{.}.{.{.{..X.X.X.X.X.X.X.X.X*X.X@X.XOX@XOXOX*X=X*X*X*X*X*X*X:X:X:X*X:X:X:X:X:X:X:X>X:X:X>X:X:X>X>X>XpXI.).~.I._.bXxXG.P P.).W.P.G.Q K.I.I.U.I.U.U.U.U.U.W.~.~.W.~.~.W.W.Q.~.W.W.W.W.T.W.W.U.U.U.U.U.I.U.U.I.I.U.I.~.xX^.P.F.M F.I.G.P.^.bX_.G.P P.`.;X>X:X>X:X>X:X:X>X:X:X:X:X:X:X:X:X:X*X*X:XOXOX:X*XOX*XOX@X@XOX@X.X=X=X.X.X.X.X.X.X.X{.{.{.{.{.{.{.}.}.}.}.}.}.4.O.O.O.o.o.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | o.o.@.o.o.o.+.+.+.4.{.}.}.}.{.}.{.{.{.{.{.{..X.X.X.X.X.X.X.XOXOX.X.XOX.XOX=X*X*X=X*X*X*X*X*X*X*X:X:X:X:X:X:X:X:X:X:X:X:X>X:X>X>X;XY.Q._.L.W.xXbXI.I I U.).L.G.^ P.I.U.U.U.U.U.U.W.U.W.W.W.W.W.W.~.^.^.^.~.~.W.W.W.W.U.W.U.U.U.U.U.I.U.U.I.I.I.I.I.^.xXI.P M M Y.I.I L._.bX~.U G.L.E.:X>X:X:X:X:X:X:X:X:X:X:X:X:X:X*X*X*X*XOXOX:XOXOX@XOX@XOX.XOX.XOX.X.XOX.X.X.X.X+X{.{.{.{.{.{.[.{.}.{.}.}.}.|.4.O.O.O.o.o.| @.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | o.o.O.O.+.+.%.4.[.}.}.{.}.[.[.[.[.[.+X[.[.+X+X.X+X+X.X+X+X.XOXOX.XOXOX=X*XN.*X*X:XN.*X*X*X*X*X*X*X*X*X:X*X:X:X:X:X:X:X:X:X>XS.L._.W.L.).bX).G.I P.).W.Q I Q L.I.I.I.U.U.U.U.U.W.U.W.W.W.~.~.~.W.^.W.~.~.~.~.W.W.W.T.W.U.U.U.U.U.U.U.I.I.I.I.I.I._.).Q F.M P T.G.^ U.cXxXP.P ^ P.1X:X:X:X:X:X:X:X:X:X:X*X*X*X*X*X*XOX*XOXOXOXOXOXOXOXOXOXOX+XOX.X.X+X+X.X+X+X{. X+X{. X[. X}.[.}.[.}.}.}.}.}.u.+.O.O.O.O.o.o.o.| { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | o.o.o.o.O.+.O.+.+.k.}.}.[.}.}.[.[.{.[.[. X.X+X+X+X+X+X+X.X+XOX.XoX.XOXOX.XN.*X*X*X*X*X*X*X*X*X*X*X*X:X*X*X:X:X:X:X:X:X:X:X:X:XiXP.~.).K.W.cXxXP.P Q U./.K.P.I K.L.I.I.I.U.U.U.U.U.U.W.W.W.W.W.~.~.~.^.^.~.W.W.W.W.W.W.W.U.U.U.U.I.U.U.U.I.I.I.I.I.I.~._.T.G.n M G.U.I P.).vX~.I P K.H.>X:X:X>X:X:X*X:X*X:X*X*X*X*X*X*X*XOXOXOX*XOXOXOXOX.XOX.XOX+X.XOX+XoX.X.X X.X.X[.+X{.[.[.[.[.}.[.'.[.'.}.[.4.+.O.O.O.o.o.@.| | | | | { o.UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | | | o.o.o.O.O.+.+.+.d.}.k.'.[.[.[.[.[.[. X[.+X[.[.+X+X+X+X+X+X+XoX+XoX+XoX.XN.=XN.*XN.*XN.*X*X*XN.:X*X*X*X*X*X*X*X*X:X:X:X:X:X:XE.L.^.I.L.).bXU.I I K._.I.Q ^ ^ ! L.I.U.I.U.I.U.U.I.U.U.U.U.W.U.W.W.~.~.~.W.W.W.W.U.U.U.U.U.U.I.I.T.I.I.I.I.I.I.L.I.L.W.).~.P.P M M L.P.I I.cXcXP.P ^ K.2X:X:X*X:X*X:X*X*X*X*X*X*X*X*XOXOXOXOXOXOXOXOXOXXXOX+XoXoXoX XOX+X+X+X+X X[.[.+X X X{. X[.[.[.[.[.[.k.}.'.[.O.+.+.O.O.O.o.| | | | | { .UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | @.o.o.o.O.O.+.+.+.+.k.'.k.[.[.[.[.[.[. X X[.[.[. X+X+X+X X+X+XoXXX XoXoX+XoX*XN.*X*X*XN.*X*X*X*X*X*X*X*X*X*X*X*X*X:X*X:X:X*X:XiXL.W.^.K.W.xX_.Q P Q ^.~.Q ^ Q Q ! L.L.I.I.L.I.I.I.I.I.U.T.I.U.U.I.U.U.U.U.U.U.U.U.I.I.U.I.I.I.I.I.I.L.I.I.L.L.L.L.L.L.I.^.^.I.I P M P W.I P.W.vX).I P Q `.-X*X:X*X:X*X*X*X*X*X*XOX*XOXOXOXOXOX XOX X XOXOXXXoX+X+XoXOX X X X X X X.X[. X X[. X[.[.[.[.[.[.[.}.[.k.d.+.+.O.O.O.@.o.o.@.| | | | { o.UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.o.O.O.+.+.+.%.[.[.[.[.[.[.[.[.[.[.[.[. X X X X X X+X X+XXX X X+XoXoXoXN.*X*XN.N.*X*XN.*XN.*X:X*X*X*X*X*X*X*X*X:X*X*X:X,XG.L.).I.I.).xXI.P I I.).K.I ^ ^ Q Q K.K.K.K.K.K.L.L.L.L.L.L.L.L.L.I.I.I.I.I.L.I.L.I.L.I.K.L.K.L.L.P.K.K.L.K.K.K.K.! K.K.I.W.~.~.K.I n M P.L.I K._.vXY.P I K.S.:X*X:X*X*X*X*X*XOX*X*X*XOXOXOXOXOXOXXXOXOXXXOX XoXXXoX+X XXX X XXX X X X X[. X[.[.[.+X[.[.k.[.'.[.d.}.[.+.+.+.+.o.O.o.o.o.| | | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.O.O.O.O.+.+.+.+.d.[.[.k.k.[.[.[.[.[. X X X X X XXX X XXX XXX XXXXX XXX XXXoXoXoX*X*XN.*X*X*XN.N.*X*X*X*X*X:X*X*X:X*X*X*XS.P.U.).K.U.xXQ.^ I Q ^.L.^ I I I ^ ^ Q Q Q ! Q Q Q Q Q ! ~ ! K.! K.! K.! K.K.! ! ! K.! ! ! ! ! Q Q Q Q Q ^ Q Q Q Q Q Q ! ! L.T.T.I.Q P n P I.P I T.cX_.I P Q K.$X*X*X*X*X*X*X*X*XOXOXOXOX*XOXOXOX XOXXX XOX XOX XoXXX XXX XXX X X X X X Xv. X X X[.j.[.[.j.[.k.k.}.d.[.+.+.+.O.O.O.O.o.| | | | { { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.o.O.+.+.$.$.%.[.[.d.[.[.k.[.k.j. Xj. X Xv. X X X X X XXX XXX XXXXXXXXXXXXXoXoX*XN.N.*X*XN.*X*XN.:XN.*XN.:X*X*X:X:X*X%X~ K.^.L.L.).).K.I K.^.I.^ I I U P I U U P I I I I I I I I I I I I I I I ^ I ^ I I I I I I I I I I I I I I I P I I P P I I I ^ E ! K.Q I P K Q I n I ~.cX~.I U ~ S.*X*X*X*X*X*X*XOXOXOXOXOXOX XOXXXOXOX X X XXX XXXXXXX X XXX X X X X X X X Xj. X[.[.[.[.j.[.k.[.[.k.}.k.$.+.+.O.O.O.o.o.@.| | | { .| { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.@.o.o.O.O.+.+.+.+.$.d.k.[.k.k.[.[.k.[.j.j.j.j.v. Xv. X X XXX XXX XXX XXXXXXXXXXXoXoXoXN.N.*X*X*X*X*X*X*XN.:X:X:XN.:X*XN.*XS.K.W.T.! U.^.W.K.K.^.I.^ L I I P K K P P K K K P K K K P U P K K P P P P K K P P K P P P P K K P K K P K K P K K K K K K K K P P I U U P K n U ^ m K L.).xXI.U I ~ 2X*X*X*XoX*XN.XXOXOXOXOXXXOX XOX XXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXv. Xv.v.[.j. X Xj.j.[.[.[.[.d.[.d.[.$.+.+.+.O.O.o.o.o.| o.| | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.O.+.+.$.%.+.k.k.k.k.[.k.k.[.v.j. X Xj. Xv. Xv.v.XX XXXv.XXXXXXXXXXXXXXXXN.oXoXoXoXoXN.*XN.N.:XN.*X:XN.N.*X*X*X*XiXL.U.^.K.L.W.^.~.Q._.I.L P K K n n M n n n n n n n n n n n n n n n n K n n n B n n K n n n n n n n n n n n n n n n n n n n n n n n n K n K K U Q L.n m I T.U.^.P.U ^ G.*XoX*X*X*X*XOXOXOXOXXXOXOX XXXXXOXXXXXXXXXXX XXX XXX XXXXXv. X X Xv. Xv.v. Xj.j.v.[.u.[.u.}.k.k.[.4.$.$.+.+.O.O.O.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | @.| o.O.O.O.+.+.+.$.$.$.u.k.k.k.[.l.j.j.j.j.v.v.[.M. X XM. X XXXM.XXXX X XXXXXm.XXXXXXXXXXXXXXXXoXoXOXXXOXOXoXOXN.:X*X*XN.,X`.W.).L.K.I.~.)._.xXT.I B m m m N m m m m n n n n n B M B B B n B B K B K K B K K K K K K n n n n n B B M B m n m m n m m m m m B m B K U U ^ L.^.L.B m B ! I.K.~.Q U W pXOX*XoXoXOXoXoXOXXXOXOXoXXXXXXXXXXXXXXXXXm.XXXXXXXX Xm.v.XXm. X Xv.v. Xj.v.j.M.j.j.j.j.j.k.k.l.k.4.$.$.+.+.+.O.O.o.o.o.| | { | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | | o.o.o.o.O.O.+.+.$.$.%.%.4.k.k.k.k.k.j.M.v.j.v.j.v. XM. Xv.m.XXM. Xn. Xn.m.XXm.XXN.N.XXXXXXXXXXXXXXoXoXoXXXOXoXoX*X:XN.:XN.aX^.^.I.L.L.U.).xXxXW.~ U B n U U U L I I Q I I Q Q I ^ P.P.P.P.P.P.K.L.Y.Y.L.I.I.L.L.K.P.P.L.K.L.K.! P.P.P.^ P.^ ^ ^ ^ ^ ^ ^ I ^ I I ^ Q K.I.T.~.L.K N m n Q T.Q Q L.I L G..XoX*X*XoXOXoXOXXXXXXXXXoXXXXXXXXXXXXXXXB.m.m.v.XXv.XXm.v.v.v.m.v.v.v.v. Xv.j.v.j.j.j.k.k.k.k.k.u.$.$.$.+.+.O.O.O.o.@.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | @.o.O.o.O.O.+.+.$.%.%.%.u.k.k.k.k.k.j.j.j.j.j.v. XM. X X X XM.XXXX Xn.XXXXXXXXXXXXXXXXXXXXXXXXXXXXoXXXoXoXoXoXoX*XN.*X*X:XNX_.^.I.L.W.).xX_.).T.L.L.L.I.I.L.K.K.K.K.L.L.L.I.I.I.U.U.U.W.^.~.~.^.^.^.^.^.).).).).).).^.^.~.~.W.W.T.T.U.T.I.I.I.L.L.L.L.! ! ! ! ~ ~ ! K.K.! W L U B U L L.).K.^ ~ L.T E Z.*XoXOXoXoXoXoXOXoXoXoXXXXXXXXXXXB.XXm.XXXXm.v.m.m.XXXXv.m. X Xv.v.v.v.j.j.v.M.j.j.j.j.k.k.k.k.4.$.$.$.$.+.O.O.o.O.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.O.+.+.$.%.%.%.3.h.k.k.k.j.j.j.j.M.j.v.M.v.M.a.M.n.XXM.a.n. Xn.XXa.XXXXm.m.XXm.XXXXXXXXXXXXoXXXoXoXXX*XN.*XN.N.aXxX).U.U.W.).).^.^.^.^.Q.^.^.~.U.I.L.L.L.L.I.I.I.I.U.T.U.U.U.W.W.W.~.~.W.~.~.^.~.^.~.^.W.W.W.W.W.W.W.W.U.U.U.T.U.I.I.I.I.L.L.L.L.L.L.L.K.K.K.K.! Q Q ~ ~ ~ K.T.W.! Y E W.~.~ I $XoXoXoXoXoXXXXXXXoXXXXXXXXXXXm.XXm.B.m.XXm.XXm.m.v.m.v.v.v.v.v.M.v.M.v.M.j.j.j.h.j.j.k.k.k.k.y.%.%.$.$.+.O.O.O.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.O.+.+.$.$.%.%.%.y.k.k.h.h.k.k.M.M.j.M.M.M.M. X Xv.m.m.v.XXXXXXn.XXa.XXa.m.XXm.XXXXXXXXXXXXXXXXXXXXXXXXOXN.*XN.0XxX).W.T.Q.~.U.L.K.K.K.L.L.L.L.L.K.K.K.K.! K.K.L.L.L.I.I.I.I.U.I.`.`.`.E.^.^.^.^.).).).^.).^.~.~.~.W.W.U.T.I.T.I.I.I.L.L.L.K.! K.! ~ ~ W ~ E E E E E E T R ~ ! L.T.T.T.I.I.I.K.Q J.OXoXoXXXXXXXXXoXXXXXXXXXXXN.XXm.XXm.m.n.XXM.m.m.v.m.m.v.n.v.M.M.v.M.j.j.M.j.h.j.h.j.h.k.k.k.3.%.%.$.$.+.+.O.O.O.@.o.| o.| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | .o.o.o.o.O.O.+.+.$.$.%.%.%.2.h.k.f.M.k.M.j.h.M.j.M.M. XM.n.M.v.M.m.XXa.XXa.XXXXXXXXm.m.XXm.XXm.XXXXXXXXXXXXXXoXOXXX*XN.*XzXaXaXaXaXaXpXpXS.S.S.pXS.S.pXS.pXS.pXS.pXpXpXpXpXpXpXaXpXpXaXaXaXaXaXaXiXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXaXpXpXpXpXpXpXpXS.pXpXS.pXpXS.S.pXZ.S.Z.S.pXZ.S.pXpXpXpXaXaXaXpXpXpXpXS.$XoXoXXXXXXXXXXXXXXXXXN.XXXXm.m.m.XXm.XXn.XXn.n.v.m.v.n.v.v.m.v.v.v.M.M.j.M.M.h.h.h.k.d.g.u.6.%.%.$.$.+.+.O.O.o.O.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.O.+.+.$.%.%.%.%.:.k.h.h.k.k.h.M.h.j.M.M.M.M. XM.n.v.m.M.a.XXa.XXa.a.XXa.m.m.XXXXm.XXXXm.XXXXN.XXXXXXXXXXN.*X,X(.9XN.*X*XN.N.*X*XN.*X*XN.oX*XN.*XN.*XN.*XoXoXoX*XOXoXOXOX*XoXN.*XN.*XoXoX*XN.*X*X*XN.*X*XoXOXOXOXOXOX.XOX:X*X:XN.:XN.*XN.*X*XN.*X*XN.*XN.oXoXOXoXoXOXOXOX*XN.*X*XN.*X*XN.oXoXoXoXE.E.N.N.XXXXXXXXXXXXXXXXXXN.N.N.N.m.m.m.XXXXb.n.n.m.v.n.M.n.M.M.n.M.M.M.M.h.k.h.h.k.k.g.k.k.f.&.$.$.%.$.+.+.O.O.O.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | .o.o.O.+.+.+.+.$.%.%.%.%.%.u.h.h.h.h.h.h.M.h.M.M.v.M.a.M.b.M.M.m.XXM.XXn.XXXXn.XXm.m.m.m.XXm.m.XXXXm.XXXXXXXXXXXXN.N.E.).(.*XN.N.N.*XN.*XN.N.N.*XoXoX*XN.*XN.*XN.oXoXOXoXoXOXoXoXoXoX*X*XN.*XoXoXN.*X*XN.N.*XN.*XoXoXoXOXoXoXOXoXN.*XN.:XN.*X*XN.N.*X*XN.N.*XN.*XoXoXoXoXoXoXoXoX*XN.N.N.*XN.N.:XXXoXoXiX~.I.iXN.XXXXXXXXm.XXXXm.N.N.N.N.m.m.m.n.a.a.XXn.v.n.b.v.n.v.M.n.M.M.M.M.M.M.M.h.h.h.h.h.h.d.u.&.%.%.%.$.+.+.O.O.O.O.o.o.| | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | | o. .O.O.O.+.+.+.%.%.%.%.&.%.u.h.h.g.h.h.h.h.M.h.M.M.M.b.M.M.b.v.b.a.XXM.n.b.m.b.m.m.m.m.m.m.m.m.B.m.XXXXm.XXXXXXXXN.aXW.^._.aXN.*XoXoXoXoXoXoXoXoXN.N.N.:X:XN.N.*XoXoXoXoXN.*XN.*XoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXN.*XN.*X*XN.*XN.N.*XN.*XoXoXoXoXoXoXoXoXN.*XN.N.*XN.N.N.oXN.+X!.).~.H.oXXXXXXXXXXXm.XXXXm.XXm.m.m.m.m.m.XXa.n.n.n.a.XXa.n.M.M.M.M.M.M.M.h.M.h.h.h.h.h.u.g.g.4.%.%.%.%.$.$.+.O.O.O.O.o.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.O.+.+.$.$.%.%.%.%.%.3.u.k.h.u.h.h.z.h.M.z.M.v.a.v.M.b.b.M.XXa.n.n.n.n.n.m.m.m.m.m.m.m.XXB.m.m.m.XXXXB.m.XXN./.Q._._.(.-XN.oXN.oXN.N.oXoXoX:X:XN.N.N.*XN.N.oXoXoXoX*XN.*XN.oXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXoXN.oX*XN.*XN.N.*XN.*X*XN.*XN.oXoXN.oXoXoXoXoXN.*X*XN.N.*X*XN.oXN.aX).)._.U.Z.XXXXXXXXm.XXm.m.m.m.m.m.m.m.m.n.a.XXn.n.a.XXa.XXb.M.M.b.b.M.M.h.h.h.h.M.z.h.h.h.g.d.y.%.%.%.%.%.$.+.+.+.O.o.o.o.o.| | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | o.o.o.O.O.O.+.+.+.%.%.&.&.&.%.6.k.u.h.h.u.a.z.h.z.M.M.a.v.a.M.n.M.b.a.XXn.n.b.n.b.m.b.m.m.m.m.m.m.m.m.m.m.XXXXXXXXXX2X).)._.).I.S.N.N.oXoXoXoXN.oXN.N.N.N.:XN.N.N.*XoXoXoXoXN.*XN.N.oXoXN.oXN.oXoXoXN.oXoXoXN.oXoXoXXXoXXXoXoXoXoXoXN.*XoXoXN.*XN.*XN.*X*XN.N.N.*XN.oXN.oXoXN.oXN.oX*XN.*XN.N.*XN.*XN.=X(.)._._.I.H.XXXXm.m.m.m.a.XXm.m.m.m.m.b.m.b.XXa.XXn.a.XXXXa.M.b.M.M.z.M.h.M.z.h.z.u.u.h.h.u.g.g.6.&.&.%.%.%.$.$.+.O.O.O.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.+.+.+.+.$.%.%.%.%.&.&.-.u.u.u.h.h.h.z.z.h.a.M.a.M.M.a.b.a.m.n.a.b.b.b.b.n.n.m.b.m.m.m.m.m.m.m.XXXXm.m.m.m..X(.).^.).W.K.L.2XoXN.N.oXN.oXoXN.N.N.N.N.N.:XN.*XN.oXN.oXN.N.N.*XN.oXoXoXoXN.oXN.oXoXN.oXN.oXoXoXXXoXXXXXN.oXN.oXN.N.oXN.N.*XN.N.N.N.N.N.N.*XN.*XXXoXN.oXoXoXN.N.N.N.N.N.N.N.N.N.N.zX).~.Q.).I.! Z.XXXXm.XXXXXXXXm.m.m.b.m.b.m.m.a.XXa.n.n.a.XXa.b.a.b.z.b.a.M.a.z.z.z.h.h.h.u.h.g.g.&.&.%.%.%.%.$.+.+.O.+.O.o.@.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.O.O.O.O.+.$.$.%.%.%.%.&.&.=.y.u.u.h.h.h.u.h.z.z. Xa.a.M.b.M.a.b.a.n.n.a.b.b.b.b.b.b.m.m.m.b.m.m.m.m.m.N.m.m.XXE.T.U.~.).W.! ~ R.N.N.oXN.XXN.oXoXN.N.N.N.N.N.*XN.N.N.N.N.N.N.N.*XN.oXN.oXoXoXoXN.N.N.oXoXoXoXN.N.XXXXXXXXXXXXXXXX*XN.*XN.N.N.N.N.N.N.N.*XN.*XN.N.*XN.*XN.N.oXN.oXN.N.N.N.N.*XN.N.2XT.U.I.~.).L.T T ].XXXXa.XXa.XXm.m.b.m.m.b.b.b.n.b.b.b.a.XXa.b.M.b.b.z.a.M.a.M.M.h.u.M.u.u.h.u.g.3.&.&.&.%.%.%.$.+.+.+.O.O.O.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | } | | .o.o.O.O.+.+.$.$.%.&.%.%.&.&.&.y.u.u.u.u.u.z.z.z.a.a.M.M.a.a.a.n.n.n.a.a.n.b.b.b.n.b.m.m.b.m.m.m.m.m.m.m.m.m.XX|.P.I.I.~.).Q.Q Y ! ].oXN.N.XXN.N.N.N.:XN.N.N.*XN.N.N.N.*XN.*XN.N.N.oXN.oXN.N.N.N.oXN.oXN.N.N.oXN.oXXXXXXXXXXXN.N.XXN.N.N.N.*XN.*XN.*XN.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.*XN.*XN.N.N.N.E.L.I.U.~.).I.J T J.XXa.a.XXXXXXm.m.m.m.m.b.m.b.b.b.b.b.n.a.n.a.a.b.a.b.M.a.M.M.a.a.h.u.u.h.h.u.g.6.&.&.&.%.%.%.$.$.+.+.O.O.o.o.o. .| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o. .| O.O.O.O.+.+.$.%.%.%.&.&.&.&.=.6.u.u.h.h.a.u.z.h.a.a.a.b.a.a.n.n.a.n.a.n.a.b.b.b.b.b.b.b.b.m.b.m.b.m.m.m.m.m.v.E.P.L.W.^._.).L.S E P.N.N.oXN.XXN.N.N.:XN.N.N.N.N.N.N.*XN.N.N.N.N.N.N.oXN.oXN.N.N.N.N.N.N.oXN.N.N.N.XXm.XXXXN.XXN.XXN.N.*XN.N.N.N.N.N.N.N.N.*XN.N.N.N.N.N.oXN.oXN.N.N.N.N.N.N.N.N.iXL.L.U.^.).).T.L S T '.XXXXXXXXa.b.m.b.b.b.m.a.m.a.n.a.n.a.n.a.n.a.b.a.a.a.a.M.u.a.a.u.M.u.h.u.u.u.6.&.&.%.&.&.%.%.$.+.O.O.O.O.o.| o.| | | | | } UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.O.o.O.O.+.+.+.$.%.&.%.&.&.&.&.=.u.u.u.u.u.z.z.u.a.M.a.a.M.a.a.a.b.a.n.a.n.a.b.b.b.b.b.m.b.b.b.m.m.b.m.m.m.m.#X! ! U.^._.^._.U.S S E S.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.*XN.N.N.N.N.N.N.N.N.N.N.N.N.oXN.N.N.N.N.N.N.m.XXXXm.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.B.`.L.I.^._.).).).^ D Y G.XXXXa.a.XXm.b.b.m.b.b.m.a.XXa.n.a.n.a.b.a.b.a.M.b.a.M.a.a.h.u.u.h.u.u.u.u.y.=.&.&.&.%.%.%.%.$.+.+.O.O.O.@.O.| .| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.O.+.+.$.%.%.%.&.&.&.=.=.=.y.u.u.u.u.a.a.a.a.a.a.a.a.a.n.a.a.b.a.b.b.b.b.n.b.b.b.b.b.b.m.b.m.a.XXa.XX XG.L.I.W.).).W.).).T D Y E |.XXm.XXN.N.N.N.N.N.N.N.N.N.N.N.N.N.n.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.n.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.n.N.N.N.N.N.N.N.N.N.N.N.N.S.K.I.T.^.^.~.^.xXL.D D Y Z.m.n.n.m.n.b.b.b.b.b.b.b.a.b.a.b.b.b.p.p.b.a.b.a.a.z.a.z.a.u.a.a.u.u.u.u.y.=.&.&.&.%.%.$.$.$.+.+.O.O.O.O.o.| | | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | .o.o.O.O.O.O.+.+.$.%.%.%.%.&.&.&.=.&.-.u.u.u.u.u.u.u.a.a.a.a.a.a.a.a.b.a.b.a.a.a.a.a.b.b.b.b.b.b.b.b.b.XXa.XXn.Z.Q I.U.U.^.~.U.^._.K.D D Y S.v.m.m.m.N.N.N.N.N.N.N.N.n.N.N.N.N.N.N.N.N.n.N.N.N.n.N.n.N.N.N.N.N.N.N.N.N.N.N.n.N.N.N.N.N.n.N.N.N.n.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.n.N.N.n.N.m.m.m.m. X! I.T.I.W.W.~.~._.~.S D J T [.n.b.b.n.b.b.b.b.a.b.b.a.b.a.a.a.p.a.b.p.a.p.a.a.a.a.a.u.i.u.u.u.u.u.y.2.=.=.&.&.&.$.&.$.$.$.+.+.O.O.o.o.o.@.| | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.+.+.+.$.%.%.%.&.%.&.=.&.-.-.6.u.u.u.i.i.i.a.u.a.a.a.a.b.a.a.a.a.a.a.b.b.a.b.a.b.a.b.b.b.b.b.n.XXn. X^ I.~.L.I.W.W.W.~.xX~.L v S T #Xm.m.m.m.N.N.N.N.n.N.N.n.N.N.N.N.N.n.N.N.N.N.N.N.N.N.N.N.N.n.N.N.N.n.N.N.n.N.N.N.n.N.N.n.N.N.N.N.N.N.N.n.N.N.N.N.n.N.N.N.N.n.N.N.N.N.N.n.m.m.m.m.m.S.! ~.I.K.T.U.~.~._._.E D D J Z.n.b.b.b.b.b.b.b.b.b.p.b.a.b.a.a.b.a.a.a.a.a.a.a.a.u.a.i.u.u.u.u.i.u.y.=.=.&.&.&.%.&.%.%.$.+.+.O.O.O.o.o.@.o.{ | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | @.o.O.O.O.+.+.$.$.%.%.%.&.&.&.=.=.=.-.6.u.q.i.u.i.i.u.a.a.a.a.a.a.a.a.a.a.a.p.p.a.b.a.b.b.b.b.b.b.b.b.a.XXa.D.W ~.I.K.U.I.U.W.^._._.K.D D J G.m.m.m.N.N.N.N.N.N.N.n.N.n.N.n.N.n.N.N.n.N.n.n.N.n.n.N.n.N.n.N.n.n.N.N.n.n.N.n.N.N.n.N.N.N.n.n.N.N.n.N.n.N.N.N.N.N.N.n.N.n.N.N.n.n.n.N.N.m.m.m.n.].~ T.T.! L.U.I.W.~.).xXW.D v S J '.b.M.b.b.b.x.b.b.b.b.a.b.a.a.p.a.a.a.b.a.a.p.a.a.a.u.i.i.q.u.u.u.q.6.=.=.=.&.&.&.%.%.%.$.$.+.+.O.O.o.o.o.@.| { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.| o.O.O.O.+.+.+.%.%.%.&.&.&.&.&.&.-.-.;.y.u.u.u.i.i.u.i.i.i.p.a.p.a.p.a.a.a.p.a.b.a.a.b.b.b.b.b.b.b.b.a.XX'.Y T.U.Q L.W.I.L.I.).^._.~.J v S R iXb.m.m.n.N.N.n.n.n.N.n.n.N.n.n.n.N.N.N.N.n.n.N.N.N.n.N.N.n.N.N.N.n.n.N.N.n.N.n.n.N.n.n.n.N.n.N.N.n.N.N.N.N.N.n.n.N.N.n.n.N.N.n.N.N.n.n.m.m.n.v.G.K.W.! ! U.U.K.I.W.^.).).! V v J F.M.b.b.n.a.b.b.x.p.a.b.a.b.a.p.p.p.a.p.i.i.p.i.i.i.i.i.q.u.u.u.u.y.=.=.&.&.&.&.&.%.%.%.%.$.+.+.O.O.O.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.o.o.o.o.O.O.+.O.$.$.%.&.&.&.&.&.-.-.-.-.=.6.q.u.q.q.i.q.i.i.i.q.p.p.a.p.p.p.p.a.a.a.a.a.a.a.a.a.b.b.b.a.m.a.P ! W.W Q U.W.! Q K.W.I.~.xXI.D v J I Xn.m.n.n.n.n.n.N.n.n.N.n.n.N.n.n.n.n.n.N.n.n.n.n.n.n.n.N.n.n.n.N.n.n.n.n.N.n.N.n.n.N.n.n.n.n.n.N.n.n.n.n.n.N.n.n.n.n.n.n.n.N.n.n.n.N.n.m.m.iXE W.K.T L.W.L.Q K.U.T.I.).~.L v A Y ].b.a.b.a.b.b.a.b.p.b.p.a.a.p.a.p.p.p.p.p.i.i.r.i.i.i.i.i.q.q.u.6.;.=.=.=.=.&.&.&.%.%.%.$.+.+.O.O.o.o.o.| o.{ | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | o.@.o.O.O.O.+.+.$.$.%.%.%.&.&.-.&.-.-.-.;.;.y.u.i.q.i.i.e.i.i.p.p.i.p.p.p.a.a.a.a.a.a.a.a.b.a.b.a.b.b.a.m.].T I.L.Y L.^.I.T T E K.K.K.^._.Q v D J Z.n.n.N.n.n.N.N.n.N.n.n.n.n.n.n.N.n.n.n.n.N.n.n.n.n.n.n.n.n.n.n.n.n.n.n.N.n.n.n.n.n.n.n.n.n.N.n.n.n.n.n.N.n.n.n.n.n.N.N.n.n.n.n.n.n.n.v.n.v.G.L.W.Y ! W.W.~ T E K.L.! T.).I.D v H P b.b.b.b.a.p.b.b.p.a.p.a.p.a.p.p.a.i.p.p.q.p.i.q.i.u.q.u.q.q.y.-.-.=.=.&.&.&.&.%.%.%.%.$.+.+.O.O.o.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.+.+.+.$.%.%.$.%.&.&.&.-.-.-.-.=.=.6.q.q.u.q.i.i.q.q.p.q.p.i.p.p.a.a.a.a.a.a.a.a.a.b.a.b.a.b.b.a.I K.W.Y ! ~.^.E H Y J S T T L._.).S v S T |.XXn.n.n.n.n.n.n.n.N.n.n.n.n.n.n.n.N.n.n.n.n.N.n.n.n.N.n.n.N.n.n.n.n.n.n.n.N.n.n.N.n.n.n.n.n.n.N.n.n.n.n.n.n.N.n.n.n.n.n.N.n.n.N.n.m.m.Z.! ~.E T I.^.K.H J J S E T E ~._.! v D J Z.a.b.a.b.b.p.a.a.a.p.p.p.p.p.p.p.i.e.i.p.q.q.i.q.q.u.q.q.u.6.=.;.=.=.=.&.&.&.&.%.%.$.$.+.+.+.O.o.O.o.o.| | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | | o.O.o.O.O.+.$.$.$.&.&.%.&.&.&.=.=.=.-.-.;.:.y.q.q.q.q.q.i.q.p.a.r.q.r.a.r.a.r.a.a.a.a.a.b.a.a.a.a.b.a.Z.T U.! Y I._.L.Z Z Y D v L J Y W._.K.V V J J.a.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n.n..5.0.t.t.t.t.q.q.t.e.e.e.e.e.e.a.e.e.a.p.p.a.M.L K.L.J T ^._.L 0 V J Q F V V v 0 1 1 T S A E ).^.S v A L l.n.x.x.x.n.n.c.n.n.n.n.c.n.n.n.c.n.c.n.c.c.n.c.n.n.n.n.c.n.n.c.n.c.n.c.c.n.c.n.n.c.n.c.n.c.c.n.c.n.n.x.n.c.x.n.n.x.x.x.Z.T U.Y J L._.L.v v C ! I.J Z V b 1 1 D E g J W._.E v g F C.a.r.a.e.e.e.e.e.e.e.e.e.e.t.t.e.0.q.t.0.y.6.;.;.;.=.=.=.-.-.-.&.&.&.&.&.%.%.$.$.+.O.O.O.o.o.@.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.O.o.O.+.+.+.$.%.%.%.&.&.&.&.-.-.=.=.=.;.;.;.;.;.;.6.0.t.t.t.9.e.9.e.t.e.e.e.e.e.e.a.e.p.p.e.C.R U.T J L._.I.g v A ! Y A V g v 0 8 2 v ! V Z I.).I.g j Z J.x.x.x.x.n.c.n.c.c.c.c.n.c.c.c.n.c.n.c.c.n.c.n.c.c.c.c.n.c.c.n.c.n.c.n.c.c.n.c.c.n.c.n.c.n.c.c.n.c.x.x.c.n.x.c.x.x.x.l.Y L.L.H E ^.^.S 8 h H U.! T Q J V 8 1 b ! D h E ^.^.S 0 C H u.r.e.a.e.e.e.e.t.e.t.t.t.t.t.0.0.q.0.0.7.;.;.;.;.;.;.=.-.-.-.&.&.&.%.%.%.%.$.+.+.+.+.o.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.+.+.$.$.&.%.%.&.&.&.&.=.=.=.=.=.;.;.;.>.;.;.>.0.0.t.t.t.t.t.t.w.e.w.e.e.e.c.e.r.r.e.'.S K.I.J ! ^.).S 0 h J Q Z h h V V v b 1 2 L J h E ^.^.S 0 A J ].x.x.x.c.x.x.x.x.x.x.x.c.c.n.c.n.c.n.c.n.c.n.c.n.c.c.c.n.c.n.n.c.c.c.c.n.n.c.n.c.n.c.c.c.n.n.c.c.c.n.c.c.c.n.c.n.n.D.~ Y.Y Y T._.E 0 v C Q T.E I.I.Y A v 1 1 D W h S I.).K.v g F D.i.r.r.e.e.e.e.e.0.e.e.9.e.0.t.0.t.0.0.;.>.;.=.;.;.=.;.=.=.=.=.&.&.&.%.$.&.$.$.+.O.O.O.O.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.o.o.o.O.O.+.+.+.$.%.%.%.&.&.&.=.=.=.=.=.=.=.;.;.;.;.>.>.5.8.0.0.9.t.9.t.9.w.w.w.e.w.w.e.e.e.q.K E T.J Y W._.! 0 v Z W J A h V V g g 0 8 2 8 T V A I.).I.V / G U n.x.x.c.x.x.x.x.c.x.x.c.c.c.c.c.c.c.c.c.c.c.c.c.n.n.c.c.c.c.c.c.c.n.c.c.c.c.c.c.n.c.n.c.c.c.n.c.c.n.c.n.c.c.c.c.C.^ I.~ F K._.W.V 0 z H I.E K.U.T Z G h 8 1 1 T S g T ^.^.S 0 V Z C.e.e.e.e.e.w.t.e.9.0.9.0.9.0.9.0.8.6.>.>.;.;.;.;.;.=.=.=.=.&.=.%.&.$.$.$.$.+.+.+.O.O.o.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | .o.o.O.+.+.+.$.$.$.$.%.&.&.&.=.=.=.=.;.;.;.;.;.;.>.;.>.;.5.0.0.9.t.t.9.w.w.w.w.w.e.e.e.r.e.'.H L.Q H K.).^.D 0 z Y W C h V V h g g g b 1 2 D T h Y ~.).T / x H C.c.c.x.c.x.c.x.x.c.c.c.c.n.n.c.c.n.c.c.c.n.n.c.c.c.c.c.c.c.c.n.n.c.c.n.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.n.F.K.I.F R W._.E 0 v C K.L.T I.! Z l C A 0 1 2 v W g A I.).L.g v Z P e.e.e.e.w.e.0.0.9.9.0.e.9.9.0.0.5.;.>.;.>.;.;.;.=.=.=.=.=.&.&.&.&.&.%.%.$.$.+.+.O.O.o.o.@.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.O.+.$.$.%.%.%.&.%.&.&.&.=.=.=.=.=.;.;.>.;.>.>.>.;.5.9.0.9.0.9.9.w.w.w.w.w.e.e.e.a.K ! I.H Y W._.W 0 g H ! H h g h V h V g g 0 8 1 1 T S z W ).Q.D 0 A Y l.x.c.x.c.x.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.n.c.c.c.c.c.c.c.c.c.c.c.c.n.c.c.n.c.c.c.c.c.c.c.n.c.Z.T W.T F K._.I.V 0 x E U.E L.I.Z z V z C V 8 1 2 L Y h J U.).T 0 g F C.t.t.t.e.9.e.0.0.e.9.0.0.0.0.5.>.;.>.;.;.;.;.=.=.=.=.=.=.=.&.%.&.$.%.%.$.$.+.O.O.O.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.O.O.O.+.+.+.%.%.%.%.%.&.&.&.=.=.=.=.;.;.;.=.;.>.;.;.>.>.1.5.0.0.0.0.9.9.9.9.w.w.w.e.e.C.J I.E H K.).U.V 0 z T T z g V h h V h h g g 0 8 2 v T d Z U.).~ / g H D.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.l.L L.L.Z T ~.).S 8 g G I.K.E ~.T l h g h l l v 1 2 8 ! V z E ).W.V 7 A S u.t.9.t.9.9.9.9.0.0.0.0.0.5.>.>.>.;.>.;.=.=.;.;.=.=.=.-.&.&.&.&.&.%.%.$.+.O.+.O.O.o.o.o.| | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.O.+.+.+.%.%.%.&.&.&.&.&.=.=.=.=.;.;.;.;.>.>.>.>.>.>.5.5.0.9.8.9.9.9.9.9.w.w.w.u.Z ! L.F E W.^.S 7 h H E Z h g h h h h h h g v 0 8 2 2 S Z h E Q.W.S 0 x H l.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.D.E I.J H L._.E 9 0 l E L.Y L.L.Z h h g V x z z 8 < 2 S Y 9 Z T.).T 0 g C V.9.e.t.9.9.9.8.9.8.0.8.6.6.>.>.>.>.>.;.;.;.;.=.=.=.&.-.&.=.%.&.%.%.%.$.$.+.O.O.O.O.o.o.| { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | o.o.o.O.O.O.+.+.+.%.%.%.&.&.&.=.=.=.=.=.=.;.=.;.;.;.>.;.>.>.>.1.5.5.9.0.9.9.9.9.9.9.9.c.V.Y I.Y H I._.P.7 0 A R J z g h g h h h h h g g g 0 8 2 b W h C I.).K.j j C F.n.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.l.Y L.K.C ~ /.^.V 8 g F I.E E U.J z h g g g h A z v 8 2 1 T A g W ^.W.A 0 h F u.e.9.9.9.9.9.9.8.9.7.5.>.>.>.>.>.;.;.;.;.=.;.=.=.=.=.&.%.&.%.%.%.%.$.+.+.O.O.o.o.o.@.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | .o.o.o.O.+.+.+.%.%.%.%.%.&.&.&.=.=.;.=.=.=.;.;.>.;.;.>.>.>.>.>.>.5.8.8.9.9.9.9.9.9.9.g.S K.K.F E ^.).S 7 f J E C d g g g h h h h h h g 0 g 8 2 , L J f Y ~.^.L 7 x F f.c.c.c.c.c.c.w.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.r.c.c.c.c.c.c.c.c.c.c.c.c.r.c.c.c.r.c.c.c.c.c.c.c.c.c.D.~ U.H J I._.Q 0 9 l E I.Y I.K.l h h g g g g h z z 8 < , D E d F L.).K.0 9 C V.0.9.9.9.8.8.0.0.8.5.,.>.>.>.;.>.;.;.;.;.;.=.=.-.=.&.=.&.&.&.%.%.%.$.+.+.+.O.o.o.o.o.| | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.O.O.O.+.+.+.$.%.%.&.&.&.=.=.=.=.=.=.;.;.=.;.>.>.>.>.>.>.,.,.,.5.8.8.9.9.9.9.9.c.M T I.J J U._.! 9 9 C E H f g g g g f f h f h h g 9 g 0 8 2 w T V x K.^.T.x 0 l L l.c.c.c.c.c.c.c.c.c.c.r.c.c.c.r.c.r.c.c.r.c.c.c.c.c.r.c.c.c.c.c.r.c.c.c.c.r.c.c.c.c.w.c.c.c.c.c.C.R I.T G K.).U.V 7 z J I.E K.T.H z g g g g d d g h z g 1 < < T S f J Q.).J 8 h Z C.9.8.9.9.8.0.8.5.,.>.>.>.>.>.>.;.;.;.;.;.;.=.-.-.-.&.&.&.&.%.%.%.+.+.+.O.O.O.o.o.| | { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o. .O.O.O.+.+.$.$.%.&.%.&.&.&.&.=.=.=.=.;.;.;.;.;.;.>.>.>.>.,.,.,.>.5.8.9.9.8.9.9.s.H K.Q C Q ).U.V 7 z J Y z g d d g g h g g h f f h g 9 9 8 1 , v J j J ~.^.Y 7 j F C.c.c.c.c.w.c.c.c.r.c.r.c.r.r.c.c.r.r.c.r.c.r.c.r.c.r.c.r.c.r.c.c.r.c.r.c.r.r.c.w.c.c.c.c.c.c.M.Y ~ L.C J W._.J 3 g l Q K.T W.E z f g d d 9 g g d g h z 7 < 2 8 W g z K.).L.d 7 A D q.9.8.8.8.5.5.>.,.,.>.>.>.>.;.>.;.;.;.-.=.=.-.-.&.-.&.%.&.%.%.+.$.+.+.+.o.o.O. .@.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | .o.o.O.O.O.+.$.%.%.%.%.&.&.&.&.=.=.=.=.=.=.;.;.>.;.;.>.>.>.>.,.,.,.,.<.8.9.8.9.c.S ~ L.F J ~.).Y 7 d F T Z f d 9 g d g f g f f h h f f g g 9 3 2 < T A x W ^.T.A 9 z L h.c.c.c.c.c.c.r.c.r.c.c.c.c.c.c.c.r.c.c.c.c.c.c.c.c.r.c.r.c.r.r.c.r.c.c.c.r.c.c.c.c.c.c.c.c.C.T I.J G K.).K.0 7 z Y L.Y K.K.G x g g g g 9 g 9 9 g f z g 8 < , D J d H U.^.Y 7 g c A.9.9.8.5.5.>.>.>.>.>.>.>.>.;.;.;.;.;.=.=.=.-.-.&.&.&.&.$.&.%.%.$.+.O.O.O.O.O.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | .| o.O.O.O.+.+.$.$.$.%.%.&.&.&.=.=.=.=.=.=.;.;.;.;.>.>.;.>.>.,.>.,.,.,.<.<.7.9.8.s.J L.Y Z K.).I.9 7 z Y J z d d g 9 g 9 d f g g f f h g g 9 9 7 1 @ v R j C L.).K.9 / l V.c.c.c.w.c.w.c.r.r.c.r.r.r.r.r.r.c.c.r.r.r.r.r.r.r.c.c.r.r.c.r.c.r.r.r.r.c.c.w.c.w.c.c.w.k.L K.L.C T Q.Q.S 3 d G L.E E I.J z f d g d g 9 9 9 9 9 9 f z 0 < , 8 ! h f W ).T.h 7 z S q.8.7.5.>.5.>.,.>.>.>.>.;.>.;.;.;.-.=.;.=.-.&.-.&.%.&.&.%.%.$.$.+.+.O.O.o.@.o.o.| { | | } UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.O.O.O.+.$.$.$.&.%.&.&.&.&.=.=.-.=.;.;.;.;.;.>.;.>.>.>.>.,.>.,.,.,.,.<.7.g.D ~ L.Z T ~.^.S q d F R C d d d 9 9 d d d f f f f f f f f 9 9 9 8 < , L Z u T Q.~.A q x F f.c.r.r.c.r.r.c.r.c.r.c.r.c.r.c.r.r.r.c.r.r.r.r.c.r.r.c.c.r.c.r.r.r.c.r.r.r.c.c.w.c.c.c.V.T I.H H L.).~ 7 7 z T L.Y L.K.c f g g d d d 9 9 d g 9 9 d h f 8 2 , A T d Z L.).W 7 7 C V.8.5.5.>.,.,.,.,.>.>.>.>.;.;.;.;.;.-.-.-.-.&.&.&.&.&.&.$.%.+.+.+.+.O.o.o.o.| o.| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.o.o.o.o.O.+.+.+.$.%.$.%.&.&.&.&.=.=.=.=.;.=.;.;.;.>.>.>.>.>.,.,.,.,.,.,.,.,.<.m Y I.H F I.).W 9 0 z Y F f d 9 9 9 d 9 9 d d d d d f d f f d 9 9 7 w , w Y j z K.).K.j 7 l U c.r.c.w.c.r.r.r.r.r.r.c.w.r.c.r.r.r.r.r.c.r.r.r.r.r.r.r.r.r.r.c.r.r.r.r.c.w.c.w.c.c.'.H K.T l E ).T.x 3 x G L.R E L.F z d d y d y y 9 9 9 9 9 9 9 d f 9 w , < Y A y Y Q.W.A 3 f l X.5.5.5.,.>.,.>.>.>.>.;.>.;.;.;.-.;.-.-.-.-.-.&.%.&.$.&.%.$.+.+.+.O.O.O.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | .| o.o.O.O.+.+.+.$.$.&.%.%.&.&.&.=.=.=.=.=.;.;.;.;.>.;.;.>.>.>.,.,.,.,.,.,.>.f.l ~ ~ c E ^.W.A 3 u F Y k d 9 9 9 9 9 d d 9 y d d f d f f f f 9 6 9 3 2 @ D H y J U.^.J / j c f.r.c.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.c.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.c.w.c.w.c.D.E L.C H I._.Y q 7 l E ! J L.T l u d y d 9 d y 9 9 9 9 9 9 6 d d f 3 < , 0 Y y z K./.W 9 4 a m 5.,.,.,.,.>.>.>.>.>.>.;.;.;.;.;.=.-.-.-.&.-.&.&.%.%.%.%.$.+.+.O.O.o.o.o.o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.o.O.O.+.$.$.$.%.&.&.&.&.&.&.=.=.=.;.=.;.;.;.;.;.>.>.>.>.>.,.,.<.,.,.,.m J K.l F I.).T 7 9 l T C u 6 9 9 y 9 y 9 9 y d d y d y d u d f d 6 9 9 w , w R x x W ^.I.x 4 k L z.w.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.r.w.c.w.c.C.J I.T C ~ ).I./ q x H L.Y ! K.C u d d d 9 y 9 9 9 9 y 9 9 6 9 9 y d y w , , L S y H U.^.S - r c X.,.,.,.,.>.>.>.>.>.;.;.;.;.;.;.=.-.-.-.-.&.&.&.%.&.%.%.+.+.+.O.O.o.o.@.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | .o.o.o.O.O.O.+.$.$.%.%.%.&.&.&.-.-.-.-.-.;.;.;.;.;.;.>.>.>.>.>.,.>.,.,.<.s.Z ! T k ~ ).T.h 3 u J J z y y 9 9 9 9 9 6 9 y d y d d d f y f u d 9 6 9 q < @ g Y 6 C T.^.W 4 d C V.r.r.r.r.r.w.r.r.r.r.r.r.r.r.r.r.r.r.r.w.c.c.w.c.w.c.w.9.c.9.c.c.9.c.c.e.c.w.z.L ~ L.C Y U.^.H q / z ! Q Y I.J z u y d y 9 9 y 9 9 9 6 6 9 7 9 9 6 y f q < , q W j x W Q.L.r - p D 6.5.,.>.>.>.>.>.>.;.;.;.;.=.=.=.=.=.-.&.&.&.%.&.&.%.%.$.+.O.O.O.o.o.| @.| | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | | | o.o.O.O.O.+.$.$.$.&.%.%.&.&.&.-.-.-.=.=.;.;.;.;.>.;.>.>.>.,.>.,.,.,.6.V T K.l J U.~.S 7 y l Y C y 9 9 6 6 6 9 y 6 y 9 y 9 y y d y d y y d d 6 6 7 3 , , S A u W W.T.z 4 z H d.e.r.r.r.r.r.r.r.r.r.r.r.r.w.r.r.w.r.c.w.w.c.w.c.w.c.c.9.c.c.9.c.9.9.c.w.c.V.Y L.H Z L.).! 5 q p H K.Y ! ~ l u d d y 9 y 9 9 9 6 6 9 6 9 6 9 6 9 6 y 6 3 , , A J : l I.~.J - : a A.>.,.,.,.>.>.>.;.>.>.;.;.;.;.=.=.=.-.&.&.&.&.&.%.$.$.$.+.+.O.o.o.o.o.| o.| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.o.O.+.O.$.$.&.%.%.&.&.&.-.=.-.-.-.;.-.;.;.;.;.;.>.>.>.>.,.,.,.<.N Z K.F l K.).! : = p J F p 6 6 6 7 6 6 6 9 6 6 9 y 6 y y y d y y y u y y 6 6 7 < X 8 R y C L.^.! y 6 k D.e.e.r.r.r.w.w.r.w.w.w.r.r.w.w.r.r.w.w.w.c.9.w.c.w.w.9.c.c.8.c.9.9.c.c.w.g.S K.~ k T ^.^.A 3 y c ~ E Y K.G p y y y 9 9 y 6 6 6 6 6 6 6 9 6 6 7 6 6 6 d 7 < , < J u e R ~.I.u - t s 3.,.>.,.>.>.>.>.;.;.;.;.;.;.=.=.=.-.&.=.%.&.$.$.$.$.$.+.O.O.o.o.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.o.| o.o.O.+.+.$.$.$.%.%.%.&.&.&.&.-.-.-.-.;.;.;.;.>.>.>.;.>.>.,.,.,.6.A T ~ s J W.^.A - 5 l J k y 6 6 6 6 6 6 6 6 6 6 6 6 y y y y y y y d y y y 6 6 6 3 , $ S S t J W.W.S = u F f.e.w.r.w.r.r.w.r.r.r.w.r.r.r.w.r.r.9.c.9.c.w.9.c.w.c.8.9.c.8.c.c.9.w.c.V.T I.F G L.).! q q p J K.Y ! Y k y y y y y y 6 y 6 6 6 6 6 6 7 6 6 7 6 7 6 y y 3 % . 0 J : k K.^.Y > > i V.,.,.>.>.>.;.;.>.;.;.;.=.=.=.=.=.-.-.%.&.$.&.&.$.$.$.+.O.O.o.o.o.o.o.| | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.o.o.o.O.$.$.$.$.%.%.&.%.&.=.&.-.=.=.=.=.=.;.;.;.;.>.>.>.,.>.>.;.m S K.G C ! ^.R ; = p H c t 9 6 4 6 6 6 6 6 6 6 6 y 6 y 6 y 6 y y y y y y y y 6 6 7 < , < R d z ! ^.L.y 7 k U z.w.r.w.w.r.w.r.w.w.r.r.r.w.r.r.w.w.w.c.w.w.c.9.9.9.c.9.c.c.9.c.c.w.].J L.Y l T Q.L.j 3 u F K.T E Q l u y y y y y 6 6 6 6 6 6 7 6 6 6 6 6 6 6 7 6 6 y 4 % $ $ F A : F U.~.A * r k X.1.,.>.>.;.;.1.;.=.;.;.;.=.=.=.-.&.%.&.%.%.%.%.$.$.O.O.o.o.o.o.| o.| | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.| o.o.o.O.O.O.$.$.%.&.%.%.&.&.-.&.=.=.;.;.;.;.;.;.>.;.>.>.>.>.>.f.l ! E k Y W.I.j - e l F s 5 4 4 6 6 6 7 6 6 6 6 5 6 6 6 6 y 6 y 9 y y y y y y 6 6 5 3 % . V Z r H W.~.H 4 y c C.r.w.r.r.w.r.w.r.w.r.w.r.r.w.w.r.c.9.c.w.w.c.w.c.c.8.c.8.9.c.9.9.g.U E L.l H L.^.H 3 5 a T ~ Y ~ J p y y 6 6 6 6 6 6 r 6 6 6 6 6 6 6 6 7 6 7 6 6 4 5 5 * $ @ 4 Y : t W ~.Q > = s B 6.1.>.>.>.>.;.;.;.;.=.=.=.=.=.-.&.&.&.%.%.%.%.$.+.O.O.o.o.o.| | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.| o.o.o.O.$.$.$.$.%.%.%.&.&.&.=.=.=.=.;.=.;.;.;.;.>.>.>.>.>.>.,.V J K.l Z U.^.Z - ; a H k t ; ; ; 4 4 6 6 6 4 5 6 6 6 5 6 5 6 y 6 6 6 y y y y 6 r 7 6 4 3 $ , Y x u W ~.I.h 4 p L r.w.r.w.r.w.r.w.w.w.w.w.w.r.w.w.w.c.9.w.8.w.w.8.c.w.8.c.9.9.c.0.s.Y L.J c ! ).K.4 3 u F ! J T T a y 6 6 6 6 6 6 6 6 6 6 5 6 6 6 6 7 4 6 6 6 5 4 ; ; : : & $ $ x C > C U.W.Z - r k s.>.>.>.;.;.;.;.;.;.=.=.=.=.&.&.&.&.&.%.%.%.+.$.$.$.O.o.o.o.| | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | @.o.o.o.o.O.O.$.$.%.%.%.%.&.&.&.=.=.=.=.=.=.;.;.;.;.;.>.>.>.>.s.Z K.H a ~ ^.L.5 * t G G i : ; ; ; 4 4 4 4 6 6 6 5 6 5 y 6 6 5 6 6 6 6 r 5 5 y 6 6 5 6 6 3 < . g R r C I.~.~ 4 5 l V.r.w.w.r.w.w.r.w.r.r.w.w.w.w.r.w.w.w.w.c.8.c.c.8.8.c.8.c.9.9.c.^ ! K.k J U.).S * 5 k E E J ~ C i y 6 6 6 5 5 6 5 6 5 6 6 5 4 6 4 6 4 6 5 4 4 ; 4 : : : - # . & R r t W ~.L.r = u V 6.1.>.;.>.;.;.;.;.=.=.=.=.=.=.&.&.%.%.%.%.$.$.O.O.O.o.o.o.o. .| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.| O.o.O.+.$.+.$.%.%.&.&.&.&.=.=.=.-.;.=.;.;.;.;.>.>.>.>.6.V T ~ k H U.^.H * : k H a r ; ; ; 4 ; ; ; 4 5 6 4 6 6 5 6 5 6 5 6 5 5 6 5 6 6 6 6 y 6 5 6 4 3 # # L A i Y W.T.A = p Z f.w.w.r.w.w.w.w.w.w.w.r.w.w.w.w.w.w.w.w.w.w.w.w.w.w.c.9.w.c.V.Y L.F C K.).K.5 q i H ! Y R Y p y 5 6 6 5 6 5 6 6 5 6 5 6 4 6 5 6 4 4 4 4 : ; 4 ; ; ; 4 : * $ @ V J e l L.~.Y = : a A.6.>.;.;.;.;.;.=.=.=.=.=.&.=.&.%.&.%.%.%.%.+.O.O.o.o.o.o.| @.| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.| o.o.o.O.+.+.$.$.%.&.%.%.&.&.&.&.=.-.-.;.=.;.;.;.>.;.>.1.N H K.G l ! ^.~ : = i F l t ; ; ; ; ; ; ; ; ; ; 5 5 4 4 6 4 6 5 6 4 6 6 5 6 6 6 6 5 5 6 6 4 6 3 < . 3 Y r z L.^.! 5 5 k U w.w.w.w.w.w.w.w.r.w.w.w.w.w.w.w.w.c.w.w.w.c.9.c.w.w.w.w.f.H K.Y a Y ~.T.x 3 t k ~ T Y T l r 6 6 5 5 6 5 6 6 5 6 4 6 6 6 4 6 6 4 4 ; 4 : ; ; ; ; ; ; 5 = # @ % Y h e J W.U.f - t k X.1.;.;.;.=.;.;.=.=.=.&.=.%.&.&.%.%.$.%.+.+.+.O.o.o.o.| o.| | { | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | { | | | o.| o.o.o.+.+.$.$.%.%.%.%.&.&.=.=.=.=.-.=.;.=.;.;.;.;.>.X.l R E a J U.U.x - e k F s 5 : ; ; ; ; ; ; ; 4 ; : ; ; 4 5 6 4 6 6 5 5 5 5 6 5 5 r 6 r 6 5 6 4 4 3 # . D Z r J T.W.H ; i C f.9.w.w.w.w.w.w.r.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.c.P T L.l C L.).Y = = p H ~ J T H p 6 5 5 5 6 5 6 5 4 6 4 6 4 4 5 4 4 4 ; ; ; ; ; ; ; ; : ; ; : : * # . 7 J > p L.~.T > ; a m 1.;.;.;.;.=.=.=.=.=.=.=.&.&.%.%.%.%.$.+.$.+.O.o.o.| o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | @.| o.| o.o.O.+.+.$.$.%.&.%.&.&.=.&.=.=.-.=.=.;.;.;.;.>.1.m J K.l C L.^.Y - ; a F k e : 4 ; ; ; ; ; ; ; ; ; ; ; ; : 4 4 4 4 4 5 6 5 6 5 5 5 5 5 6 5 r 5 4 5 4 w . & R f p ~ ~.L.j = i S c.w.w.r.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.f.H L.Y k T ^.L.6 3 t C ~ Y J J a r 5 6 5 5 5 5 4 6 4 6 4 4 6 4 4 ; ; ; ; ; ; ; ; ; : ; : ; ; ; : = & . $ S C e F U.W.A - r a X.;.;.;.=.;.=.=.=.=.&.&.&.&.&.%.%.%.$.+.O.O.o.o.o.o.| .| { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | { o.o.o.O.+.+.$.%.$.%.%.&.&.&.&.=.=.=.=.=.;.;.;.;.;.X.C ! T k Y ~.I.j * t C F s ; ; ; ; ; ; ; ; ; 4 ; ; ; ; ; ; : 4 : 4 4 5 4 4 5 5 5 5 5 5 5 5 5 5 5 5 5 3 # . V Y e G U.~.Y > 5 l C.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.w.q.U E L.l H I.^.Z * 5 p Y E J T C t 5 5 5 5 5 5 4 5 5 4 4 5 5 4 4 ; : ; ; ; ; ; ; ; ; 4 ; ; 4 : : : : * # . 3 R r p W ~.K.5 = p v 1.;.;.;.=.;.=.=.=.=.&.&.&.&.$.$.%.$.+.+.O.o.o.o.| o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.o.o.| o.o.+.+.$.$.%.%.%.%.&.&.=.&.=.=.=.;.=.;.;.;.6.V Y ! l F I.^.S > > p F a r ; ; ; ; ; ; ; ; ; : ; ; ; 4 ; ; ; ; ; : : 4 4 5 4 5 5 4 5 5 5 4 5 5 4 5 5 ; & $ # S z t T W.L.x = p Z u.w.w.w.w.w.w.w.9.w.w.9.w.w.w.9.w.w.w.w.w.w.9.w.V.J K.F l ! ).~ 5 = i C ~ J J H p 5 5 5 4 5 5 4 4 5 4 4 4 4 ; : ; ; ; ; ; ; ; ; ; ; ; : : ; : : ; 4 : ; & $ $ A Z e l I.~.Z - 5 s A.;.-.;.=.=.=.=.=.&.&.%.&.&.%.%.$.$.+.+.o.o.o.| | o.| | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | | | | o.o.o.O.+.+.$.%.%.%.%.&.&.&.=.=.=.=.=.=.;.-.;.A.G ! F k ~ ^.! : - i G l t : ; ; ; 4 : ; ; ; ; ; ; ; ; ; ; ; ; ; ; : : : ; 4 4 4 4 4 5 5 5 5 5 5 5 4 4 5 = % . 8 J e z L.^.T : 5 k V.8.w.9.w.w.w.w.w.w.9.w.9.w.w.w.w.9.w.9.9.w.9.g.S ! T a H ~.^.z * : a Y Y H J k r 5 5 4 5 4 5 4 5 4 4 : ; ; ; 4 ; ; ; ; ; ; 4 ; ; ; ; : : ; : 4 : ; ; 4 = % . & J r e T ~.L.y - i k 2.-.;.=.=.=.=.&.=.&.&.&.$.%.%.$.+.+.O.o.o.| | o.| | | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | o.o.{ o.o.o.o.+.+.$.$.%.&.%.&.&.&.&.=.=.=.=.=.;.&.:.x T E a F T.^.A - : a F a e ; ; : ; ; : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 ; : : : 5 4 : 5 4 4 5 5 5 5 5 5 5 5 < $ $ S A t J U.`.A = u A f.w.9.9.w.w.w.9.w.w.w.w.9.9.w.9.w.9.w.w.w.9.C.Y L.C l ! ).~ = 3 i F E H J Z t 5 5 4 5 4 5 4 5 4 4 ; ; ; ; ; ; ; ; 4 ; ; ; ; ; ; : ; ; ; : : : : : ; ; ; & # . v J > l L.~.J > : s A.=.=.=.=.=.&.=.&.&.%.&.%.%.%.$.+.+.o.o.o.| o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.| | @.o.o.+.+.+.%.%.%.%.%.&.&.-.&.-.-.-.-.-.;.N H K.F l ! ^.W = = i F l t ; ; ; ; ; ; ; : ; ; ; ; ; ; ; ; ; ; ; 4 4 4 : ; ; ; ; ; : ; ; ; : 5 5 ; 5 5 5 5 5 = & @ * R u i ! ^.L.5 ; p K e.w.w.9.w.9.w.w.w.9.w.w.9.9.w.w.w.w.w.w.f.Z P.T a Y W.T.u * r k T J H H p 5 : 5 : : 4 ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 ; ; ; ; ; : : ; ; 4 : : : : : ; > > % @ % T x e H T.W.z * t z X.-.-.-.-.-.&.&.&.&.%.%.%.$.$.O.O.o.o.| | | o.| } | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { { | | | o.| | o.o.O.+.+.%.%.%.%.%.&.&.&.&.-.-.-.-.-.3.x ~ ~ k Y ~.T.x - e k F i : ; ; : : ; : ; ; ; ; ; ; ; 4 ; ; ; ; ; ; : 4 ; ; ; ; ; ; : ; : ; ; : ; ; : ; 4 ; 5 5 3 @ @ V Z : F U.U.A > t l C.9.9.w.9.9.9.9.9.9.9.9.9.9.w.8.8.w.8.w.U Y P.l Z L.^.J = ; i H T H J l r 5 : ; 4 4 ; ; 4 : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 : ; ; ; : : : : : : : : ; > - $ @ 7 R r p K.^.~ = = a B -.-.-.-.&.&.&.&.%.%.%.%.$.$.O.O.o.o.o.o.o.| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | | | | o.o.o.o.+.+.+.%.%.%.%.&.&.&.-.&.-.-.-.&.v J ! l F I.^.J = > i F a t ; ; 4 : : : : ; : ; ; : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : : 4 : ; ; ; ; ; ; ; e > & @ $ J u i ~ ~.K.u = i D w.9.9.9.9.w.9.9.w.8.w.9.w.w.w.w.9.w.A.S ^ H k ~ /.L.: * t k Y H H Z t : : ; ; ; ; ; ; ; ; : 4 ; ; ; 4 ; ; ; ; ; ; ; ; : ; ; ; ; : : : : : r : 5 : ; ; > & @ $ A A e Z T.T.z - e k s.&.-.&.-.&.&.%.&.$.%.$.$.+.O.o.o.o.| | | o.| | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | .o.| { { o.o.O.+.+.+.+.&.%.&.&.&.&.-.-.-.-.s.G ~ J s T ^.I.y * t c l i : ; ; : : : : : ; : 4 4 : ; : ; ; ; ; ; ; ; ; ; 4 ; ; ; ; ; ; ; ; ; ; ; ; : : ; : : ; > > - # . 0 R e C I.^.J > r a C.9.9.9.8.9.9.9.8.w.w.8.9.8.w.8.8.w.U ^ P.a G U.Q.S * ; s H Y F F a r 4 : ; 4 : ; ; ; ; ; ; ; ; ; ; : ; ; ; ; ; ; : ; ; ; ; : 4 : : : 4 : 5 : : : : ; > - # . * J u i W ^.! 5 = s v -.-.-.&.&.&.&.%.%.%.%.+.O.O.o.o.| o.} o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | o.| o.O.O.O.%.%.+.%.&.&.&.&.-.-.&.&.B Y ! k G L.^.J - ; a C a r ; : : : : : : : 4 : ; : ; ; ; : ; ; ; ; ; ; 4 : ; ; ; ; ; 4 ; ; ; ; ; ; ; ; ; ; : : ; > : 4 & @ $ J C t Y ~.I.j = i A g.8.9.9.8.w.8.9.8.w.9.9.9.9.9.9.C.J L.F k ~ Q.! : = t c Y F G l t : : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : : ; ; : : : 4 : : : : : 5 : : r : : ; ; & $ @ j J t l L.~.H - : k s.&.&.&.&.%.%.%.%.%.$.+.+.O.o.o.| | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | o.{ o.{ o.| O.+.+.%.%.%.%.%.&.&.&.-.-.N Z K.F a E ^.! : = i G l i ; : : : 5 : 4 : : : : : ; ; : ; ; ; : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : ; ; ; ; ; ; : : * # . * H t k L.^.Y > ; k B 9.9.9.w.8.w.9.w.8.9.9.8.9.9.f.c ~ T s H I.I.x * e s J J G l i : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 ; : 4 : ; ; : 4 : : : : : : : 5 5 : : r 5 : ; : - # . % Y A t J ~.I.y * t l X.-.&.&.&.%.%.%.+.+.O.O.o.o.o.| | o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | o.| o.O.+.+.+.%.%.%.%.&.&.&.&.X.x Y ~ s F L.I.z = e a F a t ; ; : 5 : : : : : : ; ; ; : ; : ; ; : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 ; : ; ; : ; ; ; ; : ; & & @ . x F t J W.T.z = i c f.9.9.9.9.8.9.8.9.9.9.9.8.9.M J ~ k a ~ W.J = = s C T H l s i : : ; ; ; 4 ; ; ; 4 ; ; ; ; ; ; ; ; ; : ; ; ; ; ; : : 4 ; ; ; : 4 : : : : r : : : : ; : > & # . q J t a K.^.H = ; a N &.&.&.%.%.%.%.%.$.O.O.o.| | | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.{ { o.o.O.O.O.%.+.%.%.&.%.&.&.&.N Z E l k ~ ~.J = = s H c i r : ; : ; : : : ; 4 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : ; ; : : ; : : : : 5 : : : : ; * - & . % R p a W ^.! r = a B 9.9.w.8.9.9.w.9.8.9.9.9.f.Z ~ Y s J T.K.5 * e l ~ J G l s t 5 : : ; : : ; ; ; : ; ; ; 4 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : : : : : : : 5 5 4 : : > - & @ @ S Z e H T.T.z - t k X.&.%.&.%.%.%.+.O.O.o.o.o.| | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | | | o.O.O.O.%.%.%.%.%.%.$.X.x J Y s F I.L.u * e C F p t : : 4 ; ; ; ; ; = ; ; ; ; ; ; ; ; ; ; ; : ; ; : ; : : : : : 5 : : : : : r 5 5 r r r : e r e : ; = - & # @ j J e c I.^.H - r l C.8.9.8.9.9.9.9.9.9.9.w.B Y K.k l ~ T.H - ; s Y ~ F F Z k s e r r : : : : : : : 5 4 5 : ; ; ; : ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 4 ; ; ; ; 4 ; ; ; ; : : ; * # @ - R t i ~ ^.~ : = s m %.%.$.$.%.+.+.+.O.o.| | | | | o.} | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | o.| | | o.| o.O.+.+.+.%.%.%.%.*.b l Y l k E I.H = ; k J k t r e e 5 ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; : : : : r : r r r r t t t t t i i i i i i i p s p p a p i r 5 - - & @ # J u t T ~.I.u ; i A g.9.9.9.8.9.8.9.9.9.C.J ! Z i J L.R 5 - t F ! Z C J ~ ~ F k a i i i i i i t t t t e e e r 5 r r : : : : : ; ; ; ; 4 = ; ; ; = ; 4 = ; ; ; ; ; r t t e ; * # # A H e c I.^.Z - r k s.+.%.$.%.+.+.+.o.| o.| | | o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | | | o.| O.+.+.%.%.%.%.&.s.z G C i H K.E t > a J c t : 5 : r 5 : : : : ; 5 : 5 r 5 r r r r t t t t i i i i s s s a s a a k k k k c c c G G F G F G G c k s e = * # @ / Z > a L.~.W r e k V.7.8.9.8.9.9.8.9.g.S E J e z ~ L.z > e G K.H a k G R L.~ J F l l c a a a a a p s s s i s i t i i t t t r e r e : r 5 r : ; : : : ; : : 4 ; : t s k G l : * @ = R ; e Y ~.L.r = i s *.%.$.%.+.O.O.o.o.| | | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | | o.| o.+.O.+.%.%.%.*.x a l i a R K.G e z R H i e : ; ; 4 = = = = = ; = ; = ; 4 ; ; ; : : 5 : 5 r : 5 r r r r t t u i i i i i p p a p z k z k z l l l c a i = & @ 3 H = ; H I.I.H : t D g.9.9.9.9.8.9.8.C.T ~ u e Z ~ R i e H K.Z i r t t t p x x k a p p s i i i i t t t t e e r r : : 5 : : : ; ; ; > = ; = ; 4 = = = ; = = = = ; ; t a J ! J t - - F / * z ! W.Y ; : s s.%.$.+.+.O.o.| | | | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX .| | | | | | @.| | | | o.O.+.$.$.%.$.s.s s i t F ~ ~ F H ! H e : 5 ; - - - * * * * * & * * * * & & * * & * * * * * * * * * * * * * * * - * * - - - - = = * = = = = = : : : : = = & > R j % t R E K.A e p n 9.9.9.8.9.9.g.^ ~ z > z R ~ H C E ~ z : ; = - - - - - - - - = - - = - * * * * - - - - - - & - * * * * - & - - & * * * * * * * * * * * * * * & = : u l c i e J z # > F ~ K.H = e p *.#.+.O.O.| o.| | } | | | | | | .} UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | | | | @.@.O.$.%.X.C s i t k Y K.! K.I.H e - & * % # $ % % # # # # # # $ # # # # # # # # # # # # # # # # # # # # # # # % # # % # % # % % % % % % & & & & & - * - e R x $ - l J G ! l i a f.8.9.9.8.c.D.K.H e u H ~ K.~ L.L.p > & & & % % % % @ @ & & @ % @ @ & # # # # # # $ # $ # # # # # % @ # $ $ # # # # $ $ # # $ # # # # # # # . # % * : s c J ! x @ & a H G ~ j = s N $.O.O.o.| | | | | | @.| | | | .UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } | | | | O.+.$.*.M G s i k J E L.I.U.Y 5 % @ . . . . . . . . . . . . $ $ . $ $ # # # # % % % % & % & & & * * * * * - = = = ; : 5 u k c p & . # r F a p Y G s D w.8.8.8.f.L.T s p F Y L.U.W.L.l > % % - ; ; = - & * * & & & & % & @ # # # # $ $ $ @ @ @ @ @ @ @ @ @ . . . . $ * i H J i @ @ > c a u J : > s s.O.O.o.| | } } | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | | | | | @.+.X.J G l l F Y L.W.U.E a = % # # @ . . . . . . . . . $ $ $ # # # # % & & & * * * = = = ; : 5 5 r t t t i p p p a k k l l c c c F J H c = $ $ & t J l : u J k c s.c.9.9.E.~ F l F J K.W.^.I.J k x x Z J J F c k s i i i i e e e e : : ; = = - - - & & & % % # # @ @ $ $ @ @ @ @ . . . . . . # = > - # @ # r H c e A F = ; w O.o.| | | | | | | | | | | } UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } | | | | .@.M T Y F H T K.K.! ! J Z l p p t 5 = 3 = 3 = = = = = = = = 4 = ; ; ; 4 5 : 5 5 5 r r r t t u t u u p p p a a a k k k k c c G G G F H H H H H J J H C u y y p J ! C e ; C ! J L y.8.].L.E J J Y L.W.W.W.W.I.L.L.L.~ T Y H Z G c l l k k k a a a p p p i t u t t t r r r r 5 5 5 5 : : ; ; ; = ; = = = = = = = = = * = * = * = = = = ; ; = ; ; t k ~ H t i W A = : X...} } | } | | | | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | .| } | | | ..s.Y R Y J T ~ T J H F Z G l a p t t r e r e r r r t t t t t t t t t t i t i i i p i p p p s p a a a a k k k l l l c G G G Z Z F F H H H J J Y T T ~ ~ T R W K.I.Y a e e p R ~ Y S.g.I.~ Y J T K.L.L.L.U.W.W.U.K.T J J H H H Z G Z G c c c l l k k k p k k a a p p p a p i i i t t t t i i t t t t t t t r r r r r 5 5 r 5 r 6 5 5 5 r r r r t i k Y ~ J F R F r - % _ } ..} } o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } | | } ..8 j V A L L S V / 7 q w w < < , , @ @ X @ @ @ X @ @ @ , , , , , < < , < < < < < w w w 3 3 3 8 3 8 7 7 9 9 9 y d j j j j x x x A A A A A S S S L L L I ^ ^ P.`.Y.L S x j j x A A U D.L S S L ^ G.^ I ^ ^ ^ I L L S A A A A A x x x x j j j j / / / / 7 7 q q q 3 8 w w w w w w < < < @ w @ < @ @ @ @ , @ @ @ @ @ @ @ @ @ @ X X X X @ @ @ @ , , < q j S I D d q w < % N } } } | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | .} } | | } | O.O.+.$.%.%.%.&.&.&.&.&.&.&.&.-.-.=.=.-.;.;.;.>.>.>.;.>.,.,.>.,.,.,.,.,.<.<.<.,.5.,.5.5.5.5.5.5.5.5.5.5.7.7.7.7.7.8.8.7.8.7.7.8.7.8.7.7.7.7.8.8.7.8.7.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.7.8.7.8.8.8.8.8.7.7.8.8.8.8.8.8.7.8.8.8.7.8.7.8.7.8.7.8.7.7.7.7.7.7.5.7.5.5.5.5.5.<.<.<.<.<.<.<.<.<.<.,.,.5.>.>.>.>.,.>.>.;.;.;.-.;.=.=.=.=.&.-.&.&.&.&.&.$.%.%.%.$.+.O.o.| { } | } } o.| | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | } | | | } } | | | | O.+.$.$.$.$.%.$.$.&.&.=.&.-.-.=.-.=.;.;.;.;.;.;.>.>.;.>.>.>.>.,.,.,.,.<.,.,.<.,.,.,.5.,.5.5.5.<.7.<.7.5.7.5.7.5.7.7.7.7.7.7.7.7.7.8.7.8.8.8.8.8.8.8.8.8.8.8.8.7.8.8.8.8.8.8.8.8.8.7.8.8.8.8.7.8.8.7.8.8.7.7.8.7.8.8.7.7.7.8.7.8.7.7.7.7.7.7.7.7.7.7.7.5.7.<.5.<.<.5.<.<.<.<.,.<.,.,.,.,.,.1.,.>.>.>.>.>.;.;.>.;.;.;.=.=.;.=.=.-.&.&.&.&.&.&.$.%.%.+.+.+.o.| | | { } } | o.{ | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } } { | | | O.+.$.$.%.%.&.&.&.&.&.=.-.-.-.=.=.=.=.;.;.;.;.;.;.1.>.>.>.>.,.,.,.,.,.,.<.,.5.,.5.,.5.,.5.,.<.<.7.7.7.7.<.7.7.7.7.7.7.7.8.7.7.7.7.7.7.7.7.7.8.7.8.7.8.7.7.8.8.8.8.7.8.8.8.8.8.8.8.8.8.8.8.7.8.8.8.8.8.8.8.8.7.8.7.8.7.7.7.7.7.7.7.7.7.7.7.7.5.7.<.7.5.<.5.<.<.<.<.<.,.,.<.<.,.,.,.,.,.,.>.>.>.>.;.>.>.>.;.-.;.;.;.=.=.=.=.=.-.-.&.&.&.$.&.$.%.$.$.+.O.| | | | } } { | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } { | | | | @.O.$.$.$.%.$.&.&.$.&.&.&.=.=.=.=.=.;.;.;.;.;.;.>.;.>.;.>.>.>.>.>.,.,.,.,.,.,.,.,.,.,.5.,.5.7.<.7.<.<.7.7.7.7.7.7.7.7.7.7.7.8.7.7.8.8.7.8.8.8.7.7.8.8.8.8.8.8.8.8.7.8.7.8.8.7.8.8.8.7.8.8.8.8.7.8.7.7.7.8.7.8.7.7.7.7.7.8.7.7.7.7.7.7.7.7.<.7.<.5.<.7.<.<.<.<.<.<.,.<.,.,.,.,.,.,.,.,.,.,.>.>.>.>.>.;.;.;.;.-.;.=.=.=.=.=.=.&.&.&.&.&.$.$.%.%.$.+.O.o.| | | } } } | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { | | | | | } } } } | | | O.+.+.$.%.$.$.&.&.&.&.%.=.&.=.=.;.=.=.-.;.;.;.>.;.>.;.>.>.,.>.>.,.,.,.,.,.,.,.,.5.,.,.,.5.<.<.<.<.7.<.7.<.7.5.5.7.7.7.7.7.7.7.7.7.7.7.7.7.7.8.7.7.7.8.7.7.7.7.7.8.7.8.7.8.8.7.7.8.7.8.7.7.8.7.7.8.7.7.7.8.8.7.7.8.7.7.7.7.7.<.7.7.7.<.7.7.5.5.7.<.<.7.<.<.<.,.<.<.,.<.<.,.,.,.,.,.>.>.>.>.>.;.>.;.;.;.;.-.;.=.=.=.=.=.=.&.&.&.&.%.&.&.%.$.$.+.+.O.| | | | { } | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | } | | | | } } } | | | | O.$.$.$.$.&.%.&.&.&.&.&.&.-.-.-.-.-.-.;.;.;.;.;.>.;.>.>.>.>.>.>.>.,.,.,.,.<.<.,.<.<.,.<.<.5.<.<.<.<.7.<.<.7.7.7.5.7.7.5.5.7.7.7.7.7.7.7.7.7.7.7.8.8.7.7.7.8.7.8.7.8.8.7.7.8.7.8.7.8.7.8.7.7.7.7.8.7.7.7.7.7.7.7.7.7.5.7.7.7.7.5.7.<.7.<.5.5.5.<.<.<.<.<.<.<.,.,.,.,.,.,.,.,.,.,.>.>.>.>.;.>.;.;.;.;.-.;.-.-.-.-.-.-.-.&.&.&.&.%.%.%.%.$.$.+.O.| | | | ] { } | | | | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } } { { { | o.O.O.$.$.$.%.%.%.&.&.&.-.&.-.-.&.-.-.-.;.-.;.;.;.>.;.>.>.>.>.>.>.,.,.,.,.,.,.,.,.,.<.<.<.<.<.<.<.5.<.7.7.<.<.7.7.5.5.7.7.7.7.5.7.7.7.7.7.7.7.7.7.7.8.7.7.7.7.7.7.7.7.7.7.7.7.7.7.8.7.7.7.8.7.8.7.7.7.7.7.7.5.7.7.7.7.5.5.5.7.5.5.5.<.7.<.<.5.<.<.<.<.,.<.,.,.<.,.,.,.,.,.,.,.>.>.>.;.>.>.;.;.>.;.;.;.-.;.-.-.-.&.-.&.&.&.&.&.%.%.%.$.$.+.O.o.{ { | } } } | o.| | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } ] { | { | o.O.$.$.$.%.%.%.&.&.&.&.-.-.-.=.=.-.=.-.-.;.;.;.;.;.>.>.>.>.>.>.>.,.,.,.,.,.<.,.,.,.<.<.<.<.,.<.<.<.<.<.7.<.5.<.5.5.7.7.5.7.7.7.7.7.5.7.7.7.7.7.5.7.7.7.7.7.7.7.7.8.7.7.8.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.5.7.5.5.7.5.7.<.5.<.5.<.<.<.<.<.<.<.<.,.<.,.,.,.<.,.,.,.,.,.>.>.>.>.>.>.>.;.;.;.;.;.-.-.-.-.-.-.-.-.&.&.&.&.&.&.%.%.%.$.+.+.o.| | | | } ] } | | | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } ] { } } | | O.O.$.$.$.%.%.%.%.&.&.&.&.&.=.=.=.;.-.;.;.-.;.>.;.;.;.>.;.>.>.,.>.,.,.,.,.,.,.,.,.<.<.<.<.<.<.<.7.<.5.<.5.5.<.7.5.5.5.5.5.5.7.5.7.5.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.7.5.7.<.7.7.7.7.7.5.7.7.7.<.7.5.<.7.<.5.<.5.<.<.<.<.<.,.<.<.,.<.<.,.,.,.,.,.,.,.>.>.>.>.;.>.;.;.;.;.;.;.;.-.-.=.-.-.&.-.&.&.&.%.$.%.$.$.$.+.+.o.| { } ] ] ] | .| { | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | } ] { } { | | | O.+.$.%.$.%.%.&.&.&.&.&.-.&.-.=.=.;.-.-.;.;.;.;.;.>.;.>.>.>.>.>.>.,.,.,.,.,.,.,.,.,.<.<.,.<.<.<.<.<.<.<.<.<.7.<.7.<.7.5.5.7.7.7.7.7.5.5.7.7.7.7.5.7.7.7.7.5.7.7.7.7.7.7.7.7.7.<.7.7.5.7.<.7.7.7.<.<.7.<.7.7.<.7.<.<.5.<.5.<.<.<.<.<.<.<.,.<.,.,.<.,.,.,.,.>.,.>.>.>.>.>.>.;.>.;.;.>.;.;.-.;.;.-.-.-.-.-.&.&.&.&.&.&.%.$.$.$.$.+.O.| | { { } [ } | | | | | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | o.| ] ] } ] } | | O.+.+.%.$.%.%.%.&.&.&.&.&.-.-.=.=.-.-.-.;.-.;.;.;.;.;.>.>.>.>.>.>.>.>.,.,.,.,.,.<.,.,.<.<.<.,.<.<.<.<.<.<.<.5.<.5.<.7.<.<.5.<.7.<.5.7.5.5.7.5.7.7.5.<.7.7.7.7.7.5.7.<.7.7.<.7.7.5.7.7.7.7.<.7.7.5.5.7.<.<.5.<.7.<.<.<.<.<.<.<.<.<.<.<.,.<.,.,.,.,.,.,.,.,.>.>.>.>.>.>.;.;.;.;.;.;.;.;.-.-.-.-.-.&.-.&.&.&.&.%.%.%.&.$.$.$.+.O. .| } { } [ ] | | | | { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | } } ] } } } | } o.+.+.$.%.%.%.%.$.&.%.&.&.-.=.=.=.=.-.=.-.;.;.;.;.>.>.;.;.>.>.>.>.>.,.>.>.,.,.,.,.,.<.,.,.<.<.,.<.,.<.<.<.<.5.<.<.5.<.<.<.7.7.<.5.5.5.5.5.5.5.5.5.7.5.5.5.5.5.5.7.7.7.7.7.7.<.7.5.5.5.5.7.7.<.<.<.<.5.7.5.5.<.<.<.5.<.<.<.<.<.<.<.<.,.,.,.,.,.,.,.,.,.,.>.,.>.>.>.>.>.>.>.;.;.;.-.;.-.-.-.-.-.-.-.-.&.&.&.&.%.&.$.%.$.$.$.O.o.} } } } [ [ } | | | { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } ] } } } } | .+.+.+.%.%.%.&.%.&.&.&.&.&.=.=.=.=.=.;.-.-.;.;.-.;.;.>.;.>.>.>.>.,.>.,.,.,.,.,.,.,.,.<.,.,.<.<.<.<.<.<.<.<.<.<.<.<.5.5.<.<.5.5.<.5.<.5.5.<.5.5.5.5.5.5.5.5.5.<.5.5.5.<.7.7.<.<.5.<.7.<.<.7.<.<.7.<.<.<.<.<.<.<.<.<.<.<.<.<.,.<.<.,.<.,.,.,.,.,.,.,.>.>.>.>.>.>.;.;.;.;.;.;.;.;.-.-.-.-.-.&.-.&.&.&.&.&.%.%.%.%.$.$.$.O.| | | } } } [ } } | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | | | | [ [ [ ] } | | @.+.+.$.$.$.%.%.&.%.&.&.=.&.-.-.-.=.-.=.=.;.;.;.=.>.;.>.;.>.;.>.>.>.,.,.>.,.,.,.,.,.,.,.,.<.,.,.<.,.<.<.,.<.<.<.<.<.<.<.<.<.<.<.5.5.<.7.5.<.7.7.<.5.5.5.5.5.5.<.5.5.5.5.<.5.5.5.5.<.<.5.<.<.<.<.<.<.<.<.<.<.<.<.<.,.<.,.,.,.,.,.,.,.,.,.,.>.,.>.>.,.>.>.;.>.>.>.;.>.;.;.;.;.-.-.-.-.-.-.-.&.&.&.&.&.%.%.%.%.%.$.$.+.o.| | { } [ [ ] } .| { | | | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } ] [ } ] { } { o.+.$.$.$.%.%.$.&.%.&.&.&.&.-.=.-.=.-.=.=.;.;.;.;.;.;.;.>.>.>.>.>.>.>.>.>.,.,.,.>.,.,.,.,.,.<.,.<.,.<.<.,.<.,.<.<.<.<.<.<.<.<.<.<.<.<.5.<.<.<.<.<.<.<.<.5.<.5.<.<.<.<.5.5.<.5.<.<.<.<.<.<.<.<.<.<.,.<.,.<.,.,.<.<.,.,.<.,.,.,.,.,.>.,.,.,.>.,.>.>.>.>.>.;.;.;.;.;.;.=.;.=.-.-.-.-.-.-.&.&.&.&.&.&.%.%.%.%.$.+.+.o.| } { ] [ ] ] } | } | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | [ ] ] } [ { { | o.+.$.$.%.%.%.%.&.%.&.&.%.-.&.-.-.=.-.=.;.=.=.;.;.;.;.;.;.>.;.>.>.>.>.,.,.>.,.,.,.,.,.,.,.,.<.,.<.,.,.,.<.<.<.,.<.<.<.<.<.<.<.<.<.<.5.<.<.<.5.<.<.<.<.<.<.5.<.5.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.,.<.,.,.<.,.,.<.,.,.,.,.,.,.,.,.>.,.>.>.>.>.;.;.>.;.>.;.;.;.;.;.;.=.=.-.=.-.-.&.-.&.&.&.&.$.&.$.%.$.$.+.+.o.| } { ] { ] ] { | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | | | } } ] ] [ { { } | O.+.$.$.%.%.%.%.&.%.&.&.&.-.-.=.-.-.-.=.=.=.;.;.;.;.;.;.>.;.>.;.>.;.>.>.>.>.>.,.,.,.>.,.,.,.,.,.,.<.,.,.,.,.<.<.<.<.<.,.<.,.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.<.,.<.<.<.<.<.<.<.,.<.<.,.<.<.,.,.<.<.,.<.,.,.,.,.,.,.,.,.>.,.>.>.>.>.;.;.>.>.;.>.;.;.;.=.;.=.=.=.-.-.-.-.-.&.&.&.&.&.$.&.$.%.%.$.+.+.O.| | { ] } ] ] [ | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | .} ] ] [ [ ] } } | O.O.$.$.$.%.%.%.%.&.&.&.&.-.-.-.&.-.=.=.=.=.;.=.;.;.;.;.>.>.>.>.;.>.>.>.>.>.>.>.,.,.,.,.,.,.,.,.,.,.,.<.,.,.,.<.<.,.<.<.,.<.<.<.,.<.<.<.<.<.,.<.<.,.<.<.<.,.<.<.<.<.<.<.<.<.<.<.,.<.,.,.,.<.,.<.,.,.,.,.,.,.,.,.,.,.,.>.,.>.>.>.>.>.>.>.;.>.;.;.>.;.=.;.;.=.=.-.=.-.=.&.-.&.&.&.&.&.$.&.$.%.%.$.$.+.O.| } } { } ] ` ] } .| | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | | { | | } ] ] ] } ] } } | o.+.+.$.%.$.&.&.%.%.&.&.&.&.&.-.=.=.=.;.=.=.;.;.;.;.;.;.;.;.>.;.>.>.>.>.>.>.>.>.,.,.,.,.,.,.,.,.,.,.,.<.<.,.,.<.,.,.,.,.<.,.,.<.<.<.<.<.,.,.<.,.<.<.<.,.<.,.<.,.<.<.<.,.<.,.,.,.<.,.<.,.,.,.,.,.,.,.,.,.,.,.,.>.>.,.>.>.>.>.>.;.>.;.>.;.;.;.;.;.=.;.=.;.=.-.=.-.=.=.=.-.&.&.&.%.%.&.$.$.$.$.$.+.o.| } ] } ] ] } ` } o.{ | | { | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | ] ] ] } ] } } } o.+.$.$.%.%.$.&.$.&.&.&.&.&.-.-.=.=.=.-.=.=.;.;.;.;.;.;.;.;.>.;.;.>.;.>.>.>.>.>.,.,.,.,.>.,.,.,.,.,.,.,.<.,.,.,.,.<.,.,.,.<.,.,.<.,.<.,.<.<.,.<.,.,.<.,.,.,.,.,.,.<.,.<.,.<.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.>.>.>.>.>.>.>.;.>.>.>.>.;.;.>.;.;.;.;.=.;.=.=.-.-.&.-.-.&.&.&.&.&.&.%.$.&.$.$.$.+.o.| } | } } } ` ` } | | | | | { | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | { | } | | | ] ] ] ] ] { { { | o.+.$.$.$.$.$.&.$.&.&.&.&.&.-.=.=.=.-.=.;.=.=.;.;.;.;.;.;.>.;.>.;.>.>.>.>.>.>.>.>.>.>.,.>.>.,.,.,.,.,.,.,.,.,.,.,.,.<.,.,.,.,.,.<.,.<.,.,.<.,.<.,.<.,.<.,.<.<.,.,.,.,.,.,.,.,.,.,.,.,.>.,.,.,.>.,.>.,.,.>.>.>.>.>.>.;.>.>.;.;.;.;.;.;.;.;.=.=.=.=.=.=.-.-.-.=.&.&.&.&.&.%.%.%.$.$.$.$.+.o.| } ] ] ` } ` } } | | | { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | | } } } ` ] ] ] { } | | O.$.$.$.$.%.%.%.%.&.&.&.&.-.&.-.-.-.=.-.-.=.;.;.=.;.;.;.;.>.;.>.>.>.>.>.>.>.>.>.>.>.>.>.>.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.>.,.,.>.,.,.>.>.>.>.>.>.>.>.;.>.>.;.>.;.;.;.;.;.=.;.;.;.=.;.=.=.=.=.-.&.&.&.&.&.&.$.$.%.%.$.$.O.+.o.} } } ] ] } ` ] } | | | | { | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } } ` ` ] ] ] { ] | | O.$.$.$.%.%.%.%.%.&.&.&.%.-.&.-.=.-.=.-.=.=.=.;.=.;.;.;.;.;.;.;.;.>.;.>.;.>.>.>.>.>.>.>.>.>.>.>.,.>.,.,.,.,.,.>.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.>.,.>.>.>.>.>.>.>.>.;.>.>.>.;.>.;.;.;.;.;.;.=.;.=.=.=.=.=.=.=.=.&.&.=.&.&.&.$.&.$.&.$.$.$.$.O.o.} } ] ` ] ] ] ` } } | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| { { | | | | | | } ` ] [ [ ] ] } { | o.$.$.$.%.%.%.%.&.&.&.&.&.-.&.=.=.-.-.=.;.=.=.;.=.;.;.;.;.;.;.>.;.>.;.>.;.>.>.>.>.>.>.>.>.,.>.>.,.>.>.,.,.>.,.,.,.,.,.,.,.,.>.,.,.,.,.,.,.,.,.,.,.,.,.,.,.>.,.>.,.,.,.,.>.,.>.>.>.>.>.>.>.>.;.>.>.;.>.;.>.;.;.;.;.;.;.;.=.=.=.=.;.=.=.=.=.=.&.=.&.&.&.&.$.$.&.$.&.$.$.$.o.| ] { ] ` } ] ] ` ` | | | | { | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | { | | | } } ` ` [ ] ] { ] } | o.$.$.$.%.$.%.%.%.&.%.&.&.&.&.&.-.&.=.=.=.;.=.;.=.=.;.;.;.;.;.;.;.;.;.>.;.>.>.>.>.>.>.>.>.>.,.>.>.>.>.>.,.,.>.,.>.,.>.,.,.,.>.,.,.,.,.,.,.>.,.,.,.,.,.>.,.,.,.>.>.>.>.,.>.>.>.>.>.>.;.>.>.>.>.;.>.;.;.;.;.;.;.;.;.;.;.;.=.-.=.=.=.=.=.&.&.=.&.&.$.&.&.&.$.$.$.$.$.$.o.| | ] ] ] } } ] ] ] | | } | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } ` ` ` ] [ ] ] } } } | +.$.$.$.%.%.%.%.&.&.&.&.&.-.-.-.=.=.=.=.=.=.=.;.=.;.;.=.;.;.;.;.;.;.;.>.>.>.;.>.>.;.>.>.>.>.>.>.>.>.>.>.>.>.,.>.,.,.>.,.>.>.,.>.>.,.,.>.>.,.>.,.>.>.>.>.>.>.>.>.>.>.>.>.>.;.>.>.>.;.>.>.>.;.>.;.;.;.;.=.;.;.=.=.-.-.-.=.-.-.-.-.-.-.&.&.&.&.&.$.&.$.$.&.$.$.O.o.| { ] ] ` } ` ` ` ` | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | } | | | .} } ` ] ` ] [ ] } { } | o.$.$.%.%.%.%.&.&.%.$.&.&.%.-.=.&.=.=.=.=.=.=.=.=.=.;.;.;.;.;.;.>.;.;.;.;.>.;.>.>.>.;.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.,.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.;.>.>.>.;.>.>.>.>.;.;.>.;.;.;.>.=.;.;.;.;.;.;.=.=.=.-.-.-.-.&.-.&.-.&.&.%.&.&.$.$.&.%.$.$.$.$.o.| } ] } ] ] } } ` ` } | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | } } ` ` [ ] ] ] ] } } | o.$.$.$.%.%.&.%.&.&.&.&.&.&.&.=.&.&.=.=.=.=.;.=.=.;.=.=.;.;.;.;.;.;.;.>.;.;.;.;.;.>.>.>.>.;.>.;.;.>.>.>.>.>.;.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.>.;.>.>.>.>.;.>.>.;.>.;.;.;.>.;.;.>.=.;.;.;.=.;.;.=.=.=.;.=.-.-.-.-.-.&.-.%.&.&.$.&.&.&.$.&.$.$.$.O.o.| ] } ] ] ] ] _ ` ` } | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | } ` ` ` ` ] ] ] ] } } | O.$.$.$.$.$.&.$.%.&.&.&.&.&.=.=.=.=.=.=.=.=.=.=.=.;.=.;.=.;.=.;.;.;.;.;.>.;.>.;.;.>.;.;.>.;.>.>.;.>.;.>.>.>.>.>.>.>.;.;.>.>.>.;.>.;.>.>.;.>.>.>.>.;.>.;.>.;.;.>.;.;.>.;.;.=.;.;.=.;.;.=.=.=.=.=.;.=.=.=.-.&.-.&.-.&.&.$.&.&.&.&.$.$.$.$.$.$.O.o.{ ] } ] ] ] ] ` } _ } | | | { | | | | } UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX} | | | | { | | | } ] ` ] ] ] ] ] } ] } | o.$.$.$.$.$.&.%.%.&.&.&.=.%.&.-.&.-.&.-.-.-.=.=.=.=.=.=.;.;.;.;.=.;.;.;.;.>.;.;.>.;.>.;.;.>.;.>.>.;.>.>.>.;.>.>.;.>.>.>.>.>.;.;.>.;.>.;.>.;.>.;.>.;.>.;.;.;.>.;.;.;.;.=.=.;.;.;.;.=.;.;.=.=.=.=.&.=.=.=.&.&.=.&.&.%.&.%.%.%.%.%.%.%.$.$.o.| ] } ` ] ` ] ` ` ` ` } | | | | | | | | | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX| | | | | | | | | } ] _ ` ` ] ] ` ] ] } ] | O.$.$.$.$.%.%.%.%.&.%.&.&.%.-.&.-.-.&.=.-.=.=.;.-.;.=.=.;.=.;.;.;.=.;.;.;.;.=.;.>.>.;.;.>.;.;.;.;.>.;.>.;.;.>.;.>.;.;.;.>.>.;.>.;.;.;.>.;.;.;.;.;.>.=.;.;.;.;.;.;.;.;.;.=.=.=.=.=.=.=.=.=.=.=.&.=.&.&.&.&.&.&.%.&.%.%.%.%.%.$.$.o.| { { ] } ` ` } ] ` _ } | | | | | { { | { | UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | | | | | ] ` ` ` } ` ` ` ] } ] } o.$.$.$.%.$.%.%.$.&.&.&.&.&.&.=.&.-.-.=.=.-.=.=.=.=.=.=.=.;.=.;.=.;.;.=.;.;.;.;.=.;.;.;.;.;.>.;.;.;.;.;.;.;.;.;.>.;.;.;.;.>.;.;.;.;.;.;.=.;.;.;.;.;.;.;.;.=.;.;.;.=.=.=.-.-.-.-.=.=.=.=.&.=.&.=.=.&.%.%.%.&.%.&.%.%.%.%.$.+.o.} { } ] ] } ` ` } ` ` ] } | | | | | | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ { | | { | | | | } ] ` ` _ } ` } ] ] ] } } | o.$.$.%.%.$.&.$.&.&.%.&.$.&.&.&.&.-.&.=.=.=.=.=.=.=.=.=.=.=.;.=.=.;.=.;.=.;.;.;.=.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.;.=.;.=.=.=.=.=.;.=.=.-.=.-.=.=.=.=.=.=.=.&.&.&.&.&.&.%.%.&.$.%.%.+.%.@.| ] { ] ] ] ` _ } ` _ ` ] | | | | | | | | | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | | | .| } ` _ _ } } ` } } ` } ] ] | +.$.$.$.$.&.%.&.%.&.&.&.%.&.&.-.&.=.=.=.-.-.-.=.=.=.=.=.-.=.=.;.=.=.-.;.;.;.;.;.;.=.;.=.;.;.=.>.;.;.;.;.;.;.;.;.=.;.;.=.;.=.;.;.;.;.;.=.=.=.=.=.=.=.-.-.=.=.&.=.=.=.-.=.&.=.=.=.%.&.&.&.$.&.$.&.&.&.$.$.$.$.O.| ] } } } ] ] } ` ` ` } _ } | | | | | | | { | { UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX] | | | | } | { | | | } } _ _ ` ` ` } ] ] { ] { | O.$.$.$.$.$.%.%.&.&.&.&.&.%.&.&.&.&.&.&.=.=.=.=.=.=.=.=.-.-.;.-.;.-.=.=.=.=.=.;.;.;.=.;.;.=.-.;.;.;.;.-.;.=.=.;.;.;.;.;.=.;.=.=.;.=.=.=.;.=.-.=.=.-.=.=.=.=.=.&.&.=.&.&.&.&.&.&.&.%.&.&.%.&.$.$.$.$.O.| { [ [ ] ` ` ` ` ` ` ` ` } } | | | | | | | | | [ UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX_ | { | | | | | | | | } ` ` ` } ` ` ] ] ] ] ] { { o.O.$.$.%.%.%.%.%.&.&.%.&.&.&.&.&.=.&.&.=.=.&.=.=.-.-.-.-.=.=.-.-.=.=.=.=.;.=.=.=.=.;.;.;.=.=.=.=.-.=.;.;.;.=.;.=.=.=.;.=.=.=.=.=.=.=.=.-.-.-.-.-.=.=.&.=.&.=.&.&.&.&.&.&.%.&.%.&.$.&.$.$.$.$.+.o.{ [ [ { ] ] ` } ] ` ` ` ` } | | | | | | | | | } _ UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX{ | | | | | | | | | } ` _ ` ` ` ` ` ] ] ] ] ] ] | o.+.$.%.%.%.$.%.%.%.&.&.%.&.&.&.&.&.=.&.=.&.=.-.&.=.=.=.=.-.-.=.=.;.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.=.-.-.=.=.=.=.-.&.=.=.=.&.&.&.&.&.&.%.&.%.%.%.%.%.$.$.$.$.O.o.} { [ [ ` ` ] ` ] ` ` ` ` ` } | | | | | | | | | } UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX] | | | | | { | | | | { ` ` ` ` ` ` ` ` ] ] ] } ] } | O.$.$.&.%.%.%.%.%.&.&.&.&.&.&.&.&.=.&.=.&.-.-.&.-.-.-.-.=.=.=.=.=.=.=.=.-.-.-.-.=.=.=.=.=.=.=.=.-.-.-.-.=.=.=.=.&.=.=.=.=.&.-.&.-.&.-.-.&.=.&.&.&.&.&.%.%.&.%.&.%.%.$.$.%.$.O.o.{ } [ [ ` ` ` ` ` ` ` ` ` ` { | | | | { | | | { | ` UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX_ | | | | | | { | | | } } ` ` ` ] ` ] ` ] ] ] ] ] } } | o.$.%.%.%.%.%.%.%.%.&.&.&.&.&.&.&.&.&.&.&.-.&.-.&.&.=.=.=.=.&.-.=.=.-.-.&.-.-.-.-.-.-.-.-.-.=.&.=.-.=.=.=.=.&.=.=.&.-.-.&.-.-.&.&.&.&.&.%.&.%.&.%.%.%.&.$.$.%.%.$.$.o.o.} ] ] ` ] ` } ` } ` ` ` ` _ ] } | | | | | | | | | | ' UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX( { | | | | | | | | | | } ` _ ` ` ` ` ` ` ` } ] } ] ] } | o.+.%.%.%.%.%.%.&.&.$.%.&.%.%.&.&.&.&.&.&.&.&.&.=.&.&.=.=.-.&.=.=.-.-.-.=.=.=.=.&.-.-.-.=.=.-.&.=.=.=.=.&.-.&.&.&.&.&.&.%.&.&.%.%.&.%.&.%.&.%.%.$.&.$.$.$.$.o.o.} ] ] } ] ] ` ] _ ` ` ` ` _ ` } | | o.{ | | | | | | [ ( UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX_ { | | | | | | | | | } } ` _ ` ` ` ` ` ` ` ` ] ] ] ] [ { | O.$.$.%.%.$.$.$.&.%.%.&.%.$.&.&.&.&.&.&.&.%.&.&.&.&.&.=.&.&.-.&.&.=.&.&.=.-.&.&.-.&.&.&.&.&.=.%.&.&.&.&.&.&.&.&.&.&.%.&.&.&.&.%.%.%.&.%.%.$.$.$.O.o.{ ] ] ] ] ] ` ] ` ` ` } ` _ _ ` [ | | | | { | | | | | | _ UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX) { | | | | | | | | | | } } _ ` ` ` ` ` ` ` ] ` ] ] ] ] ] ] | o.+.$.$.$.$.$.&.%.%.%.&.$.&.&.%.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.%.&.&.&.%.%.%.%.$.%.%.%.$.$.$.%.O.o.| ] ] ] ] ] } ` } ` ` ` ` ` ` _ ` } } | | | | | | } | | | { ) UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo _ | | | | | | | | | | | } } _ ` ` ` ` ` _ ] ` ] ` ] ] ] ] ] ] | o.O.$.$.%.$.%.$.&.%.%.%.$.&.%.&.&.%.%.&.%.&.&.&.&.&.&.&.&.&.%.&.&.&.&.&.&.&.&.&.&.&.%.&.&.&.&.&.%.%.%.%.%.%.%.%.$.%.%.%.$.O.o.| { ] ] ] ] ] ` ] ` ` _ ` ` ` ` ` ` ` } | .| | | | | | | | | _ o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX( } | | | | | | | | | | | } ` _ _ ` ` ` ` ` ` ` ] ` ] ` ] ] ] } { } o.O.+.$.%.$.$.$.%.&.&.%.%.%.%.%.&.%.%.&.&.&.$.&.&.&.&.&.&.&.&.&.&.&.&.%.&.&.&.%.&.&.$.$.&.%.%.%.%.%.%.%.%.%.O.O.o.{ { ] ] ] ] ` ] ` ` ` ` ` ` ` ` _ ' _ ` } | | | { | | | | | | | [ ( UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ' } | | | } | | | | | | | { ` _ _ _ ` ` ` ` ` ` ` ] ` ` ] ] ] ] ] } } | o.+.$.$.%.$.$.%.%.%.%.%.%.%.&.%.%.$.&.&.$.$.%.%.%.%.$.&.%.$.&.%.%.%.%.%.%.$.&.$.$.%.%.%.%.%.$.O.o.| [ [ [ ] ] ] ] ` ] ` ` ` ` ` _ ` ` _ ` _ } } | | | | | | | | | | | | ' o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX( ` | | | | | | | { | o.| | | ` _ _ _ ` ` ` ` ` ` ` ` ` ] ] ] ] ] } ` } [ { { .o.O.$.%.%.%.%.$.%.$.%.%.%.%.$.&.$.&.&.$.$.&.%.%.%.%.%.%.$.&.$.$.$.&.$.$.$.+.o.o.{ { ] ] { ] ] ] ] ] ` ] ` ` ` ` ` ` ` ` _ ` _ ` | | | | | | | | | | | | | ] ( UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO ( [ | | | | | | | | | | | | | } _ _ _ ` ` _ _ ` ` ` ` ` ` ` ` ` ] ` ] ` [ ] [ [ { { | o.O.+.$.%.$.%.%.$.$.$.$.$.$.$.%.$.%.%.%.%.%.$.$.$.$.+.O.o.o.{ { ] ] ] { ] ] ` ] ` ` ] ` ` ` ` ` ` ` ` ` _ ` _ ` ` } | | | | | | | | | { | | { ) O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ' | | { | | | | | | | | .| | } ` _ _ ` ` ` ` _ _ ` ` ] ` ` ` } ] ` [ ] ] ] ] ] ] ] ] ] { { | | o.o.o.O.+.$.O.$.+.O.O.O.o.o.o.| | { { ] ] ] ] ` ] ] ] ] ] ` ] ` ` ` ` ` ` ` ` _ ` _ _ ` _ _ ` } | o.| | | | | | | | | | | | ' o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ' | { | | | | | | | | | | | } } } _ ` _ _ ` _ ` _ ` ` ` ` ` ] _ _ ] ] ` ` ] ] ] ] ] ] ` ] ] ] ] ] ] ` } ] ] ] ] ] ] ` ] ] ] ` ] ] ] ] ] ] ] ` ` ] ] ` ` ` ` ` ` ` ` ` ` ` _ _ ` _ _ ] } | | | | | | | | | | | | | | ' o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX+ o ' { | | | | | | | | | | | | o.| ] ` _ _ ` _ ` _ ` _ ` ` _ _ ` ` ` ` ] ` ` ` ` ` ` ` ` ` ] ` ] ` ` ` ] ] ` ] ] ` ] ` ] ` ` ] ` ` ] ` ` ] ` ` ` ` ` ` ` ` ` ` ` _ _ _ _ _ _ ` { | .| | | | | | | } | | | { { _ o + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO o _ | | | { | | | | | | | | | | .| } ` _ _ _ _ ` _ ` ` ` ` _ _ ` ` ` ` ` ` ` ` ` ` ] ` ` ] ` ` ` ` ` ` ` ` ] ] ` ` ` ` ] ` ` ` ` ` ` ` ` _ ` ` _ ` _ _ _ _ _ _ ` ` { { @.| | | | | | | | | | | | | | _ o + UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ' | | | | | | | | | | | | | | | .| | } ` ' _ _ ` _ _ ` ` ` _ _ _ ` ` ` ` _ ` ` ` _ _ ` ` ` ` ` ` ` ` ` _ ` ` ` _ ` _ ` _ ` ` _ _ ` _ ` _ _ _ _ _ _ _ } } | | | | | | | | | | | | | | | | } ' o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ) ] | | | | | | | | | | | | | } .| | } [ ] _ _ _ _ _ _ _ _ _ _ ` _ ` _ _ _ _ ` ` ` _ ` ` _ ` ` _ ` _ ` _ _ _ _ ` ` _ _ _ ` _ _ _ _ _ _ _ ] } } .| | o.| | | | | | { | | | | | | } ) o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO ( ` | | | | | | | | | | | | | | | | | o.| | } ] _ _ _ _ _ _ _ _ _ _ _ ` _ _ _ _ _ ` _ ` _ ` ` _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ } } | | | | | | | | | | | | { | | | { | | | ] ( O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ' { | | | | | { | } | { | | | | | | | | .| .| } ] ] ` ` _ _ ' _ _ _ _ _ _ _ _ _ ' _ ' ' _ _ _ _ _ _ _ _ _ ` ] ] } | | | | | o.| | | | | | | | | | | | | | | { ) o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO ( ' { | | | | | | | | | | | | | | | | | | | | { o.| | | { [ ] } ` ] ` _ _ _ _ _ ` ` ` ` ] ] ] } } | | o.o.| | .| | | | | | | | | | | | | | | | | | | _ ( O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO ( _ | | | | | | | | | | | | | | | | | | | | | | | | o.{ | | | | | o.| | { | | | | o.| | | o.| | | | | | | | | | | | | { | | | | | | | | { _ ( O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXO o ' ] | | | | | | | | | { | | | { | | | { | | | { | | | { | | | | | | | | | | | | { o.| | | | | | | | | | | | | | | | | o.} ` ' o O UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ( ' [ | | | | | | { | | | { | | | | | | | { | | | | | | | | | | | | { | | { { | | | | | | | | | | | | | | | { ' ( o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo o ) ` [ { o.{ { | | | | | | | | | | | | | | | | | | { | | | | | { | | | | | { | | | | | | | _ ) ( o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo ( ) _ ] { | | { | | | { | { | | | { | | | | | | | | | | | | | | | | ] ] ' ) o o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXo o ) ) ' _ _ [ [ { | { | | | | } { { ` ` _ ' ) ) o o UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX", + "UXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUX" +}; +#if defined ALLEGRO_WITH_XWINDOWS && defined ALLEGRO_USE_CONSTRUCTOR +extern void *allegro_icon; +CONSTRUCTOR_FUNCTION(static void _set_allegro_icon(void)); +static void _set_allegro_icon(void) +{ + allegro_icon = allegico_xpm; +} +#endif diff --git a/zq_icon.icns b/zq_icon.icns new file mode 100644 index 0000000000..cfa3f6a973 Binary files /dev/null and b/zq_icon.icns differ diff --git a/zq_icon.ico b/zq_icon.ico new file mode 100644 index 0000000000..d222d52831 Binary files /dev/null and b/zq_icon.ico differ diff --git a/zq_icon.rc b/zq_icon.rc new file mode 100644 index 0000000000..245f10ed67 --- /dev/null +++ b/zq_icon.rc @@ -0,0 +1 @@ +allegro_icon ICON MOVEABLE PURE LOADONCALL DISCARDABLE "./zq_icon.ico" diff --git a/zq_icon.xpm b/zq_icon.xpm new file mode 100644 index 0000000000..e0a0830e4d --- /dev/null +++ b/zq_icon.xpm @@ -0,0 +1,514 @@ +/* XPM */ +static const unsigned char * zq_icon_xpm[] = { +"32 32 479 2", +" c None", +"! c black", +"# c #2E45BD", +"$ c #3047BE", +"% c #4F62C8", +"& c #6A7BD1", +"' c #7A89D6", +"( c #7988D6", +") c #6879D0", +"* c #4B5FC7", +"+ c #2F46BD", +", c #2D44BC", +"- c #5467CA", +". c #97A3E0", +"0 c #C9CFF0", +"1 c #D1D7F4", +"2 c #D2D7F4", +"3 c #DDE1EE", +"4 c #DFE3EB", +"5 c #C5CCEF", +"6 c #8F9CDD", +"7 c #2F45BD", +"8 c #465BC5", +"9 c #A1ACE3", +": c #C9D0F2", +"; c #CAD1F3", +"< c #CAD1F4", +"= c #CAD1F5", +"> c #CBD2F5", +"? c #F0F1DB", +"@ c #F0F1D6", +"A c #CCD3F4", +"B c #CAD0F3", +"C c #C9CFF1", +"D c #96A2E0", +"E c #3E53C2", +"F c #BCC4ED", +"G c #C1C9F1", +"H c #C1C9F3", +"I c #C2CAF5", +"J c #C2CBF7", +"K c #C2CBF8", +"L c #D9DEE4", +"M c #F5F5D0", +"N c #EFEFC6", +"O c #D9DDDC", +"P c #C2CAF7", +"Q c #B7C0EC", +"R c #5B6ECC", +"S c #2C43BC", +"T c #6E7FD3", +"U c #B6BFED", +"V c #B7C1F0", +"W c #B8C2F3", +"X c #B9C2F6", +"Y c #B9C3F8", +"Z c #BAC4FA", +"[ c #BEC8F5", +"] c #F0F1CC", +"^ c #EDEDB8", +"_ c #E6E6B3", +"` c #EDEDC3", +"a c #C0C9F2", +"b c #BAC4F9", +"c c #B7C0F0", +"d c #B5BEEC", +"e c #6475CF", +"f c #2B42BC", +"g c #4E62C9", +"h c #ABB6EA", +"i c #ADB8EE", +"j c #AEB9F3", +"k c #AFBAF6", +"l c #AFBBF9", +"m c #B0BCFB", +"n c #B0BDFD", +"o c #D8DDD8", +"p c #EEEEBA", +"q c #EBEBA9", +"r c #EDEDAB", +"s c #E5E5B0", +"t c #D8DCCC", +"u c #B0BCFD", +"v c #AEB9F2", +"w c #AAB5E9", +"x c #2B43BD", +"y c #8A99E0", +"z c #A2AEEC", +"{ c #A3B0F1", +"| c #A4B1F5", +"} c #A5B2F9", +"~ c #A6B4FC", +" ! c #A7B5FE", +"!! c #B6C1F0", +"#! c #EFEFB9", +"$! c #E9E9A3", +"%! c #EEEEA2", +"&! c #EEEEA1", +"'! c #E4E4A3", +"(! c #E9E9AE", +")! c #B8C2E6", +"*! c #A6B3FC", +"+! c #A3B0F0", +",! c #A2AEEB", +"-! c #8A98DF", +".! c #4057C9", +"0! c #97A4E8", +"1! c #98A6EE", +"2! c #99A8F4", +"3! c #9AA9F9", +"4! c #9CABFD", +"5! c #9EADFE", +"6! c #A1AFFE", +"7! c #DDE0C4", +"8! c #E8E8A3", +"9! c #EBEB99", +":! c #EEEE9F", +";! c #EDED9F", +"! c #A1B0FD", +"?! c #9BABFC", +"@! c #9AA9F8", +"A! c #99A7F3", +"B! c #98A6ED", +"C! c #96A4E7", +"D! c #4056C7", +"E! c #2B43BE", +"F! c #5469D4", +"G! c #8C9CEA", +"H! c #8E9EF1", +"I! c #8FA0F7", +"J! c #91A2FC", +"K! c #94A4FE", +"L! c #97A7FF", +"M! c #B5C0DF", +"N! c #EBEBA6", +"O! c #E7E790", +"P! c #EDED9E", +"Q! c #EFEFA4", +"R! c #EDED9A", +"S! c #E3E399", +"T! c #E2E29A", +"U! c #B6BFD0", +"V! c #93A4FE", +"W! c #90A1FB", +"X! c #8F9FF6", +"Y! c #8E9DF0", +"Z! c #8C9BE9", +"[! c #5469D3", +"]! c #2C45C3", +"^! c #576DDA", +"_! c #8293EC", +"`! c #8395F3", +"a! c #8597FA", +"b! c #879AFE", +"c! c #8C9EFF", +"d! c #93A4FB", +"e! c #E1E4A8", +"f! c #E1E188", +"g! c #DBDB7D", +"h! c #DEDE85", +"i! c #E0E089", +"j! c #DFDF87", +"k! c #DDDD83", +"l! c #D5D57D", +"m! c #DADC99", +"n! c #94A5F6", +"o! c #8597F9", +"p! c #8395F2", +"q! c #8293EB", +"r! c #576CD8", +"s! c #2C44C1", +"t! c #2D47C8", +"u! c #4F66DC", +"v! c #788AED", +"w! c #7A8DF5", +"x! c #7B90FC", +"y! c #8093FF", +"z! c #8597FF", +"{! c #ABB8E4", +"|! c #CED4BE", +"}! c #C3C9AA", +"~! c #C4CAAA", +" # c #C7CDB4", +"!# c #C9D0BA", +"## c #C8CEB7", +"$# c #C5CCAF", +"%# c #C3C9A5", +"&# c #C6CCA5", +"'# c #C4CAA9", +"(# c #ABB7CF", +")# c #8497FF", +"*# c #7F93FE", +"+# c #7B8FFB", +",# c #798DF4", +"-# c #778AEC", +".# c #4E65DB", +"0# c #2D46C6", +"1# c #2E48CC", +"2# c #3F59DD", +"3# c #6D82EE", +"4# c #6F85F7", +"5# c #7288FD", +"6# c #778DFF", +"7# c #8799F3", +"8# c #DCDFAD", +"9# c #859AF9", +":# c #8296FF", +";# c #8297FF", +"<# c #8196FF", +"=# c #8398FC", +"># c #DADEB0", +"?# c #8A9BEA", +"@# c #778CFF", +"A# c #7187FD", +"B# c #6F84F6", +"C# c #6D82ED", +"D# c #3F58DB", +"E# c #2E48CA", +"F# c #2B42BD", +"G# c #2B44BF", +"H# c #2F49CF", +"I# c #334FDE", +"J# c #5D74EE", +"K# c #657DF8", +"L# c #6880FE", +"M# c #6F85FF", +"N# c #BCC5B4", +"O# c #EBEB93", +"P# c #ABB6B1", +"Q# c #798FFF", +"R# c #ABB7C9", +"S# c #ECEC95", +"T# c #BAC199", +"U# c #6E85FF", +"V# c #687FFE", +"W# c #657CF7", +"X# c #5D74ED", +"Y# c #334EDC", +"Z# c #2F49CD", +"[# c #2B44C0", +"]# c #2F4AD0", +"^# c #334FDF", +"_# c #435EED", +"`# c #5B74F8", +"a# c #5F78FE", +"b# c #8093E2", +"c# c #E2E27C", +"d# c #C8C84F", +"e# c #DADA74", +"f# c #7E93EA", +"g# c #7088FF", +"h# c #7A90F3", +"i# c #DEDF88", +"j# c #CDCD56", +"k# c #DADA6E", +"l# c #8394D0", +"m# c #5B74F7", +"n# c #425DEB", +"o# c #324EDD", +"p# c #2F49CE", +"q# c #2B43BF", +"r# c #3652EB", +"s# c #4965F7", +"t# c #5771FE", +"u# c #C7CD96", +"v# c #D6D65A", +"w# c #C5C53E", +"x# c #C6C655", +"y# c #B4BC94", +"z# c #6882FF", +"{# c #B4BEAE", +"|# c #DBDB6B", +"}# c #D9D95B", +"~# c #C1C14B", +" $ c #C3C87C", +"!$ c #5771FB", +"#$ c #4965F6", +"$$ c #3552EA", +"%$ c #3856F6", +"&$ c #7D90C6", +"'$ c #DCDC67", +"($ c #C9C93C", +")$ c #C6C636", +"*$ c #B7B735", +"+$ c #D7D760", +",$ c #7E92D0", +"-$ c #627CFF", +".$ c #7A90E4", +"0$ c #DDDE6D", +"1$ c #DDDD61", +"2$ c #C3C335", +"3$ c #BABA34", +"4$ c #D0D05D", +"5$ c #8090AD", +"6$ c #3856F4", +"7$ c #3552E9", +"8$ c #324EDB", +"9$ c #2E48CB", +":$ c #324DDA", +";$ c #3551E8", +"<$ c #3E5BEC", +"=$ c #CED175", +">$ c #CCCC39", +"?$ c #BCBC2B", +"@$ c #C0C02D", +"A$ c #C1C12D", +"B$ c #BABA3C", +"C$ c #C1C676", +"D$ c #5C78FD", +"E$ c #5B76FF", +"F$ c #5B77FE", +"G$ c #C3CA92", +"H$ c #D7D75A", +"I$ c #CCCC3C", +"J$ c #BDBD2C", +"K$ c #BBBB2B", +"L$ c #B1B12D", +"M$ c #C8CB5B", +"N$ c #425EE4", +"O$ c #3451E6", +"P$ c #314DD9", +"Q$ c #2D47C9", +"R$ c #2D46C5", +"S$ c #314CD6", +"T$ c #3450E4", +"U$ c #8C9BA2", +"V$ c #D5D54E", +"W$ c #BDBD23", +"X$ c #B7B720", +"Y$ c #B9B923", +"Z$ c #BBBB25", +"[$ c #B2B224", +"]$ c #CFCF52", +"^$ c #8798B0", +"_$ c #5672FF", +"`$ c #8598CA", +"a$ c #D8D85B", +"b$ c #D5D546", +"c$ c #BABA25", +"d$ c #B8B823", +"e$ c #B2B21F", +"f$ c #C4C444", +"g$ c #8D9A87", +"h$ c #3450E3", +"i$ c #314BD5", +"j$ c #475FCC", +"k$ c #D7D863", +"l$ c #C7C72A", +"m$ c #B8B820", +"n$ c #AFAF28", +"o$ c #CCCF60", +"p$ c #5A75F3", +"q$ c #5672F8", +"r$ c #CFD376", +"s$ c #D4D443", +"t$ c #BDBD24", +"u$ c #BABA20", +"v$ c #ABAB22", +"w$ c #D2D251", +"x$ c #4D64BF", +"y$ c #2A42BC", +"z$ c #A1AA72", +"{$ c #D1D14E", +"|$ c #A2A21D", +"}$ c #9D9D1B", +"~$ c #A4A41C", +" % c #ADAD1E", +"!% c #B7B721", +"#% c #BFBF27", +"$% c #B9B926", +"%% c #C7C742", +"&% c #9AA792", +"'% c #95A4AE", +"(% c #DADA57", +")% c #C7C738", +"*% c #BBBB24", +"+% c #B1B11F", +",% c #A7A71D", +"-% c #A0A01B", +".% c #9B9B1B", +"0% c #A6A621", +"1% c #BFBF39", +"2% c #A4AB63", +"3% c #2E45B8", +"4% c #6F7FA3", +"5% c #697B9F", +"6% c #5F719D", +"7% c #6375A3", +"8% c #677BAA", +"9% c #6E81AF", +":% c #7789B2", +";% c #7D8FB7", +"<% c #8092C0", +"=% c #8193C6", +">% c #7B8EBE", +"?% c #7D90D0", +"@% c #8496D2", +"A% c #7F91BD", +"B% c #7B8DB3", +"C% c #7386B0", +"D% c #6B7EAD", +"E% c #6578A8", +"F% c #6173A2", +"G% c #5D6F9C", +"H% c #607296", +"I% c #697997", +"J% c #3046B4", +"K% c #2A42BB", +"L% c #304BD3", +"M% c #3755F2", +"N% c #3957F9", +"O% c #3B5AFD", +"P% c #3F5DFE", +"Q% c #425FFF", +"R% c #4461FF", +"S% c #4562FF", +"T% c #4462FF", +"U% c #4361FF", +"V% c #3E5CFE", +"W% c #3B59FD", +"X% c #3857F8", +"Y% c #3754F1", +"Z% c #334EDE", +"[% c #304AD1", +"]% c #2A41B9", +"^% c #2A43BD", +"_% c #304BD4", +"`% c #3754EF", +"a% c #3856F5", +"b% c #3958FA", +"c% c #3A59FC", +"d% c #3C5AFE", +"e% c #3654EE", +"f% c #3551E7", +"g% c #304AD2", +"h% c #2A41BA", +"i% c #293FB6", +"j% c #2940B7", +"k% c #324EDC", +"l% c #3654EF", +"m% c #3755F3", +"n% c #2941B8", +"o% c #293FB5", +"p% c #1B297E", +"q% c #283FB3", +"r% c #2D45C5", +"s% c #314CD7", +"t% c #2C44C2", +"u% c #283EB2", +"v% c #2940B8", +"w% c #182572", +"x% c #101955", +"y% c #283DB0", +"z% c #283FB2", +"{% c #2F49D0", +"|% c #314DD8", +"}% c #2B43C0", +"~% c #273EB1", +" & c #263BAB", +"!& c #0C1346", +"#& c #040625", +"$& c #192779", +"%& c #273DAE", +"&& c #273DB0", +"'& c #2940B6", +"(& c #273DAF", +")& c #283FB4", +"*& c #17236E", +"+& c #02041F", +",& c #030523", +"-& c #121C5D", +".& c #1F308E", +"0& c #293FB4", +"1& c #263CAC", +"2& c #1D2D88", +"3& c #101956", +"4& c #02031E", +" ", +" ", +" # $ % & ' ( ) * + + ", +" , - . 0 1 2 3 4 2 1 5 6 * # ", +" 7 8 9 : ; < = > ? @ A = < B C D E ", +" , ) F G H I J K L M N O K P I H G Q R + ", +" S T U V W X Y Z [ ] ^ _ ` a b Y X W c d e 7 ", +" f g h i j k l m n o p q r s t u m l k v i w * ", +" x y z { | } ~ !!!#!$!%!&!'!(!)! !*!} | +!,!-!x ", +" f .!0!1!2!3!4!5!6!7!8!9!&!:!;!!5!?!@!A!B!C!D!f ", +" E!F!G!H!I!J!K!L!M!N!O!P!Q!&!R!S!T!U!L!V!W!X!Y!Z![!x ", +" f ]!^!_!`!a!b!c!d!e!f!g!h!i!j!k!h!l!m!n!c!b!o!p!q!r!s!f ", +" f t!u!v!w!x!y!z!{!|!}!~! #!###$#%#&#'#(#)#*#+#,#-#.#0#f ", +" E!1#2#3#4#5#6#7#8#9#:#;#;#;#;#;#;#<#=#>#?#@#A#B#C#D#E#F# ", +" G#H#I#J#K#L#M#N#O#P#Q#Q#Q#Q#Q#Q#Q#Q#R#S#T#U#V#W#X#Y#Z#E! ", +" [#]#^#_#`#a#b#c#d#e#f#g#g#g#g#g#g#h#i#j#k#l#a#m#n#o#p#q# ", +" [#]#^#r#s#t#u#v#w#x#y#z#z#z#z#z#z#{#|#}#~# $!$#$$$o#p#q# ", +" q#p#o#$$%$&$'$($)$*$+$,$-$-$-$-$.$0$1$2$3$4$5$6$7$8$1#E! ", +" x 9$:$;$<$=$>$?$@$A$B$C$D$E$E$F$G$H$I$J$K$L$M$N$O$P$Q$f ", +" f R$S$T$U$V$W$X$Y$Z$[$]$^$_$_$`$a$b$c$d$X$e$f$g$h$i$]!f ", +" f q#]#j$k$l$m$X$X$X$m$n$o$p$q$r$s$t$X$X$m$u$v$w$x$p#E! ", +" y$0#z${$|$}$~$ %!%#%$%%%&%'%(%)%*%+%,%-%.%0%1%2%]!y$ ", +" y$3%4%5%6%7%8%9%:%;%<%=%>%?%@%A%B%C%D%E%F%G%H%I%J%y$ ", +" K%y$L%^#7$M%N%O%P%Q%R%S%T%U%Q%V%W%X%Y%;$Z%[%K%K% ", +" ]%^%_%^#;$`%a%b%c%O%d%d%O%c%N%a%e%f%Z%g%K%h% ", +" i%j%h%[%k%T$$$l%m%a%%$%$6$M%l%$$h$8$p#j%n%o% ", +" p%j%q%r%s%Z%h$f%7$$$$$7$O$h$o#i$t%u%v%w% ", +" x%y%z%u%t%{%P$k%o#o#8$|%p#}%~%q% &!& ", +" #&$&o%q%%&&&'&h%h%i%(&(&)&u%*&+& ", +" ,&-&.&(&j%0&o%j%1&2&3&4& ", +" ", +" "}; \ No newline at end of file diff --git a/zq_icon_old.xpm b/zq_icon_old.xpm new file mode 100644 index 0000000000..909470b0bc --- /dev/null +++ b/zq_icon_old.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static char * zq_icon_xpm[] = { +"32 32 9 1", +" c None", +"! c black", +"# c #808080", +"$ c white", +"% c #C0C0C0", +"& c #000080", +"' c #0000FF", +"( c #FF0000", +") c #FFFF00", +" #################### ", +" #$$$$$$$$$$$$$$$$$$#! ", +" #$$$$$$$$$$$$$$$$$$##! ", +" #$$$$$$$$$$$$$$$$$$#%#! ", +" #$$$$$$$$$$$$$$$$$$#$%#! ", +" #$$$&&&&&&&&&&&&&&&#$$%#! ", +" #$$$&''''''''''''''#!!!!!! ", +" #$$$&'''''''''''''''&$$$%! ", +" #$$$&'''''''('''''''&$$$%! ", +" #$$$&''''''()(''''''&$$$%! ", +" #$$$&'''''()))('''''&$$$%! ", +" #$$$&''''()))))(''''&$$$%! ", +" #$$$&'''()))))))('''&$$$%! ", +" #$$$&''(((((((((((''&$$$%! ", +" #$$$&'('''''''''''('&$$$%! ", +" #$$$&()('''''''''()(&$$$%! ", +" #$$$()))('''''''()))($$$%! ", +" #$$()))))('''''()))))($$%! ", +" #$()))))))('''()))))))($%! ", +" #((((((((((('(((((((((((%! ", +" #$$$&'''''''''''''''&$$$%! ", +" #$$$&'''''''''''''''&$$$%! ", +" #$$$&'''''''''''''''&$$$%! ", +" #$$$$&'''''''''''''&$$$$%! ", +" #$$$$&'''''''''''''&$$$$%! ", +" #$$$$$&'''''''''''&$$$$$%! ", +" #$$$$$$&'''''''''&$$$$$$%! ", +" #$$$$$$$&&'''''&&$$$$$$$%! ", +" #$$$$$$$$$&&&&&$$$$$$$$$%! ", +" #$$$$$$$$$$$$$$$$$$$$$$$%! ", +" #%%%%%%%%%%%%%%%%%%%%%%%%! ", +" !!!!!!!!!!!!!!!!!!!!!!!!!! "}; \ No newline at end of file diff --git a/zq_icon_small.xpm b/zq_icon_small.xpm new file mode 100644 index 0000000000..41b44f929f --- /dev/null +++ b/zq_icon_small.xpm @@ -0,0 +1,172 @@ +/* XPM */ +static const unsigned char * zq_icon_small_xpm[] = { +"16 16 153 2", +" c None", +"! c black", +"# c #5265C9", +"$ c #8694DA", +"% c #A5AFE2", +"& c #A4AFE1", +"' c #8492DA", +"( c #4E62C8", +") c #3C52C1", +"* c #99A5E2", +"+ c #C6CDF3", +", c #C6CEF6", +"- c #E2E6E1", +". c #E1E4DB", +"0 c #C5CDF3", +"1 c #93A0E0", +"2 c #3A50C1", +"3 c #344ABF", +"4 c #9FABE6", +"5 c #B3BDF3", +"6 c #B4BFF9", +"7 c #C0C9F1", +"8 c #EDEEBA", +"9 c #E9EAB4", +": c #C1C9ED", +"; c #B4BFF8", +"< c #9CA8E5", +"= c #354BBF", +"> c #6376D4", +"? c #9EABF0", +"@ c #A0AEF9", +"A c #A3B1FE", +"B c #DBDEC4", +"C c #ECECA0", +"D c #EBEBA0", +"E c #D6D9B9", +"F c #A3B1FD", +"G c #9DABEF", +"H c #6375D3", +"I c #2B43BE", +"J c #6E81E1", +"K c #899BF5", +"L c #8E9FFE", +"M c #B0BBE0", +"N c #E3E38F", +"O c #E7E794", +"P c #E6E691", +"Q c #DEDE8D", +"R c #AFBAD7", +"S c #8D9FFE", +"T c #899AF4", +"U c #6E81E0", +"V c #2B43BD", +"W c #2C45C4", +"X c #5D73E5", +"Y c #758AF9", +"Z c #8194FC", +"[ c #B6C1D2", +"] c #A3B0D4", +"^ c #A5B3DB", +"_ c #A4B2D9", +"` c #A3B1D2", +"a c #B3BEC9", +"b c #8194F9", +"c c #5C72E4", +"d c #2C45C2", +"e c #2D47C8", +"f c #415CE6", +"g c #627AFB", +"h c #A3B0C4", +"i c #CED182", +"j c #788EF9", +"k c #758CFF", +"l c #778EFC", +"m c #D0D48F", +"n c #A1ADB5", +"o c #627AFA", +"p c #415BE4", +"q c #2D46C6", +"r c #2D46C7", +"s c #3450E4", +"t c #556FEC", +"u c #D1D265", +"v c #C2C23F", +"w c #9CAAB1", +"x c #657FFF", +"y c #9DABBF", +"z c #D5D557", +"{ c #C4C556", +"| c #566FE5", +"} c #3450E3", +"~ c #334FDF", +" ! c #9BA794", +"!! c #BFBF2A", +"#! c #BDBD28", +"$! c #BFC04A", +"%! c #657EEA", +"&! c #647EF1", +"'! c #D2D463", +"(! c #BFBF2C", +")! c #B5B526", +"*! c #97A182", +"+! c #324EDE", +",! c #2C44C1", +"-! c #2B42BC", +".! c #5166B5", +"0! c #C4C53E", +"1! c #ACAC1E", +"2! c #B4B41F", +"3! c #B8B825", +"4! c #A2AC89", +"5! c #A5B19D", +"6! c #C5C531", +"7! c #B2B21F", +"8! c #ABAB1D", +"9! c #B9B934", +":! c #5367AD", +";! c #3C52B5", +"! c #566FD6", +"?! c #5F77DD", +"@! c #6179E0", +"A! c #627AE8", +"B! c #5E76DB", +"C! c #546DD4", +"D! c #4C64C9", +"E! c #485EB8", +"F! c #3B51B0", +"G! c #2A41B9", +"H! c #2B44C0", +"I! c #324EDD", +"J! c #3653ED", +"K! c #3856F6", +"L! c #3A58F9", +"M! c #3856F5", +"N! c #3653EC", +"O! c #324DDC", +"P! c #2B43BF", +"Q! c #2940B8", +"R! c #152168", +"S! c #2940B7", +"T! c #2E47CA", +"U! c #324EDC", +"V! c #2D47C9", +"W! c #283FB5", +"X! c #131E61", +"Y! c #070B32", +"Z! c #1A287A", +"[! c #253AA7", +"]! c #2439A4", +"^! c #192676", +"_! c #06092D", +" ", +" # $ % & ' ( ", +" ) * + , - . , 0 1 2 ", +" 3 4 5 6 7 8 9 : ; 5 < = ", +" > ? @ A B C D E F @ G H ", +" I J K L M N O P Q R S T U V ", +" W X Y Z [ ] ^ _ ` a b Y c d ", +" e f g h i j k k l m n o p q ", +" r s t u v w x x y z { | } q ", +" d ~ !!!#!$!%!&!'!(!)!*!+!,! ", +" -!.!0!1!2!3!4!5!6!7!8!9!:!-! ", +" ;!!?!@!A!B!C!D!E!F! ", +" G!H!I!J!K!L!L!M!N!O!P!Q! ", +" R!S!T!I!} } U!V!W!X! ", +" Y!Z![!S!S!]!^!_! ", +" "}; \ No newline at end of file diff --git a/zq_icon_small_old.xpm b/zq_icon_small_old.xpm new file mode 100644 index 0000000000..4542e27586 --- /dev/null +++ b/zq_icon_small_old.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static char * zq_icon_small_xpm[] = { +"16 16 8 1", +" c None", +"! c black", +"# c #808080", +"$ c white", +"% c #C0C0C0", +"& c #000080", +"' c #0000FF", +"( c #FFFF00", +" ########## ", +" #$$$$$$$$%# ", +" #$&&&&&&&%$# ", +" #$&''''''!!!! ", +" #$&'''('''&%! ", +" #$&''(((''&%! ", +" #$&'((((('&%! ", +" #$&('''''(&%! ", +" #$((('''(((%! ", +" #((((('(((((! ", +" #$&'''''''&%! ", +" #$&'''''''&%! ", +" #$$&'''''&$%! ", +" #$$$&&&&&$$%! ", +" #%%%%%%%%%%%! ", +" !!!!!!!!!!!!! "}; \ No newline at end of file